Added routing through attributes.
This commit is contained in:
parent
2b8b31289d
commit
32254bf398
4 changed files with 109 additions and 2 deletions
2
VERSION
2
VERSION
|
@ -1 +1 @@
|
||||||
0.2309.61148
|
0.2309.72158
|
||||||
|
|
49
src/Routing/Route.php
Normal file
49
src/Routing/Route.php
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
<?php
|
||||||
|
// Route.php
|
||||||
|
// Created: 2023-09-07
|
||||||
|
// Updated: 2023-09-07
|
||||||
|
|
||||||
|
namespace Index\Routing;
|
||||||
|
|
||||||
|
use Attribute;
|
||||||
|
use ReflectionObject;
|
||||||
|
use UnexpectedValueException;
|
||||||
|
|
||||||
|
#[Attribute]
|
||||||
|
class Route {
|
||||||
|
public function __construct(
|
||||||
|
private string $method,
|
||||||
|
private string $path
|
||||||
|
) {}
|
||||||
|
|
||||||
|
public function getMethod(): string {
|
||||||
|
return $this->method;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getPath(): string {
|
||||||
|
return $this->path;
|
||||||
|
}
|
||||||
|
|
||||||
|
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) {
|
||||||
|
if($attrInfo->isRepeated())
|
||||||
|
throw new UnexpectedValueException('Only one instance of the Route attribute should be used per method.');
|
||||||
|
|
||||||
|
$routeInfo = $attrInfo->newInstance();
|
||||||
|
$router->add(
|
||||||
|
$routeInfo->getMethod(),
|
||||||
|
$routeInfo->getPath(),
|
||||||
|
$methodInfo->getClosure(
|
||||||
|
$methodInfo->isStatic() ? null : $handler
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
12
src/Routing/RouteHandlerTrait.php
Normal file
12
src/Routing/RouteHandlerTrait.php
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
<?php
|
||||||
|
// RouteHandlerTrait.php
|
||||||
|
// Created: 2023-09-07
|
||||||
|
// Updated: 2023-09-07
|
||||||
|
|
||||||
|
namespace Index\Routing;
|
||||||
|
|
||||||
|
trait RouteHandlerTrait {
|
||||||
|
public function registerRoutes(IRouter $router): void {
|
||||||
|
Route::handleAttributes($router, $this);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,11 +1,14 @@
|
||||||
<?php
|
<?php
|
||||||
// RouterTest.php
|
// RouterTest.php
|
||||||
// Created: 2022-01-20
|
// Created: 2022-01-20
|
||||||
// Updated: 2022-02-05
|
// Updated: 2023-09-07
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
use PHPUnit\Framework\TestCase;
|
use PHPUnit\Framework\TestCase;
|
||||||
|
use Index\Routing\IRouteHandler;
|
||||||
|
use Index\Routing\Route;
|
||||||
|
use Index\Routing\RouteHandlerTrait;
|
||||||
use Index\Routing\Router;
|
use Index\Routing\Router;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -111,4 +114,47 @@ final class RouterTest extends TestCase {
|
||||||
$this->assertEquals('correct', $router3->resolve('GET', '/static/0')->run());
|
$this->assertEquals('correct', $router3->resolve('GET', '/static/0')->run());
|
||||||
$this->assertEquals('correct', $router3->resolve('GET', '/variable/0')->run());
|
$this->assertEquals('correct', $router3->resolve('GET', '/variable/0')->run());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testAttribute(): void {
|
||||||
|
$router = new Router;
|
||||||
|
$handler = new class implements IRouteHandler {
|
||||||
|
use RouteHandlerTrait;
|
||||||
|
|
||||||
|
#[Route('GET', '/')]
|
||||||
|
public function getIndex() {
|
||||||
|
return 'index';
|
||||||
|
}
|
||||||
|
|
||||||
|
#[Route('POST', '/avatar')]
|
||||||
|
public function postAvatar() {
|
||||||
|
return 'avatar';
|
||||||
|
}
|
||||||
|
|
||||||
|
#[Route('PUT', '/static')]
|
||||||
|
public static function putStatic() {
|
||||||
|
return 'static';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function hasNoAttr() {
|
||||||
|
return 'meow';
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
$router->register($handler);
|
||||||
|
$this->assertEquals('index', $router->resolve('GET', '/')->run());
|
||||||
|
$this->assertEquals('avatar', $router->resolve('POST', '/avatar')->run());
|
||||||
|
$this->assertEquals('static', $router->resolve('PUT', '/static')->run());
|
||||||
|
|
||||||
|
$badHandler = new class implements IRouteHandler {
|
||||||
|
use RouteHandlerTrait;
|
||||||
|
|
||||||
|
#[Route('GET', '/')]
|
||||||
|
#[Route('POST', '/meow')]
|
||||||
|
public function getPostBad() {
|
||||||
|
return 'this is bad';
|
||||||
|
}
|
||||||
|
};
|
||||||
|
$this->expectException(UnexpectedValueException::class);
|
||||||
|
$router->register($badHandler);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue