chore: complete update

This commit is contained in:
2025-07-17 16:24:20 +02:00
parent 899227b0a4
commit 64a7051137
1300 changed files with 85570 additions and 2756 deletions

View File

@@ -4,8 +4,12 @@ declare(strict_types=1);
namespace App\Framework\Core;
final class RouteCompiler
use App\Framework\Router\CompiledPattern;
use App\Framework\Router\CompiledRoutes;
final readonly class RouteCompiler implements AttributeCompiler
{
private array $named;
/**
* @param array<int, array{method: string, path: string, controller: class-string, handler: string}> $routes
* @return array<string, array{static: array<string, array>, dynamic: array<int, array{regex: string, params: array, handler: array}>}>
@@ -13,36 +17,70 @@ final class RouteCompiler
public function compile(array $routes): array
{
$compiled = [];
$named = [];
foreach ($routes as $route) {
$method = strtoupper($route['http_method']);
$method = is_string($route['http_method']) ? strtoupper($route['http_method']) : $route['http_method']->value;
$path = $route['path'];
$routeName = $route['name'] ?? '';
$compiled[$method] ??= ['static' => [], 'dynamic' => []];
if (! str_contains($path, '{')) {
// Statische Route
$compiled[$method]['static'][$path] = new StaticRoute(
$staticRoute = new StaticRoute(
$route['class'],
$route['method'],
$route['parameters']
$route['parameters'] ?? [],
$routeName,
$path,
$route['attributes']
);
$compiled[$method]['static'][$path] = $staticRoute;
if($routeName) {
$named[$routeName] = $staticRoute;
}
} else {
// Dynamische Route
$paramNames = [];
$regex = $this->convertPathToRegex($path, $paramNames);
$compiled[$method]['dynamic'][] = new DynamicRoute(
$dynamicRoute = new DynamicRoute(
$regex,
$paramNames,
$route['class'],
$route['method'],
$route['parameters']
$route['parameters'],
[],
$routeName,
$path,
$route['attributes']
);
$compiled[$method]['dynamic'][] = $dynamicRoute;
if($routeName) {
$named[$routeName] = $dynamicRoute;
}
}
}
if(!isset($this->named)) {
$this->named = $named;
}
return $compiled;
}
public function compileNamedRoutes(array $routes): array
{
return $this->named;
}
/**
* Konvertiert zB. /user/{id}/edit → ~^/user/([^/]+)/edit$~ und gibt ['id'] als Parameternamen zurück.
*
@@ -53,12 +91,77 @@ final class RouteCompiler
private function convertPathToRegex(string $path, array &$paramNames): string
{
$paramNames = [];
$regex = preg_replace_callback('#\{(\w+)\}#', function ($matches) use (&$paramNames) {
$regex = preg_replace_callback('#\{(\w+)(\*)?}#', function ($matches) use (&$paramNames) {
$paramNames[] = $matches[1];
return '([^/]+)';
// Wenn {id*} dann erlaube Slashes, aber mache es non-greedy
if (isset($matches[2]) && $matches[2] === '*') {
return '(.+?)'; // Non-greedy: matcht so wenig wie möglich
}
return '([^/]+)'; // Keine Slashes
}, $path);
return '~^' . $regex . '$~';
}
public function getAttributeClass(): string
{
return Route::class;
}
public function compileOptimized(array $routes): CompiledRoutes
{
$compiled = $this->compile($routes);
$optimizedStatic = [];
$optimizedDynamic = [];
foreach($compiled as $method => $routes) {
$optimizedStatic[$method] = $routes['static'];
if(!empty($routes['dynamic'])) {
$optimizedDynamic[$method] = $this->createCompiledPattern($routes['dynamic']);
}
}
return new CompiledRoutes($optimizedStatic, $optimizedDynamic, $this->named);
}
private function createCompiledPattern(mixed $dynamicRoutes): CompiledPattern
{
$patterns = [];
$routeData = [];
$currentIndex = 1; // Nach Full Match (Index 0)
foreach($dynamicRoutes as $index => $route) {
$pattern = $this->stripAnchors($route->regex);
$patterns[] = "({$pattern})";
// Route-Gruppe Index merken
$routeGroupIndex = $currentIndex++;
// Parameter-Mapping KORREKT berechnen
$paramMap = [];
foreach($route->paramNames as $paramName) {
$paramMap[$paramName] = $currentIndex++;
}
$routeData[$index] = [
'route' => $route,
'paramMap' => $paramMap,
'routeGroupIndex' => $routeGroupIndex
];
}
$combinedRegex = '~^(?:' . implode('|', $patterns) . ')$~';
return new CompiledPattern($combinedRegex, $routeData);
}
private function stripAnchors($regex): string
{
if (preg_match('/^~\^(.+)\$~$/', $regex, $matches)) {
return $matches[1];
}
return $regex;
}
}