diff --git a/flight/Flight.php b/flight/Flight.php index 207d44b..020e546 100644 --- a/flight/Flight.php +++ b/flight/Flight.php @@ -121,6 +121,60 @@ class Flight return self::app()->{$name}(...$params); } + /** + * Create a resource controller customizing the methods names mapping. + * + * @param class-string $controllerClass + * @param array $methods + */ + public static function resource( + string $pattern, + string $controllerClass, + array $methods = [] + ): void { + $defaultMapping = [ + 'GET /' => 'index', + 'GET /@id/' => 'show', + 'GET /create/' => 'create', + 'POST /' => 'store', + 'GET /@id/edit/' => 'edit', + 'PUT /@id/' => 'update', + 'DELETE /@id/' => 'destroy' + ]; + + if ($methods !== []) { + static::group( + $pattern, + function () use ($controllerClass, $methods): void { + foreach ($methods as $methodPattern => $controllerMethod) { + static::route( + $methodPattern, + [$controllerClass, $controllerMethod] + ); + } + } + ); + } else { + static::group( + $pattern, + function () use ($defaultMapping, $controllerClass): void { + foreach ($defaultMapping as $methodPattern => $controllerMethod) { + $class = new ReflectionClass($controllerClass); + + if ($class->hasMethod($controllerMethod) === false) { + continue; + } + + static::route( + $methodPattern, + [$controllerClass, $controllerMethod] + ); + } + } + ); + } + } + /** @return Engine Application instance */ public static function app(): Engine { diff --git a/tests/groupcompactsyntax/FlightRouteCompactSyntaxTest.php b/tests/groupcompactsyntax/FlightRouteCompactSyntaxTest.php new file mode 100644 index 0000000..3e522a2 --- /dev/null +++ b/tests/groupcompactsyntax/FlightRouteCompactSyntaxTest.php @@ -0,0 +1,101 @@ +clear(); + } + + public function testCanMapMethodsWithVerboseSyntax(): void + { + Flight::route('GET /users', [UsersController::class, 'list']); + Flight::route('POST /users', [UsersController::class, 'handleRegister']); + + $routes = Flight::router()->getRoutes(); + + $this->assertCount(2, $routes); + + $this->assertSame('/users', $routes[0]->pattern); + $this->assertSame([UsersController::class, 'list'], $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]); + } + + public function testCanMapSomeMethods(): void + { + Flight::resource('/users', UsersController::class, [ + 'GET /' => 'list', + 'POST /' => 'handleRegister' + ]); + + $routes = Flight::router()->getRoutes(); + + $this->assertCount(2, $routes); + + $this->assertSame('/users/', $routes[0]->pattern); + $this->assertSame('GET', $routes[0]->methods[0]); + $this->assertSame([UsersController::class, 'list'], $routes[0]->callback); + + $this->assertSame('/users/', $routes[1]->pattern); + $this->assertSame('POST', $routes[1]->methods[0]); + $this->assertSame([UsersController::class, 'handleRegister'], $routes[1]->callback); + } + + public function testCanMapDefaultMethods(): void + { + Flight::resource('/posts', PostsController::class); + + $routes = Flight::router()->getRoutes(); + + $this->assertCount(7, $routes); + + $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('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('GET', $routes[4]->methods[0]); + $this->assertSame([PostsController::class, 'edit'], $routes[4]->callback); + + $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/@id/', $routes[6]->pattern); + $this->assertSame('DELETE', $routes[6]->methods[0]); + $this->assertSame([PostsController::class, 'destroy'], $routes[6]->callback); + } + + public function testCanMapExistingMethods(): void + { + Flight::resource('/todos', TodosController::class); + + $routes = Flight::router()->getRoutes(); + + $this->assertCount(2, $routes); + } +} diff --git a/tests/groupcompactsyntax/PostsController.php b/tests/groupcompactsyntax/PostsController.php new file mode 100644 index 0000000..ac2c497 --- /dev/null +++ b/tests/groupcompactsyntax/PostsController.php @@ -0,0 +1,34 @@ +