From a5aac57ce94eaf9112765ed30d36168ad2aade39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20Sessing=C3=B8?= Date: Sun, 3 Sep 2017 18:24:51 +0100 Subject: [PATCH] Added RoutePartialGroup support. --- README.md | 26 +++++++++++++++-- .../SimpleRouter/Route/IPartialGroupRoute.php | 8 ++++++ src/Pecee/SimpleRouter/Route/RouteGroup.php | 14 ++-------- .../SimpleRouter/Route/RoutePartialGroup.php | 6 ++-- src/Pecee/SimpleRouter/Router.php | 16 +++++++++-- src/Pecee/SimpleRouter/SimpleRouter.php | 28 +++++++++++++++++++ ...oupTest.php => RouterPartialGroupTest.php} | 4 +-- 7 files changed, 82 insertions(+), 20 deletions(-) create mode 100644 src/Pecee/SimpleRouter/Route/IPartialGroupRoute.php rename test/{RouterGroupTest.php => RouterPartialGroupTest.php} (75%) diff --git a/README.md b/README.md index ae47b7b..2d59d25 100644 --- a/README.md +++ b/README.md @@ -43,6 +43,7 @@ If you want a great new feature or experience any issues what-so-ever, please fe - [Namespaces](#namespaces) - [Subdomain-routing](#subdomain-routing) - [Route prefixes](#route-prefixes) + - [Partial groups](#partial-groups) - [Form Method Spoofing](#form-method-spoofing) - [Accessing The Current Route](#accessing-the-current-route) - [Other examples](#other-examples) @@ -357,7 +358,7 @@ SimpleRouter::any('foo', function() { }); ``` -We've created a simple method which matches `GET` and `POST` which is most commenly used: +We've created a simple method which matches `GET` and `POST` which is most commonly used: ```php SimpleRouter::form('foo', function() { @@ -541,7 +542,7 @@ SimpleRouter::group(['namespace' => 'Admin'], function () { }); ``` -### Subdomain-routing +### Sub domain-routing Route groups may also be used to handle sub-domain routing. Sub-domains may be assigned route parameters just like route URIs, allowing you to capture a portion of the sub-domain for usage in your route or controller. The sub-domain may be specified using the `domain` key on the group attribute array: @@ -565,6 +566,27 @@ SimpleRouter::group(['prefix' => '/admin'], function () { }); ``` +## Partial groups + +Partial router groups has the same benefits as a normal group, but supports parameters and are only rendered when the url is matched. + +This can be extremely useful in situations where you only want certain routes added when certain criteria has been met. + +**NOTE:** Use partial groups with caution as routes added within are only rendered and available once the url of the partial-group has matched. This can cause `url()` not to find urls for the routes added within. + +**Example:** + +```php +SimpleRouter::partialGroup('/admin/{applicationId}', function ($applicationId) { + + // Routes within are rendered when the group matches + + // The url "/admin/{applicationId}" will be prepended to any routes added here. + +}); +``` + + ## Form Method Spoofing HTML forms do not support `PUT`, `PATCH` or `DELETE` actions. So, when defining `PUT`, `PATCH` or `DELETE` routes that are called from an HTML form, you will need to add a hidden `_method` field to the form. The value sent with the `_method` field will be used as the HTTP request method: diff --git a/src/Pecee/SimpleRouter/Route/IPartialGroupRoute.php b/src/Pecee/SimpleRouter/Route/IPartialGroupRoute.php new file mode 100644 index 0000000..c1ddd4d --- /dev/null +++ b/src/Pecee/SimpleRouter/Route/IPartialGroupRoute.php @@ -0,0 +1,8 @@ +prefix !== null) { - /* Parse parameters from current route */ - $parameters = $this->parseParameters($this->prefix, $url); - - /* If no custom regular expression or parameters was found on this route, we stop */ - if ($parameters === null) { - return false; - } - - /* Set the parameters */ - $this->setParameters((array)$parameters); + /* Skip if prefix doesn't match */ + if ($this->prefix !== null && stripos($url, $this->prefix) === false) { + return false; } return $this->matchDomain($request); diff --git a/src/Pecee/SimpleRouter/Route/RoutePartialGroup.php b/src/Pecee/SimpleRouter/Route/RoutePartialGroup.php index 12613c4..3790c0d 100644 --- a/src/Pecee/SimpleRouter/Route/RoutePartialGroup.php +++ b/src/Pecee/SimpleRouter/Route/RoutePartialGroup.php @@ -4,8 +4,10 @@ namespace Pecee\SimpleRouter\Route; use Pecee\Http\Request; -class PartialGroup extends RouteGroup +class RoutePartialGroup extends RouteGroup implements IPartialGroupRoute { + protected $urlRegex = '/^%s\/?/u'; + /** * Method called to check if route matches * @@ -15,7 +17,7 @@ class PartialGroup extends RouteGroup */ public function matchRoute($url, Request $request) { - if($this->prefix !== null) { + if ($this->prefix !== null) { /* Parse parameters from current route */ $parameters = $this->parseParameters($this->prefix, $url); diff --git a/src/Pecee/SimpleRouter/Router.php b/src/Pecee/SimpleRouter/Router.php index 02837fc..8144a95 100644 --- a/src/Pecee/SimpleRouter/Router.php +++ b/src/Pecee/SimpleRouter/Router.php @@ -10,6 +10,7 @@ use Pecee\SimpleRouter\Exceptions\NotFoundHttpException; use Pecee\SimpleRouter\Route\IControllerRoute; use Pecee\SimpleRouter\Route\IGroupRoute; use Pecee\SimpleRouter\Route\ILoadableRoute; +use Pecee\SimpleRouter\Route\IPartialGroupRoute; use Pecee\SimpleRouter\Route\IRoute; class Router @@ -158,11 +159,20 @@ class Router $exceptionHandlers += $route->getExceptionHandlers(); } + /* Only render partial group if it matches */ + if ($route instanceof IPartialGroupRoute) { + $this->processingRoute = true; + $route->renderRoute($this->request); + $this->processingRoute = false; + } + } - $this->processingRoute = true; - $route->renderRoute($this->request); - $this->processingRoute = false; + if (($route instanceof IPartialGroupRoute) === false) { + $this->processingRoute = true; + $route->renderRoute($this->request); + $this->processingRoute = false; + } } if ($route instanceof ILoadableRoute) { diff --git a/src/Pecee/SimpleRouter/SimpleRouter.php b/src/Pecee/SimpleRouter/SimpleRouter.php index 84734d3..2c545a2 100644 --- a/src/Pecee/SimpleRouter/SimpleRouter.php +++ b/src/Pecee/SimpleRouter/SimpleRouter.php @@ -16,6 +16,7 @@ use Pecee\Http\Response; use Pecee\SimpleRouter\Exceptions\HttpException; use Pecee\SimpleRouter\Exceptions\NotFoundHttpException; use Pecee\SimpleRouter\Route\IRoute; +use Pecee\SimpleRouter\Route\RoutePartialGroup; use Pecee\SimpleRouter\Route\RouteController; use Pecee\SimpleRouter\Route\RouteGroup; use Pecee\SimpleRouter\Route\RouteResource; @@ -171,14 +172,41 @@ class SimpleRouter */ public static function group(array $settings = [], \Closure $callback) { + if (is_callable($callback) === false) { + throw new \InvalidArgumentException('Invalid callback provided. Only functions or methods supported'); + } + $group = new RouteGroup(); $group->setCallback($callback); $group->setSettings($settings); + static::router()->addRoute($group); + + return $group; + } + + /** + * Special group that has the same benefits as group but supports + * parameters and which are only rendered when the url matches. + * + * @param string $url + * @param array $settings + * @param \Closure $callback + * @throws \InvalidArgumentException + * @return RoutePartialGroup + */ + public static function partialGroup($url, \Closure $callback, array $settings = []) + { if (is_callable($callback) === false) { throw new \InvalidArgumentException('Invalid callback provided. Only functions or methods supported'); } + $settings['prefix'] = $url; + + $group = new RoutePartialGroup(); + $group->setSettings($settings); + $group->setCallback($callback); + static::router()->addRoute($group); return $group; diff --git a/test/RouterGroupTest.php b/test/RouterPartialGroupTest.php similarity index 75% rename from test/RouterGroupTest.php rename to test/RouterPartialGroupTest.php index ff806d7..9c805e5 100644 --- a/test/RouterGroupTest.php +++ b/test/RouterPartialGroupTest.php @@ -5,7 +5,7 @@ require_once 'Dummy/DummyController.php'; require_once 'Dummy/Handler/ExceptionHandler.php'; require_once 'Helpers/TestRouter.php'; -class RouterGroupTest extends PHPUnit_Framework_TestCase +class RouterPartialGroupTest extends PHPUnit_Framework_TestCase { public function testParameters() @@ -13,7 +13,7 @@ class RouterGroupTest extends PHPUnit_Framework_TestCase $result1 = null; $result2 = null; - TestRouter::group(['prefix' => '{param1}/{param2}'], function ($param1 = null, $param2 = null) use (&$result1, &$result2) { + TestRouter::partialGroup('{param1}/{param2}', function ($param1 = null, $param2 = null) use (&$result1, &$result2) { $result1 = $param1; $result2 = $param2;