91 lines
3.0 KiB
PHP
91 lines
3.0 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Core;
|
|
|
|
use FastRoute\RouteCollector;
|
|
use function FastRoute\simpleDispatcher;
|
|
|
|
final class Router
|
|
{
|
|
private array $routes = [];
|
|
public Container $container;
|
|
|
|
public function __construct(Container $container)
|
|
{
|
|
$this->container = $container;
|
|
}
|
|
|
|
public function addRoute(string $method, string $path, array|callable $handler): void
|
|
{
|
|
$this->routes[] = [$method, $path, $handler];
|
|
}
|
|
|
|
public function dispatch(Request $request): void
|
|
{
|
|
$dispatcher = simpleDispatcher(function (RouteCollector $r) {
|
|
foreach ($this->routes as $route) {
|
|
$r->addRoute($route[0], $route[1], $route[2]);
|
|
}
|
|
});
|
|
|
|
$routeInfo = $dispatcher->dispatch($request->getMethod(), $request->getPath());
|
|
|
|
switch ($routeInfo[0]) {
|
|
case \FastRoute\Dispatcher::NOT_FOUND:
|
|
Response::error('المسار غير موجود', 'NOT_FOUND', 404);
|
|
break;
|
|
case \FastRoute\Dispatcher::METHOD_NOT_ALLOWED:
|
|
Response::error('الطريقة غير مسموح بها', 'METHOD_NOT_ALLOWED', 405);
|
|
break;
|
|
case \FastRoute\Dispatcher::FOUND:
|
|
$handler = $routeInfo[1];
|
|
$vars = $routeInfo[2];
|
|
|
|
$this->executeHandler($handler, $request, $container, $vars);
|
|
break;
|
|
}
|
|
}
|
|
|
|
private function executeHandler(mixed $handler, Request $request, Container $container, array $vars): void
|
|
{
|
|
if (is_array($handler) && isset($handler['middleware'])) {
|
|
$middlewares = (array) $handler['middleware'];
|
|
$finalHandler = $handler['handler'];
|
|
|
|
$pipeline = $this->createPipeline($middlewares, $finalHandler, $container, $vars);
|
|
$pipeline($request);
|
|
} else {
|
|
$this->callHandler($handler, $request, $container, $vars);
|
|
}
|
|
}
|
|
|
|
private function createPipeline(array $middlewares, mixed $handler, Container $container, array $vars): callable
|
|
{
|
|
return array_reduce(
|
|
array_reverse($middlewares),
|
|
function ($next, $middleware) use ($container) {
|
|
return function ($request) use ($next, $middleware, $container) {
|
|
$instance = $container->get($middleware);
|
|
return $instance->handle($request, $next);
|
|
};
|
|
},
|
|
function ($request) use ($handler, $container, $vars) {
|
|
$this->callHandler($handler, $request, $container, $vars);
|
|
}
|
|
);
|
|
}
|
|
|
|
private function callHandler(mixed $handler, Request $request, Container $container, array $vars): void
|
|
{
|
|
if (is_array($handler)) {
|
|
[$controllerClass, $method] = $handler;
|
|
$controller = $container->get($controllerClass);
|
|
$controller->$method($request, ...array_values($vars));
|
|
} else {
|
|
$handler($request, ...array_values($vars));
|
|
}
|
|
}
|
|
}
|