From 12073629cc2089c7e4de13a65cb56c10b998e783 Mon Sep 17 00:00:00 2001 From: Austin Collier Date: Wed, 3 Jan 2024 17:16:56 -0700 Subject: [PATCH] added ability to group routes together --- flight/Engine.php | 14 +++++++++++++- flight/Flight.php | 1 + flight/net/Router.php | 23 +++++++++++++++++++++- tests/FlightTest.php | 22 +++++++++++++++++++++ tests/RouterTest.php | 45 +++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 103 insertions(+), 2 deletions(-) diff --git a/flight/Engine.php b/flight/Engine.php index 4b1bdca..47866ca 100644 --- a/flight/Engine.php +++ b/flight/Engine.php @@ -33,6 +33,7 @@ use Throwable; * * Routing * @method void route(string $pattern, callable $callback, bool $pass_route = false) Routes a URL to a callback function. + * @method void group(string $pattern, callable $callback) Groups a set of routes together under a common prefix. * @method void get(string $pattern, callable $callback, bool $pass_route = false) Routes a GET URL to a callback function. * @method void post(string $pattern, callable $callback, bool $pass_route = false) Routes a POST URL to a callback function. * @method void put(string $pattern, callable $callback, bool $pass_route = false) Routes a PUT URL to a callback function. @@ -151,7 +152,7 @@ class Engine $methods = [ 'start', 'stop', 'route', 'halt', 'error', 'notFound', 'render', 'redirect', 'etag', 'lastModified', 'json', 'jsonp', - 'post', 'put', 'patch', 'delete', + 'post', 'put', 'patch', 'delete', 'group', ]; foreach ($methods as $name) { $this->dispatcher->set($name, [$this, '_' . $name]); @@ -468,6 +469,17 @@ class Engine $this->router()->map($pattern, $callback, $pass_route); } + /** + * Routes a URL to a callback function. + * + * @param string $pattern URL pattern to match + * @param callable $callback Callback function that includes the Router class as first parameter + */ + public function _group(string $pattern, callable $callback): void + { + $this->router()->group($pattern, $callback); + } + /** * Routes a URL to a callback function. * diff --git a/flight/Flight.php b/flight/Flight.php index 69a8b65..7dac34d 100644 --- a/flight/Flight.php +++ b/flight/Flight.php @@ -24,6 +24,7 @@ use flight\template\View; * @method static void halt(int $code = 200, string $message = '') Stop the framework with an optional status code and message. * * @method static void route(string $pattern, callable $callback, bool $pass_route = false) Maps a URL pattern to a callback. + * @method static void group(string $pattern, callable $callback) Groups a set of routes together under a common prefix. * @method static Router router() Returns Router instance. * * @method static void map(string $name, callable $callback) Creates a custom framework method. diff --git a/flight/net/Router.php b/flight/net/Router.php index f1f8842..d08e039 100644 --- a/flight/net/Router.php +++ b/flight/net/Router.php @@ -32,6 +32,13 @@ class Router */ protected int $index = 0; + /** + * When groups are used, this is mapped against all the routes + * + * @var string + */ + protected string $group_prefix = ''; + /** * Gets mapped routes. * @@ -59,7 +66,7 @@ class Router */ public function map(string $pattern, callable $callback, bool $pass_route = false): void { - $url = trim($pattern); + $url = $this->group_prefix.trim($pattern); $methods = ['*']; if (false !== strpos($url, ' ')) { @@ -71,6 +78,20 @@ class Router $this->routes[] = new Route($url, $callback, $methods, $pass_route); } + /** + * Group together a set of routes + * + * @param string $group_prefix group URL prefix (such as /api/v1) + * @param callable $callback The necessary calling that holds the Router class + * @return void + */ + public function group(string $group_prefix, callable $callback): void { + $old_group_prefix = $this->group_prefix; + $this->group_prefix .= $group_prefix; + $callback($this); + $this->group_prefix = $old_group_prefix; + } + /** * Routes the current request. * diff --git a/tests/FlightTest.php b/tests/FlightTest.php index 588ebb2..8254e60 100644 --- a/tests/FlightTest.php +++ b/tests/FlightTest.php @@ -96,4 +96,26 @@ class FlightTest extends PHPUnit\Framework\TestCase Flight::doesNotExist(); } + + public function testStaticRoute() { + Flight::route('/test', function() { + echo 'test'; + }); + Flight::request()->url = '/test'; + Flight::start(); + + $this->expectOutputString('test'); + } + + public function testStaticRouteGroup() { + Flight::group('/group', function() { + Flight::route('/test', function() { + echo 'test'; + }); + }); + Flight::request()->url = '/group/test'; + Flight::start(); + + $this->expectOutputString('test'); + } } diff --git a/tests/RouterTest.php b/tests/RouterTest.php index 6715652..45b1f7c 100644 --- a/tests/RouterTest.php +++ b/tests/RouterTest.php @@ -358,4 +358,49 @@ class RouterTest extends PHPUnit\Framework\TestCase $router->reset(); $this->assertEquals(0, $router->getIndex()); } + + // Passing URL parameters + public function testGroupRoutes() + { + $this->router->group('/user', function(Router $router) { + $router->map('/@id', function ($id) { + echo $id; + }); + $router->map('/@id/@name', function ($id, $name) { + echo $id . $name; + }); + }); + $this->request->url = '/user/123'; + $this->check('123'); + } + + public function testGroupRoutesMultiParams() + { + $this->router->group('/user', function(Router $router) { + $router->map('/@id', function ($id) { + echo $id; + }); + $router->map('/@id/@name', function ($id, $name) { + echo $id . $name; + }); + }); + $this->request->url = '/user/123/abc'; + $this->check('123abc'); + } + + public function testGroupNestedRoutes() + { + $this->router->group('/client', function(Router $router) { + $router->group('/user', function(Router $router) { + $router->map('/@id', function ($id) { + echo $id; + }); + $router->map('/@id/@name', function ($id, $name) { + echo $id . $name; + }); + }); + }); + $this->request->url = '/client/user/123/abc'; + $this->check('123abc'); + } }