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\Container; |
||||
13 | |||||
14 | use BlitzPHP\Autoloader\Autoloader; |
||||
15 | use BlitzPHP\Autoloader\Locator; |
||||
16 | use BlitzPHP\Autoloader\LocatorCached; |
||||
17 | use BlitzPHP\Cache\Cache; |
||||
18 | use BlitzPHP\Cache\Handlers\FileVarExportHandler; |
||||
19 | use BlitzPHP\Cache\ResponseCache; |
||||
20 | use BlitzPHP\Config\Config; |
||||
21 | use BlitzPHP\Contracts\Autoloader\LocatorInterface; |
||||
22 | use BlitzPHP\Contracts\Cache\CacheInterface; |
||||
23 | use BlitzPHP\Contracts\Container\ContainerInterface; |
||||
24 | use BlitzPHP\Contracts\Database\ConnectionResolverInterface; |
||||
25 | use BlitzPHP\Contracts\Event\EventManagerInterface; |
||||
26 | use BlitzPHP\Contracts\Mail\MailerInterface; |
||||
27 | use BlitzPHP\Contracts\Router\RouteCollectionInterface; |
||||
28 | use BlitzPHP\Contracts\Router\RouterInterface; |
||||
29 | use BlitzPHP\Contracts\Security\EncrypterInterface; |
||||
30 | use BlitzPHP\Contracts\Security\HasherInterface; |
||||
31 | use BlitzPHP\Contracts\Session\CookieManagerInterface; |
||||
32 | use BlitzPHP\Contracts\Session\SessionInterface; |
||||
33 | use BlitzPHP\Debug\Logger; |
||||
34 | use BlitzPHP\Debug\Timer; |
||||
35 | use BlitzPHP\Debug\Toolbar; |
||||
36 | use BlitzPHP\Event\EventManager; |
||||
37 | use BlitzPHP\Filesystem\Filesystem; |
||||
38 | use BlitzPHP\Filesystem\FilesystemManager; |
||||
39 | use BlitzPHP\Http\Negotiator; |
||||
40 | use BlitzPHP\Http\Redirection; |
||||
41 | use BlitzPHP\Http\Request; |
||||
42 | use BlitzPHP\Http\Response; |
||||
43 | use BlitzPHP\Http\ResponseEmitter; |
||||
44 | use BlitzPHP\Http\ServerRequest; |
||||
45 | use BlitzPHP\Http\ServerRequestFactory; |
||||
46 | use BlitzPHP\Http\Uri; |
||||
47 | use BlitzPHP\Http\UrlGenerator; |
||||
48 | use BlitzPHP\Mail\Mail; |
||||
49 | use BlitzPHP\Router\RouteCollection; |
||||
50 | use BlitzPHP\Router\Router; |
||||
51 | use BlitzPHP\Security\Encryption\Encryption; |
||||
52 | use BlitzPHP\Security\Hashing\Hasher; |
||||
53 | use BlitzPHP\Session\Cookie\Cookie; |
||||
54 | use BlitzPHP\Session\Cookie\CookieManager; |
||||
55 | use BlitzPHP\Session\Handlers\Database as DatabaseSessionHandler; |
||||
56 | use BlitzPHP\Session\Handlers\Database\MySQL as MySQLSessionHandler; |
||||
57 | use BlitzPHP\Session\Handlers\Database\Postgre as PostgreSessionHandler; |
||||
58 | use BlitzPHP\Session\Store; |
||||
59 | use BlitzPHP\Translator\Translate; |
||||
60 | use BlitzPHP\Utilities\Helpers; |
||||
61 | use BlitzPHP\Utilities\String\Text; |
||||
62 | use BlitzPHP\View\Components\ComponentLoader; |
||||
63 | use BlitzPHP\View\View; |
||||
64 | use Psr\Http\Message\UriInterface; |
||||
65 | use Psr\Log\LoggerInterface; |
||||
66 | use stdClass; |
||||
67 | |||||
68 | /** |
||||
69 | * Service |
||||
70 | * |
||||
71 | * Les services sont simplement d'autres classes/bibliothèques que le système utilise |
||||
72 | * pour faire son travail. Ceci est utilisé par BlitzPHP pour permettre au coeur du |
||||
73 | * framework à échanger facilement sans affecter l'utilisation à l'intérieur |
||||
74 | * le reste de votre application. |
||||
75 | * |
||||
76 | * Ceci est utilisé à la place d'un conteneur d'injection de dépendance principalement |
||||
77 | * en raison de sa simplicité, qui permet un meilleur entretien à long terme |
||||
78 | * des applications construites sur BlitzPHP. Un effet secondaire bonus |
||||
79 | * est que les IDE sont capables de déterminer quelle classe vous appelez |
||||
80 | * alors qu'avec les conteneurs DI, il n'y a généralement aucun moyen pour eux de le faire. |
||||
81 | */ |
||||
82 | class Services |
||||
83 | { |
||||
84 | /** |
||||
85 | * Cache des instances des services demander comme instance "partagee". |
||||
86 | * La cle est le FQCN du service. |
||||
87 | */ |
||||
88 | protected static array $instances = []; |
||||
89 | |||||
90 | /** |
||||
91 | * Objets simulés à tester qui sont renvoyés s'ils existent. |
||||
92 | */ |
||||
93 | protected static array $mocks = []; |
||||
94 | |||||
95 | /** |
||||
96 | * Cache d'autres classe de que nous avons trouver via la methode cacheService. |
||||
97 | */ |
||||
98 | protected static array $services = []; |
||||
99 | |||||
100 | /** |
||||
101 | * Avons-nous déjà découvert d'autres Services ? |
||||
102 | */ |
||||
103 | protected static bool $discovered = false; |
||||
104 | |||||
105 | /** |
||||
106 | * Un cache des noms de classes de services trouvés. |
||||
107 | * |
||||
108 | * @var list<string> |
||||
0 ignored issues
–
show
|
|||||
109 | */ |
||||
110 | private static array $serviceNames = []; |
||||
111 | |||||
112 | /** |
||||
113 | * La classe Autoloader permet de charger les fichiers simplement. |
||||
114 | */ |
||||
115 | public static function autoloader(bool $shared = true): Autoloader |
||||
116 | { |
||||
117 | if (true === $shared && isset(static::$instances[Autoloader::class])) { |
||||
118 | 68 | return static::$instances[Autoloader::class]; |
|||
119 | } |
||||
120 | |||||
121 | 2 | $config = static::config()->get('autoload'); |
|||
122 | 2 | $helpers = array_merge(['url'], ($config['helpers'] ?? [])); |
|||
123 | |||||
124 | 2 | return static::$instances[Autoloader::class] = new Autoloader(/** @scrutinizer ignore-type */ $config, $helpers); |
|||
125 | } |
||||
126 | |||||
127 | /** |
||||
128 | * La classe de cache fournit un moyen simple de stocker et de récupérer |
||||
129 | * données complexes pour plus tard |
||||
130 | * |
||||
131 | * @return Cache |
||||
132 | */ |
||||
133 | public static function cache(?array $config = null, bool $shared = true): CacheInterface |
||||
134 | { |
||||
135 | if ($config === null || $config === []) { |
||||
136 | 4 | $config = static::config()->get('cache'); |
|||
137 | } |
||||
138 | |||||
139 | if (true === $shared && isset(static::$instances[Cache::class])) { |
||||
140 | 4 | $instance = static::$instances[Cache::class]; |
|||
141 | if (empty(func_get_args()[0])) { |
||||
142 | 4 | return $instance; |
|||
143 | } |
||||
144 | |||||
145 | 2 | return $instance->setConfig($config); |
|||
146 | } |
||||
147 | |||||
148 | 2 | return static::$instances[Cache::class] = new Cache($config); |
|||
149 | } |
||||
150 | |||||
151 | /** |
||||
152 | * Les composants sont destinées à vous permettre d'insérer du HTML dans la vue |
||||
153 | * qui a été généré par n'importe quel appel dans le système. |
||||
154 | */ |
||||
155 | public static function componentLoader(bool $shared = true): ComponentLoader |
||||
156 | { |
||||
157 | if (true === $shared && isset(static::$instances[ComponentLoader::class])) { |
||||
158 | return static::$instances[ComponentLoader::class]; |
||||
159 | } |
||||
160 | |||||
161 | return static::$instances[ComponentLoader::class] = new ComponentLoader(static::cache()); |
||||
162 | } |
||||
163 | |||||
164 | /** |
||||
165 | * La clase Config offre une api fluide por gerer les configurations de l'application |
||||
166 | */ |
||||
167 | public static function config(bool $shared = true): Config |
||||
168 | { |
||||
169 | if (true === $shared && isset(static::$instances[Config::class])) { |
||||
170 | 210 | return static::$instances[Config::class]; |
|||
171 | } |
||||
172 | |||||
173 | return static::$instances[Config::class] = new Config(); |
||||
174 | } |
||||
175 | |||||
176 | /** |
||||
177 | * Conteneur d'injection de dependances |
||||
178 | * |
||||
179 | * @return Container |
||||
180 | */ |
||||
181 | public static function container(bool $shared = true): ContainerInterface |
||||
182 | { |
||||
183 | if (true === $shared && isset(static::$instances[Container::class])) { |
||||
184 | 81 | return static::$instances[Container::class]; |
|||
185 | } |
||||
186 | |||||
187 | return static::$instances[Container::class] = new Container(); |
||||
188 | } |
||||
189 | |||||
190 | /** |
||||
191 | * Gestionnaire de cookies |
||||
192 | * |
||||
193 | * @return CookieManager |
||||
194 | */ |
||||
195 | public static function cookie(bool $shared = true): CookieManagerInterface |
||||
196 | { |
||||
197 | if (true === $shared && isset(static::$instances[CookieManager::class])) { |
||||
198 | 2 | return static::$instances[CookieManager::class]; |
|||
199 | } |
||||
200 | |||||
201 | 2 | $config = (object) static::config()->get('cookie'); |
|||
202 | |||||
203 | return static::$instances[CookieManager::class] = (new CookieManager())->setDefaultPathAndDomain( |
||||
204 | $config->path ?: '/', |
||||
205 | $config->domain ?: '', |
||||
206 | $config->secure ?: false, |
||||
207 | $config->httponly ?: true, |
||||
208 | $config->samesite ?: 'Lax' |
||||
209 | 2 | ); |
|||
210 | } |
||||
211 | |||||
212 | /** |
||||
213 | * Émetteur de réponse au client |
||||
214 | */ |
||||
215 | public static function emitter(bool $shared = true): ResponseEmitter |
||||
216 | { |
||||
217 | if (true === $shared && isset(static::$instances[ResponseEmitter::class])) { |
||||
218 | 2 | return static::$instances[ResponseEmitter::class]; |
|||
219 | } |
||||
220 | |||||
221 | 2 | return static::$instances[ResponseEmitter::class] = new ResponseEmitter(); |
|||
222 | } |
||||
223 | |||||
224 | /** |
||||
225 | * La classe Encryption fournit un cryptage bidirectionnel. |
||||
226 | * |
||||
227 | * @return Encryption |
||||
228 | */ |
||||
229 | public static function encrypter(?array $config = null, bool $shared = false): EncrypterInterface |
||||
230 | { |
||||
231 | if (true === $shared && isset(static::$instances[Encryption::class])) { |
||||
232 | 2 | return static::$instances[Encryption::class]; |
|||
233 | } |
||||
234 | |||||
235 | 4 | $config ??= config('encryption'); |
|||
236 | 4 | $config = (object) $config; |
|||
237 | 4 | $encryption = new Encryption($config); |
|||
238 | 4 | $encryption->initialize($config); |
|||
239 | |||||
240 | 4 | return static::$instances[Encryption::class] = $encryption; |
|||
241 | } |
||||
242 | |||||
243 | /** |
||||
244 | * Gestionnaire d'evenement |
||||
245 | * |
||||
246 | * @return EventManager |
||||
247 | */ |
||||
248 | public static function event(bool $shared = true): EventManagerInterface |
||||
249 | { |
||||
250 | if (true === $shared && isset(static::$instances[EventManager::class])) { |
||||
251 | 3 | return static::$instances[EventManager::class]; |
|||
252 | } |
||||
253 | |||||
254 | return static::$instances[EventManager::class] = new EventManager(); |
||||
255 | } |
||||
256 | |||||
257 | /** |
||||
258 | * System de gestion de fichier |
||||
259 | */ |
||||
260 | public static function fs(bool $shared = true): Filesystem |
||||
261 | { |
||||
262 | if (true === $shared && isset(static::$instances[Filesystem::class])) { |
||||
263 | 24 | return static::$instances[Filesystem::class]; |
|||
264 | } |
||||
265 | |||||
266 | 2 | return static::$instances[Filesystem::class] = new Filesystem(); |
|||
267 | } |
||||
268 | |||||
269 | /** |
||||
270 | * La classe Encryption fournit un cryptage bidirectionnel. |
||||
271 | * |
||||
272 | * @return Hasher |
||||
273 | */ |
||||
274 | public static function hashing(?array $config = null, bool $shared = true): HasherInterface |
||||
275 | { |
||||
276 | if (true === $shared && isset(static::$instances[Hasher::class])) { |
||||
277 | 4 | return static::$instances[Hasher::class]; |
|||
278 | } |
||||
279 | |||||
280 | 2 | $config ??= config('hashing'); |
|||
281 | 2 | $config = (object) $config; |
|||
282 | 2 | $hasher = new Hasher($config); |
|||
283 | 2 | $hasher->initialize($config); |
|||
284 | |||||
285 | 2 | return static::$instances[Hasher::class] = $hasher; |
|||
286 | } |
||||
287 | |||||
288 | /** |
||||
289 | * Responsable du chargement des traductions des chaînes de langue. |
||||
290 | * |
||||
291 | * @deprecated 0.9 use translators instead |
||||
292 | */ |
||||
293 | public static function language(?string $locale = null, bool $shared = true): Translate |
||||
294 | { |
||||
295 | return static::translator($locale, $shared); |
||||
296 | } |
||||
297 | |||||
298 | /** |
||||
299 | * Le file locator fournit des methodes utilitaire pour chercher les fichiers non-classes dans les dossiers de namespace. |
||||
300 | * C'est une excelente methode pour charger les 'vues', 'helpers', et 'libraries'. |
||||
301 | */ |
||||
302 | public static function locator(bool $shared = true): LocatorInterface |
||||
303 | { |
||||
304 | if ($shared) { |
||||
305 | if (! isset(static::$instances[Locator::class])) { |
||||
306 | 131 | $locator = new Locator(static::autoloader()); |
|||
307 | if (true === config('optimize.locator_cache_enabled', false)) { |
||||
0 ignored issues
–
show
|
|||||
308 | static::$instances[Locator::class] = new LocatorCached($locator, new FileVarExportHandler(FRAMEWORK_STORAGE_PATH . 'cache')); |
||||
309 | } else { |
||||
310 | static::$instances[Locator::class] = $locator; |
||||
311 | } |
||||
312 | } |
||||
313 | |||||
314 | 131 | return static::$instances[Locator::class]; |
|||
315 | } |
||||
316 | |||||
317 | return static::$instances[Locator::class] = new Locator(static::autoloader()); |
||||
318 | } |
||||
319 | |||||
320 | /** |
||||
321 | * La classe Logger est une classe Logging compatible PSR-3 qui prend en charge |
||||
322 | * plusieurs gestionnaires qui traitent la journalisation réelle. |
||||
323 | * |
||||
324 | * @return Logger |
||||
325 | */ |
||||
326 | public static function logger(bool $shared = true): LoggerInterface |
||||
327 | { |
||||
328 | if ($shared && isset(static::$instances[Logger::class])) { |
||||
329 | 43 | return static::$instances[Logger::class]; |
|||
330 | } |
||||
331 | |||||
332 | return static::$instances[Logger::class] = new Logger(); |
||||
333 | } |
||||
334 | |||||
335 | /** |
||||
336 | * La classe de mail vous permet d'envoyer par courrier électronique via mail, sendmail, SMTP. |
||||
337 | * |
||||
338 | * @return Mail |
||||
339 | */ |
||||
340 | public static function mail(?array $config = null, bool $shared = true): MailerInterface |
||||
341 | { |
||||
342 | if ($config === null || $config === []) { |
||||
343 | $config = static::config()->get('mail'); |
||||
344 | } |
||||
345 | |||||
346 | if (true === $shared && isset(static::$instances[Mail::class])) { |
||||
347 | /** @var Mail $instance */ |
||||
348 | $instance = static::$instances[Mail::class]; |
||||
349 | if (empty(func_get_args()[0])) { |
||||
350 | return $instance; |
||||
351 | } |
||||
352 | |||||
353 | return $instance->merge($config); |
||||
354 | } |
||||
355 | |||||
356 | return static::$instances[Mail::class] = new Mail($config); |
||||
357 | } |
||||
358 | |||||
359 | /** |
||||
360 | * La classe Input générale modélise une requête HTTP. |
||||
361 | */ |
||||
362 | public static function negotiator(?ServerRequest $request = null, bool $shared = true): Negotiator |
||||
363 | { |
||||
364 | if ($request === null) { |
||||
365 | $request = static::request(true); |
||||
366 | } |
||||
367 | |||||
368 | if (true === $shared && isset(static::$instances[Negotiator::class])) { |
||||
369 | $instance = static::$instances[Negotiator::class]; |
||||
370 | if (empty(func_get_args()[0])) { |
||||
371 | return $instance; |
||||
372 | } |
||||
373 | |||||
374 | return $instance->setRequest($request); |
||||
375 | } |
||||
376 | |||||
377 | return static::$instances[Negotiator::class] = new Negotiator($request); |
||||
378 | } |
||||
379 | |||||
380 | /** |
||||
381 | * La classe des redirections HTTP |
||||
382 | */ |
||||
383 | public static function redirection(bool $shared = true): Redirection |
||||
384 | { |
||||
385 | if (true === $shared && isset(static::$instances[Redirection::class])) { |
||||
386 | return static::$instances[Redirection::class]; |
||||
387 | } |
||||
388 | |||||
389 | return static::$instances[Redirection::class] = new Redirection(static::factory(UrlGenerator::class)); |
||||
390 | } |
||||
391 | |||||
392 | /** |
||||
393 | * La classe Resquest modélise une reqûete HTTP. |
||||
394 | */ |
||||
395 | public static function request(bool $shared = true): Request |
||||
396 | { |
||||
397 | if (true === $shared && isset(static::$instances[Request::class])) { |
||||
398 | 45 | return static::$instances[Request::class]; |
|||
399 | } |
||||
400 | |||||
401 | 2 | return static::$instances[Request::class] = ServerRequestFactory::fromGlobals(); |
|||
402 | } |
||||
403 | |||||
404 | /** |
||||
405 | * La classe Response modélise une réponse HTTP. |
||||
406 | */ |
||||
407 | public static function response(bool $shared = true): Response |
||||
408 | { |
||||
409 | if (true === $shared && isset(static::$instances[Response::class])) { |
||||
410 | 6 | return static::$instances[Response::class]; |
|||
411 | } |
||||
412 | |||||
413 | 1 | return static::$instances[Response::class] = new Response(); |
|||
414 | } |
||||
415 | |||||
416 | /** |
||||
417 | * CacheResponse |
||||
418 | */ |
||||
419 | public static function responsecache(bool $shared = true): ResponseCache |
||||
420 | { |
||||
421 | if (true === $shared && isset(static::$instances[ResponseCache::class])) { |
||||
422 | return static::$instances[ResponseCache::class]; |
||||
423 | } |
||||
424 | |||||
425 | return static::$instances[ResponseCache::class] = new ResponseCache(static::cache(), /** @scrutinizer ignore-type */ static::config()->get('cache.cache_query_string')); |
||||
426 | } |
||||
427 | |||||
428 | /** |
||||
429 | * Le service Routes est une classe qui permet de construire facilement une collection de routes. |
||||
430 | * |
||||
431 | * @return RouteCollection |
||||
432 | */ |
||||
433 | public static function routes(bool $shared = true): RouteCollectionInterface |
||||
434 | { |
||||
435 | if (true === $shared && isset(static::$instances[RouteCollection::class])) { |
||||
436 | 4 | return static::$instances[RouteCollection::class]; |
|||
437 | } |
||||
438 | |||||
439 | 10 | return static::$instances[RouteCollection::class] = new RouteCollection(static::locator(), (object) static::config()->get('routing')); |
|||
440 | } |
||||
441 | |||||
442 | /** |
||||
443 | * La classe Router utilise le tableau de routes d'une RouteCollection et détermine |
||||
444 | * le contrôleur et la méthode corrects à exécuter. |
||||
445 | * |
||||
446 | * @return Router |
||||
447 | */ |
||||
448 | public static function router(?RouteCollection $routes = null, ?ServerRequest $request = null, bool $shared = true): RouterInterface |
||||
449 | { |
||||
450 | if (true === $shared && isset(static::$instances[Router::class])) { |
||||
451 | 12 | return static::$instances[Router::class]; |
|||
452 | } |
||||
453 | |||||
454 | if ($routes === null) { |
||||
455 | 12 | $routes = static::routes(true); |
|||
456 | } |
||||
457 | if ($request === null) { |
||||
458 | 2 | $request = static::request(true); |
|||
459 | } |
||||
460 | |||||
461 | 12 | return static::$instances[Router::class] = new Router($routes, $request); |
|||
462 | } |
||||
463 | |||||
464 | /** |
||||
465 | * Retourne le gestionnaire de session. |
||||
466 | * |
||||
467 | * @return Store |
||||
468 | */ |
||||
469 | public static function session(bool $shared = true): SessionInterface |
||||
470 | { |
||||
471 | if (true === $shared && isset(static::$instances[Store::class])) { |
||||
472 | 12 | return static::$instances[Store::class]; |
|||
473 | } |
||||
474 | |||||
475 | 21 | $config = static::config()->get('session'); |
|||
476 | 21 | $db = null; |
|||
477 | |||||
478 | if (Text::contains($config['handler'], [DatabaseSessionHandler::class, 'database'])) { |
||||
479 | 21 | $group = $config['group'] ?? static::config()->get('database.connection'); |
|||
480 | $db = static::singleton(ConnectionResolverInterface::class)->connection($group); |
||||
481 | |||||
482 | $driver = $db->getPlatform(); |
||||
483 | |||||
484 | if (Text::contains($driver, ['mysql', MySQLSessionHandler::class])) { |
||||
485 | $config['handler'] = MySQLSessionHandler::class; |
||||
486 | } elseif (Text::contains($driver, ['postgre', PostgreSessionHandler::class])) { |
||||
487 | $config['handler'] = PostgreSessionHandler::class; |
||||
488 | } |
||||
489 | } |
||||
490 | |||||
491 | 21 | Cookie::setDefaults($cookies = /** @scrutinizer ignore-type */ static::config()->get('cookie')); |
|||
0 ignored issues
–
show
It seems like
$cookies = static::config()->get('cookie') can also be of type null ; however, parameter $options of BlitzPHP\Session\Cookie\Cookie::setDefaults() does only seem to accept array , maybe add an additional type check?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
492 | 21 | $session = new Store((array) $config, (array) $cookies, Helpers::ipAddress()); |
|||
493 | 21 | $session->setLogger(static::logger()); |
|||
494 | 21 | $session->setDatabase($db); |
|||
495 | |||||
496 | if (session_status() === PHP_SESSION_NONE) { |
||||
497 | 21 | $session->start(); |
|||
498 | } |
||||
499 | |||||
500 | 21 | return static::$instances[Store::class] = $session; |
|||
501 | } |
||||
502 | |||||
503 | /** |
||||
504 | * System de gestion de fichier par disque |
||||
505 | */ |
||||
506 | public static function storage(bool $shared = true): FilesystemManager |
||||
507 | { |
||||
508 | if ($shared && isset(static::$instances[FilesystemManager::class])) { |
||||
509 | 2 | return static::$instances[FilesystemManager::class]; |
|||
510 | } |
||||
511 | |||||
512 | 2 | return static::$instances[FilesystemManager::class] = new FilesystemManager(/** @scrutinizer ignore-type */ static::config()->get('filesystems')); |
|||
513 | } |
||||
514 | |||||
515 | /** |
||||
516 | * La classe Timer fournit un moyen simple d'évaluer des parties de votre application. |
||||
517 | */ |
||||
518 | public static function timer(bool $shared = true): Timer |
||||
519 | { |
||||
520 | if (true === $shared && isset(static::$instances[Timer::class])) { |
||||
521 | return static::$instances[Timer::class]; |
||||
522 | } |
||||
523 | |||||
524 | return static::$instances[Timer::class] = new Timer(); |
||||
525 | } |
||||
526 | |||||
527 | /** |
||||
528 | * Renvoie la barre d'outils de débogage. |
||||
529 | */ |
||||
530 | public static function toolbar(?stdClass $config = null, bool $shared = true): Toolbar |
||||
531 | { |
||||
532 | if ($shared && isset(static::$instances[Toolbar::class])) { |
||||
533 | return static::$instances[Toolbar::class]; |
||||
534 | } |
||||
535 | |||||
536 | $config ??= (object) static::config()->get('toolbar'); |
||||
537 | |||||
538 | return static::$instances[Toolbar::class] = new Toolbar($config); |
||||
539 | } |
||||
540 | |||||
541 | /** |
||||
542 | * Responsable du chargement des traductions des chaînes de langue. |
||||
543 | */ |
||||
544 | public static function translator(?string $locale = null, bool $shared = true): Translate |
||||
545 | { |
||||
546 | if (null === $locale || $locale === '' || $locale === '0') { |
||||
547 | 64 | $locale = is_cli() ? static::config()->get('app.language') : static::request()->getLocale(); |
|||
548 | } |
||||
549 | |||||
550 | if (true === $shared && isset(static::$instances[Translate::class])) { |
||||
551 | 64 | return static::$instances[Translate::class]->setLocale($locale); |
|||
552 | } |
||||
553 | |||||
554 | 2 | return static::$instances[Translate::class] = new Translate($locale, static::locator()); |
|||
555 | } |
||||
556 | |||||
557 | /** |
||||
558 | * La classe URI fournit un moyen de modéliser et de manipuler les URI. |
||||
559 | * |
||||
560 | * @return Uri |
||||
561 | */ |
||||
562 | public static function uri(?string $uri = null, bool $shared = true): UriInterface |
||||
563 | { |
||||
564 | if (true === $shared && isset(static::$instances[Uri::class])) { |
||||
565 | return static::$instances[Uri::class]->setURI($uri); |
||||
566 | } |
||||
567 | |||||
568 | return static::$instances[Uri::class] = new Uri($uri); |
||||
569 | } |
||||
570 | |||||
571 | /** |
||||
572 | * La classe Renderer est la classe qui affiche réellement un fichier à l'utilisateur. |
||||
573 | * La classe View par défaut dans BlitzPHP est intentionnellement simple, mais |
||||
574 | * le service peut facilement être remplacé par un moteur de modèle si l'utilisateur en a besoin. |
||||
575 | */ |
||||
576 | public static function viewer(bool $shared = true): View |
||||
577 | { |
||||
578 | if (true === $shared && isset(static::$instances[View::class])) { |
||||
579 | 2 | return static::$instances[View::class]; |
|||
580 | } |
||||
581 | |||||
582 | 2 | return static::$instances[View::class] = new View(); |
|||
583 | } |
||||
584 | |||||
585 | /** |
||||
586 | * Offre la possibilité d'effectuer des appels insensibles à la casse des noms de service. |
||||
587 | * |
||||
588 | * @return mixed |
||||
589 | */ |
||||
590 | public static function __callStatic(string $name, array $arguments) |
||||
591 | { |
||||
592 | if (null === $service = static::serviceExists($name)) { |
||||
593 | 24 | return static::discoverServices($name, $arguments); |
|||
594 | } |
||||
595 | |||||
596 | 2 | return $service::$name(...$arguments); |
|||
597 | } |
||||
598 | |||||
599 | /** |
||||
600 | * Vérifiez si le service demandé est défini et renvoyez la classe déclarante. |
||||
601 | * Renvoie null s'il n'est pas trouvé. |
||||
602 | */ |
||||
603 | public static function serviceExists(string $name): ?string |
||||
604 | { |
||||
605 | 26 | static::cacheServices(); |
|||
606 | 26 | $services = array_merge(self::$serviceNames, [self::class]); |
|||
607 | 26 | $name = strtolower($name); |
|||
608 | |||||
609 | foreach ($services as $service) { |
||||
610 | if (method_exists($service, $name)) { |
||||
611 | 2 | return $service; |
|||
612 | } |
||||
613 | } |
||||
614 | |||||
615 | 24 | return null; |
|||
616 | } |
||||
617 | |||||
618 | /** |
||||
619 | * Essaie d'obtenir un service à partir du conteneur |
||||
620 | * |
||||
621 | * @return mixed |
||||
622 | */ |
||||
623 | protected static function discoverServices(string $name, array $arguments) |
||||
624 | { |
||||
625 | if (true !== array_pop($arguments)) { |
||||
626 | 24 | return static::factory($name, $arguments); |
|||
627 | } |
||||
628 | |||||
629 | return static::singleton($name, ...$arguments); |
||||
630 | } |
||||
631 | |||||
632 | protected static function cacheServices(): void |
||||
633 | { |
||||
634 | if (! static::$discovered) { |
||||
635 | 26 | $locator = static::locator(); |
|||
636 | $files = $locator->search('Config/Services'); |
||||
637 | |||||
638 | // Obtenez des instances de toutes les classes de service et mettez-les en cache localement. |
||||
639 | foreach ($files as $file) { |
||||
640 | if (false === $classname = $locator->findQualifiedNameFromPath($file)) { |
||||
641 | continue; |
||||
642 | } |
||||
643 | if (self::class !== $classname) { |
||||
644 | self::$serviceNames[] = $classname; |
||||
645 | static::$services[] = new $classname(); |
||||
646 | } |
||||
647 | } |
||||
648 | |||||
649 | static::$discovered = true; |
||||
650 | } |
||||
651 | } |
||||
652 | |||||
653 | /** |
||||
654 | * Injecter une seule instance de la classe donnée |
||||
655 | * |
||||
656 | * @return mixed |
||||
657 | */ |
||||
658 | public static function singleton(string $name) |
||||
659 | { |
||||
660 | $arguments = func_get_args(); |
||||
661 | $name = array_shift($arguments); |
||||
662 | |||||
663 | if (empty(static::$instances[$name])) { |
||||
664 | static::$instances[$name] = $arguments !== [] ? static::factory($name, $arguments) : static::container()->get($name); |
||||
665 | } |
||||
666 | |||||
667 | return static::$instances[$name]; |
||||
668 | } |
||||
669 | |||||
670 | /** |
||||
671 | * Injecter une nouvelle instance de la classe donnée |
||||
672 | * |
||||
673 | * @return mixed |
||||
674 | */ |
||||
675 | public static function factory(string $name, array $arguments = []) |
||||
676 | { |
||||
677 | 28 | return static::container()->make($name, $arguments); |
|||
678 | } |
||||
679 | |||||
680 | /** |
||||
681 | * Définissez un objet ou une valeur dans le conteneur. |
||||
682 | * |
||||
683 | * @param string $name Nom de l'entrée |
||||
684 | * @param mixed $value utilisez les aides à la définition pour définir les objets |
||||
685 | */ |
||||
686 | public static function set(string $name, $value) |
||||
687 | { |
||||
688 | 48 | static::$instances[$name] = $value; |
|||
689 | 48 | static::container()->set($name, $value); |
|||
690 | } |
||||
691 | |||||
692 | /** |
||||
693 | * Injectez un objet fictif pour les tests. |
||||
694 | * |
||||
695 | * @testTag disponible uniquement pour le code de test |
||||
696 | */ |
||||
697 | public static function injectMock(string $name, object $mock): void |
||||
698 | { |
||||
699 | 3 | static::$mocks[strtolower($name)] = $mock; |
|||
700 | } |
||||
701 | |||||
702 | /** |
||||
703 | * Réinitialisez les instances partagées et les simulations pour les tests. |
||||
704 | * |
||||
705 | * @testTag disponible uniquement pour le code de test |
||||
706 | */ |
||||
707 | public static function reset(bool $initAutoloader = true): void |
||||
708 | { |
||||
709 | static::$mocks = []; |
||||
710 | static::$instances = []; |
||||
711 | |||||
712 | if ($initAutoloader) { |
||||
713 | static::autoloader()->initialize(); |
||||
714 | } |
||||
715 | } |
||||
716 | |||||
717 | /** |
||||
718 | * Réinitialise toutes les instances fictives et partagées pour un seul service. |
||||
719 | * |
||||
720 | * @testTag disponible uniquement pour le code de test |
||||
721 | */ |
||||
722 | public static function resetSingle(string ...$name) |
||||
723 | { |
||||
724 | foreach ($name as $n) { |
||||
725 | unset(static::$mocks[$n], static::$instances[$n]); |
||||
726 | $n = strtolower($n); |
||||
727 | unset(static::$mocks[$n], static::$instances[$n]); |
||||
728 | } |
||||
729 | } |
||||
730 | } |
||||
731 |
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