index/src/Routing/Route.php

82 lines
2.1 KiB
PHP

<?php
// Route.php
// Created: 2023-09-07
// Updated: 2023-09-08
namespace Index\Routing;
use Attribute;
use ReflectionObject;
/**
* Provides an attribute for marking methods in a class as routes.
*/
#[Attribute(Attribute::TARGET_METHOD | Attribute::IS_REPEATABLE)]
class Route {
private ?string $method;
private string $path;
/** @internal */
public function __construct(string $pathOrMethod, ?string $path = null) {
if($path === null) {
$this->method = null;
$this->path = $pathOrMethod;
} else {
$this->method = $pathOrMethod;
$this->path = $path;
}
}
/**
* Returns the target method name.
*
* @return ?string
*/
public function getMethod(): ?string {
return $this->method;
}
/**
* Whether this route should be used as middleware.
*
* @return bool
*/
public function isMiddleware(): bool {
return $this->method === null;
}
/**
* Returns the target path.
*
* @return string
*/
public function getPath(): string {
return $this->path;
}
/**
* Reads attributes from methods in a IRouteHandler instance and registers them to a given IRouter instance.
*
* @param IRouter $router Router instance.
* @param IRouteHandler $handler Handler instance.
*/
public static function handleAttributes(IRouter $router, IRouteHandler $handler): void {
$objectInfo = new ReflectionObject($handler);
$methodInfos = $objectInfo->getMethods();
foreach($methodInfos as $methodInfo) {
$attrInfos = $methodInfo->getAttributes(Route::class);
foreach($attrInfos as $attrInfo) {
$routeInfo = $attrInfo->newInstance();
$closure = $methodInfo->getClosure($methodInfo->isStatic() ? null : $handler);
if($routeInfo->isMiddleware())
$router->use($routeInfo->getPath(), $closure);
else
$router->add($routeInfo->getMethod(), $routeInfo->getPath(), $closure);
}
}
}
}