diff options
Diffstat (limited to 'src/Routing/RouteLoader.php')
| -rw-r--r-- | src/Routing/RouteLoader.php | 98 |
1 files changed, 98 insertions, 0 deletions
diff --git a/src/Routing/RouteLoader.php b/src/Routing/RouteLoader.php new file mode 100644 index 0000000..596340f --- /dev/null +++ b/src/Routing/RouteLoader.php @@ -0,0 +1,98 @@ +<?php + +declare(strict_types=1); + +namespace BrettParson\MiniRoute\Routing; + +use BrettParson\MiniRoute\Attribute\Middleware; +use BrettParson\MiniRoute\Attribute\RouteAttribute; +use ReflectionAttribute; +use ReflectionClass; +use ReflectionException; +use ReflectionMethod; + +final class RouteLoader +{ + /** + * Scan a controller class and compile the routes declared on its public + * methods. + * + * @param class-string $controllerClass + * @return list<RouteDef> + */ + public function load(string $controllerClass): array + { + if (!class_exists($controllerClass)) { + throw new RouteRegistrationException("Controller class not found: {$controllerClass}"); + } + + try { + $reflector = new ReflectionClass($controllerClass); + } catch (ReflectionException $e) { + throw new RouteRegistrationException("Unable to reflect controller: {$controllerClass}", 0, $e); + } + + $classMiddleware = $this->middlewareClasses($reflector->getAttributes(Middleware::class)); + + $routes = []; + + foreach ($reflector->getMethods(ReflectionMethod::IS_PUBLIC) as $method) { + foreach ($this->loadMethod($controllerClass, $method, $classMiddleware) as $route) { + $routes[] = $route; + } + } + + return $routes; + } + + /** + * @param list<string> $classMiddleware + * @return list<RouteDef> + */ + private function loadMethod(string $controllerClass, ReflectionMethod $method, array $classMiddleware): array + { + $routeAttributes = $method->getAttributes(RouteAttribute::class, ReflectionAttribute::IS_INSTANCEOF); + + if ($routeAttributes === []) { + return []; + } + + $methodMiddleware = $this->middlewareClasses($method->getAttributes(Middleware::class)); + + $middleware = array_merge($classMiddleware, $methodMiddleware); + + $routes = []; + + foreach ($routeAttributes as $attribute) { + /** @var RouteAttribute $route */ + $route = $attribute->newInstance(); + + $routes[] = new RouteDef( + strtoupper($route->method()), + $route->path(), + $controllerClass, + $method->getName(), + $middleware, + ); + } + + return $routes; + } + + /** + * @param list<ReflectionAttribute> $attributes + * @return list<string> + */ + private function middlewareClasses(array $attributes): array + { + $classes = []; + + foreach ($attributes as $attribute) { + /** @var Middleware $middleware */ + $middleware = $attribute->newInstance(); + $classes[] = $middleware->middlewareClass; + } + + return $classes; + } +} |
