From b34738a51a2b461cd58d79596f077f285deeb5aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20Sessing=C3=B8?= Date: Sat, 9 Apr 2016 05:51:27 +0200 Subject: [PATCH 1/9] [OPTIMISATION] Optimised CSRF-token management. --- src/Pecee/CsrfToken.php | 6 ++-- .../Http/Middleware/BaseCsrfVerifier.php | 29 ++++++++++++++++--- src/Pecee/SimpleRouter/RouterBase.php | 12 +------- 3 files changed, 29 insertions(+), 18 deletions(-) diff --git a/src/Pecee/CsrfToken.php b/src/Pecee/CsrfToken.php index dec2409..98943ab 100644 --- a/src/Pecee/CsrfToken.php +++ b/src/Pecee/CsrfToken.php @@ -37,7 +37,7 @@ class CsrfToken { * @param $token */ public function setToken($token) { - setcookie(self::CSRF_KEY, $token, time() + 60 * 120, '/'); + setcookie(static::CSRF_KEY, $token, time() + 60 * 120, '/'); } /** @@ -46,7 +46,7 @@ class CsrfToken { */ public function getToken(){ if($this->hasToken()) { - return $_COOKIE[self::CSRF_KEY]; + return $_COOKIE[static::CSRF_KEY]; } return null; } @@ -56,7 +56,7 @@ class CsrfToken { * @return bool */ public function hasToken() { - return isset($_COOKIE[self::CSRF_KEY]); + return isset($_COOKIE[static::CSRF_KEY]); } } \ No newline at end of file diff --git a/src/Pecee/Http/Middleware/BaseCsrfVerifier.php b/src/Pecee/Http/Middleware/BaseCsrfVerifier.php index cebd3a8..682a9dc 100644 --- a/src/Pecee/Http/Middleware/BaseCsrfVerifier.php +++ b/src/Pecee/Http/Middleware/BaseCsrfVerifier.php @@ -12,10 +12,13 @@ class BaseCsrfVerifier implements IMiddleware { protected $except; protected $csrfToken; - + protected $token; public function __construct() { $this->csrfToken = new CsrfToken(); + + // Generate or get the CSRF-Token from Cookie. + $this->token = (!$this->hasToken()) ? $this->generateToken() : $this->csrfToken->getToken(); } /** @@ -50,14 +53,14 @@ class BaseCsrfVerifier implements IMiddleware { if($request->getMethod() != 'get' && !$this->skip($request)) { - $token = (isset($_POST[self::POST_KEY])) ? $_POST[self::POST_KEY] : null; + $token = (isset($_POST[static::POST_KEY])) ? $_POST[static::POST_KEY] : null; // If the token is not posted, check headers for valid x-csrf-token if($token === null) { - $token = $request->getHeader(self::HEADER_KEY); + $token = $request->getHeader(static::HEADER_KEY); } - if( !$this->csrfToken->validate( $token ) ) { + if( !$this->csrfToken->validate($token) ) { throw new TokenMismatchException('Invalid csrf-token.'); } @@ -65,4 +68,22 @@ class BaseCsrfVerifier implements IMiddleware { } + public function generateToken() { + $token = $this->csrfToken->generateToken(); + $this->csrfToken->setToken($token); + return $token; + } + + public function hasToken() { + if($this->token != null) { + return true; + } + + return $this->csrfToken->hasToken(); + } + + public function getToken() { + return $this->token; + } + } \ No newline at end of file diff --git a/src/Pecee/SimpleRouter/RouterBase.php b/src/Pecee/SimpleRouter/RouterBase.php index 3999f01..7fd9b49 100644 --- a/src/Pecee/SimpleRouter/RouterBase.php +++ b/src/Pecee/SimpleRouter/RouterBase.php @@ -1,7 +1,6 @@ routes = array(); $this->backStack = array(); $this->controllerUrlMap = array(); - $this->baseCsrfVerifier = new BaseCsrfVerifier(); $this->request = Request::getInstance(); $this->bootManagers = array(); - - $csrf = new CsrfToken(); - $token = ($csrf->hasToken()) ? $csrf->getToken() : $csrf->generateToken(); - $csrf->setToken($token); } public function addRoute(RouterEntry $route) { @@ -124,10 +118,7 @@ class RouterBase { // Verify csrf token for request if($this->baseCsrfVerifier !== null) { - /* @var $csrfVerifier BaseCsrfVerifier */ - $csrfVerifier = $this->baseCsrfVerifier; - $csrfVerifier = new $csrfVerifier(); - $csrfVerifier->handle($this->request); + $this->baseCsrfVerifier->handle($this->request); } // Loop through each route-request @@ -431,7 +422,6 @@ class RouterBase { $url = '/' . trim(join('/', $url), '/') . '/'; - if($getParams !== null && count($getParams)) { $url .= '?' . $this->arrayToParams($getParams); } From 2f2c3ca3caaaab68eb9b36203a9809ef6531cc27 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20Sessing=C3=B8?= Date: Sat, 9 Apr 2016 05:58:18 +0200 Subject: [PATCH 2/9] [OPTIMISATIONS] Optimised code and removed unused references --- README.md | 2 +- src/Pecee/SimpleRouter/RouterController.php | 6 ++++++ src/Pecee/SimpleRouter/RouterEntry.php | 4 +--- src/Pecee/SimpleRouter/RouterResource.php | 4 ++++ src/Pecee/SimpleRouter/RouterRoute.php | 1 - src/Pecee/SimpleRouter/SimpleRouter.php | 2 +- 6 files changed, 13 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index b4ce627..fbc0d86 100644 --- a/README.md +++ b/README.md @@ -264,7 +264,7 @@ SimpleRouter::csrfVerifier(new \Demo\Middleware\CsrfVerifier()); Sometimes it can be necessary to keep urls stored in the database, file or similar. In this example, we want the url ```/my-cat-is-beatiful``` to load the route ```/article/view/1``` which the router knows, because it's defined in the ```routes.php``` file. -To interfere with the router, we create a class that inherits from ```RouterBootManager```. This class will be loaded before any other rules in ```routes.php``` and allow us to "change" the current route, if any of our criteria are fulfilled (like comming from the url ```/my-cat-is-beatiful```). +To interfere with the router, we create a class that inherits from ```RouterBootManager```. This class will be loaded before any other rules in ```routes.php``` and allow us to "change" the current route, if any of our criteria are fulfilled (like coming from the url ```/my-cat-is-beatiful```). ```php diff --git a/src/Pecee/SimpleRouter/RouterController.php b/src/Pecee/SimpleRouter/RouterController.php index 14230b5..bcb5cdc 100644 --- a/src/Pecee/SimpleRouter/RouterController.php +++ b/src/Pecee/SimpleRouter/RouterController.php @@ -79,10 +79,12 @@ class RouterController extends RouterEntry { /** * @param string $url + * @return static */ public function setUrl($url) { $url = rtrim($url, '/') . '/'; $this->url = $url; + return $this; } /** @@ -94,9 +96,11 @@ class RouterController extends RouterEntry { /** * @param string $controller + * @return static */ public function setController($controller) { $this->controller = $controller; + return $this; } /** @@ -108,9 +112,11 @@ class RouterController extends RouterEntry { /** * @param string $method + * @return static */ public function setMethod($method) { $this->method = $method; + return $this; } } \ No newline at end of file diff --git a/src/Pecee/SimpleRouter/RouterEntry.php b/src/Pecee/SimpleRouter/RouterEntry.php index 87e6b9f..3543e51 100644 --- a/src/Pecee/SimpleRouter/RouterEntry.php +++ b/src/Pecee/SimpleRouter/RouterEntry.php @@ -123,7 +123,7 @@ abstract class RouterEntry { } /** - * @return string + * @return string|array */ public function getMiddleware() { return $this->middleware; @@ -360,9 +360,7 @@ abstract class RouterEntry { } public function renderRoute(Request $request) { - if(is_object($this->getCallback()) && is_callable($this->getCallback())) { - // When the callback is a function call_user_func_array($this->getCallback(), $this->getParameters()); } else { diff --git a/src/Pecee/SimpleRouter/RouterResource.php b/src/Pecee/SimpleRouter/RouterResource.php index e2c1920..3ba17ad 100644 --- a/src/Pecee/SimpleRouter/RouterResource.php +++ b/src/Pecee/SimpleRouter/RouterResource.php @@ -109,10 +109,12 @@ class RouterResource extends RouterEntry { /** * @param string $url + * @return static */ public function setUrl($url) { $url = rtrim($url, '/') . '/'; $this->url = $url; + return $this; } /** @@ -124,9 +126,11 @@ class RouterResource extends RouterEntry { /** * @param string $controller + * @return static */ public function setController($controller) { $this->controller = $controller; + return $this; } } \ No newline at end of file diff --git a/src/Pecee/SimpleRouter/RouterRoute.php b/src/Pecee/SimpleRouter/RouterRoute.php index 8b11afa..86c0a8d 100644 --- a/src/Pecee/SimpleRouter/RouterRoute.php +++ b/src/Pecee/SimpleRouter/RouterRoute.php @@ -2,7 +2,6 @@ namespace Pecee\SimpleRouter; -use Pecee\ArrayUtil; use Pecee\Http\Request; class RouterRoute extends RouterEntry { diff --git a/src/Pecee/SimpleRouter/SimpleRouter.php b/src/Pecee/SimpleRouter/SimpleRouter.php index 6a4d671..4469aa0 100644 --- a/src/Pecee/SimpleRouter/SimpleRouter.php +++ b/src/Pecee/SimpleRouter/SimpleRouter.php @@ -16,7 +16,7 @@ class SimpleRouter { /** * Start/route request * @param null $defaultNamespace - * @throws RouterException + * @throws \Pecee\Exception\RouterException */ public static function start($defaultNamespace = null) { $router = RouterBase::getInstance(); From fc4fd0edf1613665103e41cf7d7afa63cb337346 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20Sessing=C3=B8?= Date: Sat, 9 Apr 2016 07:05:49 +0200 Subject: [PATCH 3/9] =?UTF-8?q?[FEATURE]=C2=A0Added=20ExceptionHandling=20?= =?UTF-8?q?functionality=20+=20tests.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Somehow the ExceptionHandling functionality never really get implemented and/or got lost in translation, it's back whup! - Added some basic tests for Middleware + routing. --- .gitignore | 3 +- README.md | 23 +----- src/Pecee/Handler/ExceptionHandler.php | 11 +++ src/Pecee/SimpleRouter/RouterBase.php | 23 +++++- test/Dummy/DummyController.php | 9 ++ test/Dummy/DummyMiddleware.php | 14 ++++ .../Exceptions/MiddlewareLoadedException.php | 2 + test/MiddlewareTest.php | 39 +++++++++ test/RouterRouteTest.php | 82 +++++++++++++++++++ 9 files changed, 183 insertions(+), 23 deletions(-) create mode 100644 src/Pecee/Handler/ExceptionHandler.php create mode 100644 test/Dummy/DummyController.php create mode 100644 test/Dummy/DummyMiddleware.php create mode 100644 test/Dummy/Exceptions/MiddlewareLoadedException.php create mode 100644 test/MiddlewareTest.php create mode 100644 test/RouterRouteTest.php diff --git a/.gitignore b/.gitignore index 005d2e3..848a58c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ .idea -composer.lock \ No newline at end of file +composer.lock +vendor/ \ No newline at end of file diff --git a/README.md b/README.md index fbc0d86..5d4197e 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ Simple, fast and yet powerful PHP router that is easy to get integrated and in a Add the latest version of Simple PHP Router running this command. ``` -composer require pecee/framework +composer require pecee/simple-router ``` ## Notes @@ -34,7 +34,7 @@ In your ```index.php``` require your ```routes.php``` and call the ```routeReque This is an example of a basic ```index.php``` file: ```php -use \Pecee\SimpleRouter; +use \Pecee\SimpleRouter\SimpleRouter; require_once 'routes.php'; // change this to whatever makes sense in your project @@ -42,7 +42,7 @@ require_once 'routes.php'; // change this to whatever makes sense in your projec $defaultControllerNamespace = 'MyWebsite\\Controller'; // Do the routing -SimpleRouter::init($defaultControllerNamespace); +SimpleRouter::start($defaultControllerNamespace); ``` ## Adding routes @@ -160,23 +160,6 @@ class Router extends SimpleRouter { parent::start($defaultNamespace); } catch(\Exception $e) { - $route = RouterBase::getInstance()->getLoadedRoute(); - - $exceptionHandler = null; - - // Load and use exception-handler defined on group - - if($route && $route->getGroup()) { - $exceptionHandler = $route->getGroup()->getExceptionHandler(); - - if($exceptionHandler !== null) { - $class = new $exceptionHandler(); - $class->handleError(RouterBase::getInstance()->getRequest(), $route, $e); - } - } - - // Otherwise use the fallback default exceptions handler - if(self::$defaultExceptionHandler !== null) { $class = new self::$defaultExceptionHandler(); $class->handleError(RouterBase::getInstance()->getRequest(), $route, $e); diff --git a/src/Pecee/Handler/ExceptionHandler.php b/src/Pecee/Handler/ExceptionHandler.php new file mode 100644 index 0000000..0c44a80 --- /dev/null +++ b/src/Pecee/Handler/ExceptionHandler.php @@ -0,0 +1,11 @@ +request->loadedRoute = $route; $route->loadMiddleware($this->request); - $this->request->loadedRoute->renderRoute($this->request); + try { + $this->request->loadedRoute->renderRoute($this->request); + } catch(\Exception $e) { + $this->handleException($e); + } + break; } } if($routeNotAllowed) { - throw new RouterException('Route or method not allowed', 403); + $this->handleException(new RouterException('Route or method not allowed', 403)); } if(!$this->request->loadedRoute) { @@ -172,6 +178,19 @@ class RouterBase { } } + protected function handleException(\Exception $e) { + if($this->request->loadedRoute !== null && $this->request->loadedRoute->exceptionHandler !== null) { + $handler = new $this->request->loadedRoute->exceptionHandler(); + if(!($handler instanceof ExceptionHandler)) { + throw new RouterException('Exception handler must be instanceof ExceptionHandler.'); + } + + $handler->handleError($this->request, $this->request->loadedRoute, $e); + } + + throw $e; + } + /** * @return string */ diff --git a/test/Dummy/DummyController.php b/test/Dummy/DummyController.php new file mode 100644 index 0000000..be3254b --- /dev/null +++ b/test/Dummy/DummyController.php @@ -0,0 +1,9 @@ +setMethod('get'); + + $router = new \Pecee\SimpleRouter\RouterBase(); + + $route = new \Pecee\SimpleRouter\RouterRoute('/my/test/url', 'DummyController@start'); + $route->setRequestMethods(array(\Pecee\SimpleRouter\RouterRoute::REQUEST_TYPE_GET)); + $route->addSettings(['middleware' => 'DummyMiddleware']); + $router->addRoute($route); + + try { + $router->routeRequest(); + }catch(Exception $e) { + $this->assertTrue(($e instanceof MiddlewareLoadedException)); + return; + } + + throw new Exception('Middleware not loaded'); + + } + + + +} \ No newline at end of file diff --git a/test/RouterRouteTest.php b/test/RouterRouteTest.php new file mode 100644 index 0000000..c003dce --- /dev/null +++ b/test/RouterRouteTest.php @@ -0,0 +1,82 @@ +setMethod('get'); + + $router = new \Pecee\SimpleRouter\RouterBase(); + + $route = new \Pecee\SimpleRouter\RouterRoute('/my/test/url', 'DummyController@start'); + $route->setRequestMethods(array(\Pecee\SimpleRouter\RouterRoute::REQUEST_TYPE_GET)); + + $router->addRoute($route); + $router->routeRequest(); + } + + public function testPost() { + \Pecee\Http\Request::getInstance()->setMethod('post'); + + $router = new \Pecee\SimpleRouter\RouterBase(); + + $route = new \Pecee\SimpleRouter\RouterRoute('/my/test/url', 'DummyController@start'); + + $route->addSettings(array()); + $route->setRequestMethods(array(\Pecee\SimpleRouter\RouterRoute::REQUEST_TYPE_POST)); + + $router->addRoute($route); + $router->routeRequest(); + } + + public function testPut() { + \Pecee\Http\Request::getInstance()->setMethod('put'); + + $router = new \Pecee\SimpleRouter\RouterBase(); + + $route = new \Pecee\SimpleRouter\RouterRoute('/my/test/url', 'DummyController@start'); + $route->addSettings(array()); + $route->setRequestMethods(array(\Pecee\SimpleRouter\RouterRoute::REQUEST_TYPE_PUT)); + + $router->addRoute($route); + $router->routeRequest(); + + } + + public function testDelete() { + \Pecee\Http\Request::getInstance()->setMethod('delete'); + + $router = new \Pecee\SimpleRouter\RouterBase(); + + $route = new \Pecee\SimpleRouter\RouterRoute('/my/test/url', 'DummyController@start'); + $route->addSettings(array()); + $route->setRequestMethods(array(\Pecee\SimpleRouter\RouterRoute::REQUEST_TYPE_DELETE)); + + $router->addRoute($route); + $router->routeRequest(); + + } + + public function testMethodNotAllowed() { + \Pecee\Http\Request::getInstance()->setMethod('post'); + + \Pecee\SimpleRouter\SimpleRouter::get('/my/test/url', 'DummyController@start'); + + try { + \Pecee\SimpleRouter\SimpleRouter::start(); + } catch(\Exception $e) { + $this->assertEquals(403, $e->getCode()); + } + + } + +} \ No newline at end of file From 457dbc57100f79b3fcab9bd3403eb831ff2a9fc7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20Sessing=C3=B8?= Date: Sat, 9 Apr 2016 07:51:03 +0200 Subject: [PATCH 4/9] [BUGFIX] Fixed issue #83 - Added more tests. --- src/Pecee/SimpleRouter/RouterBase.php | 8 +++-- test/GroupTest.php | 51 +++++++++++++++++++++++++++ test/MiddlewareTest.php | 9 ++--- test/RouterRouteTest.php | 47 +++++++++--------------- 4 files changed, 77 insertions(+), 38 deletions(-) create mode 100644 test/GroupTest.php diff --git a/src/Pecee/SimpleRouter/RouterBase.php b/src/Pecee/SimpleRouter/RouterBase.php index da7d6e1..e6c6242 100644 --- a/src/Pecee/SimpleRouter/RouterBase.php +++ b/src/Pecee/SimpleRouter/RouterBase.php @@ -69,12 +69,12 @@ class RouterBase { $newPrefixes = $prefixes; if($route->getPrefix()) { - array_push($newPrefixes, rtrim($route->getPrefix(), '/')); + array_push($newPrefixes, trim($route->getPrefix(), '/')); } if(!($route instanceof RouterGroup)) { if(is_array($newPrefixes) && count($newPrefixes) && $backStack) { - $route->setUrl( join('/', $newPrefixes) . $route->getUrl() ); + $route->setUrl( '/' . join('/', $newPrefixes) . $route->getUrl() ); } $group = null; @@ -455,4 +455,8 @@ class RouterBase { return self::$instance; } + public static function reset() { + self::$instance = null; + } + } \ No newline at end of file diff --git a/test/GroupTest.php b/test/GroupTest.php new file mode 100644 index 0000000..160a4f6 --- /dev/null +++ b/test/GroupTest.php @@ -0,0 +1,51 @@ +result = true; + } + + public function testGroup() { + \Pecee\SimpleRouter\RouterBase::reset(); + + $this->result = false; + + \Pecee\SimpleRouter\SimpleRouter::group(['prefix' => '/group'], $this->group()); + + try { + \Pecee\SimpleRouter\SimpleRouter::start(); + } catch(Exception $e) { + + } + + $this->assertTrue($this->result); + } + + public function testNestedGroup() { + \Pecee\SimpleRouter\RouterBase::reset(); + + \Pecee\Http\Request::getInstance()->setUri('/api/v1/test'); + + \Pecee\SimpleRouter\SimpleRouter::group(['prefix' => '/api'], function() { + \Pecee\SimpleRouter\SimpleRouter::group(['prefix' => '/v1'], function() { + \Pecee\SimpleRouter\SimpleRouter::get('/test', 'DummyController@start'); + }); + }); + + \Pecee\SimpleRouter\SimpleRouter::start(); + } + +} \ No newline at end of file diff --git a/test/MiddlewareTest.php b/test/MiddlewareTest.php index 7487e2b..129df6d 100644 --- a/test/MiddlewareTest.php +++ b/test/MiddlewareTest.php @@ -16,15 +16,12 @@ class MiddlewareTest extends PHPUnit_Framework_TestCase { \Pecee\Http\Request::getInstance()->setMethod('get'); - $router = new \Pecee\SimpleRouter\RouterBase(); + \Pecee\SimpleRouter\RouterBase::reset(); - $route = new \Pecee\SimpleRouter\RouterRoute('/my/test/url', 'DummyController@start'); - $route->setRequestMethods(array(\Pecee\SimpleRouter\RouterRoute::REQUEST_TYPE_GET)); - $route->addSettings(['middleware' => 'DummyMiddleware']); - $router->addRoute($route); + \Pecee\SimpleRouter\SimpleRouter::get('/my/test/url', 'DummyController@start', ['middleware' => 'DummyMiddleware']); try { - $router->routeRequest(); + \Pecee\SimpleRouter\SimpleRouter::start(); }catch(Exception $e) { $this->assertTrue(($e instanceof MiddlewareLoadedException)); return; diff --git a/test/RouterRouteTest.php b/test/RouterRouteTest.php index c003dce..01984ae 100644 --- a/test/RouterRouteTest.php +++ b/test/RouterRouteTest.php @@ -13,60 +13,47 @@ class RouterRouteTest extends PHPUnit_Framework_TestCase { } public function testGet() { + + \Pecee\SimpleRouter\RouterBase::reset(); + \Pecee\Http\Request::getInstance()->setMethod('get'); - $router = new \Pecee\SimpleRouter\RouterBase(); - - $route = new \Pecee\SimpleRouter\RouterRoute('/my/test/url', 'DummyController@start'); - $route->setRequestMethods(array(\Pecee\SimpleRouter\RouterRoute::REQUEST_TYPE_GET)); - - $router->addRoute($route); - $router->routeRequest(); + \Pecee\SimpleRouter\SimpleRouter::get('/my/test/url', 'DummyController@start'); + \Pecee\SimpleRouter\SimpleRouter::start(); } public function testPost() { \Pecee\Http\Request::getInstance()->setMethod('post'); - $router = new \Pecee\SimpleRouter\RouterBase(); + \Pecee\SimpleRouter\RouterBase::reset(); - $route = new \Pecee\SimpleRouter\RouterRoute('/my/test/url', 'DummyController@start'); - - $route->addSettings(array()); - $route->setRequestMethods(array(\Pecee\SimpleRouter\RouterRoute::REQUEST_TYPE_POST)); - - $router->addRoute($route); - $router->routeRequest(); + \Pecee\SimpleRouter\SimpleRouter::post('/my/test/url', 'DummyController@start'); + \Pecee\SimpleRouter\SimpleRouter::start(); } public function testPut() { \Pecee\Http\Request::getInstance()->setMethod('put'); - $router = new \Pecee\SimpleRouter\RouterBase(); - - $route = new \Pecee\SimpleRouter\RouterRoute('/my/test/url', 'DummyController@start'); - $route->addSettings(array()); - $route->setRequestMethods(array(\Pecee\SimpleRouter\RouterRoute::REQUEST_TYPE_PUT)); - - $router->addRoute($route); - $router->routeRequest(); + \Pecee\SimpleRouter\RouterBase::reset(); + \Pecee\SimpleRouter\SimpleRouter::put('/my/test/url', 'DummyController@start'); + \Pecee\SimpleRouter\SimpleRouter::start(); } public function testDelete() { \Pecee\Http\Request::getInstance()->setMethod('delete'); - $router = new \Pecee\SimpleRouter\RouterBase(); + \Pecee\SimpleRouter\RouterBase::reset(); - $route = new \Pecee\SimpleRouter\RouterRoute('/my/test/url', 'DummyController@start'); - $route->addSettings(array()); - $route->setRequestMethods(array(\Pecee\SimpleRouter\RouterRoute::REQUEST_TYPE_DELETE)); - - $router->addRoute($route); - $router->routeRequest(); + \Pecee\SimpleRouter\SimpleRouter::delete('/my/test/url', 'DummyController@start'); + \Pecee\SimpleRouter\SimpleRouter::start(); } public function testMethodNotAllowed() { + + \Pecee\SimpleRouter\RouterBase::reset(); + \Pecee\Http\Request::getInstance()->setMethod('post'); \Pecee\SimpleRouter\SimpleRouter::get('/my/test/url', 'DummyController@start'); From 9b743e6e57445b1e004cbca367e8465340861186 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20Sessing=C3=B8?= Date: Sat, 9 Apr 2016 08:05:18 +0200 Subject: [PATCH 5/9] [FEATURE] Added requirements (issue: #80) --- README.md | 7 +++++++ composer.json | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 5d4197e..604518a 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,10 @@ Add the latest version of Simple PHP Router running this command. composer require pecee/simple-router ``` +## Requirements + +- PHP 5.4 or greater + ## Notes The goal of this project is to create a router that is 100% compatible with the Laravel documentation, but as simple as possible and as easy to integrate and change as possible. @@ -62,6 +66,9 @@ use Pecee\SimpleRouter\SimpleRouter; * the request, for instance if a user is not authenticated. */ +// Add CSRF support (if needed) +SimpleRouter::csrfVerifier(new \Pecee\Http\Middleware\BaseCsrfVerifier()); + SimpleRouter::group(['prefix' => 'v1', 'middleware' => '\MyWebsite\Middleware\SomeMiddlewareClass'], function() { SimpleRouter::group(['prefix' => '/services', 'exceptionHandler' => '\MyProject\Handler\CustomExceptionHandler'], function() { diff --git a/composer.json b/composer.json index aa22e5d..7468967 100644 --- a/composer.json +++ b/composer.json @@ -13,7 +13,7 @@ } ], "require": { - + "php": ">=5.4.0" }, "require-dev": { "phpunit/phpunit": "4.7.7" From 257875c6f9a6bc446c9d13d41d592e18a5336e27 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20Sessing=C3=B8?= Date: Sat, 9 Apr 2016 09:25:41 +0200 Subject: [PATCH 6/9] [TASK] Load group middleware if prefix matches - Middlewares from groups are now loaded if prefix matches. - Optimisations. --- src/Pecee/SimpleRouter/RouterBase.php | 8 +++++++- src/Pecee/SimpleRouter/RouterEntry.php | 2 +- src/Pecee/SimpleRouter/RouterGroup.php | 4 ---- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/Pecee/SimpleRouter/RouterBase.php b/src/Pecee/SimpleRouter/RouterBase.php index e6c6242..3265fab 100644 --- a/src/Pecee/SimpleRouter/RouterBase.php +++ b/src/Pecee/SimpleRouter/RouterBase.php @@ -68,7 +68,7 @@ class RouterBase { $newPrefixes = $prefixes; - if($route->getPrefix()) { + if($route->getPrefix() && trim($route->getPrefix(), '/') !== '') { array_push($newPrefixes, trim($route->getPrefix(), '/')); } @@ -85,6 +85,12 @@ class RouterBase { if($route instanceof RouterGroup && is_callable($route->getCallback())) { $group = $route; + + // Load middleware on group if route matches + if($route->matchRoute($this->request)) { + $route->loadMiddleware($this->request); + } + $route->renderRoute($this->request); $mergedSettings = array_merge($settings, $route->getMergeableSettings()); } diff --git a/src/Pecee/SimpleRouter/RouterEntry.php b/src/Pecee/SimpleRouter/RouterEntry.php index 3543e51..bb6b598 100644 --- a/src/Pecee/SimpleRouter/RouterEntry.php +++ b/src/Pecee/SimpleRouter/RouterEntry.php @@ -93,7 +93,7 @@ abstract class RouterEntry { * @return self */ public function setPrefix($prefix) { - $this->prefix = '/' . trim($prefix, '/') . '/'; + $this->prefix = '/' . ltrim($prefix, '/'); return $this; } diff --git a/src/Pecee/SimpleRouter/RouterGroup.php b/src/Pecee/SimpleRouter/RouterGroup.php index 015fb6b..231bb52 100644 --- a/src/Pecee/SimpleRouter/RouterGroup.php +++ b/src/Pecee/SimpleRouter/RouterGroup.php @@ -7,10 +7,6 @@ use Pecee\Http\Request; class RouterGroup extends RouterEntry { - public function __construct() { - parent::__construct(); - } - public function matchDomain(Request $request) { if($this->domain !== null) { From 7234415e24c59e6a0e8572953b550b0e4b7954c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20Sessing=C3=B8?= Date: Sat, 9 Apr 2016 09:42:57 +0200 Subject: [PATCH 7/9] [TASK] Made abstract ExceptionHandler class an interface. - Updated documentation to reflect new changes. --- README.md | 3 +++ src/Pecee/Handler/ExceptionHandler.php | 11 ----------- src/Pecee/Handler/IExceptionHandler.php | 11 +++++++++++ src/Pecee/SimpleRouter/RouterBase.php | 6 +++--- 4 files changed, 17 insertions(+), 14 deletions(-) delete mode 100644 src/Pecee/Handler/ExceptionHandler.php create mode 100644 src/Pecee/Handler/IExceptionHandler.php diff --git a/README.md b/README.md index 604518a..1ba92d0 100644 --- a/README.md +++ b/README.md @@ -55,6 +55,9 @@ This router is heavily inspired by the Laravel 5.* router, so anything you find ### Basic example +- ExceptionsHandlers must implement the `IExceptionHandler` interface. +- Middlewares must implement the `IMiddleware` interface. + ```php use Pecee\SimpleRouter\SimpleRouter; diff --git a/src/Pecee/Handler/ExceptionHandler.php b/src/Pecee/Handler/ExceptionHandler.php deleted file mode 100644 index 0c44a80..0000000 --- a/src/Pecee/Handler/ExceptionHandler.php +++ /dev/null @@ -1,11 +0,0 @@ -request->loadedRoute !== null && $this->request->loadedRoute->exceptionHandler !== null) { $handler = new $this->request->loadedRoute->exceptionHandler(); - if(!($handler instanceof ExceptionHandler)) { - throw new RouterException('Exception handler must be instanceof ExceptionHandler.'); + if(!($handler instanceof IExceptionHandler)) { + throw new RouterException('Exception handler must be instanceof IExceptionHandler.'); } $handler->handleError($this->request, $this->request->loadedRoute, $e); From 5f95290e4ba5bd4551e83dc4dc8e3a48b9d08ccc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20Sessing=C3=B8?= Date: Sat, 9 Apr 2016 09:45:39 +0200 Subject: [PATCH 8/9] [OPTIMISATION] Optimised exception-message thrown when not using IExceptionHandler interface. --- src/Pecee/SimpleRouter/RouterBase.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Pecee/SimpleRouter/RouterBase.php b/src/Pecee/SimpleRouter/RouterBase.php index 0fcd3c8..d73b67a 100644 --- a/src/Pecee/SimpleRouter/RouterBase.php +++ b/src/Pecee/SimpleRouter/RouterBase.php @@ -188,7 +188,7 @@ class RouterBase { if($this->request->loadedRoute !== null && $this->request->loadedRoute->exceptionHandler !== null) { $handler = new $this->request->loadedRoute->exceptionHandler(); if(!($handler instanceof IExceptionHandler)) { - throw new RouterException('Exception handler must be instanceof IExceptionHandler.'); + throw new RouterException('Exception handler must implement the IExceptionHandler interface.'); } $handler->handleError($this->request, $this->request->loadedRoute, $e); From 6cef09911082d1ef3f87288c9cdcf7bdd87d0ac8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20Sessing=C3=B8?= Date: Sat, 9 Apr 2016 09:49:59 +0200 Subject: [PATCH 9/9] [TASK] Updated documentation with list of sites that uses project in production --- README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/README.md b/README.md index 1ba92d0..628aef2 100644 --- a/README.md +++ b/README.md @@ -325,6 +325,12 @@ $route->setClass('Example\MyCustomClass'); $route->setMethod('hello'); ``` +## Sites +This is some sites that uses the simple-router project in production. + +- [holla.dk](http://www.holla.dk) +- [ninjaimg.com](http://ninjaimg.com) + ## Documentation While I work on a better documentation, please refer to the Laravel 5 routing documentation here: