From edcd1ad092dd0511222dc3cadc5fa8b031d3d9c7 Mon Sep 17 00:00:00 2001 From: n0nag0n Date: Fri, 27 Sep 2024 23:26:49 -0600 Subject: [PATCH] got unit tests up and running --- flight/Engine.php | 60 +--------- flight/Flight.php | 2 +- flight/net/Router.php | 65 ++++++++++- .../FlightRouteCompactSyntaxTest.php | 107 ++++++++++++------ tests/groupcompactsyntax/UsersController.php | 4 +- 5 files changed, 141 insertions(+), 97 deletions(-) diff --git a/flight/Engine.php b/flight/Engine.php index 8572b69..83f0c1b 100644 --- a/flight/Engine.php +++ b/flight/Engine.php @@ -740,65 +740,7 @@ class Engine string $controllerClass, array $options = [] ): void { - // $defaultMapping = [ - // 'GET ' => 'index', - // 'GET /create' => 'create', - // 'POST ' => 'store', - // 'GET /@id' => 'show', - // 'GET /@id/edit' => 'edit', - // 'PUT /@id' => 'update', - // 'DELETE /@id' => 'destroy' - // ]; - - $defaultMapping = [ - 'index' => 'GET ', - 'create' => 'GET /create', - 'store' => 'POST ', - 'show' => 'GET /@id', - 'edit' => 'GET /@id/edit', - 'update' => 'PUT /@id', - 'destroy' => 'DELETE /@id' - ]; - - // Create a custom alias base - $aliasBase = trim(basename($pattern), '/'); - if (isset($options['alias_base']) === true) { - $aliasBase = $options['alias_base']; - } - - // Only use these controller methods - if (isset($options['only']) === true) { - $only = $options['only']; - $defaultMapping = array_filter($defaultMapping, function ($key) use ($only) { - return in_array($key, $only, true) === true; - }, ARRAY_FILTER_USE_KEY); - - // Exclude these controller methods - } elseif (isset($options['except']) === true) { - $except = $options['except']; - $defaultMapping = array_filter($defaultMapping, function ($key) use ($except) { - return in_array($key, $except, true) === false; - }, ARRAY_FILTER_USE_KEY); - } - - // Add group middleware - $middleware = []; - if (isset($options['middleware']) === true) { - $middleware = $options['middleware']; - } - - $this->group( - $pattern, - function (Router $router) use ($controllerClass, $defaultMapping, $aliasBase): void { - foreach ($defaultMapping as $controllerMethod => $methodPattern) { - $router->map( - $methodPattern, - $controllerClass . '->' . $controllerMethod - )->setAlias($aliasBase . '.' . $controllerMethod); - } - }, - $middleware - ); + $this->router()->mapResource($pattern, $controllerClass, $options); } /** diff --git a/flight/Flight.php b/flight/Flight.php index 4942b25..287d43a 100644 --- a/flight/Flight.php +++ b/flight/Flight.php @@ -42,7 +42,7 @@ require_once __DIR__ . '/autoload.php'; * Routes a PATCH URL to a callback function. * @method static Route delete(string $pattern, callable|string $callback, bool $pass_route = false, string $alias = '') * Routes a DELETE URL to a callback function. - * @method void resource(string $pattern, string $controllerClass, array $methods = []) + * @method static void resource(string $pattern, string $controllerClass, array $methods = []) * Adds standardized RESTful routes for a controller. * @method static Router router() Returns Router instance. * @method static string getUrl(string $alias, array $params = []) Gets a url from an alias diff --git a/flight/net/Router.php b/flight/net/Router.php index a43b5ba..f80fab6 100644 --- a/flight/net/Router.php +++ b/flight/net/Router.php @@ -87,7 +87,7 @@ class Router public function map(string $pattern, $callback, bool $pass_route = false, string $route_alias = ''): Route { - // This means that the route ies defined in a group, but the defined route is the base + // This means that the route is defined in a group, but the defined route is the base // url path. Note the '' in route() // Ex: Flight::group('/api', function() { // Flight::route('', function() {}); @@ -276,6 +276,69 @@ class Router throw new Exception($exception_message); } + /** + * Create a resource controller customizing the methods names mapping. + * + * @param class-string $controllerClass + * @param array $options + */ + public function mapResource( + string $pattern, + string $controllerClass, + array $options = [] + ): void { + + $defaultMapping = [ + 'index' => 'GET ', + 'create' => 'GET /create', + 'store' => 'POST ', + 'show' => 'GET /@id', + 'edit' => 'GET /@id/edit', + 'update' => 'PUT /@id', + 'destroy' => 'DELETE /@id' + ]; + + // Create a custom alias base + $aliasBase = trim(basename($pattern), '/'); + if (isset($options['alias_base']) === true) { + $aliasBase = $options['alias_base']; + } + + // Only use these controller methods + if (isset($options['only']) === true) { + $only = $options['only']; + $defaultMapping = array_filter($defaultMapping, function ($key) use ($only) { + return in_array($key, $only, true) === true; + }, ARRAY_FILTER_USE_KEY); + + // Exclude these controller methods + } elseif (isset($options['except']) === true) { + $except = $options['except']; + $defaultMapping = array_filter($defaultMapping, function ($key) use ($except) { + return in_array($key, $except, true) === false; + }, ARRAY_FILTER_USE_KEY); + } + + // Add group middleware + $middleware = []; + if (isset($options['middleware']) === true) { + $middleware = $options['middleware']; + } + + $this->group( + $pattern, + function (Router $router) use ($controllerClass, $defaultMapping, $aliasBase): void { + foreach ($defaultMapping as $controllerMethod => $methodPattern) { + $router->map( + $methodPattern, + [ $controllerClass, $controllerMethod ] + )->setAlias($aliasBase . '.' . $controllerMethod); + } + }, + $middleware + ); + } + /** * Rewinds the current route index. */ diff --git a/tests/groupcompactsyntax/FlightRouteCompactSyntaxTest.php b/tests/groupcompactsyntax/FlightRouteCompactSyntaxTest.php index 3e522a2..719946d 100644 --- a/tests/groupcompactsyntax/FlightRouteCompactSyntaxTest.php +++ b/tests/groupcompactsyntax/FlightRouteCompactSyntaxTest.php @@ -17,85 +17,124 @@ final class FlightRouteCompactSyntaxTest extends TestCase public function testCanMapMethodsWithVerboseSyntax(): void { - Flight::route('GET /users', [UsersController::class, 'list']); - Flight::route('POST /users', [UsersController::class, 'handleRegister']); + Flight::route('GET /users', [UsersController::class, 'index']); + Flight::route('DELETE /users/@id', [UsersController::class, 'destroy']); $routes = Flight::router()->getRoutes(); $this->assertCount(2, $routes); $this->assertSame('/users', $routes[0]->pattern); - $this->assertSame([UsersController::class, 'list'], $routes[0]->callback); + $this->assertSame([UsersController::class, 'index'], $routes[0]->callback); $this->assertSame('GET', $routes[0]->methods[0]); - $this->assertSame('/users', $routes[1]->pattern); - $this->assertSame([UsersController::class, 'handleRegister'], $routes[1]->callback); - $this->assertSame('POST', $routes[1]->methods[0]); + $this->assertSame('/users/@id', $routes[1]->pattern); + $this->assertSame([UsersController::class, 'destroy'], $routes[1]->callback); + $this->assertSame('DELETE', $routes[1]->methods[0]); } - public function testCanMapSomeMethods(): void + public function testOptionsOnly(): void { Flight::resource('/users', UsersController::class, [ - 'GET /' => 'list', - 'POST /' => 'handleRegister' + 'only' => [ 'index', 'destroy' ] ]); $routes = Flight::router()->getRoutes(); $this->assertCount(2, $routes); - $this->assertSame('/users/', $routes[0]->pattern); + $this->assertSame('/users', $routes[0]->pattern); $this->assertSame('GET', $routes[0]->methods[0]); - $this->assertSame([UsersController::class, 'list'], $routes[0]->callback); + $this->assertSame([UsersController::class, 'index'], $routes[0]->callback); - $this->assertSame('/users/', $routes[1]->pattern); - $this->assertSame('POST', $routes[1]->methods[0]); - $this->assertSame([UsersController::class, 'handleRegister'], $routes[1]->callback); + $this->assertSame('/users/@id', $routes[1]->pattern); + $this->assertSame('DELETE', $routes[1]->methods[0]); + $this->assertSame([UsersController::class, 'destroy'], $routes[1]->callback); } - public function testCanMapDefaultMethods(): void + public function testDefaultMethods(): void { Flight::resource('/posts', PostsController::class); $routes = Flight::router()->getRoutes(); - $this->assertCount(7, $routes); - $this->assertSame('/posts/', $routes[0]->pattern); + $this->assertSame('/posts', $routes[0]->pattern); $this->assertSame('GET', $routes[0]->methods[0]); $this->assertSame([PostsController::class, 'index'], $routes[0]->callback); - - $this->assertSame('/posts/@id/', $routes[1]->pattern); + $this->assertSame('posts.index', $routes[0]->alias); + + $this->assertSame('/posts/create', $routes[1]->pattern); $this->assertSame('GET', $routes[1]->methods[0]); - $this->assertSame([PostsController::class, 'show'], $routes[1]->callback); - - $this->assertSame('/posts/create/', $routes[2]->pattern); - $this->assertSame('GET', $routes[2]->methods[0]); - $this->assertSame([PostsController::class, 'create'], $routes[2]->callback); - - $this->assertSame('/posts/', $routes[3]->pattern); - $this->assertSame('POST', $routes[3]->methods[0]); - $this->assertSame([PostsController::class, 'store'], $routes[3]->callback); - - $this->assertSame('/posts/@id/edit/', $routes[4]->pattern); + $this->assertSame([PostsController::class, 'create'], $routes[1]->callback); + $this->assertSame('posts.create', $routes[1]->alias); + + $this->assertSame('/posts', $routes[2]->pattern); + $this->assertSame('POST', $routes[2]->methods[0]); + $this->assertSame([PostsController::class, 'store'], $routes[2]->callback); + $this->assertSame('posts.store', $routes[2]->alias); + + $this->assertSame('/posts/@id', $routes[3]->pattern); + $this->assertSame('GET', $routes[3]->methods[0]); + $this->assertSame([PostsController::class, 'show'], $routes[3]->callback); + $this->assertSame('posts.show', $routes[3]->alias); + + $this->assertSame('/posts/@id/edit', $routes[4]->pattern); $this->assertSame('GET', $routes[4]->methods[0]); $this->assertSame([PostsController::class, 'edit'], $routes[4]->callback); + $this->assertSame('posts.edit', $routes[4]->alias); - $this->assertSame('/posts/@id/', $routes[5]->pattern); + $this->assertSame('/posts/@id', $routes[5]->pattern); $this->assertSame('PUT', $routes[5]->methods[0]); $this->assertSame([PostsController::class, 'update'], $routes[5]->callback); + $this->assertSame('posts.update', $routes[5]->alias); - $this->assertSame('/posts/@id/', $routes[6]->pattern); + $this->assertSame('/posts/@id', $routes[6]->pattern); $this->assertSame('DELETE', $routes[6]->methods[0]); $this->assertSame([PostsController::class, 'destroy'], $routes[6]->callback); + $this->assertSame('posts.destroy', $routes[6]->alias); } - public function testCanMapExistingMethods(): void + public function testOptionsExcept(): void { - Flight::resource('/todos', TodosController::class); + Flight::resource('/todos', TodosController::class, [ + 'except' => [ 'create', 'store', 'update', 'destroy', 'edit' ] + ]); $routes = Flight::router()->getRoutes(); $this->assertCount(2, $routes); + + $this->assertSame('/todos', $routes[0]->pattern); + $this->assertSame('GET', $routes[0]->methods[0]); + $this->assertSame([TodosController::class, 'index'], $routes[0]->callback); + + $this->assertSame('/todos/@id', $routes[1]->pattern); + $this->assertSame('GET', $routes[1]->methods[0]); + $this->assertSame([TodosController::class, 'show'], $routes[1]->callback); } + + public function testOptionsMiddlewareAndAliasBase(): void + { + Flight::resource('/todos', TodosController::class, [ + 'middleware' => [ 'auth' ], + 'alias_base' => 'nothanks' + ]); + + $routes = Flight::router()->getRoutes(); + + $this->assertCount(7, $routes); + + $this->assertSame('/todos', $routes[0]->pattern); + $this->assertSame('GET', $routes[0]->methods[0]); + $this->assertSame([TodosController::class, 'index'], $routes[0]->callback); + $this->assertSame('auth', $routes[0]->middleware[0]); + $this->assertSame('nothanks.index', $routes[0]->alias); + + $this->assertSame('/todos/create', $routes[1]->pattern); + $this->assertSame('GET', $routes[1]->methods[0]); + $this->assertSame([TodosController::class, 'create'], $routes[1]->callback); + $this->assertSame('auth', $routes[1]->middleware[0]); + $this->assertSame('nothanks.create', $routes[1]->alias); + } } diff --git a/tests/groupcompactsyntax/UsersController.php b/tests/groupcompactsyntax/UsersController.php index 90e1b68..2727ac6 100644 --- a/tests/groupcompactsyntax/UsersController.php +++ b/tests/groupcompactsyntax/UsersController.php @@ -4,12 +4,12 @@ namespace tests\groupcompactsyntax; final class UsersController { - public function list(): void + public function index(): void { echo __METHOD__; } - public function handleRegister(): void + public function destroy(): void { echo __METHOD__; }