From 3f522c55faf186d457865b624e42597e909d828b Mon Sep 17 00:00:00 2001 From: Abel Hoogeveen Date: Thu, 28 Jan 2021 15:42:38 +0100 Subject: [PATCH] Added categories to the router, without breaking (most) backwards compatibility. Categories can be added using the routeConfig, by using a 'category' key. Router::route() can then distinguish between them using its second parameter. Also added drone support. --- .drone.yml | 15 ++++++++++ src/FuzeWorks/Router.php | 60 ++++++++++++++++++++++++---------------- test/mcr/RouterTest.php | 34 +++++++++++++++++++---- 3 files changed, 80 insertions(+), 29 deletions(-) create mode 100644 .drone.yml diff --git a/.drone.yml b/.drone.yml new file mode 100644 index 0000000..686d8e4 --- /dev/null +++ b/.drone.yml @@ -0,0 +1,15 @@ +kind: pipeline +type: docker +name: test + +steps: + - name: composer + image: composer:latest + commands: + - composer install + + - name: test + image: registry.i15.nl/i15/fuzephp:7.4-alpine + commands: + - docker-php-ext-enable xdebug + - vendor/bin/phpunit -c test/phpunit.xml \ No newline at end of file diff --git a/src/FuzeWorks/Router.php b/src/FuzeWorks/Router.php index 91c456e..3aff36b 100644 --- a/src/FuzeWorks/Router.php +++ b/src/FuzeWorks/Router.php @@ -165,7 +165,7 @@ class Router * Add a route to the Router * * @param string $route - * @param null $routeConfig + * @param mixed $routeConfig * @param int $priority */ public function addRoute(string $route, $routeConfig = null, int $priority = Priority::NORMAL) @@ -174,14 +174,19 @@ class Router if (is_null($routeConfig)) $routeConfig = ['callable' => [$this, 'defaultCallable']]; + // Select the category + $category = is_array($routeConfig) && isset($routeConfig['category']) ? $routeConfig['category'] : 'default'; + if (!isset($this->routes[$category])) + $this->routes[$category] = []; + // Convert wildcards to Regex $route = str_replace([':any',':num'], ['[^/]+', '[0-9]+'], $route); - if (!isset($this->routes[$priority])) - $this->routes[$priority] = []; + if (!isset($this->routes[$category][$priority])) + $this->routes[$category][$priority] = []; - if (!isset($this->routes[$priority][$route])) - $this->routes[$priority][$route] = $routeConfig; + if (!isset($this->routes[$category][$priority][$route])) + $this->routes[$category][$priority][$route] = $routeConfig; Logger::log('Route added with ' . Priority::getPriority($priority) . ": '" . $route."'"); } @@ -189,30 +194,33 @@ class Router /** * Removes a route from the array based on the given route. * - * @param $route string The route to remove - * @param int $priority + * @param string $route The route to remove + * @param string $category The category to remove it from (defaults to 'default') + * @param int $priority The priority to remove it from (defaults to Priority::NORMAL) */ - public function removeRoute(string $route, int $priority = Priority::NORMAL) + public function removeRoute(string $route, string $category = 'default', int $priority = Priority::NORMAL) { - if (!isset($this->routes[$priority][$route])) + if (!isset($this->routes[$category][$priority][$route])) return; - unset($this->routes[$priority][$route]); + unset($this->routes[$category][$priority][$route]); Logger::log('Route removed: '.$route); } /** - * @param string $path - * @param array $routes Optional routes for not using the default - * @return mixed - * @throws NotFoundException - * @throws RouterException - * @throws HaltException + * @param string $path The string to route using Router + * @param string $category The category of routes to search in (defaults to 'default') + * @param array $routes Alternative routes if using global routes is not desired + * @return mixed The output of the callable + * @throws NotFoundException Thrown if route failed to deliver + * @throws RouterException Thrown if things fatally break + * @throws HaltException Thrown if route results in an unauthorised request */ - public function route(string $path, array $routes = []) + public function route(string $path, string $category = 'default', array $routes = []) { // Select the routes to use - $routes = empty($routes) ? $this->routes : $routes; + $globalRoutes = isset($this->routes[$category]) ? $this->routes[$category] : []; + $routes = empty($routes) ? $globalRoutes : $routes; // Check all the provided custom paths, ordered by priority for ($i=Priority::getHighestPriority(); $i<=Priority::getLowestPriority(); $i++) { @@ -433,13 +441,17 @@ class Router /** * Returns an array with all the routes. * + * @param string $category * @param int $priority * @return array * @codeCoverageIgnore */ - public function getRoutes(int $priority = Priority::NORMAL): array + public function getRoutes(string $category = 'default', int $priority = Priority::NORMAL): array { - return $this->routes[$priority]; + if (isset($this->routes[$category][$priority])) + return $this->routes[$category][$priority]; + + return []; } /** @@ -448,7 +460,7 @@ class Router * @return string|null * @codeCoverageIgnore */ - public function getCurrentRoute() + public function getCurrentRoute(): ?string { return $this->route; } @@ -459,7 +471,7 @@ class Router * @return null|array * @codeCoverageIgnore */ - public function getCurrentMatches() + public function getCurrentMatches(): ?array { return $this->matches; } @@ -470,7 +482,7 @@ class Router * @return View|null * @codeCoverageIgnore */ - public function getCurrentView() + public function getCurrentView(): ?View { return $this->view; } @@ -481,7 +493,7 @@ class Router * @return Controller|null * @codeCoverageIgnore */ - public function getCurrentController() + public function getCurrentController(): ?Controller { return $this->controller; } diff --git a/test/mcr/RouterTest.php b/test/mcr/RouterTest.php index 552b681..c7fcfb6 100644 --- a/test/mcr/RouterTest.php +++ b/test/mcr/RouterTest.php @@ -139,10 +139,25 @@ class RouterTest extends TestCase // Test if the order is correct // First for Priority::NORMAL - $this->assertSame(['testRoute' => $testRouteFunction], $this->router->getRoutes(Priority::NORMAL)); + $this->assertSame(['testRoute' => $testRouteFunction], $this->router->getRoutes('default', Priority::NORMAL)); // Then for Priority::LOW - $this->assertSame(['testAppendRoute' => $testAppendRouteFunction], $this->router->getRoutes(Priority::LOW)); + $this->assertSame(['testAppendRoute' => $testAppendRouteFunction], $this->router->getRoutes('default', Priority::LOW)); + } + + /** + * @depends testAddRoutes + * @covers ::addRoute + * @covers ::getRoutes + */ + public function testRouteCategories() + { + $this->router->addRoute('defaultRoute', []); + $this->router->addRoute('defaultRoute2', ['category' => 'default']); + $this->router->addRoute('otherRoute', ['category' => 'other']); + + $this->assertEquals(['defaultRoute' => [], 'defaultRoute2' => ['category' => 'default']], $this->router->getRoutes('default')); + $this->assertEquals(['otherRoute' => ['category' => 'other']], $this->router->getRoutes('other')); } /** @@ -154,13 +169,22 @@ class RouterTest extends TestCase public function testRemoveRoutes() { // First add routes - $this->router->addRoute('testRemoveRoute', function () { - }); + $this->router->addRoute('testRemoveRoute', function () {}); $this->assertArrayHasKey('testRemoveRoute', $this->router->getRoutes()); + // Add a route with a category + $this->router->addRoute('categoryRoute', ['category' => 'other']); + $this->assertArrayHasKey('categoryRoute', $this->router->getRoutes('other')); + + // Check if the categories do not cross + $this->assertArrayNotHasKey('testRemoveRoute', $this->router->getRoutes('other')); + $this->assertArrayNotHasKey('categoryRoute', $this->router->getRoutes('default')); + // Then remove $this->router->removeRoute('testRemoveRoute'); $this->assertArrayNotHasKey('testRemoveRoute', $this->router->getRoutes()); + $this->router->removeRoute('categoryRoute', 'other'); + $this->assertArrayNotHasKey('categoryRoute', $this->router->getRoutes('other')); } /** @@ -496,7 +520,7 @@ class RouterTest extends TestCase class_alias(get_class($mockController), '\Application\Controller\TestDistinctRouteController'); class_alias(get_class($mockView), '\Application\View\TestDistinctRouteTestView'); - $this->assertNull($this->router->route('testDistinctRoute/testMethod/testParameters.test', [ + $this->assertNull($this->router->route('testDistinctRoute/testMethod/testParameters.test', 'default', [ 3 => [ '(?P.*?)(|\/(?P.*?)(|\/(?P.*?))).test' => ['viewType' => 'test'] ]