1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
|
<?php
namespace App\http;
use App\http\Support\RouteLoader;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Exception\MethodNotAllowedException;
use Symfony\Component\Routing\Exception\ResourceNotFoundException;
use Symfony\Component\Routing\Generator\UrlGenerator;
use Symfony\Component\Routing\Loader\AnnotationFileLoader;
use Symfony\Component\Routing\Matcher\UrlMatcher;
use Symfony\Component\Routing\RequestContext;
use Symfony\Component\Routing\RouteCollection;
class Router
{
public static Request $request;
public static RequestContext $context;
public static RouteCollection $routes;
public static function init(Request $request): void
{
self::$request = $request;
self::$context = new RequestContext();
self::$context->fromRequest($request);
self::$routes = new RouteCollection();
$loader = new AnnotationFileLoader(new FileLocator(), new RouteLoader());
$iterator = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator(__DIR__ . '/Controller'));
foreach ($iterator as $file) {
/**@var \SplFileInfo $file*/
if (in_array($file->getFilename(), ['.', '..'])) continue;
$collection = $loader->load($file->getPathname(), 'attribute');
self::$routes->addCollection($collection);
}
}
public static function execute(): Response
{
try {
$matcher = new UrlMatcher(self::$routes, self::$context);
$match = $matcher->matchRequest(self::$request);
foreach ($match as $key => $value) {
if (str_starts_with($key, '_')) continue;
self::$request->query->set($key, $value);
}
/**@var \ReflectionClass $class*/
$class = $match['_']['class'];
/**@var \ReflectionMethod $method*/
$method = $match['_']['method'];
return ($class->newInstance())->{$method->getName()}(self::$request);
} catch (ResourceNotFoundException $exception) {
return new Response('404', 404);
} catch (MethodNotAllowedException $exception) {
return new Response('403', 403);
} catch (\Exception $exception) {
return new Response('500: ' . $exception->getMessage(), 500);
}
}
/**
* @param string $name
* @param array $parameters
* @param int $referenceType
*/
public static function generate(string $name, array $parameters = [], int $referenceType = 1): string
{
$generator = new UrlGenerator(self::$routes, self::$context);
return $generator->generate($name, $parameters, $referenceType);
}
}
|