1 | <?php namespace Limoncello\Core\Application; |
||
41 | abstract class Application implements ApplicationInterface |
||
42 | { |
||
43 | /** Method name for default request factory. */ |
||
44 | const FACTORY_METHOD = 'defaultRequestFactory'; |
||
45 | |||
46 | /** |
||
47 | * @var SapiInterface|null |
||
48 | */ |
||
49 | private $sapi; |
||
50 | |||
51 | /** |
||
52 | * @var RouterInterface |
||
53 | */ |
||
54 | private $router; |
||
55 | |||
56 | /** |
||
57 | * @return ContainerInterface |
||
58 | */ |
||
59 | abstract protected function createContainer(); |
||
60 | |||
61 | /** |
||
62 | * @return array |
||
63 | */ |
||
64 | abstract protected function getRoutesData(); |
||
65 | |||
66 | /** |
||
67 | * @return callable[] |
||
68 | */ |
||
69 | abstract protected function getGlobalMiddleware(); |
||
70 | |||
71 | /** |
||
72 | * @param SapiInterface $sapi |
||
73 | * @param ContainerInterface $container |
||
74 | * |
||
75 | * @return void |
||
76 | */ |
||
77 | abstract protected function setUpExceptionHandler(SapiInterface $sapi, ContainerInterface $container); |
||
78 | |||
79 | /** |
||
80 | * @inheritdoc |
||
81 | */ |
||
82 | 5 | public function setSapi(SapiInterface $sapi) |
|
83 | { |
||
84 | 5 | $this->sapi = $sapi; |
|
85 | |||
86 | 5 | return $this; |
|
87 | } |
||
88 | |||
89 | /** |
||
90 | * @inheritdoc |
||
91 | */ |
||
92 | 6 | public function run() |
|
93 | 1 | { |
|
94 | 6 | if ($this->sapi === null) { |
|
95 | 1 | throw new LogicException('SAPI not set.'); |
|
96 | } |
||
97 | |||
98 | 5 | $userContainer = $this->createContainer(); |
|
99 | |||
100 | 5 | $this->setUpExceptionHandler($this->sapi, $userContainer); |
|
101 | |||
102 | list($matchCode, $allowedMethods, $handlerParams, $handler, $routeMiddleware, $configurators, $requestFactory) = |
||
103 | 5 | $this->getRouter()->match($this->sapi->getMethod(), $this->sapi->getUri()->getPath()); |
|
104 | |||
105 | 5 | if (empty($configurators) === false) { |
|
106 | 2 | $this->configureUserContainer($userContainer, $configurators); |
|
107 | 2 | } |
|
108 | |||
109 | switch ($matchCode) { |
||
110 | 5 | case RouterInterface::MATCH_FOUND: |
|
111 | 3 | $handler = $this->createOrdinaryTerminalHandler($handler, $handlerParams, $userContainer); |
|
112 | 3 | break; |
|
113 | 2 | case RouterInterface::MATCH_METHOD_NOT_ALLOWED: |
|
114 | 1 | $handler = $this->createMethodNotAllowedTerminalHandler($allowedMethods); |
|
115 | 1 | break; |
|
116 | 1 | default: |
|
117 | 1 | $handler = $this->createNotFoundTerminalHandler(); |
|
118 | 1 | break; |
|
119 | 1 | } |
|
120 | |||
121 | 5 | $globalMiddleware = $this->getGlobalMiddleware(); |
|
122 | 5 | $handler = $this->createMiddlewareChain($handler, $userContainer, $globalMiddleware, $routeMiddleware); |
|
123 | |||
124 | // if handler consists only from Controller and user didn't asked for Request creation |
||
125 | 5 | $requestNotNeeded = $requestFactory === null && empty($globalMiddleware) === true && empty($routeMiddleware) && |
|
126 | 5 | $matchCode === RouterInterface::MATCH_FOUND; |
|
127 | 5 | $request = $requestNotNeeded === true ? |
|
128 | 5 | null : $this->createRequest($this->sapi, $userContainer, $requestFactory); |
|
129 | |||
130 | // send Request down all middleware (global then route's then terminal handler in Controller and back) and |
||
131 | // then send Response to SAPI |
||
132 | 5 | $this->sapi->handleResponse($this->handleRequest($handler, $request)); |
|
133 | 5 | } |
|
134 | |||
135 | /** |
||
136 | * @return callable |
||
|
|||
137 | */ |
||
138 | 5 | public static function getDefaultRequestFactory() |
|
142 | |||
143 | /** |
||
144 | * @param SapiInterface $sapi |
||
145 | * |
||
146 | * @return ServerRequestInterface |
||
147 | */ |
||
148 | 3 | public static function defaultRequestFactory(SapiInterface $sapi) |
|
162 | |||
163 | /** |
||
164 | * @param Closure $handler |
||
165 | * @param RequestInterface|null $request |
||
166 | * |
||
167 | * @return ResponseInterface |
||
168 | */ |
||
169 | 5 | protected function handleRequest(Closure $handler, RequestInterface $request = null) |
|
176 | |||
177 | /** |
||
178 | * @param int $status |
||
179 | * @param array $headers |
||
180 | * |
||
181 | * @return ResponseInterface |
||
182 | */ |
||
183 | 2 | protected function createEmptyResponse($status = 204, array $headers = []) |
|
189 | |||
190 | /** |
||
191 | * @return RouterInterface |
||
192 | */ |
||
193 | 5 | protected function getRouter() |
|
202 | |||
203 | /** |
||
204 | * @return array |
||
205 | */ |
||
206 | 5 | protected function getCoreConfig() |
|
213 | |||
214 | /** |
||
215 | * @return RouterInterface |
||
216 | */ |
||
217 | 5 | private function createRouter() |
|
236 | |||
237 | /** |
||
238 | * @param ContainerInterface $container |
||
239 | * @param callable[] $configurators |
||
240 | * |
||
241 | * @return void |
||
242 | */ |
||
243 | 2 | private function configureUserContainer(ContainerInterface $container, array $configurators) |
|
249 | |||
250 | /** |
||
251 | * @param SapiInterface $sapi |
||
252 | * @param ContainerInterface $userContainer |
||
253 | * @param callable|null $requestFactory |
||
254 | * |
||
255 | * @return ServerRequestInterface |
||
256 | */ |
||
257 | 4 | private function createRequest( |
|
270 | |||
271 | /** |
||
272 | * @param callable $handler |
||
273 | * @param array $handlerParams |
||
274 | * @param ContainerInterface $container |
||
275 | * |
||
276 | * @return Closure |
||
277 | */ |
||
278 | 3 | private function createOrdinaryTerminalHandler( |
|
287 | |||
288 | /** |
||
289 | * @param array $allowedMethods |
||
290 | * |
||
291 | * @return Closure |
||
292 | */ |
||
293 | 1 | private function createMethodNotAllowedTerminalHandler(array $allowedMethods) |
|
300 | |||
301 | /** |
||
302 | * @return Closure |
||
303 | */ |
||
304 | 1 | private function createNotFoundTerminalHandler() |
|
311 | |||
312 | /** |
||
313 | * @param Closure $handler |
||
314 | * @param ContainerInterface $userContainer |
||
315 | * @param array|null $globalMiddleware |
||
316 | * @param array|null $routeMiddleware |
||
317 | * |
||
318 | * @return Closure |
||
319 | */ |
||
320 | 5 | private function createMiddlewareChain( |
|
331 | |||
332 | /** |
||
333 | * @param Closure $handler |
||
334 | * @param ContainerInterface $userContainer |
||
335 | * @param array|null $middleware |
||
336 | * |
||
337 | * @return Closure |
||
338 | */ |
||
339 | 5 | private function createMiddlewareChainImpl( |
|
351 | |||
352 | /** |
||
353 | * @param Closure $next |
||
354 | * @param callable $middleware |
||
355 | * @param ContainerInterface $userContainer |
||
356 | * |
||
357 | * @return Closure |
||
358 | */ |
||
359 | private function createMiddlewareChainLink(Closure $next, callable $middleware, ContainerInterface $userContainer) |
||
365 | |||
366 | /** |
||
367 | * @param array $config |
||
368 | * @param int|string $key |
||
369 | * @param mixed $default |
||
370 | * |
||
371 | * @return mixed |
||
372 | */ |
||
373 | 5 | private function getValue(array $config, $key, $default) |
|
379 | } |
||
380 |
This check looks for the generic type
array
as a return type and suggests a more specific type. This type is inferred from the actual code.