1 | <?php namespace Limoncello\Core\Routing; |
||
34 | class Router implements RouterInterface |
||
35 | { |
||
36 | use ClassIsTrait; |
||
37 | |||
38 | /** |
||
39 | * @var false|array |
||
40 | */ |
||
41 | private $cachedRoutes = false; |
||
42 | |||
43 | /** |
||
44 | * @var string |
||
45 | */ |
||
46 | private $generatorClass; |
||
47 | |||
48 | /** |
||
49 | * @var string |
||
50 | */ |
||
51 | private $dispatcherClass; |
||
52 | |||
53 | /** |
||
54 | * @var DispatcherInterface |
||
55 | */ |
||
56 | private $dispatcher; |
||
57 | |||
58 | /** |
||
59 | * @param string $generatorClass |
||
60 | * @param string $dispatcherClass |
||
61 | */ |
||
62 | 14 | public function __construct(string $generatorClass, string $dispatcherClass) |
|
63 | { |
||
64 | 14 | assert(static::classImplements($generatorClass, DataGenerator::class)); |
|
65 | 14 | assert(static::classImplements($dispatcherClass, Dispatcher::class)); |
|
66 | |||
67 | 14 | $this->generatorClass = $generatorClass; |
|
68 | 14 | $this->dispatcherClass = $dispatcherClass; |
|
69 | } |
||
70 | |||
71 | /** |
||
72 | * @inheritdoc |
||
73 | */ |
||
74 | 13 | public function getCachedRoutes(GroupInterface $group): array |
|
75 | { |
||
76 | 13 | $collector = $this->createRouteCollector(); |
|
77 | |||
78 | 13 | $routeIndex = 0; |
|
79 | 13 | $allRoutesInfo = []; |
|
80 | 13 | $namedRouteUriPaths = []; |
|
81 | 13 | foreach ($group->getRoutes() as $route) { |
|
82 | /** @var RouteInterface $route */ |
||
83 | 13 | $allRoutesInfo[] = [ |
|
84 | 13 | $route->getHandler(), |
|
85 | 13 | $route->getMiddleware(), |
|
86 | 13 | $route->getContainerConfigurators(), |
|
87 | 13 | $route->getRequestFactory(), |
|
88 | ]; |
||
89 | |||
90 | 13 | $routeName = $route->getName(); |
|
91 | 13 | if (empty($routeName) === false) { |
|
92 | 7 | $namedRouteUriPaths[$routeName] = $route->getUriPath(); |
|
93 | } |
||
94 | |||
95 | 13 | $collector->addRoute($route->getMethod(), $route->getUriPath(), $routeIndex); |
|
96 | |||
97 | 13 | $routeIndex++; |
|
98 | } |
||
99 | |||
100 | 13 | return [$collector->getData(), $allRoutesInfo, $namedRouteUriPaths]; |
|
101 | } |
||
102 | |||
103 | /** |
||
104 | * @inheritdoc |
||
105 | */ |
||
106 | 13 | public function loadCachedRoutes(array $cachedRoutes): void |
|
107 | { |
||
108 | 13 | $this->cachedRoutes = $cachedRoutes; |
|
109 | 13 | list($collectorData) = $cachedRoutes; |
|
110 | |||
111 | 13 | $this->dispatcher = $this->createDispatcher(); |
|
112 | 13 | $this->dispatcher->setData($collectorData); |
|
113 | } |
||
114 | |||
115 | /** |
||
116 | * @inheritdoc |
||
117 | */ |
||
118 | 12 | public function match(string $method, string $uriPath): array |
|
119 | { |
||
120 | 12 | $this->checkRoutesLoaded(); |
|
121 | |||
122 | 11 | $result = $this->dispatcher->dispatchRequest($method, $uriPath); |
|
123 | |||
124 | // Array contains matching result code, allowed methods list, handler parameters list, handler, |
||
125 | // middleware list, container configurators list, custom request factory. |
||
126 | 11 | switch ($result[0]) { |
|
127 | 11 | case DispatcherInterface::ROUTE_FOUND: |
|
128 | 9 | $routeIndex = $result[1]; |
|
129 | 9 | $handlerParams = $result[2]; |
|
130 | |||
131 | 9 | list(, $allRoutesInfo) = $this->cachedRoutes; |
|
132 | 9 | $routeInfo = $allRoutesInfo[$routeIndex]; |
|
133 | |||
134 | 9 | return array_merge([self::MATCH_FOUND, null, $handlerParams], $routeInfo); |
|
135 | |||
136 | 6 | case DispatcherInterface::ROUTE_METHOD_NOT_ALLOWED: |
|
137 | 5 | $allowedMethods = $result[1]; |
|
138 | |||
139 | 5 | return [self::MATCH_METHOD_NOT_ALLOWED, $allowedMethods, null, null, null, null, null]; |
|
140 | |||
141 | default: |
||
142 | 5 | return [self::MATCH_NOT_FOUND, null, null, null, null, null, null]; |
|
143 | } |
||
144 | } |
||
145 | |||
146 | /** |
||
147 | * @inheritdoc |
||
148 | */ |
||
149 | 5 | public function getUriPath(string $routeName): ?string |
|
150 | { |
||
151 | 5 | $this->checkRoutesLoaded(); |
|
152 | |||
153 | 5 | list(, , $namedRouteUriPaths) = $this->cachedRoutes; |
|
154 | |||
155 | 5 | $result = array_key_exists($routeName, $namedRouteUriPaths) === true ? $namedRouteUriPaths[$routeName] : null; |
|
156 | |||
157 | 5 | return $result; |
|
158 | } |
||
159 | |||
160 | /** |
||
161 | * @inheritdoc |
||
162 | */ |
||
163 | 1 | public function get( |
|
175 | |||
176 | /** |
||
177 | * @inheritdoc |
||
178 | */ |
||
179 | 1 | public function getHostUri(ServerRequestInterface $request): string |
|
180 | { |
||
189 | |||
190 | /** |
||
191 | * @return RouteCollector |
||
192 | */ |
||
193 | 13 | protected function createRouteCollector(): RouteCollector |
|
197 | |||
198 | /** |
||
199 | * @return DispatcherInterface |
||
200 | */ |
||
201 | 13 | protected function createDispatcher(): DispatcherInterface |
|
205 | |||
206 | /** |
||
207 | * @param string $path |
||
208 | * @param array $placeholders |
||
209 | * |
||
210 | * @return string |
||
211 | * |
||
212 | * @SuppressWarnings(PHPMD.ElseExpression) |
||
213 | */ |
||
214 | 1 | private function replacePlaceholders(string $path, array $placeholders): string |
|
251 | |||
252 | /** |
||
253 | * @return void |
||
254 | */ |
||
255 | 13 | private function checkRoutesLoaded(): void |
|
261 | } |
||
262 |