Files
CMS/app/Core/Router.php
2025-10-28 14:08:03 +01:00

98 lines
3.0 KiB
PHP

<?php
namespace App\Core;
class Router
{
/** @var array<string, array<int, array{path:string,action:callable,middleware:array}>> */
private array $routes = [];
/** @var array<int, array<int, class-string>> */
private array $middlewareStack = [];
public function get(string $path, callable $action, array $middleware = []): void
{
$this->addRoute('GET', $path, $action, $middleware);
}
public function post(string $path, callable $action, array $middleware = []): void
{
$this->addRoute('POST', $path, $action, $middleware);
}
public function put(string $path, callable $action, array $middleware = []): void
{
$this->addRoute('PUT', $path, $action, $middleware);
}
public function delete(string $path, callable $action, array $middleware = []): void
{
$this->addRoute('DELETE', $path, $action, $middleware);
}
public function group(array $attributes, \Closure $callback): void
{
$groupMiddleware = $attributes['middleware'] ?? [];
$this->middlewareStack[] = $groupMiddleware;
$callback($this);
array_pop($this->middlewareStack);
}
/**
* @param array<int, class-string> $middleware
*/
private function addRoute(string $method, string $path, callable $action, array $middleware = []): void
{
$stackedMiddleware = [];
foreach ($this->middlewareStack as $group) {
$stackedMiddleware = array_merge($stackedMiddleware, $group);
}
$combinedMiddleware = array_merge($stackedMiddleware, $middleware);
$this->routes[$method][] = [
'path' => $path,
'action' => $action,
'middleware' => $combinedMiddleware,
];
}
public function dispatch(string $method, string $uri): Response
{
$uri = parse_url($uri, PHP_URL_PATH) ?? '/';
$routes = $this->routes[$method] ?? [];
foreach ($routes as $route) {
$pattern = '#^' . preg_replace('#\{(.*?)\}#', '(?P<$1>[^/]+)', $route['path']) . '$#';
if (preg_match($pattern, $uri, $matches)) {
$params = array_filter($matches, 'is_string', ARRAY_FILTER_USE_KEY);
$handler = $this->applyMiddleware($route['action'], $route['middleware']);
$result = $handler($params);
if ($result instanceof Response) {
return $result;
}
return new Response((string) $result);
}
}
return new Response('Not Found', 404);
}
/**
* @param callable $action
* @param array<int, class-string> $middleware
*/
private function applyMiddleware(callable $action, array $middleware): callable
{
return array_reduce(
array_reverse($middleware),
function ($next, $middlewareClass) {
$middlewareInstance = new $middlewareClass();
return fn(array $params) => $middlewareInstance->handle($params, $next);
},
$action
);
}
}