From 6213f2fb75130ed8fa59084ec15f40df67816227 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20Sessing=C3=B8?= Date: Sat, 26 Nov 2016 04:30:00 +0100 Subject: [PATCH] Development - Optimised Input-classes. - `get` and `getObject` methods on `Input` now supports filtering on multiple method-types when using the `$method` parameter. - Input classes now know how to parse that stupid nested $_FILES array. - It's now possible to change method-names on ResourceControllers. - Removed `getValue` and `setValue` from `InputFile` classes. - Ensured that request-method are only parsed from $_POST or $_SERVER. - Fixed minor parameter-issues with subdomain routing. - Added PHPDocs. - Added even more unit-tests. - Many small optimisations tweaks. --- README.md | 8 +- src/Pecee/Controllers/IRestController.php | 14 +- src/Pecee/Http/Input/IInputItem.php | 4 - src/Pecee/Http/Input/Input.php | 214 +++++++++++------ src/Pecee/Http/Input/InputFile.php | 134 ++++++++--- src/Pecee/Http/Input/InputItem.php | 1 + .../Http/Middleware/BaseCsrfVerifier.php | 6 +- src/Pecee/Http/Request.php | 21 +- src/Pecee/Http/Response.php | 9 +- .../SimpleRouter/Route/ILoadableRoute.php | 2 +- src/Pecee/SimpleRouter/Route/IRoute.php | 2 +- .../SimpleRouter/Route/LoadableRoute.php | 11 +- src/Pecee/SimpleRouter/Route/Route.php | 17 +- .../SimpleRouter/Route/RouteController.php | 17 +- src/Pecee/SimpleRouter/Route/RouteGroup.php | 4 +- .../SimpleRouter/Route/RouteResource.php | 66 +++-- src/Pecee/SimpleRouter/Router.php | 30 ++- src/Pecee/SimpleRouter/SimpleRouter.php | 1 + .../Exceptions/ExceptionHandlerException.php | 4 + test/Dummy/Handler/ExceptionHandler.php | 2 +- .../Handler/TestExceptionHandlerFirst.php | 13 + .../Handler/TestExceptionHandlerSecond.php | 13 + .../Handler/TestExceptionHandlerThird.php | 12 + test/GroupTest.php | 114 ++++----- test/MiddlewareTest.php | 41 ++-- test/RouterRouteTest.php | 225 ++++++++++-------- test/RouterUrlTest.php | 117 ++++----- 27 files changed, 685 insertions(+), 417 deletions(-) create mode 100644 test/Dummy/Exceptions/ExceptionHandlerException.php create mode 100644 test/Dummy/Handler/TestExceptionHandlerFirst.php create mode 100644 test/Dummy/Handler/TestExceptionHandlerSecond.php create mode 100644 test/Dummy/Handler/TestExceptionHandlerThird.php diff --git a/README.md b/README.md index b7eb3ac..feed827 100644 --- a/README.md +++ b/README.md @@ -756,7 +756,7 @@ If items is grouped in the html, it will return an array of items. **Note:** `get` will automatically trim the value and ensure that it's not empty. If it's empty the `$defaultValue` will be returned. ```php -$value = input()->get($index, $defaultValue); +$value = input()->get($index, $defaultValue, $methods); ``` **Return parameter object (matches both GET, POST, FILE):** @@ -772,7 +772,7 @@ If items is grouped in the html, it will return an array of items. **Note:** `getObject` will only return `$defaultValue` if the item doesn't exist. If you want `$defaultValue` to be returned if the item is empty, please use `input()->get()` instead. ```php -$object = input()->getObject($index); +$object = input()->getObject($index, $defaultValue = null, $methods = null); ``` **Return specific GET parameter (where name is the name of your parameter):** @@ -853,8 +853,8 @@ All object implements the `IInputItem` interface and will always contain these m Below example requires you to have the helper functions added. Please refer to the helper functions section in the documentation. ```php -// Get parameter site_id or default-value 2 -$siteId = input()->get('site_id', 2); +/* Get parameter site_id or default-value 2 from either post-value or query-string */ +$siteId = input()->get('site_id', 2, ['post', 'get']); ``` --- diff --git a/src/Pecee/Controllers/IRestController.php b/src/Pecee/Controllers/IRestController.php index 9fe070b..aa91c22 100644 --- a/src/Pecee/Controllers/IRestController.php +++ b/src/Pecee/Controllers/IRestController.php @@ -7,41 +7,41 @@ interface IRestController /** * @return void */ - function index(); + public function index(); /** * @param mixed $id * @return void */ - function show($id); + public function show($id); /** * @return void */ - function store(); + public function store(); /** * @return void */ - function create(); + public function create(); /** * View * @param mixed $id * @return void */ - function edit($id); + public function edit($id); /** * @param mixed $id * @return void */ - function update($id); + public function update($id); /** * @param mixed $id * @return void */ - function destroy($id); + public function destroy($id); } \ No newline at end of file diff --git a/src/Pecee/Http/Input/IInputItem.php b/src/Pecee/Http/Input/IInputItem.php index 36c4cb0..c35f2ec 100644 --- a/src/Pecee/Http/Input/IInputItem.php +++ b/src/Pecee/Http/Input/IInputItem.php @@ -12,10 +12,6 @@ interface IInputItem public function setName($name); - public function getValue(); - - public function setValue($value); - public function __toString(); } \ No newline at end of file diff --git a/src/Pecee/Http/Input/Input.php b/src/Pecee/Http/Input/Input.php index 0850a78..f7b4b4e 100644 --- a/src/Pecee/Http/Input/Input.php +++ b/src/Pecee/Http/Input/Input.php @@ -32,7 +32,7 @@ class Input $this->parseInputs(); } - protected function parseInputs() + public function parseInputs() { /* Parse get requests */ if (count($_GET) > 0) { @@ -42,7 +42,7 @@ class Input /* Parse post requests */ $postVars = $_POST; - if (in_array($this->request->getMethod(), ['put', 'patch', 'delete']) === true) { + if (in_array($this->request->getMethod(), ['put', 'patch', 'delete'], false) === true) { parse_str(file_get_contents('php://input'), $postVars); } @@ -51,49 +51,86 @@ class Input } /* Parse get requests */ - - if (count($_FILES) > 0) { - - $max = count($_FILES) - 1; - $keys = array_keys($_FILES); - - for ($i = $max; $i >= 0; $i--) { - - $key = $keys[$i]; - $value = $_FILES[$key]; - - // Handle array input - if (is_array($value['name']) === false) { - $values['index'] = $key; - $this->file[$key] = InputFile::createFromArray(array_merge($value, $values)); - continue; - } - - $subMax = count($value['name']) - 1; - $keys = array_keys($value['name']); - $output = []; - - for ($i = $subMax; $i >= 0; $i--) { - - $output[$keys[$i]] = InputFile::createFromArray([ - 'index' => $key, - 'error' => $value['error'][$keys[$i]], - 'tmp_name' => $value['tmp_name'][$keys[$i]], - 'type' => $value['type'][$keys[$i]], - 'size' => $value['size'][$keys[$i]], - 'name' => $value['name'][$keys[$i]], - ]); - - } - - $this->file[$key] = $output; - } - } + $this->parseFiles(); } - protected function handleGetPost($array) + public function parseFiles() { - $tmp = []; + if (count($_FILES) === 0) { + return []; + } + + $list = []; + + foreach ($_FILES as $key => $value) { + + // Handle array input + if (is_array($value['name']) === false) { + $values['index'] = $key; + $list[$key] = InputFile::createFromArray(array_merge($value, $values)); + continue; + } + + $keys = []; + + $list = array_merge_recursive($list, [$key => $this->rearrangeFiles($value['name'], $keys, $value)]); + + } + + return $list; + } + + protected function rearrangeFiles(array $values, &$index, $original) + { + + $output = []; + + $getItem = function ($key, $property = 'name') use ($original, $index) { + + $path = $original[$property]; + + foreach (array_values($index) as $i) { + $path = $path[$i]; + } + + return $path[$key]; + }; + + foreach ($values as $key => $value) { + + if (is_array($getItem($key)) === false) { + + $file = InputFile::createFromArray([ + 'index' => $key, + 'error' => $getItem($key, 'error'), + 'tmp_name' => $getItem($key, 'tmp_name'), + 'type' => $getItem($key, 'type'), + 'size' => $getItem($key, 'size'), + 'filename' => $getItem($key, 'name'), + ]); + + $output = array_merge_recursive($output, [$key => $file]); + + if (isset($output[$key])) { + $output[$key][] = $file; + } else { + $output[$key] = $file; + } + + continue; + } + + $index[] = $key; + $output = array_merge_recursive($output, [$key => $this->rearrangeFiles($value, $index, $original)]); + + } + + return $output; + } + + protected function handleGetPost(array $array) + { + $list = []; $max = count($array) - 1; $keys = array_keys($array); @@ -105,77 +142,110 @@ class Input // Handle array input if (is_array($value) === false) { - $tmp[$key] = new InputItem($key, $value); + $list[$key] = new InputItem($key, $value); continue; } - $subMax = count($value) - 1; - $keys = array_keys($value); - $output = []; + $output = $this->handleGetPost($value); - for ($i = $subMax; $i >= 0; $i--) { - $output[$keys[$i]] = new InputItem($key, $value[$keys[$i]]); - } - - $tmp[$key] = $output; + $list[$key] = $output; } - return $tmp; + return $list; } - public function findPost($index, $default = null) + /** + * Find post-value by index or return default value. + * + * @param string $index + * @param string|null $defaultValue + * @return InputItem|string + */ + public function findPost($index, $defaultValue = null) { - return isset($this->post[$index]) ? $this->post[$index] : $default; + return $this->post[$index] ?? $defaultValue; } - public function findFile($index, $default = null) + /** + * Find file by index or return default value. + * + * @param string $index + * @param string|null $defaultValue + * @return InputFile|string + */ + public function findFile($index, $defaultValue = null) { - return isset($this->file[$index]) ? $this->file[$index] : $default; + return $this->file[$index] ?? $defaultValue; } - public function findGet($index, $default = null) + /** + * Find parameter/query-string by index or return default value. + * + * @param string $index + * @param string|null $defaultValue + * @return InputItem|string + */ + public function findGet($index, $defaultValue = null) { - return isset($this->get[$index]) ? $this->get[$index] : $default; + return $this->get[$index] ?? $defaultValue; } - public function getObject($index, $default = null, $method = null) + /** + * Get input object + * + * @param string $index + * @param string|null $defaultValue + * @param array|string|null $methods + * @return IInputItem|string + */ + public function getObject($index, $defaultValue = null, $methods = null) { + if ($methods !== null && is_string($methods) === true) { + $methods = [$methods]; + } + $element = null; - if ($method === null || strtolower($method) === 'get') { + if ($methods === null || in_array('get', $methods)) { $element = $this->findGet($index); } - if ($element === null && $method === null || strtolower($method) === 'post') { + if (($element === null && $methods === null) || ($methods !== null && in_array('post', $methods))) { $element = $this->findPost($index); } - if ($element === null && $method === null || strtolower($method) === 'file') { + if (($element === null && $methods === null) || ($methods !== null && in_array('file', $methods))) { $element = $this->findFile($index); } - return ($element === null) ? $default : $element; + return ($element !== null) ? $element : $defaultValue; } /** * Get input element value matching index * * @param string $index - * @param string|null $default - * @param string|null $method + * @param string|null $defaultValue + * @param array|string|null $methods * @return InputItem|string */ - public function get($index, $default = null, $method = null) + public function get($index, $defaultValue = null, $methods = null) { - $input = $this->getObject($index, $default, $method); + $input = $this->getObject($index, $defaultValue, $methods); if ($input instanceof InputItem) { - return (trim($input->getValue()) === '') ? $default : $input->getValue(); + return (trim($input->getValue()) === '') ? $defaultValue : $input->getValue(); } return $input; } + /** + * Check if a input-item exist + * + * @param string $index + * @return bool + */ public function exists($index) { return ($this->getObject($index) !== null); @@ -194,7 +264,7 @@ class Input $contents = file_get_contents('php://input'); - if (stripos(trim($contents), '{') === 0) { + if (strpos(trim($contents), '{') === 0) { $output = json_decode($contents, true); if ($output === false) { $output = []; @@ -206,11 +276,7 @@ class Input if ($filter !== null) { $output = array_filter($output, function ($key) use ($filter) { - if (in_array($key, $filter)) { - return true; - } - - return false; + return (in_array($key, $filter) === true); }, ARRAY_FILTER_USE_KEY); } diff --git a/src/Pecee/Http/Input/InputFile.php b/src/Pecee/Http/Input/InputFile.php index 0d405f7..6fdec72 100644 --- a/src/Pecee/Http/Input/InputFile.php +++ b/src/Pecee/Http/Input/InputFile.php @@ -4,8 +4,8 @@ namespace Pecee\Http\Input; class InputFile implements IInputItem { public $index; - public $value; public $name; + public $filename; public $size; public $type; public $error; @@ -21,7 +21,9 @@ class InputFile implements IInputItem /** * Create from array + * * @param array $values + * @throws \InvalidArgumentException * @return static */ public static function createFromArray(array $values) @@ -30,12 +32,22 @@ class InputFile implements IInputItem throw new \InvalidArgumentException('Index key is required'); } + /* Easy way of ensuring that all indexes-are set and not filling the screen with isset() */ + + $values = array_merge([ + 'tmp_name' => null, + 'type' => null, + 'size' => null, + 'name' => null, + 'error' => null, + ], $values); + $input = new static($values['index']); - $input->setError(isset($values['error']) ? $values['error'] : null); - $input->setName(isset($values['name']) ? $values['name'] : null); - $input->setSize(isset($values['size']) ? $values['size'] : null); - $input->setType(isset($values['type']) ? $values['type'] : null); - $input->setTmpName(isset($values['tmp_name']) ? $values['tmp_name'] : null); + $input->setError($values['error']) + ->setSize($values['size']) + ->setType($values['type']) + ->setTmpName($values['tmp_name']) + ->setFilename($values['name']); return $input; } @@ -48,6 +60,11 @@ class InputFile implements IInputItem return $this->index; } + /** + * Set input index + * @param string $index + * @return static $this + */ public function setIndex($index) { $this->index = $index; @@ -75,6 +92,10 @@ class InputFile implements IInputItem return $this; } + /** + * Get mime-type of file + * @return string + */ public function getMime() { return $this->getType(); @@ -100,12 +121,19 @@ class InputFile implements IInputItem return $this; } + /** + * Returns extension without "." + * + * @return string + */ public function getExtension() { return pathinfo($this->getName(), PATHINFO_EXTENSION); } /** + * Get human friendly name + * * @return string */ public function getName() @@ -113,6 +141,13 @@ class InputFile implements IInputItem return $this->name; } + /** + * Set human friendly name. + * Useful for adding validation etc. + * + * @param string $name + * @return static $this + */ public function setName($name) { $this->name = $name; @@ -120,29 +155,63 @@ class InputFile implements IInputItem return $this; } + /** + * Set filename + * + * @param string $name + * @return static $this + */ + public function setFilename($name) + { + $this->filename = $name; + + return $this; + } + + /** + * Get filename + * + * @return string mixed + */ + public function getFilename() + { + return $this->filename; + } + + /** + * Move the uploaded temporary file to it's new home + * + * @param string $destination + * @return bool + */ public function move($destination) { return move_uploaded_file($this->tmpName, $destination); } + /** + * Get file contents + * + * @return string + */ public function getContents() { return file_get_contents($this->tmpName); } - public function setValue($value) - { - $this->value = $value; - - return $this; - } - + /** + * Return true if an upload error occured. + * + * @return bool + */ public function hasError() { return ($this->getError() !== 0); } /** + * Get upload-error code. + * * @return string */ public function getError() @@ -152,6 +221,7 @@ class InputFile implements IInputItem /** * Set error + * * @param int $error * @return static $this */ @@ -162,27 +232,6 @@ class InputFile implements IInputItem return $this; } - public function toArray() - { - return [ - 'tmp_name' => $this->tmpName, - 'type' => $this->type, - 'size' => $this->size, - 'name' => $this->name, - 'error' => $this->error, - ]; - } - - public function __toString() - { - return $this->getValue(); - } - - public function getValue() - { - return $this->getTmpName(); - } - /** * @return string */ @@ -202,4 +251,21 @@ class InputFile implements IInputItem return $this; } + + public function __toString() + { + return $this->getTmpName(); + } + + public function toArray() + { + return [ + 'tmp_name' => $this->tmpName, + 'type' => $this->type, + 'size' => $this->size, + 'name' => $this->filename, + 'error' => $this->error, + ]; + } + } \ No newline at end of file diff --git a/src/Pecee/Http/Input/InputItem.php b/src/Pecee/Http/Input/InputItem.php index 91dd56c..8554088 100644 --- a/src/Pecee/Http/Input/InputItem.php +++ b/src/Pecee/Http/Input/InputItem.php @@ -75,4 +75,5 @@ class InputItem implements IInputItem { return (string)$this->value; } + } \ No newline at end of file diff --git a/src/Pecee/Http/Middleware/BaseCsrfVerifier.php b/src/Pecee/Http/Middleware/BaseCsrfVerifier.php index d6ea61d..046251b 100644 --- a/src/Pecee/Http/Middleware/BaseCsrfVerifier.php +++ b/src/Pecee/Http/Middleware/BaseCsrfVerifier.php @@ -58,7 +58,7 @@ class BaseCsrfVerifier implements IMiddleware public function handle(Request $request, ILoadableRoute &$route = null) { - if (in_array($request->getMethod(), ['post', 'put', 'delete']) === true && $this->skip($request) === false) { + if ($this->skip($request) === false && in_array($request->getMethod(), ['post', 'put', 'delete']) === true) { $token = $request->getInput()->get(static::POST_KEY, null, 'post'); @@ -77,7 +77,7 @@ class BaseCsrfVerifier implements IMiddleware public function generateToken() { - $token = $this->csrfToken->generateToken(); + $token = CsrfToken::generateToken(); $this->csrfToken->setToken($token); return $token; @@ -85,7 +85,7 @@ class BaseCsrfVerifier implements IMiddleware public function hasToken() { - if ($this->token != null) { + if ($this->token !== null) { return true; } diff --git a/src/Pecee/Http/Request.php b/src/Pecee/Http/Request.php index 8ce9075..b6ada6b 100644 --- a/src/Pecee/Http/Request.php +++ b/src/Pecee/Http/Request.php @@ -15,10 +15,10 @@ class Request public function __construct() { $this->parseHeaders(); - $this->host = $this->getHeader('http-host');; + $this->host = $this->getHeader('http-host'); $this->uri = $this->getHeader('request-uri'); $this->input = new Input($this); - $this->method = strtolower($this->input->get('_method', $this->getHeader('request-method'))); + $this->method = strtolower($this->input->get('_method', $this->getHeader('request-method'), 'post')); } protected function parseHeaders() @@ -40,11 +40,7 @@ class Request public function isSecure() { - if ($this->getHeader('http-x-forwarded-proto') === 'https' || $this->getHeader('https') !== null || $this->getHeader('server-port') === 443) { - return true; - } - - return false; + return $this->getHeader('http-x-forwarded-proto') === 'https' || $this->getHeader('https') !== null || $this->getHeader('server-port') === 443; } /** @@ -108,7 +104,7 @@ class Request return $this->getHeader('http-cf-connecting-ip'); } - if ($this->getHeader('http-x-forwarded-for') !== null && strlen($this->getHeader('http-x-forwarded-for'))) { + if ($this->getHeader('http-x-forwarded-for') !== null) { return $this->getHeader('http-x-forwarded_for'); } @@ -137,7 +133,7 @@ class Request * Get header value by name * * @param string $name - * @param object|null $defaultValue + * @param string|null $defaultValue * * @return string|null */ @@ -217,6 +213,11 @@ class Request $this->method = $method; } + public function __isset($name) + { + return $this->data[$name] ?? null; + } + public function __set($name, $value = null) { $this->data[$name] = $value; @@ -224,7 +225,7 @@ class Request public function __get($name) { - return isset($this->data[$name]) ? $this->data[$name] : null; + return $this->data[$name] ?? null; } } \ No newline at end of file diff --git a/src/Pecee/Http/Response.php b/src/Pecee/Http/Response.php index a1bba1f..c5730f1 100644 --- a/src/Pecee/Http/Response.php +++ b/src/Pecee/Http/Response.php @@ -64,14 +64,14 @@ class Response $this->headers([ 'Cache-Control: public', - 'Last-Modified: ' . gmdate("D, d M Y H:i:s", $lastModified) . ' GMT', + 'Last-Modified: ' . gmdate('D, d M Y H:i:s', $lastModified) . ' GMT', 'Etag: ' . $eTag, ]); $httpModified = $this->request->getHeader('http-if-modified-since'); $httpIfNoneMatch = $this->request->getHeader('http-if-none-match'); - if ($httpModified !== null && strtotime($httpModified) == $lastModified || $httpIfNoneMatch !== null && $httpIfNoneMatch === $eTag) { + if (($httpIfNoneMatch !== null && $httpIfNoneMatch === $eTag) || ($httpModified !== null && strtotime($httpModified) === $lastModified)) { $this->header('HTTP/1.1 304 Not Modified'); @@ -111,9 +111,8 @@ class Response */ public function headers(array $headers) { - $max = count($headers); - for ($i = 0; $i < $max; $i++) { - $this->header($headers[$i]); + foreach ($headers as $header) { + $this->header($header); } return $this; diff --git a/src/Pecee/SimpleRouter/Route/ILoadableRoute.php b/src/Pecee/SimpleRouter/Route/ILoadableRoute.php index bebe009..92ef82a 100644 --- a/src/Pecee/SimpleRouter/Route/ILoadableRoute.php +++ b/src/Pecee/SimpleRouter/Route/ILoadableRoute.php @@ -22,7 +22,7 @@ interface ILoadableRoute extends IRoute * @param Request $request * @param ILoadableRoute $route */ - public function loadMiddleware(Request $request, ILoadableRoute &$route); + public function loadMiddleware(Request $request, ILoadableRoute $route); public function getUrl(); diff --git a/src/Pecee/SimpleRouter/Route/IRoute.php b/src/Pecee/SimpleRouter/Route/IRoute.php index 63c5cf1..14bcbe8 100644 --- a/src/Pecee/SimpleRouter/Route/IRoute.php +++ b/src/Pecee/SimpleRouter/Route/IRoute.php @@ -18,7 +18,7 @@ interface IRoute * Returns class to be rendered. * * @param Request $request - * @return object + * @return \Closure|string */ public function renderRoute(Request $request); diff --git a/src/Pecee/SimpleRouter/Route/LoadableRoute.php b/src/Pecee/SimpleRouter/Route/LoadableRoute.php index d4d93ff..a23c73f 100644 --- a/src/Pecee/SimpleRouter/Route/LoadableRoute.php +++ b/src/Pecee/SimpleRouter/Route/LoadableRoute.php @@ -9,7 +9,14 @@ abstract class LoadableRoute extends Route implements ILoadableRoute { const PARAMETERS_REGEX_MATCH = '%s([\w\-\_]*?)\%s{0,1}%s'; + /** + * @var + */ protected $url; + + /** + * @var string + */ protected $name; /** @@ -19,7 +26,7 @@ abstract class LoadableRoute extends Route implements ILoadableRoute * @param ILoadableRoute $route * @throws HttpException */ - public function loadMiddleware(Request $request, ILoadableRoute &$route) + public function loadMiddleware(Request $request, ILoadableRoute $route) { if (count($this->getMiddlewares()) > 0) { @@ -114,7 +121,7 @@ abstract class LoadableRoute extends Route implements ILoadableRoute $param = $keys[$i]; $value = $params[$param]; - $value = (isset($parameters[$param])) ? $parameters[$param] : $value; + $value = $parameters[$param] ?? $value; if (stripos($url, $param1) !== false || stripos($url, $param) !== false) { $url = str_ireplace([sprintf($param1, $param), sprintf($param2, $param)], $value, $url); diff --git a/src/Pecee/SimpleRouter/Route/Route.php b/src/Pecee/SimpleRouter/Route/Route.php index 64464af..8649e9a 100644 --- a/src/Pecee/SimpleRouter/Route/Route.php +++ b/src/Pecee/SimpleRouter/Route/Route.php @@ -86,7 +86,7 @@ abstract class Route implements IRoute if ($character === '{') { /* Remove "/" and "\" from regex */ if (substr($regex, strlen($regex) - 1) === '/') { - $regex = substr($regex, 0, strlen($regex) - 2); + $regex = substr($regex, 0, -2); } $isParameter = true; @@ -99,7 +99,7 @@ abstract class Route implements IRoute } if ($lastCharacter === '?') { - $parameter = substr($parameter, 0, strlen($parameter) - 1); + $parameter = substr($parameter, 0, -1); $regex .= '(?:\/?(?P<' . $parameter . '>' . $parameterRegex . ')[^\/]?)?'; $required = false; } else { @@ -136,13 +136,13 @@ abstract class Route implements IRoute $name = $parameterNames[$i]; - $parameterValue = isset($parameterValues[$name['name']]) ? $parameterValues[$name['name']] : null; + $parameterValue = $parameterValues[$name['name']] ?? null; - if ($name['required'] && $parameterValue === null) { + if ($parameterValue === null && $name['required']) { throw new HttpException('Missing required parameter ' . $name['name'], 404); } - if ($name['required'] === false && $parameterValue === null) { + if ($parameterValue === null && $name['required'] === false) { continue; } @@ -384,10 +384,13 @@ abstract class Route implements IRoute } if (count($this->parameters) > 0) { + /* Ensure the right order + values */ - $parameters = ($values['parameters'] + $this->parameters); + $parameters = ($values['parameters'] ?? []) + $this->parameters; $parameters = array_merge($parameters, $this->parameters); + $this->setParameters($parameters); + $values['parameters'] = $parameters; } if (count($this->middlewares) > 0) { @@ -406,7 +409,7 @@ abstract class Route implements IRoute */ public function setSettings(array $values, $merge = false) { - if (isset($values['namespace']) && $this->namespace === null) { + if ($this->namespace === null && isset($values['namespace'])) { $this->setNamespace($values['namespace']); } diff --git a/src/Pecee/SimpleRouter/Route/RouteController.php b/src/Pecee/SimpleRouter/Route/RouteController.php index 6f96f50..486d92a 100644 --- a/src/Pecee/SimpleRouter/Route/RouteController.php +++ b/src/Pecee/SimpleRouter/Route/RouteController.php @@ -31,11 +31,11 @@ class RouteController extends LoadableRoute implements IControllerRoute } /* Remove method/type */ - if (stripos($name, '.') !== false) { + if (strpos($name, '.') !== false) { $method = substr($name, strrpos($name, '.') + 1); $newName = substr($name, 0, strrpos($name, '.')); - if (strtolower($this->name) === strtolower($newName) && in_array($method, $this->names)) { + if (in_array($method, $this->names) === true && strtolower($this->name) === strtolower($newName)) { return true; } } @@ -43,10 +43,15 @@ class RouteController extends LoadableRoute implements IControllerRoute return parent::hasName($name); } + /** + * @param string|null $method + * @param string|array|null $parameters + * @param string|null $name + * @return string + */ public function findUrl($method = null, $parameters = null, $name = null) { - - if (stripos($name, '.') !== false) { + if (strpos($name, '.') !== false) { $found = array_search(substr($name, strrpos($name, '.') + 1), $this->names); if ($found !== false) { $method = $found; @@ -54,7 +59,6 @@ class RouteController extends LoadableRoute implements IControllerRoute } $url = ''; - $parameters = (array)$parameters; /* Remove requestType from method-name, if it exists */ @@ -115,7 +119,7 @@ class RouteController extends LoadableRoute implements IControllerRoute $url = parse_url(urldecode($request->getUri()), PHP_URL_PATH); $url = rtrim($url, '/') . '/'; - if (strtolower($url) == strtolower($this->url) || stripos($url, $this->url) === 0) { + if (stripos($url, $this->url) === 0 && strtolower($url) === strtolower($this->url)) { $strippedUrl = trim(str_ireplace($this->url, '/', $url), '/'); @@ -127,6 +131,7 @@ class RouteController extends LoadableRoute implements IControllerRoute $this->method = $method; array_shift($path); + $this->parameters = $path; // Set callback diff --git a/src/Pecee/SimpleRouter/Route/RouteGroup.php b/src/Pecee/SimpleRouter/Route/RouteGroup.php index 2c04556..f55567d 100644 --- a/src/Pecee/SimpleRouter/Route/RouteGroup.php +++ b/src/Pecee/SimpleRouter/Route/RouteGroup.php @@ -27,8 +27,8 @@ class RouteGroup extends Route implements IGroupRoute $domain = $this->domains[$i]; $parameters = $this->parseParameters($domain, $request->getHost(), '.*'); - if ($parameters !== null) { - $this->parameters = $parameters; + if ($parameters !== null && count($parameters) > 0) { + $this->parameters = array_merge($this->parameters, $parameters); return true; } diff --git a/src/Pecee/SimpleRouter/Route/RouteResource.php b/src/Pecee/SimpleRouter/Route/RouteResource.php index b877e29..0a5cfba 100644 --- a/src/Pecee/SimpleRouter/Route/RouteResource.php +++ b/src/Pecee/SimpleRouter/Route/RouteResource.php @@ -15,6 +15,17 @@ class RouteResource extends LoadableRoute implements IControllerRoute 'update' => '', 'destroy' => '', ]; + + protected $methodNames = [ + 'index' => 'index', + 'create' => 'create', + 'store' => 'store', + 'show' => 'show', + 'edit' => 'edit', + 'update' => 'update', + 'destroy' => 'destroy', + ]; + protected $names = []; protected $controller; @@ -42,7 +53,7 @@ class RouteResource extends LoadableRoute implements IControllerRoute } /* Remove method/type */ - if (stripos($name, '.') !== false) { + if (strpos($name, '.') !== false) { $name = substr($name, 0, strrpos($name, '.')); } @@ -51,7 +62,7 @@ class RouteResource extends LoadableRoute implements IControllerRoute public function findUrl($method = null, $parameters = null, $name = null) { - $method = array_search($name, $this->names); + $method = array_search($name, $this->names, false); if ($method !== false) { return rtrim($this->url . $this->urls[$method], '/') . '/'; } @@ -104,43 +115,43 @@ class RouteResource extends LoadableRoute implements IControllerRoute $parameters = array_merge($this->parameters, (array)$parameters); - $action = isset($parameters['action']) ? $parameters['action'] : null; + $action = $parameters['action'] ?? null; unset($parameters['action']); $method = $request->getMethod(); // Delete - if (isset($parameters['id']) && $method === static::REQUEST_TYPE_DELETE) { - return $this->call('destroy', $parameters); + if ($method === static::REQUEST_TYPE_DELETE && isset($parameters['id'])) { + return $this->call($this->methodNames['destroy'], $parameters); } // Update if (isset($parameters['id']) && in_array($method, [static::REQUEST_TYPE_PATCH, static::REQUEST_TYPE_PUT])) { - return $this->call('update', $parameters); + return $this->call($this->methodNames['update'], $parameters); } // Edit - if (isset($parameters['id']) && strtolower($action) === 'edit' && $method === static::REQUEST_TYPE_GET) { - return $this->call('edit', $parameters); + if ($method === static::REQUEST_TYPE_GET && isset($parameters['id']) && strtolower($action) === 'edit') { + return $this->call($this->methodNames['edit'], $parameters); } // Create - if (strtolower($action) === 'create' && $method === static::REQUEST_TYPE_GET) { - return $this->call('create', $parameters); + if ($method === static::REQUEST_TYPE_GET && strtolower($action) === 'create') { + return $this->call($this->methodNames['create'], $parameters); } // Save if ($method === static::REQUEST_TYPE_POST) { - return $this->call('store', $parameters); + return $this->call($this->methodNames['store'], $parameters); } // Show - if (isset($parameters['id']) && $method === static::REQUEST_TYPE_GET) { - return $this->call('show', $parameters); + if ($method === static::REQUEST_TYPE_GET && isset($parameters['id'])) { + return $this->call($this->methodNames['show'], $parameters); } // Index - return $this->call('index', $parameters); + return $this->call($this->methodNames['index'], $parameters); } return null; @@ -182,6 +193,29 @@ class RouteResource extends LoadableRoute implements IControllerRoute return $this; } + /** + * Define custom method name for resource controller + * + * @param array $names + * @return static $this + */ + public function setMethodNames(array $names) + { + $this->methodNames = $names; + + return $this; + } + + /** + * Get method names + * + * @return array $this + */ + public function getMethodNames() + { + return $this->methodNames; + } + /** * Merge with information from another route. * @@ -195,6 +229,10 @@ class RouteResource extends LoadableRoute implements IControllerRoute $this->names = $values['names']; } + if (isset($values['methods'])) { + $this->methodNames = $values['methods']; + } + parent::setSettings($values, $merge); return $this; diff --git a/src/Pecee/SimpleRouter/Router.php b/src/Pecee/SimpleRouter/Router.php index 62c22d2..e031431 100644 --- a/src/Pecee/SimpleRouter/Router.php +++ b/src/Pecee/SimpleRouter/Router.php @@ -100,7 +100,7 @@ class Router return static::$instance; } - public function __construct() + protected function __construct() { $this->reset(); } @@ -137,16 +137,26 @@ class Router return $route; } + /** + * Process added routes. + * + * @param array $routes + * @param IGroupRoute|null $group + * @param IRoute|null $parent + */ protected function processRoutes(array $routes, IGroupRoute $group = null, IRoute $parent = null) { // Loop through each route-request $max = count($routes) - 1; + $exceptionHandlers = []; + /* @var $route IRoute */ for ($i = $max; $i >= 0; $i--) { $route = $routes[$i]; + /* @var $route IGroupRoute */ if ($route instanceof IGroupRoute) { $group = $route; @@ -159,9 +169,9 @@ class Router if ($route->matchRoute($this->request)) { - /* Add exceptionhandlers */ + /* Add exception handlers */ if (count($route->getExceptionHandlers()) > 0) { - $this->exceptionHandlers = array_merge($route->getExceptionHandlers(), $this->exceptionHandlers); + $exceptionHandlers += $route->getExceptionHandlers(); } } @@ -172,7 +182,6 @@ class Router /* Add the parent group */ $route->setGroup($group); - } if ($parent !== null) { @@ -201,6 +210,8 @@ class Router $this->processRoutes($stack, $route, $group); } } + + $this->exceptionHandlers = array_unique(array_merge($exceptionHandlers, $this->exceptionHandlers)); } public function routeRequest($rewrite = false) @@ -253,7 +264,7 @@ class Router if ($route->matchRoute($this->request)) { /* Check if request method matches */ - if (count($route->getRequestMethods()) > 0 && !in_array($this->request->getMethod(), $route->getRequestMethods())) { + if (count($route->getRequestMethods()) > 0 && in_array($this->request->getMethod(), $route->getRequestMethods()) === false) { $routeNotAllowed = true; continue; } @@ -262,7 +273,7 @@ class Router $this->loadedRoute->loadMiddleware($this->request, $this->loadedRoute); /* If the request has changed, we reinitialize the router */ - if ($this->request->getUri() !== $this->originalUrl && !in_array($this->request->getUri(), $this->routeRewrites)) { + if ($this->request->getUri() !== $this->originalUrl && in_array($this->request->getUri(), $this->routeRewrites) === false) { $this->routeRewrites[] = $this->request->getUri(); $this->routeRequest(true); @@ -309,7 +320,7 @@ class Router $request = $handler->handleError($this->request, $this->loadedRoute, $e); /* If the request has changed */ - if ($request !== null && $this->request->getUri() !== $this->originalUrl && !in_array($request->getUri(), $this->routeRewrites)) { + if ($request !== null && $this->request->getUri() !== $this->originalUrl && in_array($request->getUri(), $this->routeRewrites) === false) { $this->request = $request; $this->routeRewrites[] = $request->getUri(); $this->routeRequest(true); @@ -375,7 +386,7 @@ class Router if (strpos($name, '@') !== false && strpos($route->getCallback(), '@') !== false && !is_callable($route->getCallback())) { /* Check if the entire callback is matching */ - if (strtolower($route->getCallback()) === strtolower($name) || strpos($route->getCallback(), $name) === 0) { + if (strpos($route->getCallback(), $name) === 0 || strtolower($route->getCallback()) === strtolower($name)) { return $route; } @@ -404,6 +415,7 @@ class Router * @param string|null $name * @param string|array|null $parameters * @param array|null $getParams + * @throws \InvalidArgumentException * @return string */ public function getUrl($name = null, $parameters = null, $getParams = null) @@ -439,7 +451,7 @@ class Router } /* Using @ is most definitely a controller@method or alias@method */ - if (stripos($name, '@') !== false) { + if (strpos($name, '@') !== false) { list($controller, $method) = explode('@', $name); /* Loop through all the routes to see if we can find a match */ diff --git a/src/Pecee/SimpleRouter/SimpleRouter.php b/src/Pecee/SimpleRouter/SimpleRouter.php index 5c1722d..1f577a0 100644 --- a/src/Pecee/SimpleRouter/SimpleRouter.php +++ b/src/Pecee/SimpleRouter/SimpleRouter.php @@ -309,6 +309,7 @@ class SimpleRouter * @param string|null $name * @param string|array|null $parameters * @param array|null $getParams + * @throws \Exception * @return string */ public static function getUrl($name = null, $parameters = null, $getParams = null) diff --git a/test/Dummy/Exceptions/ExceptionHandlerException.php b/test/Dummy/Exceptions/ExceptionHandlerException.php new file mode 100644 index 0000000..066241f --- /dev/null +++ b/test/Dummy/Exceptions/ExceptionHandlerException.php @@ -0,0 +1,4 @@ +getMessage(); } } \ No newline at end of file diff --git a/test/Dummy/Handler/TestExceptionHandlerFirst.php b/test/Dummy/Handler/TestExceptionHandlerFirst.php new file mode 100644 index 0000000..282621b --- /dev/null +++ b/test/Dummy/Handler/TestExceptionHandlerFirst.php @@ -0,0 +1,13 @@ +setUri('/'); + return $request; + } + +} \ No newline at end of file diff --git a/test/Dummy/Handler/TestExceptionHandlerSecond.php b/test/Dummy/Handler/TestExceptionHandlerSecond.php new file mode 100644 index 0000000..e43cb27 --- /dev/null +++ b/test/Dummy/Handler/TestExceptionHandlerSecond.php @@ -0,0 +1,13 @@ +setUri('/'); + return $request; + } + +} \ No newline at end of file diff --git a/test/Dummy/Handler/TestExceptionHandlerThird.php b/test/Dummy/Handler/TestExceptionHandlerThird.php new file mode 100644 index 0000000..b1e47bb --- /dev/null +++ b/test/Dummy/Handler/TestExceptionHandlerThird.php @@ -0,0 +1,12 @@ +result = false; + public function testGroupLoad() + { + $this->result = false; - SimpleRouter::group(['prefix' => '/group'], function () { - $this->result = true; - }); + SimpleRouter::group(['prefix' => '/group'], function () { + $this->result = true; + }); - try { - SimpleRouter::start(); - } catch (Exception $e) { - // ignore RouteNotFound exception - } + try { + SimpleRouter::start(); + } catch (Exception $e) { + // ignore RouteNotFound exception + } - $this->assertTrue($this->result); - } + $this->assertTrue($this->result); + } - public function testNestedGroup() - { + public function testNestedGroup() + { - SimpleRouter::router()->reset(); - SimpleRouter::request()->setUri('/api/v1/test'); - SimpleRouter::request()->setMethod('get'); + SimpleRouter::router()->reset(); + SimpleRouter::request()->setUri('/api/v1/test'); + SimpleRouter::request()->setMethod('get'); - SimpleRouter::group(['prefix' => '/api'], function () { + SimpleRouter::group(['prefix' => '/api'], function () { - SimpleRouter::group(['prefix' => '/v1'], function () { - SimpleRouter::get('/test', 'DummyController@start'); - }); + SimpleRouter::group(['prefix' => '/v1'], function () { + SimpleRouter::get('/test', 'DummyController@start'); + }); - }); + }); - SimpleRouter::start(); - } + SimpleRouter::start(); + } - public function testManyRoutes() - { + public function testManyRoutes() + { - SimpleRouter::router()->reset(); - SimpleRouter::request()->setUri('/my/match'); - SimpleRouter::request()->setMethod('get'); + SimpleRouter::router()->reset(); + SimpleRouter::request()->setUri('/my/match'); + SimpleRouter::request()->setMethod('get'); - SimpleRouter::group(['prefix' => '/api'], function () { + SimpleRouter::group(['prefix' => '/api'], function () { - SimpleRouter::group(['prefix' => '/v1'], function () { - SimpleRouter::get('/test', 'DummyController@start'); - }); + SimpleRouter::group(['prefix' => '/v1'], function () { + SimpleRouter::get('/test', 'DummyController@start'); + }); - }); + }); - SimpleRouter::get('/my/match', 'DummyController@start'); + SimpleRouter::get('/my/match', 'DummyController@start'); - SimpleRouter::group(['prefix' => '/service'], function () { + SimpleRouter::group(['prefix' => '/service'], function () { - SimpleRouter::group(['prefix' => '/v1'], function () { - SimpleRouter::get('/no-match', 'DummyController@start'); - }); + SimpleRouter::group(['prefix' => '/v1'], function () { + SimpleRouter::get('/no-match', 'DummyController@start'); + }); - }); + }); - SimpleRouter::start(); - } + SimpleRouter::start(); + } - public function testUrls() - { + public function testUrls() + { - SimpleRouter::router()->reset(); - SimpleRouter::request()->setUri('/my/fancy/url/1'); - SimpleRouter::request()->setMethod('get'); + SimpleRouter::router()->reset(); + SimpleRouter::request()->setUri('/my/fancy/url/1'); + SimpleRouter::request()->setMethod('get'); - // Test array name - SimpleRouter::get('/my/fancy/url/1', 'DummyController@start', ['as' => 'fancy1']); + // Test array name + SimpleRouter::get('/my/fancy/url/1', 'DummyController@start', ['as' => 'fancy1']); - // Test method name - SimpleRouter::get('/my/fancy/url/2', 'DummyController@start')->setName('fancy2'); + // Test method name + SimpleRouter::get('/my/fancy/url/2', 'DummyController@start')->setName('fancy2'); - SimpleRouter::start(); + SimpleRouter::start(); - $this->assertEquals('/my/fancy/url/1/', SimpleRouter::getUrl('fancy1')); - $this->assertEquals('/my/fancy/url/2/', SimpleRouter::getUrl('fancy2')); + $this->assertEquals('/my/fancy/url/1/', SimpleRouter::getUrl('fancy1')); + $this->assertEquals('/my/fancy/url/2/', SimpleRouter::getUrl('fancy2')); - } + } } \ No newline at end of file diff --git a/test/MiddlewareTest.php b/test/MiddlewareTest.php index d746298..3b53270 100644 --- a/test/MiddlewareTest.php +++ b/test/MiddlewareTest.php @@ -8,25 +8,34 @@ use Pecee\SimpleRouter\SimpleRouter as SimpleRouter; class MiddlewareTest extends PHPUnit_Framework_TestCase { - public function testMiddlewareFound() - { - SimpleRouter::router()->reset(); - SimpleRouter::request()->setMethod('get'); - SimpleRouter::request()->setUri('/my/test/url'); + public function testMiddlewareFound() + { + $this->setExpectedException('MiddlewareLoadedException'); - SimpleRouter::group(['exceptionHandler' => 'ExceptionHandler'], function () { - SimpleRouter::get('/my/test/url', 'DummyController@start', ['middleware' => 'DummyMiddleware']); - }); + SimpleRouter::router()->reset(); + SimpleRouter::request()->setMethod('get'); + SimpleRouter::request()->setUri('/my/test/url'); - $found = false; + SimpleRouter::group(['exceptionHandler' => 'ExceptionHandler'], function () { + SimpleRouter::get('/my/test/url', 'DummyController@start', ['middleware' => 'DummyMiddleware']); + }); - try { - SimpleRouter::start(); - } catch (\Exception $e) { - $found = ($e instanceof MiddlewareLoadedException); - } + SimpleRouter::start(); + } - $this->assertTrue($found); - } + public function testNestedMiddlewareLoad() + { + $this->setExpectedException('MiddlewareLoadedException'); + + SimpleRouter::router()->reset(); + SimpleRouter::request()->setMethod('get'); + SimpleRouter::request()->setUri('/my/test/url'); + + SimpleRouter::group(['exceptionHandler' => 'ExceptionHandler', 'middleware' => 'DummyMiddleware'], function () { + SimpleRouter::get('/my/test/url', 'DummyController@start'); + }); + + SimpleRouter::start(); + } } \ No newline at end of file diff --git a/test/RouterRouteTest.php b/test/RouterRouteTest.php index 6207d3d..23bdaff 100644 --- a/test/RouterRouteTest.php +++ b/test/RouterRouteTest.php @@ -2,140 +2,161 @@ require_once 'Dummy/DummyMiddleware.php'; require_once 'Dummy/DummyController.php'; -require_once 'Dummy/Handler/ExceptionHandler.php'; +require_once 'Dummy/Exceptions/ExceptionHandlerException.php'; +require_once 'Dummy/Handler/TestExceptionHandlerFirst.php'; +require_once 'Dummy/Handler/TestExceptionHandlerSecond.php'; +require_once 'Dummy/Handler/TestExceptionHandlerThird.php'; -use Pecee\SimpleRouter\SimpleRouter as SimpleRouter; use Pecee\SimpleRouter\Exceptions\NotFoundHttpException as NotFoundHttpException; +use Pecee\SimpleRouter\SimpleRouter as SimpleRouter; class RouterRouteTest extends PHPUnit_Framework_TestCase { - protected $result = false; + protected $result = false; - public function testNotFound() - { - SimpleRouter::router()->reset(); - SimpleRouter::request()->setMethod('get'); - SimpleRouter::request()->setUri('/test-param1-param2'); + /** + * Redirects to another route through 3 exception handlers. + * + * You will see "ExceptionHandler 1 loaded" 2 times. This happen because + * the exceptionhandler is asking the router to reload. + * + * That means that the exceptionhandler is loaded again, but this time + * the router ignores the same rewrite-route to avoid loop - loads + * the second which have same behavior and is also ignored before + * throwing the final Exception in ExceptionHandler 3. + * + * So this tests: + * 1. If ExceptionHandlers loads + * 2. If ExceptionHandlers load in the correct order + * 3. If ExceptionHandlers can rewrite the page on error + * 4. If the router can avoid redirect-loop due to developer has started loop. + * 5. And finally if we reaches the last exception-handler and that the correct + * exception-type is being thrown. + */ + public function testNotFound() + { + $this->setExpectedException('ExceptionHandlerException'); - SimpleRouter::group(['exceptionHandler' => 'ExceptionHandler'], function () { - SimpleRouter::get('/non-existing-path', 'DummyController@start'); - }); + SimpleRouter::router()->reset(); + SimpleRouter::request()->setMethod('get'); + SimpleRouter::request()->setUri('/test-param1-param2'); - $found = false; + SimpleRouter::group(['exceptionHandler' => ['TestExceptionHandlerFirst', 'TestExceptionHandlerSecond']], function () { - try { - SimpleRouter::start(); - } catch (\Exception $e) { - $found = ($e instanceof NotFoundHttpException && $e->getCode() == 404); - } + SimpleRouter::group(['exceptionHandler' => 'TestExceptionHandlerThird'], function () { - $this->assertTrue($found); - } + SimpleRouter::get('/non-existing-path', 'DummyController@start'); - public function testGet() - { - SimpleRouter::router()->reset(); - SimpleRouter::request()->setUri('/my/test/url'); - SimpleRouter::request()->setMethod('get'); + }); + }); - SimpleRouter::get('/my/test/url', 'DummyController@start'); - SimpleRouter::start(); - } + SimpleRouter::start(); + } - public function testPost() - { - SimpleRouter::router()->reset(); - SimpleRouter::request()->setUri('/my/test/url'); - SimpleRouter::request()->setMethod('post'); + public function testGet() + { + SimpleRouter::router()->reset(); + SimpleRouter::request()->setUri('/my/test/url'); + SimpleRouter::request()->setMethod('get'); - SimpleRouter::post('/my/test/url', 'DummyController@start'); - SimpleRouter::start(); - } + SimpleRouter::get('/my/test/url', 'DummyController@start'); + SimpleRouter::start(); + } - public function testPut() - { - SimpleRouter::router()->reset(); - SimpleRouter::request()->setUri('/my/test/url'); - SimpleRouter::request()->setMethod('put'); + public function testPost() + { + SimpleRouter::router()->reset(); + SimpleRouter::request()->setUri('/my/test/url'); + SimpleRouter::request()->setMethod('post'); - SimpleRouter::put('/my/test/url', 'DummyController@start'); - SimpleRouter::start(); - } + SimpleRouter::post('/my/test/url', 'DummyController@start'); + SimpleRouter::start(); + } - public function testDelete() - { - SimpleRouter::router()->reset(); - SimpleRouter::request()->setUri('/my/test/url'); - SimpleRouter::request()->setMethod('delete'); + public function testPut() + { + SimpleRouter::router()->reset(); + SimpleRouter::request()->setUri('/my/test/url'); + SimpleRouter::request()->setMethod('put'); - SimpleRouter::delete('/my/test/url', 'DummyController@start'); - SimpleRouter::start(); - } + SimpleRouter::put('/my/test/url', 'DummyController@start'); + SimpleRouter::start(); + } - public function testMethodNotAllowed() - { - SimpleRouter::router()->reset(); - SimpleRouter::request()->setUri('/my/test/url'); - SimpleRouter::request()->setMethod('post'); + public function testDelete() + { + SimpleRouter::router()->reset(); + SimpleRouter::request()->setUri('/my/test/url'); + SimpleRouter::request()->setMethod('delete'); - SimpleRouter::get('/my/test/url', 'DummyController@start'); + SimpleRouter::delete('/my/test/url', 'DummyController@start'); + SimpleRouter::start(); + } - try { - SimpleRouter::start(); - } catch (\Exception $e) { - $this->assertEquals(403, $e->getCode()); - } - } + public function testMethodNotAllowed() + { + SimpleRouter::router()->reset(); + SimpleRouter::request()->setUri('/my/test/url'); + SimpleRouter::request()->setMethod('post'); - public function testSimpleParam() - { - SimpleRouter::router()->reset(); - SimpleRouter::request()->setMethod('get'); - SimpleRouter::request()->setUri('/test-param1'); + SimpleRouter::get('/my/test/url', 'DummyController@start'); - SimpleRouter::get('/test-{param1}', 'DummyController@param'); - SimpleRouter::start(); - } + try { + SimpleRouter::start(); + } catch (\Exception $e) { + $this->assertEquals(403, $e->getCode()); + } + } - public function testMultiParam() - { - SimpleRouter::router()->reset(); - SimpleRouter::request()->setMethod('get'); - SimpleRouter::request()->setUri('/test-param1-param2'); + public function testSimpleParam() + { + SimpleRouter::router()->reset(); + SimpleRouter::request()->setMethod('get'); + SimpleRouter::request()->setUri('/test-param1'); - SimpleRouter::get('/test-{param1}-{param2}', 'DummyController@param'); - SimpleRouter::start(); - } + SimpleRouter::get('/test-{param1}', 'DummyController@param'); + SimpleRouter::start(); + } - public function testPathParamRegex() - { - SimpleRouter::router()->reset(); - SimpleRouter::request()->setMethod('get'); - SimpleRouter::request()->setUri('/test/path/123123'); + public function testMultiParam() + { + SimpleRouter::router()->reset(); + SimpleRouter::request()->setMethod('get'); + SimpleRouter::request()->setUri('/test-param1-param2'); - SimpleRouter::get('/test/path/{myParam}', 'DummyController@param', ['where' => ['myParam' => '([0-9]+)']]); - SimpleRouter::start(); - } + SimpleRouter::get('/test-{param1}-{param2}', 'DummyController@param'); + SimpleRouter::start(); + } - public function testDomainRoute() - { - SimpleRouter::router()->reset(); - SimpleRouter::request()->setMethod('get'); - SimpleRouter::request()->setUri('/test'); - SimpleRouter::request()->setHost('hello.world.com'); + public function testPathParamRegex() + { + SimpleRouter::router()->reset(); + SimpleRouter::request()->setMethod('get'); + SimpleRouter::request()->setUri('/test/path/123123'); - $this->result = false; + SimpleRouter::get('/test/path/{myParam}', 'DummyController@param', ['where' => ['myParam' => '([0-9]+)']]); + SimpleRouter::start(); + } - SimpleRouter::group(['domain' => '{subdomain}.world.com'], function () { - SimpleRouter::get('/test', function ($subdomain = null) { - $this->result = ($subdomain === 'hello'); - }); - }); + public function testDomainRoute() + { + SimpleRouter::router()->reset(); + SimpleRouter::request()->setMethod('get'); + SimpleRouter::request()->setUri('/test'); + SimpleRouter::request()->setHost('hello.world.com'); - SimpleRouter::start(); + $this->result = false; - $this->assertTrue($this->result); + SimpleRouter::group(['domain' => '{subdomain}.world.com'], function () { + SimpleRouter::get('/test', function ($subdomain = null) { + $this->result = ($subdomain === 'hello'); + }); + }); - } + SimpleRouter::start(); + + $this->assertTrue($this->result); + + } } \ No newline at end of file diff --git a/test/RouterUrlTest.php b/test/RouterUrlTest.php index 3ab345e..66de841 100644 --- a/test/RouterUrlTest.php +++ b/test/RouterUrlTest.php @@ -8,94 +8,95 @@ use Pecee\SimpleRouter\SimpleRouter as SimpleRouter; class RouterUrlTest extends PHPUnit_Framework_TestCase { - protected $result = false; + protected $result = false; - protected function getUrl($name = null, $parameters = null, array $getParams = []) { - return SimpleRouter::getUrl($name, $parameters, $getParams); - } + protected function getUrl($name = null, $parameters = null, array $getParams = []) + { + return SimpleRouter::getUrl($name, $parameters, $getParams); + } - public function testUrls() - { - SimpleRouter::router()->reset(); - SimpleRouter::request()->setMethod('get'); - SimpleRouter::request()->setUri('/'); + public function testUrls() + { + SimpleRouter::router()->reset(); + SimpleRouter::request()->setMethod('get'); + SimpleRouter::request()->setUri('/'); - // Match normal route on alias - SimpleRouter::get('/', 'DummyController@silent', ['as' => 'home']); + // Match normal route on alias + SimpleRouter::get('/', 'DummyController@silent', ['as' => 'home']); - SimpleRouter::get('/about', 'DummyController@about'); + SimpleRouter::get('/about', 'DummyController@about'); - SimpleRouter::group(['prefix' => '/admin', 'as' => 'admin'], function() { + SimpleRouter::group(['prefix' => '/admin', 'as' => 'admin'], function () { - // Match route with prefix on alias - SimpleRouter::get('/{id?}', 'DummyController@start', ['as' => 'home']); + // Match route with prefix on alias + SimpleRouter::get('/{id?}', 'DummyController@start', ['as' => 'home']); - // Match controller with prefix and alias - SimpleRouter::controller('/users', 'DummyController', ['as' => 'users']); + // Match controller with prefix and alias + SimpleRouter::controller('/users', 'DummyController', ['as' => 'users']); - // Match controller with prefix and NO alias - SimpleRouter::controller('/pages', 'DummyController'); + // Match controller with prefix and NO alias + SimpleRouter::controller('/pages', 'DummyController'); - }); + }); - SimpleRouter::group(['prefix' => 'api', 'as' => 'api'], function() { + SimpleRouter::group(['prefix' => 'api', 'as' => 'api'], function () { - // Match resource controller - SimpleRouter::resource('phones', 'DummyController'); + // Match resource controller + SimpleRouter::resource('phones', 'DummyController'); - }); + }); - SimpleRouter::controller('gadgets', 'DummyController', ['names' => ['getIphoneInfo' => 'iphone']]); + SimpleRouter::controller('gadgets', 'DummyController', ['names' => ['getIphoneInfo' => 'iphone']]); - // Match controller with no prefix and no alias - SimpleRouter::controller('/cats', 'CatsController'); + // Match controller with no prefix and no alias + SimpleRouter::controller('/cats', 'CatsController'); - // Pretend to load page - SimpleRouter::start(); + // Pretend to load page + SimpleRouter::start(); - $this->assertEquals('/gadgets/iphoneinfo/', $this->getUrl('gadgets.iphone')); + $this->assertEquals('/gadgets/iphoneinfo/', $this->getUrl('gadgets.iphone')); - $this->assertEquals('/api/phones/create/', $this->getUrl('api.phones.create')); + $this->assertEquals('/api/phones/create/', $this->getUrl('api.phones.create')); - // Should match / - $this->assertEquals('/', $this->getUrl('home')); + // Should match / + $this->assertEquals('/', $this->getUrl('home')); - // Should match /about/ - $this->assertEquals('/about/', $this->getUrl('DummyController@about')); + // Should match /about/ + $this->assertEquals('/about/', $this->getUrl('DummyController@about')); - // Should match /admin/ - $this->assertEquals('/admin/', $this->getUrl('DummyController@start')); + // Should match /admin/ + $this->assertEquals('/admin/', $this->getUrl('DummyController@start')); - // Should match /admin/ - $this->assertEquals('/admin/', $this->getUrl('admin.home')); + // Should match /admin/ + $this->assertEquals('/admin/', $this->getUrl('admin.home')); - // Should match /admin/2/ - $this->assertEquals('/admin/2/', $this->getUrl('admin.home', ['id' => 2])); + // Should match /admin/2/ + $this->assertEquals('/admin/2/', $this->getUrl('admin.home', ['id' => 2])); - // Should match /admin/users/ - $this->assertEquals('/admin/users/', $this->getUrl('admin.users')); + // Should match /admin/users/ + $this->assertEquals('/admin/users/', $this->getUrl('admin.users')); - // Should match /admin/users/home/ - $this->assertEquals('/admin/users/home/', $this->getUrl('admin.users@home')); + // Should match /admin/users/home/ + $this->assertEquals('/admin/users/home/', $this->getUrl('admin.users@home')); - // Should match /cats/ - $this->assertEquals('/cats/', $this->getUrl('CatsController')); + // Should match /cats/ + $this->assertEquals('/cats/', $this->getUrl('CatsController')); - // Should match /cats/view/ - $this->assertEquals('/cats/view/', $this->getUrl('CatsController', 'view')); + // Should match /cats/view/ + $this->assertEquals('/cats/view/', $this->getUrl('CatsController', 'view')); - // Should match /cats/view/ - //$this->assertEquals('/cats/view/', $this->getUrl('CatsController', ['view'])); + // Should match /cats/view/ + //$this->assertEquals('/cats/view/', $this->getUrl('CatsController', ['view'])); - // Should match /cats/view/666 - $this->assertEquals('/cats/view/666/', $this->getUrl('CatsController@getView', ['666'])); + // Should match /cats/view/666 + $this->assertEquals('/cats/view/666/', $this->getUrl('CatsController@getView', ['666'])); - // Should match /funny/man/ - $this->assertEquals('/funny/man/', $this->getUrl('/funny/man')); + // Should match /funny/man/ + $this->assertEquals('/funny/man/', $this->getUrl('/funny/man')); - // Should match /?jackdaniels=true&cola=yeah - $this->assertEquals('/?jackdaniels=true&cola=yeah', $this->getUrl('home', null, ['jackdaniels' => 'true', 'cola' => 'yeah'])); + // Should match /?jackdaniels=true&cola=yeah + $this->assertEquals('/?jackdaniels=true&cola=yeah', $this->getUrl('home', null, ['jackdaniels' => 'true', 'cola' => 'yeah'])); - } + } } \ No newline at end of file