diff --git a/Config/SettingsAbstract.php b/Config/SettingsAbstract.php index 7cf6a8eb1..a0ead306e 100644 --- a/Config/SettingsAbstract.php +++ b/Config/SettingsAbstract.php @@ -18,6 +18,7 @@ namespace phpOMS\Config; use phpOMS\DataStorage\Database\DatabaseType; use phpOMS\DataStorage\Database\Query\Builder; +use phpOMS\DataStorage\Database\DatabaseExceptionFactory; /** * Settings class. @@ -90,25 +91,30 @@ abstract class SettingsAbstract implements OptionsInterface */ public function get(array $columns) { - $options = []; + try { + $options = []; - switch ($this->connection->getType()) { - case DatabaseType::MYSQL: - $query = new Builder($this->connection); - $sql = $query->select(...static::$columns) - ->from($this->connection->prefix . static::$table) - ->where(static::$columns[0], 'in', $columns) - ->toSql(); + switch ($this->connection->getType()) { + case DatabaseType::MYSQL: + $query = new Builder($this->connection); + $sql = $query->select(...static::$columns) + ->from($this->connection->prefix . static::$table) + ->where(static::$columns[0], 'in', $columns) + ->toSql(); - $sth = $this->connection->con->prepare($sql); - $sth->execute(); + $sth = $this->connection->con->prepare($sql); + $sth->execute(); - $options = $sth->fetchAll(\PDO::FETCH_KEY_PAIR); - $this->setOptions($options); - break; + $options = $sth->fetchAll(\PDO::FETCH_KEY_PAIR); + $this->setOptions($options); + break; + } + + return $options; + } catch (\PDOException $e) { + // todo does it mean that the recognition isn't here but at the place where the new happens? + throw DatabaseExceptionFactory::create($e); } - - return $options; } /** diff --git a/DataStorage/Database/Connection/ConnectionException.php b/DataStorage/Database/Connection/ConnectionException.php new file mode 100644 index 000000000..e69de29bb diff --git a/DataStorage/Database/DatabaseExceptionFactory.php b/DataStorage/Database/DatabaseExceptionFactory.php new file mode 100644 index 000000000..1524f84b2 --- /dev/null +++ b/DataStorage/Database/DatabaseExceptionFactory.php @@ -0,0 +1,57 @@ + + * @author Dennis Eichhorn + * @copyright 2013 Dennis Eichhorn + * @license OMS License 1.0 + * @version 1.0.0 + * @link http://orange-management.com + */ +namespace phpOMS\DataStorage\Database; + +use phpOMS\DataStorage\Database\Schema\Exception\TableException; + +/** + * Path exception class. + * + * @category System + * @package Framework + * @author OMS Development Team + * @author Dennis Eichhorn + * @license OMS License 1.0 + * @link http://orange-management.com + * @since 1.0.0 + */ +class DatabaseExceptionFactory +{ + /** + * Constructor. + * + * @param string $message Exception message + * @param int $code Exception code + * @param \Exception Previous exception + * + * @since 1.0.0 + * @author Dennis Eichhorn + */ + public static function create(\PDOException $e) : \PDOException + { + switch($e->getCode()) { + case '42S02': + return self::createTableViewException($e); + default: + return $e; + } + } + + private static function createTableViewException(\PDOException $e) : \PDOException + { + return new TableException(TableException::findTable($e->getMessage())); + } +} diff --git a/DataStorage/Database/Schema/Exception/TableException.php b/DataStorage/Database/Schema/Exception/TableException.php new file mode 100644 index 000000000..836ad46c9 --- /dev/null +++ b/DataStorage/Database/Schema/Exception/TableException.php @@ -0,0 +1,62 @@ + + * @author Dennis Eichhorn + * @copyright 2013 Dennis Eichhorn + * @license OMS License 1.0 + * @version 1.0.0 + * @link http://orange-management.com + */ +namespace phpOMS\DataStorage\Database\Schema\Exception; + +/** + * Path exception class. + * + * @category System + * @package Framework + * @author OMS Development Team + * @author Dennis Eichhorn + * @license OMS License 1.0 + * @link http://orange-management.com + * @since 1.0.0 + */ +class TableException extends \PDOException +{ + /** + * Constructor. + * + * @param string $message Exception message + * @param int $code Exception code + * @param \Exception Previous exception + * + * @since 1.0.0 + * @author Dennis Eichhorn + */ + public function __construct(string $message, int $code = 0, \Exception $previous = null) + { + parent::__construct('The table "' . $message . '" doesn\'t exist.', $code, $previous); + } + + public static function findTable(string $message) : string + { + $pos1 = strpos($message, '\''); + + if($pos1 === false) { + return $message; + } + + $pos2 = strpos($message, '\'', $pos1+1); + + if($pos2 === false) { + return $message; + } + + return substr($message, $pos1+1, $pos2-$pos1-1); + } +} diff --git a/Dispatcher/ConsoleDispatcher.php b/Dispatcher/ConsoleDispatcher.php new file mode 100644 index 000000000..e69de29bb diff --git a/Dispatcher/Dispatcher.php b/Dispatcher/Dispatcher.php index 49b60b33a..dd113d76b 100644 --- a/Dispatcher/Dispatcher.php +++ b/Dispatcher/Dispatcher.php @@ -85,31 +85,16 @@ class Dispatcher $views = []; $type = ViewLayout::UNDEFINED; - if (is_array($controller) && isset($controller['type'])) { - $type = $controller['type']; + if (is_array($controller) && isset($controller['dest'])) { $controller = $controller['dest']; } if (is_string($controller)) { - $dispatch = explode(':', $controller); - $this->get($dispatch[0]); - - if (($c = count($dispatch)) == 3) { - /* Handling static functions */ - $views[$type][$controller] = $dispatch[0]::$dispatch[2](); - } elseif ($c == 2) { - $views[$type][$controller] = $this->controllers[$dispatch[0]]->{$dispatch[1]}($request, $response, $data); - } else { - throw new \UnexpectedValueException('Unexpected function.'); - } + $views += $this->dispatchString($controller, $request, $response, $data); } elseif (is_array($controller)) { - foreach ($controller as $controllerSingle) { - foreach ($controllerSingle as $c) { - $views += $this->dispatch($c, $request, $response, $data); - } - } + $views += $this->dispatchArray($controller, $request, $response, $data); } elseif ($controller instanceof \Closure) { - $views[$type][] = $controller($this->app, $request, $response, $data); + $views[] = $this->dispatchClosure($controller, $request, $response, $data); } else { throw new \UnexpectedValueException('Unexpected controller type.'); } @@ -117,17 +102,42 @@ class Dispatcher return $views; } - /** - * Get controller. - * - * @param string $controller Controller string - * - * @return mixed - * - * @since 1.0.0 - * @author Dennis Eichhorn - */ - public function get(string $controller) + private function dispatchString(string $controller, RequestAbstract $request, ResponseAbstract $response, $data = null) + { + $views =[]; + $dispatch = explode(':', $controller); + $this->getController($dispatch[0]); + + if (($c = count($dispatch)) == 3) { + /* Handling static functions */ + $views[$controller] = $dispatch[0]::$dispatch[2](); + } elseif ($c == 2) { + $views[$controller] = $this->controllers[$dispatch[0]]->{$dispatch[1]}($request, $response, $data); + } else { + throw new \UnexpectedValueException('Unexpected function.'); + } + + return $views; + } + + private function dispatchArray(array $controller, RequestAbstract $request, ResponseAbstract $response, $data = null) : array + { + $views = []; + foreach ($controller as $controllerSingle) { + foreach ($controllerSingle as $c) { + $views += $this->dispatch($c, $request, $response, $data); + } + } + + return $views; + } + + private function dispatchClosure(\Closure $controller, RequestAbstract $request, ResponseAbstract $response, $data = null) + { + return $controller($this->app, $request, $response, $data); + } + + private function getController(string $controller) { if (!isset($this->controllers[$controller])) { if (realpath($path = ROOT_PATH . '/' . str_replace('\\', '/', $controller) . '.php') === false) { @@ -158,8 +168,7 @@ class Dispatcher return true; } - + return false; } - } diff --git a/Dispatcher/DispatcherInterface.php b/Dispatcher/DispatcherInterface.php new file mode 100644 index 000000000..e69de29bb diff --git a/Dispatcher/HttpDispatcher.php b/Dispatcher/HttpDispatcher.php new file mode 100644 index 000000000..e69de29bb diff --git a/Dispatcher/LocalDispatcher.php b/Dispatcher/LocalDispatcher.php new file mode 100644 index 000000000..e69de29bb diff --git a/Dispatcher/SocketDispatcher.php b/Dispatcher/SocketDispatcher.php new file mode 100644 index 000000000..e69de29bb diff --git a/Message/HeaderAbstract.php b/Message/HeaderAbstract.php new file mode 100644 index 000000000..def6fb17c --- /dev/null +++ b/Message/HeaderAbstract.php @@ -0,0 +1,32 @@ + + * @author Dennis Eichhorn + * @copyright 2013 Dennis Eichhorn + * @license OMS License 1.0 + * @version 1.0.0 + * @link http://orange-management.com + */ +namespace phpOMS\Message; + +/** + * Response class. + * + * @category Framework + * @package phpOMS\Response + * @author OMS Development Team + * @author Dennis Eichhorn + * @license OMS License 1.0 + * @link http://orange-management.com + * @since 1.0.0 + */ +class HeaderAbstract +{ + private static $isLocked = false; +} \ No newline at end of file diff --git a/Message/Http/Header.php b/Message/Http/Header.php new file mode 100644 index 000000000..0ca37694e --- /dev/null +++ b/Message/Http/Header.php @@ -0,0 +1,201 @@ + + * @author Dennis Eichhorn + * @copyright 2013 Dennis Eichhorn + * @license OMS License 1.0 + * @version 1.0.0 + * @link http://orange-management.com + */ +namespace phpOMS\Message\Http; + +use phpOMS\Message\HeaderAbstract; +use phpOMS\Utils\ArrayUtils; +use phpOMS\DataStorage\Cookie\CookieJar; +use phpOMS\DataStorage\Session\HttpSession; + +/** + * Response class. + * + * @category Framework + * @package phpOMS\Response + * @author OMS Development Team + * @author Dennis Eichhorn + * @license OMS License 1.0 + * @link http://orange-management.com + * @since 1.0.0 + */ +class Header extends HeaderAbstract +{ + + /** + * Header. + * + * @var string[][] + * @since 1.0.0 + */ + private $header = []; + + public function __constrct() + { + $this->setHeader('Content-Type', 'text/html; charset=utf-8'); + } + + public function getHeaders() : array + { + return getallheaders(); + } + + /** + * {@inheritdoc} + */ + public function getHeader(string $name) : string + { + return getallheaders()[$name]; + } + + /** + * Remove header by ID. + * + * @param int $key Header key + * + * @return bool + * + * @since 1.0.0 + * @author Dennis Eichhorn + */ + public function remove(int $key) : bool + { + if (self::$isLocked) { + throw new \Exception('Already locked'); + } + + if (isset($this->header[$key])) { + unset($this->header[$key]); + + return true; + } + + return false; + } + + /** + * {@inheritdoc} + */ + public function get(string $id) : array + { + return $this->header[$id] ?? []; + } + + /** + * {@inheritdoc} + */ + public function has(string $name) : bool + { + return array_key_exists($name, $this->header); + } + + /** + * {@inheritdoc} + */ + public function set($key, string $header, bool $overwrite = false) : bool + { + if (self::$isLocked) { + throw new \Exception('Already locked'); + } + + if (!$overwrite && isset($this->header[$key])) { + return false; + } elseif ($overwrite) { + unset($this->header[$key]); + } + + if (!isset($this->header[$key])) { + $this->header[$key] = []; + } + + $this->header[$key][] = $header; + + return true; + } + + /** + * Push all headers. + * + * @since 1.0.0 + * @author Dennis Eichhorn + */ + public function push() + { + if (self::$isLocked) { + throw new \Exception('Already locked'); + } + + foreach ($this->header as $name => $arr) { + foreach ($arr as $ele => $value) { + header($name . ': ' . $value); + } + } + + $this->lock(); + } + + private function lock() + { + CookieJar::lock(); + HttpSession::lock(); + self::$isLocked = true; + } + + /** + * Generate header automatically based on code. + * + * @param string $code HTTP status code + * + * @return void + * + * @since 1.0.0 + * @author Dennis Eichhorn + */ + public function generate(string $code) + { + switch($code) { + case RequestStatus::R_403: + $this->generate403(); + break; + case RequestStatus::R_406: + $this->generate406(); + break; + case RequestStatus::R_407: + $this->generate503(); + break; + default: + throw new \Exception('Unexpected header code'); + } + } + + private function generate403() + { + $this->setHeader('HTTP', 'HTTP/1.0 403 Forbidden'); + $this->setHeader('Status', 'Status: HTTP/1.0 403 Forbidden'); + } + + private function generate406() + { + $this->setHeader('HTTP', 'HTTP/1.0 406 Not acceptable'); + $this->setHeader('Status', 'Status: 406 Not acceptable'); + } + + private function generate503() + { + $this->setHeader('HTTP', 'HTTP/1.0 503 Service Temporarily Unavailable'); + $this->setHeader('Status', 'Status: 503 Service Temporarily Unavailable'); + $this->setHeader('Retry-After', 'Retry-After: 300'); + } +} \ No newline at end of file diff --git a/Message/Http/Request.php b/Message/Http/Request.php index 70b48507a..629f9a8c6 100644 --- a/Message/Http/Request.php +++ b/Message/Http/Request.php @@ -20,6 +20,7 @@ use phpOMS\Message\RequestAbstract; use phpOMS\Uri\Http; use phpOMS\Uri\UriFactory; use phpOMS\Uri\UriInterface; +use phpOMS\Router\RouteVerb; /** * Request class. @@ -387,7 +388,7 @@ class Request extends RequestAbstract public function getMethod() : string { if (!isset($this->method)) { - $this->method = $_SERVER['REQUEST_METHOD']; + $this->method = $_SERVER['REQUEST_METHOD'] ?? RequestMethod::GET; } return $this->method; @@ -399,31 +400,7 @@ class Request extends RequestAbstract public function getProtocolVersion() : string { return $_SERVER['SERVER_PROTOCOL']; - } - - /** - * {@inheritdoc} - */ - public function getHeaders() : array - { - return getallheaders(); - } - - /** - * {@inheritdoc} - */ - public function hasHeader(string $name) : bool - { - return array_key_exists($name, getallheaders()); - } - - /** - * {@inheritdoc} - */ - public function getHeader(string $name) : string - { - return getallheaders()[$name]; - } + } /** * {@inheritdoc} @@ -454,21 +431,17 @@ class Request extends RequestAbstract return $this->files; } - public function setHeader($key, string $header, bool $overwrite = true) + public function getRouteVerb() : int { - // NOT Required for Http request - } - - /** - * Get request route. - * - * @return string - * - * @since 1.0.0 - * @author Dennis Eichhorn - */ - public function getRoutify() : string - { - return $this->uri->__toString(); + switch($this->getMethod()) { + case RequestMethod::GET: + return RouteVerb::GET; + case RequestMethod::PUT: + return RouteVerb::PUT; + case RequestMethod::POST: + return RouteVerb::SET; + default: + throw new \Exception(); + } } } diff --git a/Message/RequestMethod.php b/Message/Http/RequestMethod.php similarity index 96% rename from Message/RequestMethod.php rename to Message/Http/RequestMethod.php index 9f51448fb..dcdd4c4f7 100644 --- a/Message/RequestMethod.php +++ b/Message/Http/RequestMethod.php @@ -13,7 +13,7 @@ * @version 1.0.0 * @link http://orange-management.com */ -namespace phpOMS\Message; +namespace phpOMS\Message\Http; use phpOMS\Datatypes\Enum; diff --git a/Message/Http/Response.php b/Message/Http/Response.php index c44a01cba..752937651 100644 --- a/Message/Http/Response.php +++ b/Message/Http/Response.php @@ -15,10 +15,9 @@ */ namespace phpOMS\Message\Http; -use phpOMS\Contract\ArrayableInterface; +use phpOMS\System\MimeType; use phpOMS\Contract\RenderableInterface; use phpOMS\Message\ResponseAbstract; -use phpOMS\Model\Html\Head; use phpOMS\Utils\ArrayUtils; use phpOMS\DataStorage\Cookie\CookieJar; use phpOMS\DataStorage\Session\HttpSession; @@ -36,25 +35,6 @@ use phpOMS\DataStorage\Session\HttpSession; */ class Response extends ResponseAbstract implements RenderableInterface { - - /** - * Header. - * - * @var string[][] - * @since 1.0.0 - */ - private $header = []; - - /** - * html head. - * - * @var Head - * @since 1.0.0 - */ - private $head = null; - - private static $isLocked = false; - /** * Constructor. * @@ -63,96 +43,7 @@ class Response extends ResponseAbstract implements RenderableInterface */ public function __construct() { - $this->setHeader('Content-Type', 'text/html; charset=utf-8'); - $this->head = new Head(); - } - - /** - * Push header by ID. - * - * @param mixed $name Header ID - * - * @return void - * - * @since 1.0.0 - * @author Dennis Eichhorn - */ - public function pushHeaderId($name) - { - if (self::$isLocked) { - throw new \Exception('Already locked'); - } - - foreach ($this->header[$name] as $key => $value) { - header($name, $value); - } - - $this->lock(); - } - - /** - * Remove header by ID. - * - * @param int $key Header key - * - * @return bool - * - * @since 1.0.0 - * @author Dennis Eichhorn - */ - public function removeHeader(int $key) : bool - { - if (self::$isLocked) { - throw new \Exception('Already locked'); - } - - if (isset($this->header[$key])) { - unset($this->header[$key]); - - return true; - } - - return false; - } - - /** - * Generate header automatically based on code. - * - * @param int $code HTTP status code - * - * @return void - * - * @since 1.0.0 - * @author Dennis Eichhorn - */ - public function generateHeader(int $code) - { - if ($code === 403) { - $this->generate403(); - } elseif ($code === 406) { - $this->generate406(); - } elseif ($code === 503) { - $this->generate503(); - } - } - - private function generate403() - { - $this->setHeader('HTTP', 'HTTP/1.0 403 Forbidden'); - $this->setHeader('Status', 'Status: HTTP/1.0 403 Forbidden'); - } - - private function generate406() - { - $this->setHeader('HTTP', 'HTTP/1.0 406 Not acceptable'); - $this->setHeader('Status', 'Status: 406 Not acceptable'); - } - - private function generate503() - { - $this->setHeader('HTTP', 'HTTP/1.0 503 Service Temporarily Unavailable'); - $this->setHeader('Status', 'Status: 503 Service Temporarily Unavailable'); - $this->setHeader('Retry-After', 'Retry-After: 300'); + $this->header = new Header(); } /** @@ -187,44 +78,6 @@ class Response extends ResponseAbstract implements RenderableInterface ob_end_flush(); } - /** - * Generate response. - * - * @return \Iterator - * - * @since 1.0.0 - * @author Dennis Eichhorn - */ - public function getYield() : \Iterator - { - yield $this->head->render(); - - foreach ($this->response as $key => $response) { - yield $response; - } - } - - /** - * Push all headers. - * - * @since 1.0.0 - * @author Dennis Eichhorn - */ - public function pushHeader() - { - if (self::$isLocked) { - throw new \Exception('Already locked'); - } - - foreach ($this->header as $name => $arr) { - foreach ($arr as $ele => $value) { - header($name . ': ' . $value); - } - } - - $this->lock(); - } - /** * Remove response by ID. * @@ -250,14 +103,6 @@ class Response extends ResponseAbstract implements RenderableInterface return false; } - /** - * {@inheritdoc} - */ - public function getHead() - { - return $this->head; - } - /** * {@inheritdoc} */ @@ -266,22 +111,6 @@ class Response extends ResponseAbstract implements RenderableInterface return '1.0'; } - /** - * {@inheritdoc} - */ - public function getHeaders() : array - { - return $this->header; - } - - /** - * {@inheritdoc} - */ - public function hasHeader(string $name) : bool - { - return array_key_exists($name, $this->header); - } - /** * {@inheritdoc} */ @@ -302,20 +131,33 @@ class Response extends ResponseAbstract implements RenderableInterface */ public function render() : string { - $render = $this->head->render(); + switch($this->header->get('Content-Type')) { + case MimeType::M_JSON: + return $this->getJson(); + default: + return $this->getRaw(); + } + } + + private function getJson() : string + { + return json_encode($this->getArray()); + } + + private function getRaw() : string + { + $render = ''; - // todo: fix api return - // right now it is_object hence not printing the request key => object and only object->render(); - // this can't be changed easily since view uses this as well and this mustn't print a key. maybe view instanceof View? foreach ($this->response as $key => $response) { - if (is_object($response)) { - $render .= $response->render(); + if ($response instanceOf \Serializable) { + $render .= $response->serialize(); } elseif (is_string($response) || is_numeric($response)) { $render .= $response; } elseif (is_array($response)) { $render .= json_encode($response); // TODO: remove this. This should never happen since then someone forgot to set the correct header. it should be json header! } else { + var_dump($response); throw new \Exception('Wrong response type'); } } @@ -323,30 +165,25 @@ class Response extends ResponseAbstract implements RenderableInterface return $render; } - /** - * {@inheritdoc} - */ - public function toCsv() : string + private function getArray() : array { - return ArrayUtils::arrayToCSV($this->toArray()); - } + $result = []; - /** - * {@inheritdoc} - */ - public function toArray() : array - { - $arr = []; - - foreach ($this->response as $key => $response) { - if ($response instanceof ArrayableInterface) { - $arr = ArrayUtils::setArray($key, $arr, $response->toArray(), ':'); + foreach($this->response as $key => $response) { + if($reponse instanceof Views) { + $result += $response->getArray(); + } elseif(is_array($response)) { + $result += $response; + } elseif(is_scalar($response)) { + $result[] = $response; + } elseif($response instanceof \Serializable) { + $result[] = $response->serialize(); } else { - $arr = ArrayUtils::setArray($key, $arr, $response, ':'); + throw new \Exception('Wrong response type'); } } - return $arr; + return $result; } /** @@ -354,49 +191,6 @@ class Response extends ResponseAbstract implements RenderableInterface */ public function getReasonPhrase() : string { - return $this->getHeader('Status'); - } - - /** - * {@inheritdoc} - */ - public function getHeader(string $name) - { - if (isset($this->header[$name])) { - return $this->header[$name]; - } - - return null; - } - - /** - * {@inheritdoc} - */ - public function setHeader($key, string $header, bool $overwrite = false) : bool - { - if (self::$isLocked) { - throw new \Exception('Already locked'); - } - - if (!$overwrite && isset($this->header[$key])) { - return false; - } elseif ($overwrite) { - unset($this->header[$key]); - } - - if (!isset($this->header[$key])) { - $this->header[$key] = []; - } - - $this->header[$key][] = $header; - - return true; - } - - private function lock() - { - CookieJar::lock(); - HttpSession::lock(); - self::$isLocked = true; + return $this->header->getHeader('Status'); } } diff --git a/Message/Http/Rest.php b/Message/Http/Rest.php index d99435014..39210d4c3 100644 --- a/Message/Http/Rest.php +++ b/Message/Http/Rest.php @@ -15,7 +15,7 @@ */ namespace phpOMS\Message\Http; -use phpOMS\Message\RequestMethod; +use phpOMS\Message\Http\RequestMethod; /** * Rest request class. diff --git a/Message/MessageInterface.php b/Message/MessageInterface.php index ad0984cb2..853e4fd6f 100644 --- a/Message/MessageInterface.php +++ b/Message/MessageInterface.php @@ -45,45 +45,7 @@ interface MessageInterface * @since 1.0.0 * @author Dennis Eichhorn */ - public function getHeaders() : array; - - /** - * Checks if a header exists by the given case-insensitive name. - * - * @param string $name Header name - * - * @return bool - * - * @since 1.0.0 - * @author Dennis Eichhorn - */ - public function hasHeader(string $name) : bool; - - /** - * Retrieves a message header value by the given case-insensitive name. - * - * @param string $name Header name - * - * @return void - * - * @since 1.0.0 - * @author Dennis Eichhorn - */ - public function getHeader(string $name); - - /** - * Add header by ID. - * - * @param mixed $key Header ID - * @param string $header Header string - * @param bool $overwrite Overwrite existing headers - * - * @return bool - * - * @since 1.0.0 - * @author Dennis Eichhorn - */ - public function setHeader($key, string $header, bool $overwrite = true); + public function getHeader() : HeaderAbstract; /** * Gets the body of the message. diff --git a/Message/RequestAbstract.php b/Message/RequestAbstract.php index 6fec593cd..a59e9d70b 100644 --- a/Message/RequestAbstract.php +++ b/Message/RequestAbstract.php @@ -122,6 +122,8 @@ abstract class RequestAbstract implements MessageInterface */ protected $hash = []; + protected $header = null; + /** * Constructor. * @@ -321,6 +323,11 @@ abstract class RequestAbstract implements MessageInterface return $this->status; } + public function getHeader() : HeaderAbstract + { + return $this->header; + } + /** * {@inheritdoc} */ @@ -343,4 +350,6 @@ abstract class RequestAbstract implements MessageInterface * @author Dennis Eichhorn */ abstract public function getRequestTarget() : string; + + abstract public function getRouteVerb() : int; } diff --git a/Message/RequestDestination.php b/Message/RequestDestination.php deleted file mode 100644 index 7b39125ae..000000000 --- a/Message/RequestDestination.php +++ /dev/null @@ -1,52 +0,0 @@ - - * @author Dennis Eichhorn - * @copyright 2013 Dennis Eichhorn - * @license OMS License 1.0 - * @version 1.0.0 - * @link http://orange-management.com - */ -namespace phpOMS\Message; - -use phpOMS\Datatypes\Enum; - -/** - * Request page enum. - * - * Possible page requests. Page requests can have completely different themes, permissions and page structures. - * - * @category Request - * @package Framework - * @author OMS Development Team - * @author Dennis Eichhorn - * @license OMS License 1.0 - * @link http://orange-management.com - * @since 1.0.0 - */ -abstract class RequestDestination extends Enum -{ - const WEBSITE = 'Website'; /* Website */ - const API = 'Api'; /* API */ - const SHOP = 'Shop'; /* Shop */ - const BACKEND = 'Backend'; /* Backend */ - const STATICP = 'Static'; /* Static content */ - const FORUM = 'Forum'; /* Forum */ - const TICKET = 'Ticket'; /* ???? */ - const SUPPORT = 'Support'; /* Support center */ - const SURVEY = 'Survey'; /* Survey page */ - const BLOG = 'Blog'; /* Blog */ - const CHART = 'Chart'; /* Chart view */ - const CALENDAR = 'Calendar'; /* Calendar */ - const PROFILE = 'Profile'; /* User profile page */ - const CHAT = 'Chat'; /* Chat page */ - const GALLERY = 'Gallery'; /* Chat page */ - const REPORTER = 'Reporter'; /* Reporter page */ - // This or let api handle this const GUI = 'gui'; /* Request GUI elements */ -} diff --git a/Message/ResponseAbstract.php b/Message/ResponseAbstract.php index c54d694b6..4c1ecb88b 100644 --- a/Message/ResponseAbstract.php +++ b/Message/ResponseAbstract.php @@ -15,10 +15,9 @@ */ namespace phpOMS\Message; -use phpOMS\Contract\ArrayableInterface; -use phpOMS\Contract\JsonableInterface; use phpOMS\Localization\Localization; use phpOMS\Utils\ArrayUtils; +use phpOMS\Message\Http\Header; /** * Response abstract class. @@ -31,7 +30,7 @@ use phpOMS\Utils\ArrayUtils; * @link http://orange-management.com * @since 1.0.0 */ -abstract class ResponseAbstract implements MessageInterface, ArrayableInterface, JsonableInterface +abstract class ResponseAbstract implements MessageInterface { /** @@ -66,10 +65,7 @@ abstract class ResponseAbstract implements MessageInterface, ArrayableInterface, */ protected $account = null; - /** - * {@inheritdoc} - */ - abstract public function setHeader($key, string $header, bool $overwrite = true); + protected $header = null; /** * {@inheritdoc} @@ -125,7 +121,7 @@ abstract class ResponseAbstract implements MessageInterface, ArrayableInterface, public function setStatusCode(string $status) { $this->status = $status; - $this->generateHeader($status); + $this->header->generate($status); } /** @@ -160,15 +156,10 @@ abstract class ResponseAbstract implements MessageInterface, ArrayableInterface, return json_encode($this->toArray()); } - /** - * Generate header automatically based on code. - * - * @param int $code HTTP status code - * - * @return void - * - * @since 1.0.0 - * @author Dennis Eichhorn - */ - abstract public function generateHeader(int $code); + public function getHeader() : HeaderAbstract + { + return $this->header; + } + + abstract public function getBody() : string; } diff --git a/Module/InfoManager.php b/Module/InfoManager.php index d0ad53b61..343491d2a 100644 --- a/Module/InfoManager.php +++ b/Module/InfoManager.php @@ -59,14 +59,18 @@ class InfoManager * @since 1.0.0 * @author Dennis Eichhorn */ - public function __construct(string $module) + public function __construct($path) { - if (($path = realpath($oldPath = ModuleAbstract::MODULE_PATH . '/' . $module . '/info.json')) === false || Validator::startsWith($path, ModuleAbstract::MODULE_PATH)) { - throw new PathException($oldPath); + $this->path = $path; + } + + public function load() + { + if (($path = realpath($this->path)) === false) { + throw new PathException($this->path); } - $this->path = $path; - $this->info = json_decode(file_get_contents($this->path), true); + $this->info = json_decode(file_get_contents($path), true); } /** @@ -111,4 +115,34 @@ class InfoManager { return $this->info; } + + public function getInternalName() : string + { + return $this->info['name']['internal']; + } + + public function getDependencies() : array + { + return $this->info['dependencies']; + } + + public function getProviding() : array + { + return $this->info['providing']; + } + + public function getDirectory() : string + { + return $this->info['directory']; + } + + public function getVersion() : string + { + return $this->info['version']; + } + + public function getLoad() : array + { + return $this->info['load']; + } } diff --git a/Module/InstallerAbstract.php b/Module/InstallerAbstract.php index 3add342ff..8fb39a65e 100644 --- a/Module/InstallerAbstract.php +++ b/Module/InstallerAbstract.php @@ -16,6 +16,9 @@ namespace phpOMS\Module; use phpOMS\DataStorage\Database\Pool; +use phpOMS\Module\InfoManager; +use phpOMS\Router\RouteVerb; +use phpOMS\Utils\Parser\Php\ArrayParser; /** * Installer Abstract class. @@ -42,7 +45,25 @@ class InstallerAbstract * @since 1.0.0 * @author Dennis Eichhorn */ - public static function install(Pool $dbPool, array $info) + public static function install(Pool $dbPool, InfoManager $info) { + self::installRoutes(ROOT_PATH . '/Web/Routes.php', ROOT_PATH . '/Modules/' . $info->getDirectory() . '/Admin/Routes/http.php'); + self::installRoutes(ROOT_PATH . '/Socket/Routes.php', ROOT_PATH . '/Modules/' . $info->getDirectory() . '/Admin/Routes/socket.php'); + self::installRoutes(ROOT_PATH . '/Console/Routes.php', ROOT_PATH . '/Modules/' . $info->getDirectory() . '/Admin/Routes/console.php'); + } + + private static function installRoutes(string $appRoutePath, string $moduleRoutePath) + { + if(file_exists($appRoutePath) && file_exists($moduleRoutePath)) { + $appRoutes = include $appRoutePath; + $moduleRoutes = include $moduleRoutePath; + $appRoutes = array_merge_recursive($appRoutes, $moduleRoutes); + + if(is_writable($appRoutePath)) { + file_put_contents($appRoutePath, 'app = $app; - - foreach (static::$routes as $route => $destinations) { - foreach ($destinations as $destination) { - $this->app->router->add($route, $destination['dest'], $destination['method'], $destination['type']); - } - } } /** @@ -148,20 +134,13 @@ abstract class ModuleAbstract public function getLocalization(string $language, string $destination) : array { $lang = []; - if (isset(static::$localization[$destination])) { - /** @noinspection PhpUnusedLocalVariableInspection */ - foreach (static::$localization[$destination] as $file) { - if (($path = realpath($oldPath = __DIR__ . '/../../Modules/' . static::MODULE_NAME . '/Theme/' . $destination . '/Lang/' . $language . '.lang.php')) === false) { - throw new PathException($oldPath); - } - - /** @noinspection PhpIncludeInspection */ - include realpath($path); - /** @var array $MODLANG */ - $lang += $MODLANG; - } + if (($path = realpath($oldPath = __DIR__ . '/../../Modules/' . static::MODULE_NAME . '/Theme/' . $destination . '/Lang/' . $language . '.lang.php')) === false) { + throw new PathException($oldPath); } + /** @noinspection PhpIncludeInspection */ + $lang = include $path; + return $lang; } diff --git a/Module/ModuleManager.php b/Module/ModuleManager.php index efdaf7dc5..011d2db84 100644 --- a/Module/ModuleManager.php +++ b/Module/ModuleManager.php @@ -20,6 +20,7 @@ use phpOMS\DataStorage\Database\DatabaseType; use phpOMS\Log\FileLogger; use phpOMS\Message\Http\Request; use phpOMS\System\File\PathException; +use phpOMS\Autoloader; use phpOMS\Utils\IO\Json\InvalidJsonException; /** @@ -296,18 +297,34 @@ class ModuleManager // todo download; } - $path = realpath($oldPath = self::MODULE_PATH . '/' . $module . '/' . 'info.json'); + try { + $info = $this->loadInfo($module); - if ($path === false || strpos($path, self::MODULE_PATH) === false) { - throw new PathException($module); - } - - $info = json_decode(file_get_contents($path), true); - - if (!isset($info)) { - throw new InvalidJsonException($path); + $this->registerInDatabase($info); + $this->installed[$module] = $info; + $this->installDependencies($info->getDependencies()); + $this->installModule($info); + + /* Install providing */ + $providing = $info->getProviding(); + foreach ($providing as $key => $version) { + $this->installProviding($module, $key); + } + + /* Install receiving */ + foreach ($installed as $key => $value) { + $this->installProviding($key, $module); + } + } catch(PathException $e) { + // todo: handle module doesn't exist or files are missing + //echo $e->getMessage(); + } catch(\Exception $e) { + //echo $e->getMessage(); } + } + private function registerInDatabase(InfoManager $info) + { switch ($this->app->dbPool->get('core')->getType()) { case DatabaseType::MYSQL: $this->app->dbPool->get('core')->con->beginTransaction(); @@ -317,11 +334,11 @@ class ModuleManager (:internal, :theme, :path, :active, :version);' ); - $sth->bindValue(':internal', $info['name']['internal'], \PDO::PARAM_INT); + $sth->bindValue(':internal', $info->getInternalName(), \PDO::PARAM_INT); $sth->bindValue(':theme', 'Default', \PDO::PARAM_STR); - $sth->bindValue(':path', $info['directory'], \PDO::PARAM_STR); + $sth->bindValue(':path', $info->getDirectory(), \PDO::PARAM_STR); $sth->bindValue(':active', 1, \PDO::PARAM_INT); - $sth->bindValue(':version', $info['version'], \PDO::PARAM_STR); + $sth->bindValue(':version', $info->getVersion(), \PDO::PARAM_STR); $sth->execute(); @@ -330,7 +347,8 @@ class ModuleManager (:pid, :type, :from, :for, :file);' ); - foreach ($info['load'] as $val) { + $load = $info->getLoad(); + foreach ($load as $val) { foreach ($val['pid'] as $pid) { $sth->bindValue(':pid', $pid, \PDO::PARAM_STR); $sth->bindValue(':type', $val['type'], \PDO::PARAM_INT); @@ -346,26 +364,39 @@ class ModuleManager break; } + } - foreach ($info['dependencies'] as $key => $version) { + private function installDependencies(array $dependencies) + { + foreach ($dependencies as $key => $version) { $this->install($key); } + } + + private function installModule(InfoManager $info) + { + $class = '\\Modules\\' . $info->getDirectory() . '\\Admin\\Installer'; + + if(!Autoloader::exists($class)) { + throw new \Exception('Module installer does not exist'); + } - $class = '\\Modules\\' . $module . '\\Admin\\Installer'; /** @var $class InstallerAbstract */ $class::install($this->app->dbPool, $info); + } - // TODO: change this - $this->installed[$module] = true; + private function loadInfo(string $module) : InfoManager + { + $path = realpath($oldPath = self::MODULE_PATH . '/' . $module . '/' . 'info.json'); - foreach ($info['providing'] as $key => $version) { - $this->installProviding($module, $key); + if ($path === false || strpos($path, self::MODULE_PATH) === false) { + throw new PathException($oldPath); } - /* Install receiving */ - foreach ($installed as $key => $value) { - $this->installProviding($key, $module); - } + $info = new InfoManager($path); + $info->load(); + + return $info; } /** @@ -426,25 +457,35 @@ class ModuleManager public function initModule($module) { if (is_array($module)) { - foreach ($module as $m) { - try { - $this->initModule($m); - } catch (\InvalidArgumentException $e) { - $this->app->logger->warning(FileLogger::MSG_FULL, [ - 'message' => 'Trying to initialize ' . $m . ' without controller.', - 'line' => $e->getLine(), - 'file' => $e->getFile(), - ]); - } - } + $this->initModuleArray($module); } elseif (is_string($module) && realpath(self::MODULE_PATH . '/' . $module . '/Controller.php') !== false) { - $this->running[$module] = ModuleFactory::getInstance($module, $this->app); - $this->app->dispatcher->set($this->running[$module], '\Modules\\' . $module . '\\Controller'); + $this->initModuleController($module); } else { throw new \InvalidArgumentException('Invalid Module'); } } + private function initModuleArray(array $modules) + { + foreach ($modules as $module) { + try { + $this->initModule($module); + } catch (\InvalidArgumentException $e) { + $this->app->logger->warning(FileLogger::MSG_FULL, [ + 'message' => 'Trying to initialize ' . $module . ' without controller.', + 'line' => $e->getLine(), + 'file' => $e->getFile(), + ]); + } + } + } + + private function initModuleController(string $module) + { + $this->running[$module] = ModuleFactory::getInstance($module, $this->app); + $this->app->dispatcher->set($this->running[$module], '\Modules\\' . $module . '\\Controller'); + } + /** * Get module instance. * diff --git a/Module/UninstallAbstract.php b/Module/UninstallAbstract.php index cfc9c06f6..9da0da83d 100644 --- a/Module/UninstallAbstract.php +++ b/Module/UninstallAbstract.php @@ -42,7 +42,7 @@ class UninstallAbstract * @since 1.0.0 * @author Dennis Eichhorn */ - public static function uninstall(Pool $dbPool, array $info) + public static function uninstall(Pool $dbPool, InfoManager $info) { } diff --git a/Router/RouteAbstract.php b/Router/RouteAbstract.php index e69de29bb..5eec48460 100644 --- a/Router/RouteAbstract.php +++ b/Router/RouteAbstract.php @@ -0,0 +1,34 @@ + + * @author Dennis Eichhorn + * @copyright 2013 Dennis Eichhorn + * @license OMS License 1.0 + * @version 1.0.0 + * @link http://orange-management.com + */ +namespace phpOMS\Router; + +/** + * Router class. + * + * @category Framework + * @package phpOMS\Socket + * @author OMS Development Team + * @author Dennis Eichhorn + * @license OMS License 1.0 + * @link http://orange-management.com + * @since 1.0.0 + */ +class RouteAbstract +{ + + + +} \ No newline at end of file diff --git a/Router/RouteVerb.php b/Router/RouteVerb.php new file mode 100644 index 000000000..7fe08ddfb --- /dev/null +++ b/Router/RouteVerb.php @@ -0,0 +1,37 @@ + + * @author Dennis Eichhorn + * @copyright 2013 Dennis Eichhorn + * @license OMS License 1.0 + * @version 1.0.0 + * @link http://orange-management.com + */ +namespace phpOMS\Router; + +use phpOMS\Datatypes\Enum; + +/** + * View layout enum. + * + * @category Framework + * @package phpOMS\Socket + * @author OMS Development Team + * @author Dennis Eichhorn + * @license OMS License 1.0 + * @link http://orange-management.com + * @since 1.0.0 + */ +abstract class RouteVerb extends Enum +{ + const GET = 1; + const PUT = 2; + const SET = 3; + const ANY = 4; +} diff --git a/Router/Router.php b/Router/Router.php index 41594f3e8..8723951ee 100644 --- a/Router/Router.php +++ b/Router/Router.php @@ -15,8 +15,8 @@ */ namespace phpOMS\Router; -use phpOMS\Message\RequestMethod; use phpOMS\Views\ViewLayout; +use phpOMS\Message\RequestAbstract; /** * Router class. @@ -50,25 +50,29 @@ class Router { } + public function importFromFile(string $path) + { + $this->routes = include $path; + } + /** * Add route. * * @param string $route Route regex - * @param mixed $destination Destination e.g. Module:function & method - * @param string $method Request method - * @param int $type Result type + * @param mixed $destination Destination e.g. Module:function & verb + * @param string $verb Request verb + * @param int $layout Result layout * * @return void * * @since 1.0.0 * @author Dennis Eichhorn */ - public function add(string $route, $destination, string $method = RequestMethod::GET, int $type = ViewLayout::MAIN) + public function add(string $route, $destination, string $verb = RouteVerb::GET) { $this->routes[$route][] = [ 'dest' => $destination, - 'method' => $method, - 'type' => $type, + 'verb' => $verb, ]; } @@ -76,20 +80,20 @@ class Router * Route uri. * * @param string $uri Uri to route - * @param string $remoteMethod GET/POST etc. + * @param string $verb GET/POST etc. * * @return string[] * * @since 1.0.0 * @author Dennis Eichhorn */ - public function route(string $uri, string $remoteMethod = RequestMethod::GET) : array + public function route(RequestAbstract $request) : array { $bound = []; foreach ($this->routes as $route => $destination) { foreach ($destination as $d) { - if ($this->match($route, $d['method'], $uri, $remoteMethod)) { - $bound[$route][] = ['dest' => $d['dest'], 'type' => $d['type']]; + if ($this->match($route, $d['verb'], $request->getUri(), $request->getRouteVerb())) { + $bound[] = ['dest' => $d['dest']]; } } } @@ -101,17 +105,17 @@ class Router * Match route and uri. * * @param string $route Route - * @param string $method GET,POST for this route + * @param string $verb GET,POST for this route * @param string $uri Uri - * @param string $remoteMethod Method this request is using + * @param string $verb Verb this request is using * * @return bool * * @since 1.0.0 * @author Dennis Eichhorn */ - private function match(string $route, string $method, string $uri, string $remoteMethod = RequestMethod::GET) : bool + private function match(string $route, string $routeVerb, string $uri, string $remoteVerb = RouteVerb::GET) : bool { - return (bool) preg_match('~^' . $route . '$~', $uri) && ($method == 'any' || $remoteMethod == $method); + return (bool) preg_match('~^' . $route . '$~', $uri) && ($routeVerb == RouteVerb::ANY || $remoteVerb == $routeVerb); } } diff --git a/System/File/Directory.php b/System/File/Directory.php index 1d6b15dbe..62f66d96a 100644 --- a/System/File/Directory.php +++ b/System/File/Directory.php @@ -217,7 +217,7 @@ class Directory extends FileAbstract implements \Iterator, \ArrayAccess /** * {@inheritdoc} */ - private function createNode() : bool + public function createNode() : bool { return self::createPath($this->path, $this->permission, true); } @@ -225,7 +225,7 @@ class Directory extends FileAbstract implements \Iterator, \ArrayAccess /** * {@inheritdoc} */ - private function removeNode() : bool + public function removeNode() : bool { return true; } diff --git a/System/File/File.php b/System/File/File.php index 611548f07..4af2bd6d9 100644 --- a/System/File/File.php +++ b/System/File/File.php @@ -77,7 +77,7 @@ class File extends FileAbstract /** * {@inheritdoc} */ - private function createNode() : bool + public function createNode() : bool { return self::create($this->path); } @@ -85,7 +85,7 @@ class File extends FileAbstract /** * {@inheritdoc} */ - private function removeNode() : bool + public function removeNode() : bool { return true; } diff --git a/System/File/FileAbstract.php b/System/File/FileAbstract.php index 87dca8ef3..88ce3f03f 100644 --- a/System/File/FileAbstract.php +++ b/System/File/FileAbstract.php @@ -184,7 +184,7 @@ abstract class FileAbstract * @since 1.0.0 * @author Dennis Eichhorn */ - abstract private function createNode() : bool; + abstract public function createNode() : bool; /** * Get created at. diff --git a/Uri/Http.php b/Uri/Http.php index 87d5d19ca..3fe8aee18 100644 --- a/Uri/Http.php +++ b/Uri/Http.php @@ -15,8 +15,6 @@ */ namespace phpOMS\Uri; - - /** * Uri interface. * diff --git a/Views/View.php b/Views/View.php index 1c6b62cad..9e08b94a3 100644 --- a/Views/View.php +++ b/Views/View.php @@ -16,7 +16,6 @@ namespace phpOMS\Views; use phpOMS\ApplicationAbstract; -use phpOMS\Contract\RenderableInterface; use phpOMS\Localization\Localization; use phpOMS\Message\RequestAbstract; use phpOMS\Message\ResponseAbstract; @@ -34,7 +33,7 @@ use phpOMS\Validation\Validator; * @link http://orange-management.com * @since 1.0.0 */ -class View implements RenderableInterface +class View implements \Serializable { /** @@ -250,25 +249,6 @@ class View implements RenderableInterface } } - /** - * Get view/template response of all views. - * - * @return string - * - * @since 1.0.0 - * @author Dennis Eichhorn - */ - public function renderAll() : string - { - ob_start(); - - foreach ($this->views as $key => $view) { - echo $view->render(); - } - - return ob_get_clean(); - } - /** * Get view/template response. * @@ -288,9 +268,14 @@ class View implements RenderableInterface ob_start(); /** @noinspection PhpIncludeInspection */ - include $path; + $data = include $path; + $ob = ob_get_clean(); - return ob_get_clean(); + if(is_array($data)) { + return $data; + } + + return $ob; } /** @@ -355,4 +340,25 @@ class View implements RenderableInterface $this->data[$id] = $data; } + public function getArray() : array + { + $viewArray = []; + + $viewArray[] = $this->render(); + + foreach($this->views as $key => $view) { + $viewArray[$key] = $view->getArray(); + } + } + + public function serialize() + { + return $this->render(); + } + + public function unserialize($raw) + { + + } + }