1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
declare(strict_types=1); |
4
|
|
|
|
5
|
|
|
namespace Spiral\Bootloader\Http; |
6
|
|
|
|
7
|
|
|
use Psr\Container\ContainerInterface; |
8
|
|
|
use Psr\EventDispatcher\EventDispatcherInterface; |
9
|
|
|
use Psr\Http\Message\ServerRequestInterface; |
10
|
|
|
use Psr\Http\Server\RequestHandlerInterface; |
11
|
|
|
use Spiral\Boot\AbstractKernel; |
12
|
|
|
use Spiral\Boot\Bootloader\Bootloader; |
13
|
|
|
use Spiral\Config\ConfiguratorInterface; |
14
|
|
|
use Spiral\Core\Attribute\Proxy; |
15
|
|
|
use Spiral\Core\BinderInterface; |
16
|
|
|
use Spiral\Core\Core; |
17
|
|
|
use Spiral\Core\CoreInterface; |
18
|
|
|
use Spiral\Core\Exception\ScopeException; |
19
|
|
|
use Spiral\Framework\Kernel; |
20
|
|
|
use Spiral\Framework\Spiral; |
21
|
|
|
use Spiral\Http\Config\HttpConfig; |
22
|
|
|
use Spiral\Interceptors\HandlerInterface; |
23
|
|
|
use Spiral\Router\GroupRegistry; |
24
|
|
|
use Spiral\Router\Loader\Configurator\RoutingConfigurator; |
25
|
|
|
use Spiral\Router\Loader\DelegatingLoader; |
26
|
|
|
use Spiral\Router\Loader\LoaderInterface; |
27
|
|
|
use Spiral\Router\Loader\LoaderRegistry; |
28
|
|
|
use Spiral\Router\Loader\LoaderRegistryInterface; |
29
|
|
|
use Spiral\Router\Loader\PhpFileLoader; |
30
|
|
|
use Spiral\Router\Registry\DefaultPatternRegistry; |
31
|
|
|
use Spiral\Router\Registry\RoutePatternRegistryInterface; |
32
|
|
|
use Spiral\Router\RouteInterface; |
33
|
|
|
use Spiral\Router\Router; |
34
|
|
|
use Spiral\Router\RouterInterface; |
35
|
|
|
use Spiral\Router\UriHandler; |
36
|
|
|
use Spiral\Telemetry\Bootloader\TelemetryBootloader; |
37
|
|
|
use Spiral\Telemetry\TracerInterface; |
38
|
|
|
|
39
|
|
|
final class RouterBootloader extends Bootloader |
40
|
|
|
{ |
41
|
360 |
|
public function __construct( |
42
|
|
|
private readonly ConfiguratorInterface $config, |
43
|
|
|
private readonly BinderInterface $binder, |
44
|
|
|
) { |
45
|
360 |
|
} |
46
|
|
|
|
47
|
360 |
|
public function defineDependencies(): array |
48
|
|
|
{ |
49
|
360 |
|
return [ |
50
|
360 |
|
HttpBootloader::class, |
51
|
360 |
|
TelemetryBootloader::class, |
52
|
360 |
|
]; |
53
|
|
|
} |
54
|
|
|
|
55
|
360 |
|
public function defineSingletons(): array |
56
|
|
|
{ |
57
|
360 |
|
$this->binder |
58
|
360 |
|
->getBinder(Spiral::HttpRequest) |
|
|
|
|
59
|
360 |
|
->bindSingleton(RouteInterface::class, [self::class, 'route']); |
60
|
|
|
|
61
|
360 |
|
return [ |
62
|
360 |
|
HandlerInterface::class => Core::class, |
63
|
360 |
|
CoreInterface::class => Core::class, |
64
|
360 |
|
RouterInterface::class => [self::class, 'router'], |
65
|
360 |
|
RequestHandlerInterface::class => RouterInterface::class, |
66
|
360 |
|
LoaderInterface::class => DelegatingLoader::class, |
67
|
360 |
|
LoaderRegistryInterface::class => [self::class, 'initRegistry'], |
68
|
360 |
|
GroupRegistry::class => GroupRegistry::class, |
69
|
360 |
|
RoutingConfigurator::class => RoutingConfigurator::class, |
70
|
360 |
|
RoutePatternRegistryInterface::class => DefaultPatternRegistry::class, |
71
|
360 |
|
]; |
72
|
|
|
} |
73
|
|
|
|
74
|
360 |
|
public function boot(AbstractKernel $kernel): void |
75
|
|
|
{ |
76
|
360 |
|
$configuratorCallback = static function (RouterInterface $router, RoutingConfigurator $routes): void { |
77
|
360 |
|
$router->import($routes); |
78
|
360 |
|
}; |
79
|
360 |
|
$groupsCallback = static function (RouterInterface $router, GroupRegistry $groups): void { |
80
|
360 |
|
$groups->registerRoutes($router); |
81
|
360 |
|
}; |
82
|
|
|
|
83
|
360 |
|
if ($kernel instanceof Kernel) { |
84
|
355 |
|
$kernel->appBooted($configuratorCallback); |
85
|
355 |
|
$kernel->appBooted($groupsCallback); |
86
|
|
|
} else { |
87
|
5 |
|
$kernel->booted($configuratorCallback); |
88
|
5 |
|
$kernel->booted($groupsCallback); |
89
|
|
|
} |
90
|
|
|
} |
91
|
|
|
|
92
|
|
|
/** |
93
|
|
|
* @noRector RemoveUnusedPrivateMethodRector |
94
|
|
|
*/ |
95
|
360 |
|
private function router( |
96
|
|
|
UriHandler $uriHandler, |
97
|
|
|
#[Proxy] ContainerInterface $container, |
98
|
|
|
TracerInterface $tracer, |
99
|
|
|
?EventDispatcherInterface $dispatcher = null |
100
|
|
|
): RouterInterface { |
101
|
360 |
|
return new Router( |
102
|
360 |
|
$this->config->getConfig(HttpConfig::CONFIG)['basePath'], |
103
|
360 |
|
$uriHandler, |
104
|
360 |
|
$container, |
105
|
360 |
|
$dispatcher, |
106
|
360 |
|
$tracer, |
107
|
360 |
|
); |
108
|
|
|
} |
109
|
|
|
|
110
|
|
|
/** |
111
|
|
|
* @noRector RemoveUnusedPrivateMethodRector |
112
|
|
|
*/ |
113
|
3 |
|
private function route(ServerRequestInterface $request): RouteInterface |
114
|
|
|
{ |
115
|
3 |
|
$route = $request->getAttribute(Router::ROUTE_ATTRIBUTE, null); |
116
|
3 |
|
if ($route === null) { |
117
|
1 |
|
throw new ScopeException('Unable to resolve Route, invalid request scope'); |
118
|
|
|
} |
119
|
|
|
|
120
|
2 |
|
return $route; |
121
|
|
|
} |
122
|
|
|
|
123
|
|
|
/** |
124
|
|
|
* @noRector RemoveUnusedPrivateMethodRector |
125
|
|
|
*/ |
126
|
360 |
|
private function initRegistry(ContainerInterface $container): LoaderRegistryInterface |
127
|
|
|
{ |
128
|
360 |
|
return new LoaderRegistry([ |
129
|
360 |
|
$container->get(PhpFileLoader::class), |
130
|
360 |
|
]); |
131
|
|
|
} |
132
|
|
|
} |
133
|
|
|
|