1 | <?php |
||||
2 | |||||
3 | /** |
||||
4 | * This file is part of Blitz PHP framework. |
||||
5 | * |
||||
6 | * (c) 2022 Dimitri Sitchet Tomkeu <[email protected]> |
||||
7 | * |
||||
8 | * For the full copyright and license information, please view |
||||
9 | * the LICENSE file that was distributed with this source code. |
||||
10 | */ |
||||
11 | |||||
12 | namespace BlitzPHP\Router; |
||||
13 | |||||
14 | use BlitzPHP\Contracts\Router\AutoRouterInterface; |
||||
15 | use BlitzPHP\Exceptions\MethodNotFoundException; |
||||
16 | use BlitzPHP\Exceptions\PageNotFoundException; |
||||
17 | use BlitzPHP\Utilities\Helpers; |
||||
18 | use BlitzPHP\Utilities\String\Text; |
||||
19 | use ReflectionClass; |
||||
20 | use ReflectionException; |
||||
21 | |||||
22 | /** |
||||
23 | * Routeur sécurisé pour le routage automatique |
||||
24 | * |
||||
25 | * @credit <a href="http://www.codeigniter.com">CodeIgniter 4.4 - CodeIgniter\Router\AutoRouterImproved</a> |
||||
26 | */ |
||||
27 | final class AutoRouter implements AutoRouterInterface |
||||
28 | { |
||||
29 | /** |
||||
30 | * Sous-répertoire contenant la classe contrôleur demandée. |
||||
31 | * Principalement utilisé par 'autoRoute'. |
||||
32 | */ |
||||
33 | private ?string $directory = null; |
||||
34 | |||||
35 | /** |
||||
36 | * Le nom de la classe du contrôleur. |
||||
37 | */ |
||||
38 | private string $controller; |
||||
39 | |||||
40 | /** |
||||
41 | * Nom de la méthode à utiliser. |
||||
42 | */ |
||||
43 | private string $method; |
||||
44 | |||||
45 | /** |
||||
46 | * Tableau de paramètres de la méthode du contrôleur. |
||||
47 | * |
||||
48 | * @var list<string> |
||||
0 ignored issues
–
show
|
|||||
49 | */ |
||||
50 | private array $params = []; |
||||
51 | |||||
52 | /** |
||||
53 | * Indique si on doit traduire les tirets de l'URL pour les controleurs/methodes en CamelCase. |
||||
54 | * E.g., blog-controller -> BlogController |
||||
55 | */ |
||||
56 | private readonly bool $translateUriToCamelCase; |
||||
57 | |||||
58 | /** |
||||
59 | * Namespace des controleurs |
||||
60 | */ |
||||
61 | private string $namespace; |
||||
62 | |||||
63 | /** |
||||
64 | * Segments de l'URI |
||||
65 | * |
||||
66 | * @var list<string> |
||||
67 | */ |
||||
68 | private array $segments = []; |
||||
69 | |||||
70 | /** |
||||
71 | * Position du contrôleur dans les segments URI. |
||||
72 | * Null pour le contrôleur par défaut. |
||||
73 | */ |
||||
74 | private ?int $controllerPos = null; |
||||
75 | |||||
76 | /** |
||||
77 | * Position de la méthode dans les segments URI. |
||||
78 | * Null pour la méthode par défaut. |
||||
79 | */ |
||||
80 | private ?int $methodPos = null; |
||||
81 | |||||
82 | /** |
||||
83 | * Position du premier Paramètre dans les segments URI. |
||||
84 | * Null pour les paramètres non definis. |
||||
85 | */ |
||||
86 | private ?int $paramPos = null; |
||||
87 | |||||
88 | /** |
||||
89 | * Carte des segments URI et des namespace. |
||||
90 | * |
||||
91 | * La clé est le premier segment URI. La valeur est le namespace du contrôleur. |
||||
92 | * Ex., |
||||
93 | * [ |
||||
94 | * 'blog' => 'Acme\Blog\Controllers', |
||||
95 | * ] |
||||
96 | * |
||||
97 | * @var array [ uri_segment => namespace ] |
||||
98 | */ |
||||
99 | private array $moduleRoutes; |
||||
100 | |||||
101 | /** |
||||
102 | * URI courant |
||||
103 | */ |
||||
104 | private ?string $uri = null; |
||||
105 | |||||
106 | /** |
||||
107 | * Constructeur |
||||
108 | * |
||||
109 | * @param list<class-string> $protectedControllers Liste des contrôleurs enregistrés pour le verbe CLI qui ne doivent pas être accessibles sur le Web. |
||||
110 | * @param string $namespace Espace de noms par défaut pour les contrôleurs. |
||||
111 | * @param string $defaultController Nom du controleur par defaut. |
||||
112 | * @param string $defaultMethod Nom de la methode par defaut. |
||||
113 | * @param bool $translateURIDashes Indique si les tirets dans les URI doivent être convertis en traits de soulignement lors de la détermination des noms de méthode. |
||||
114 | */ |
||||
115 | public function __construct( |
||||
116 | private readonly array $protectedControllers, |
||||
117 | string $namespace, |
||||
118 | private readonly string $defaultController, |
||||
119 | private readonly string $defaultMethod, |
||||
120 | private readonly bool $translateURIDashes |
||||
121 | ) { |
||||
122 | 4 | $this->namespace = rtrim($namespace, '\\'); |
|||
123 | |||||
124 | 4 | $routingConfig = (object) config('routing'); |
|||
125 | 4 | $this->moduleRoutes = $routingConfig->module_routes; |
|||
126 | 4 | $this->translateUriToCamelCase = $routingConfig->translate_uri_to_camel_case; |
|||
0 ignored issues
–
show
|
|||||
127 | |||||
128 | // Definir les valeurs par defaut |
||||
129 | 4 | $this->controller = $this->defaultController; |
|||
130 | } |
||||
131 | |||||
132 | private function createSegments(string $uri): array |
||||
133 | { |
||||
134 | 4 | $segments = explode('/', $uri); |
|||
135 | 4 | $segments = array_filter($segments, static fn ($segment) => $segment !== ''); |
|||
136 | |||||
137 | // réindexer numériquement le tableau, en supprimant les lacunes |
||||
138 | 4 | return array_values($segments); |
|||
139 | } |
||||
140 | |||||
141 | /** |
||||
142 | * Recherchez le premier contrôleur correspondant au segment URI. |
||||
143 | * |
||||
144 | * S'il y a un contrôleur correspondant au premier segment, la recherche s'arrête là. |
||||
145 | * Les segments restants sont des paramètres du contrôleur. |
||||
146 | * |
||||
147 | * @return bool true si une classe de contrôleur est trouvée. |
||||
148 | */ |
||||
149 | private function searchFirstController(): bool |
||||
150 | { |
||||
151 | 4 | $segments = $this->segments; |
|||
0 ignored issues
–
show
It seems like
$this->segments of type array is incompatible with the declared type BlitzPHP\Router\list of property $segments .
Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property. Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property.. ![]() |
|||||
152 | |||||
153 | 4 | $controller = '\\' . $this->namespace; |
|||
154 | |||||
155 | 4 | $controllerPos = -1; |
|||
156 | |||||
157 | while ($segments !== []) { |
||||
158 | 4 | $segment = array_shift($segments); |
|||
159 | 4 | $controllerPos++; |
|||
160 | |||||
161 | 4 | $class = $this->translateURI($segment); |
|||
162 | |||||
163 | // dès que nous rencontrons un segment qui n'est pas compatible PSR-4, arrêter la recherche |
||||
164 | if (! $this->isValidSegment($class)) { |
||||
165 | return false; |
||||
166 | } |
||||
167 | |||||
168 | 4 | $controller = $this->makeController($controller . '\\' . $class); |
|||
169 | |||||
170 | if (class_exists($controller)) { |
||||
171 | 4 | $this->controller = $controller; |
|||
172 | 4 | $this->controllerPos = $controllerPos; |
|||
173 | |||||
174 | 4 | $this->checkUriForController($controller); |
|||
175 | |||||
176 | // Le premier élément peut être un nom de méthode. |
||||
177 | 4 | $this->params = $segments; |
|||
178 | if ($segments !== []) { |
||||
179 | 2 | $this->paramPos = $this->controllerPos + 1; |
|||
180 | } |
||||
181 | |||||
182 | 4 | return true; |
|||
183 | } |
||||
184 | } |
||||
185 | |||||
186 | 2 | return false; |
|||
187 | } |
||||
188 | |||||
189 | /** |
||||
190 | * Recherchez le dernier contrôleur par défaut correspondant aux segments URI. |
||||
191 | * |
||||
192 | * @return bool true si une classe de contrôleur est trouvée. |
||||
193 | */ |
||||
194 | private function searchLastDefaultController(): bool |
||||
195 | { |
||||
196 | 2 | $segments = $this->segments; |
|||
0 ignored issues
–
show
It seems like
$this->segments of type array is incompatible with the declared type BlitzPHP\Router\list of property $segments .
Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property. Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property.. ![]() |
|||||
197 | |||||
198 | 2 | $segmentCount = count($this->segments); |
|||
199 | 2 | $paramPos = null; |
|||
200 | 2 | $params = []; |
|||
201 | |||||
202 | while ($segments !== []) { |
||||
203 | if ($segmentCount > count($segments)) { |
||||
204 | $paramPos = count($segments); |
||||
205 | } |
||||
206 | |||||
207 | $namespaces = array_map( |
||||
208 | fn ($segment) => $this->translateURI($segment), |
||||
209 | $segments |
||||
210 | ); |
||||
211 | |||||
212 | $controller = '\\' . $this->namespace |
||||
213 | . '\\' . implode('\\', $namespaces) |
||||
214 | . '\\' . $this->defaultController; |
||||
215 | |||||
216 | if (class_exists($controller)) { |
||||
217 | $this->controller = $controller; |
||||
218 | $this->params = $params; |
||||
0 ignored issues
–
show
It seems like
$params of type array is incompatible with the declared type BlitzPHP\Router\list of property $params .
Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property. Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property.. ![]() |
|||||
219 | |||||
220 | if ($params !== []) { |
||||
221 | $this->paramPos = $paramPos; |
||||
222 | } |
||||
223 | |||||
224 | return true; |
||||
225 | } |
||||
226 | |||||
227 | // ajoutons le dernier élément dans $segments au début de $params. |
||||
228 | array_unshift($params, array_pop($segments)); |
||||
229 | } |
||||
230 | |||||
231 | // Vérifiez le contrôleur par défaut dans le répertoire des contrôleurs. |
||||
232 | $controller = '\\' . $this->namespace |
||||
233 | 2 | . '\\' . $this->defaultController; |
|||
234 | |||||
235 | if (class_exists($controller)) { |
||||
236 | 2 | $this->controller = $controller; |
|||
237 | 2 | $this->params = $params; |
|||
238 | |||||
239 | if ($params !== []) { |
||||
240 | $this->paramPos = 0; |
||||
241 | } |
||||
242 | |||||
243 | 2 | return true; |
|||
244 | } |
||||
245 | |||||
246 | return false; |
||||
247 | } |
||||
248 | |||||
249 | /** |
||||
250 | * Recherche contrôleur, méthode et params dans l'URI. |
||||
251 | * |
||||
252 | * @return array [directory_name, controller_name, controller_method, params] |
||||
253 | */ |
||||
254 | public function getRoute(string $uri, string $httpVerb): array |
||||
255 | { |
||||
256 | 4 | $this->uri = $uri; |
|||
257 | 4 | $httpVerb = strtolower($httpVerb); |
|||
258 | |||||
259 | // Reinitialise les parametres de la methode du controleur. |
||||
260 | 4 | $this->params = []; |
|||
0 ignored issues
–
show
It seems like
array() of type array is incompatible with the declared type BlitzPHP\Router\list of property $params .
Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property. Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property.. ![]() |
|||||
261 | |||||
262 | 4 | $defaultMethod = $httpVerb . ucfirst($this->defaultMethod); |
|||
263 | 4 | $this->method = $defaultMethod; |
|||
264 | |||||
265 | 4 | $this->segments = $this->createSegments($uri); |
|||
0 ignored issues
–
show
It seems like
$this->createSegments($uri) of type array is incompatible with the declared type BlitzPHP\Router\list of property $segments .
Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property. Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property.. ![]() |
|||||
266 | |||||
267 | // Verifier les routes de modules |
||||
268 | if ($this->segments !== [] && array_key_exists($this->segments[0], $this->moduleRoutes)) { |
||||
269 | 2 | $uriSegment = array_shift($this->segments); |
|||
270 | 2 | $this->namespace = rtrim($this->moduleRoutes[$uriSegment], '\\'); |
|||
271 | } |
||||
272 | |||||
273 | if ($this->searchFirstController()) { |
||||
274 | // Le contrôleur a ete trouvé. |
||||
275 | 4 | $baseControllerName = Helpers::classBasename($this->controller); |
|||
276 | |||||
277 | // Empêcher l'accès au chemin de contrôleur par défaut |
||||
278 | if (strtolower($baseControllerName) === strtolower($this->defaultController)) { |
||||
279 | throw new PageNotFoundException( |
||||
280 | 'Impossible d\'accéder au contrôleur par défaut "' . $this->controller . '" avec le nom du contrôleur comme chemin de l\'URI.' |
||||
281 | 4 | ); |
|||
282 | } |
||||
283 | } elseif ($this->searchLastDefaultController()) { |
||||
284 | // Le controleur par defaut a ete trouve. |
||||
285 | 2 | $baseControllerName = Helpers::classBasename($this->controller); |
|||
286 | } else { |
||||
287 | // Aucun controleur trouvé |
||||
288 | throw new PageNotFoundException('Aucun contrôleur trouvé pour: ' . $uri); |
||||
289 | } |
||||
290 | |||||
291 | // Le premier élément peut être un nom de méthode. |
||||
292 | /** @var list<string> $params */ |
||||
293 | 4 | $params = $this->params; |
|||
294 | |||||
295 | 4 | $methodParam = array_shift($params); |
|||
0 ignored issues
–
show
$params of type BlitzPHP\Router\list is incompatible with the type array expected by parameter $array of array_shift() .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
296 | |||||
297 | 4 | $method = ''; |
|||
298 | if ($methodParam !== null) { |
||||
299 | 2 | $method = $httpVerb . $this->translateURI($methodParam); |
|||
300 | |||||
301 | 2 | $this->checkUriForMethod($method); |
|||
302 | } |
||||
303 | |||||
304 | if ($methodParam !== null && method_exists($this->controller, $method)) { |
||||
305 | // Methode trouvee. |
||||
306 | 2 | $this->method = $method; |
|||
307 | 2 | $this->params = $params; |
|||
308 | |||||
309 | // Mise a jour des positions. |
||||
310 | 2 | $this->methodPos = $this->paramPos; |
|||
311 | if ($params === []) { |
||||
312 | 2 | $this->paramPos = null; |
|||
313 | } |
||||
314 | if ($this->paramPos !== null) { |
||||
315 | 2 | $this->paramPos++; |
|||
316 | } |
||||
317 | |||||
318 | // Empêcher l'accès à la méthode du contrôleur par défaut |
||||
319 | if (strtolower($baseControllerName) === strtolower($this->defaultController)) { |
||||
320 | throw new PageNotFoundException( |
||||
321 | 'Impossible d\'accéder au contrôleur par défaut "' . $this->controller . '::' . $this->method . '"' |
||||
322 | 2 | ); |
|||
323 | } |
||||
324 | |||||
325 | // Empêcher l'accès au chemin de méthode par défaut |
||||
326 | if (strtolower($this->method) === strtolower($defaultMethod)) { |
||||
327 | throw new PageNotFoundException( |
||||
328 | 'Impossible d\'accéder à la méthode par défaut "' . $this->method . '" avec le nom de méthode comme chemin d\'URI.' |
||||
329 | 2 | ); |
|||
330 | } |
||||
331 | } elseif (method_exists($this->controller, $defaultMethod)) { |
||||
332 | // La methode par defaut a ete trouvée |
||||
333 | 4 | $this->method = $defaultMethod; |
|||
334 | } else { |
||||
335 | // Aucune methode trouvee |
||||
336 | throw PageNotFoundException::controllerNotFound($this->controller, $method); |
||||
337 | } |
||||
338 | |||||
339 | // Vérifiez le contrôleur n'est pas défini dans les routes. |
||||
340 | 4 | $this->protectDefinedRoutes(); |
|||
341 | |||||
342 | // Assurez-vous que le contrôleur n'a pas la méthode _remap(). |
||||
343 | 4 | $this->checkRemap(); |
|||
344 | |||||
345 | // Assurez-vous que les segments URI pour le contrôleur et la méthode |
||||
346 | // ne contiennent pas de soulignement lorsque $translateURIDashes est true. |
||||
347 | 4 | $this->checkUnderscore(); |
|||
348 | |||||
349 | // Verifier le nombre de parametres |
||||
350 | try { |
||||
351 | 4 | $this->checkParameters(); |
|||
352 | } catch (MethodNotFoundException) { |
||||
353 | 2 | throw PageNotFoundException::controllerNotFound($this->controller, $this->method); |
|||
354 | } |
||||
355 | |||||
356 | 4 | $this->setDirectory(); |
|||
357 | |||||
358 | 4 | return [$this->directory, $this->controllerName(), $this->methodName(), $this->params]; |
|||
359 | } |
||||
360 | |||||
361 | /** |
||||
362 | * @internal Juste pour les tests. |
||||
363 | * |
||||
364 | * @return array<string, int|null> |
||||
365 | */ |
||||
366 | public function getPos(): array |
||||
367 | { |
||||
368 | return [ |
||||
369 | 'controller' => $this->controllerPos, |
||||
370 | 'method' => $this->methodPos, |
||||
371 | 'params' => $this->paramPos, |
||||
372 | 2 | ]; |
|||
373 | } |
||||
374 | |||||
375 | private function checkParameters(): void |
||||
376 | { |
||||
377 | try { |
||||
378 | 4 | $refClass = new ReflectionClass($this->controller); |
|||
379 | } catch (ReflectionException) { |
||||
380 | throw PageNotFoundException::controllerNotFound($this->controller, $this->method); |
||||
381 | } |
||||
382 | |||||
383 | try { |
||||
384 | 4 | $refMethod = $refClass->getMethod($this->method); |
|||
385 | 4 | $refParams = $refMethod->getParameters(); |
|||
386 | } catch (ReflectionException) { |
||||
387 | throw new MethodNotFoundException(); |
||||
388 | } |
||||
389 | |||||
390 | if (! $refMethod->isPublic()) { |
||||
391 | 4 | throw new MethodNotFoundException(); |
|||
392 | } |
||||
393 | |||||
394 | if (count($refParams) < count($this->params)) { |
||||
395 | throw new PageNotFoundException( |
||||
396 | 'Le nombre de param dans l\'URI est supérieur aux paramètres de la méthode du contrôleur.' |
||||
397 | . ' Handler:' . $this->controller . '::' . $this->method |
||||
398 | . ', URI:' . $this->uri |
||||
399 | 4 | ); |
|||
400 | } |
||||
401 | } |
||||
402 | |||||
403 | private function checkRemap(): void |
||||
404 | { |
||||
405 | try { |
||||
406 | 4 | $refClass = new ReflectionClass($this->controller); |
|||
407 | 4 | $refClass->getMethod('_remap'); |
|||
408 | |||||
409 | throw new PageNotFoundException( |
||||
410 | 'AutoRouterImproved ne prend pas en charge la methode `_remap()`.' |
||||
411 | . ' Contrôleur:' . $this->controller |
||||
412 | ); |
||||
413 | } catch (ReflectionException) { |
||||
414 | // Ne rien faire |
||||
415 | } |
||||
416 | } |
||||
417 | |||||
418 | private function checkUnderscore(): void |
||||
419 | { |
||||
420 | if ($this->translateURIDashes === false) { |
||||
421 | return; |
||||
422 | } |
||||
423 | |||||
424 | 4 | $paramPos = $this->paramPos ?? count($this->segments); |
|||
425 | |||||
426 | 4 | for ($i = 0; $i < $paramPos; $i++) { |
|||
427 | if (str_contains($this->segments[$i], '_')) { |
||||
428 | throw new PageNotFoundException( |
||||
429 | 'AutoRouterImproved interdit l\'accès à l\'URI' |
||||
430 | . ' contenant les undescore ("' . $this->segments[$i] . '")' |
||||
431 | . ' quand $translate_uri_dashes est activé.' |
||||
432 | . ' Veuillez utiliser les tiret.' |
||||
433 | . ' Handler:' . $this->controller . '::' . $this->method |
||||
434 | . ', URI:' . $this->uri |
||||
435 | 4 | ); |
|||
436 | } |
||||
437 | } |
||||
438 | } |
||||
439 | |||||
440 | /** |
||||
441 | * Vérifier l'URI du contrôleur pour $translateUriToCamelCase |
||||
442 | * |
||||
443 | * @param string $classname Nom de classe du contrôleur généré à partir de l'URI. |
||||
444 | * La casse peut être un peu incorrecte. |
||||
445 | */ |
||||
446 | private function checkUriForController(string $classname): void |
||||
447 | { |
||||
448 | if ($this->translateUriToCamelCase === false) { |
||||
449 | 4 | return; |
|||
450 | } |
||||
451 | |||||
452 | if (! in_array(ltrim($classname, '\\'), get_declared_classes(), true)) { |
||||
453 | throw new PageNotFoundException( |
||||
454 | '"' . $classname . '" n\'a pas été trouvé.' |
||||
455 | ); |
||||
456 | } |
||||
457 | } |
||||
458 | |||||
459 | /** |
||||
460 | * Vérifier l'URI pour la méthode $translateUriToCamelCase |
||||
461 | * |
||||
462 | * @param string $method Nom de la méthode du contrôleur généré à partir de l'URI. |
||||
463 | * La casse peut être un peu incorrecte. |
||||
464 | */ |
||||
465 | private function checkUriForMethod(string $method): void |
||||
466 | { |
||||
467 | if ($this->translateUriToCamelCase === false) { |
||||
468 | 2 | return; |
|||
469 | } |
||||
470 | |||||
471 | if ( |
||||
472 | // Par exemple, si `getSomeMethod()` existe dans le contrôleur, seul l'URI `controller/some-method` devrait être accessible. |
||||
473 | // Mais si un visiteur navigue vers l'URI `controller/somemethod`, `getSomemethod()` sera vérifié, et `method_exists()` retournera true parce que les noms de méthodes en PHP sont insensibles à la casse. |
||||
474 | method_exists($this->controller, $method) |
||||
475 | // Mais nous n'autorisons pas `controller/somemethod`, donc vérifiez le nom exact de la méthode. |
||||
476 | && ! in_array($method, get_class_methods($this->controller), true) |
||||
477 | ) { |
||||
478 | throw new PageNotFoundException( |
||||
479 | '"' . $this->controller . '::' . $method . '()" n\'a pas été trouvé.' |
||||
480 | ); |
||||
481 | } |
||||
482 | } |
||||
483 | |||||
484 | /** |
||||
485 | * Renvoie true si la chaîne $segment fournie représente un segment d'espace de noms/répertoire valide conforme à PSR-4 |
||||
486 | * |
||||
487 | * La regex vient de https://www.php.net/manual/en/language.variables.basics.php |
||||
488 | */ |
||||
489 | private function isValidSegment(string $segment): bool |
||||
490 | { |
||||
491 | 4 | return (bool) preg_match('/^[a-zA-Z_\x80-\xff][a-zA-Z0-9_\x80-\xff]*$/', $segment); |
|||
492 | } |
||||
493 | |||||
494 | private function translateURI(string $segment): string |
||||
495 | { |
||||
496 | if ($this->translateUriToCamelCase) { |
||||
497 | if (strtolower($segment) !== $segment) { |
||||
498 | throw new PageNotFoundException( |
||||
499 | 'AutoRouter interdit l\'accès à l\'URI' |
||||
500 | . ' contenant des lettres majuscules ("' . $segment . '")' |
||||
501 | . ' lorsque $translateUriToCamelCase est activé.' |
||||
502 | . ' Veuillez utiliser le tiret.' |
||||
503 | . ' URI:' . $this->uri |
||||
504 | ); |
||||
505 | } |
||||
506 | |||||
507 | if (str_contains($segment, '--')) { |
||||
508 | throw new PageNotFoundException( |
||||
509 | 'AutoRouter interdit l\'accès à l\'URI' |
||||
510 | . ' contenant un double tiret ("' . $segment . '")' |
||||
511 | . ' lorsque $translateUriToCamelCase est activé.' |
||||
512 | . ' Veuillez utiliser le tiret simple.' |
||||
513 | . ' URI:' . $this->uri |
||||
514 | ); |
||||
515 | } |
||||
516 | |||||
517 | return str_replace( |
||||
518 | ' ', |
||||
519 | '', |
||||
520 | ucwords( |
||||
521 | preg_replace('/[\-]+/', ' ', $segment) |
||||
522 | ) |
||||
523 | ); |
||||
524 | } |
||||
525 | |||||
526 | 4 | $segment = ucfirst($segment); |
|||
527 | |||||
528 | if ($this->translateURIDashes) { |
||||
529 | 4 | return str_replace('-', '_', $segment); |
|||
530 | } |
||||
531 | |||||
532 | return $segment; |
||||
533 | } |
||||
534 | |||||
535 | /** |
||||
536 | * Obtenez le chemin du dossier du contrôleur et définissez-le sur la propriété. |
||||
537 | */ |
||||
538 | private function setDirectory(): void |
||||
539 | { |
||||
540 | 4 | $segments = explode('\\', trim($this->controller, '\\')); |
|||
541 | |||||
542 | // Supprimer le court nom de classe. |
||||
543 | 4 | array_pop($segments); |
|||
544 | |||||
545 | 4 | $namespaces = implode('\\', $segments); |
|||
546 | |||||
547 | $dir = str_replace( |
||||
548 | '\\', |
||||
549 | '/', |
||||
550 | ltrim(substr($namespaces, strlen($this->namespace)), '\\') |
||||
551 | 4 | ); |
|||
552 | |||||
553 | if ($dir !== '') { |
||||
554 | 4 | $this->directory = $dir . '/'; |
|||
555 | } |
||||
556 | } |
||||
557 | |||||
558 | private function protectDefinedRoutes(): void |
||||
559 | { |
||||
560 | 4 | $controller = strtolower($this->controller); |
|||
561 | |||||
562 | foreach ($this->protectedControllers as $controllerInRoutes) { |
||||
563 | 4 | $routeLowerCase = strtolower($controllerInRoutes); |
|||
564 | |||||
565 | if ($routeLowerCase === $controller) { |
||||
566 | throw new PageNotFoundException( |
||||
567 | 'Impossible d\'accéder à un contrôleur définie dans les routes. Contrôleur : ' . $controllerInRoutes |
||||
568 | ); |
||||
569 | } |
||||
570 | } |
||||
571 | } |
||||
572 | |||||
573 | /** |
||||
574 | * Renvoie le nom du sous-répertoire dans lequel se trouve le contrôleur. |
||||
575 | * Relatif à CONTROLLER_PATH |
||||
576 | * |
||||
577 | * @deprecated 1.0 |
||||
578 | */ |
||||
579 | public function directory(): string |
||||
580 | { |
||||
581 | return $this->directory !== null && $this->directory !== '' && $this->directory !== '0' ? $this->directory : ''; |
||||
582 | } |
||||
583 | |||||
584 | /** |
||||
585 | * Renvoie le nom du contrôleur matché |
||||
586 | */ |
||||
587 | private function controllerName(): string |
||||
588 | { |
||||
589 | return $this->translateURIDashes |
||||
590 | ? str_replace('-', '_', trim($this->controller, '/\\')) |
||||
591 | 4 | : Text::convertTo($this->controller, 'pascal'); |
|||
592 | } |
||||
593 | |||||
594 | /** |
||||
595 | * Retourne le nom de la méthode à exécuter |
||||
596 | */ |
||||
597 | private function methodName(): string |
||||
598 | { |
||||
599 | return $this->translateURIDashes |
||||
600 | ? str_replace('-', '_', $this->method) |
||||
601 | 4 | : Text::convertTo($this->method, 'camel'); |
|||
602 | } |
||||
603 | |||||
604 | /** |
||||
605 | * Construit un nom de contrôleur valide |
||||
606 | */ |
||||
607 | public function makeController(string $name): string |
||||
608 | { |
||||
609 | return preg_replace( |
||||
610 | ['#(\_)?Controller$#i', '#' . config('app.url_suffix') . '$#i'], |
||||
0 ignored issues
–
show
Are you sure
config('app.url_suffix') of type T|null|object can be used in concatenation ?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
611 | '', |
||||
612 | ucfirst($name) |
||||
613 | 4 | ) . 'Controller'; |
|||
614 | } |
||||
615 | } |
||||
616 |
The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g.
excluded_paths: ["lib/*"]
, you can move it to the dependency path list as follows:For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths