Passed
Push — main ( 172c86...5eb528 )
by Dimitri
03:20
created

Services::session()   B

Complexity

Conditions 7
Paths 9

Size

Total Lines 32
Code Lines 19

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 7
eloc 19
c 1
b 0
f 0
nc 9
nop 1
dl 0
loc 32
rs 8.8333
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\Cache\Cache;
17
use BlitzPHP\Config\Config;
18
use BlitzPHP\Config\Database as DatabaseConfig;
19
use BlitzPHP\Debug\Logger;
20
use BlitzPHP\Debug\Timer;
21
use BlitzPHP\Debug\Toolbar;
22
use BlitzPHP\Event\EventManager;
23
use BlitzPHP\Filesystem\Filesystem;
24
use BlitzPHP\Filesystem\FilesystemManager;
25
use BlitzPHP\Http\Negotiator;
26
use BlitzPHP\HTTP\Redirection;
27
use BlitzPHP\Http\Request;
28
use BlitzPHP\Http\Response;
29
use BlitzPHP\Http\ResponseEmitter;
30
use BlitzPHP\Http\ServerRequest;
31
use BlitzPHP\Http\Uri;
32
use BlitzPHP\HttpClient\Request as ClientRequest;
0 ignored issues
show
Bug introduced by
The type BlitzPHP\HttpClient\Request was not found. Maybe you did not declare it correctly or list all dependencies?

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:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
33
use BlitzPHP\Mail\Mail;
34
use BlitzPHP\Router\RouteCollection;
35
use BlitzPHP\Router\Router;
36
use BlitzPHP\Session\Cookie\Cookie;
37
use BlitzPHP\Session\Handlers\Database as DatabaseSessionHandler;
38
use BlitzPHP\Session\Handlers\Database\MySQL as MySQLSessionHandler;
39
use BlitzPHP\Session\Handlers\Database\Postgre as PostgreSessionHandler;
40
use BlitzPHP\Session\Session;
41
use BlitzPHP\Translator\Translate;
42
use BlitzPHP\Utilities\Helpers;
43
use BlitzPHP\Utilities\String\Text;
44
use BlitzPHP\View\View;
45
use DI\NotFoundException;
46
use stdClass;
47
48
/**
49
 * Service
50
 *
51
 * Les services sont simplement d'autres classes/bibliothèques que le système utilise
52
 * pour faire son travail. Ceci est utilisé par BlitzPHP pour permettre au coeur du
53
 * framework à échanger facilement sans affecter l'utilisation à l'intérieur
54
 * le reste de votre application.
55
 *
56
 * Ceci est utilisé à la place d'un conteneur d'injection de dépendance principalement
57
 * en raison de sa simplicité, qui permet un meilleur entretien à long terme
58
 * des applications construites sur BlitzPHP. Un effet secondaire bonus
59
 * est que les IDE sont capables de déterminer quelle classe vous appelez
60
 * alors qu'avec les conteneurs DI, il n'y a généralement aucun moyen pour eux de le faire.
61
 */
62
class Services
63
{
64
    /**
65
     * Cache des instances des services demander comme instance "partagee".
66
     * La cle est le FQCN du service.
67
     */
68
    protected static array $instances = [];
69
70
    /**
71
     * Cache d'autres classe de que nous avons trouver via la methode discoverService.
72
     */
73
    protected static array $services = [];
74
75
    /**
76
     * @return Injector
77
     */
78
    public static function injector()
79
    {
80
        return Injector::instance();
81
    }
82
83
    /**
84
     * @return \DI\Container
85
     */
86
    public static function container()
87
    {
88
        return Injector::container();
89
    }
90
91
    /**
92
     * La classe Autoloader permet de charger les fichiers simplement.
93
     */
94
    public static function autoloader(bool $shared = true): Autoloader
95
    {
96
        if (true === $shared && isset(static::$instances[Autoloader::class])) {
97
            return static::$instances[Autoloader::class];
98
        }
99
100
        $config  = Config::get('autoload');
101
        $helpers = array_merge(['url'], ($config['helpers'] ?? []));
102
103
        return static::$instances[Autoloader::class] = static::factory(Autoloader::class, compact('config', 'helpers'));
104
    }
105
106
    /**
107
     * La classe de cache fournit un moyen simple de stocker et de récupérer
108
     * données complexes pour plus tard
109
     */
110
    public static function cache(?array $config = null, bool $shared = true): Cache
111
    {
112
        if (empty($config)) {
113
            $config = Config::get('cache');
114
        }
115
116
        if (true === $shared && isset(static::$instances[Cache::class])) {
117
            $instance = static::$instances[Cache::class];
118
            if (empty(func_get_args()[0])) {
119
                return $instance;
120
            }
121
122
            return $instance->setConfig($config);
123
        }
124
125
        return static::$instances[Cache::class] = static::factory(Cache::class, compact('config'));
126
    }
127
128
    /**
129
     * Émetteur de réponse au client
130
     */
131
    public static function emitter(bool $shared = true): ResponseEmitter
132
    {
133
        if (true === $shared && isset(static::$instances[ResponseEmitter::class])) {
134
            return static::$instances[ResponseEmitter::class];
135
        }
136
137
        return static::$instances[ResponseEmitter::class] = static::factory(ResponseEmitter::class);
138
    }
139
140
    /**
141
     * Gestionnaire d'evenement
142
     */
143
    public static function event(bool $shared = true): EventManager
144
    {
145
        if (true === $shared && isset(static::$instances[EventManager::class])) {
146
            return static::$instances[EventManager::class];
147
        }
148
149
        return static::$instances[EventManager::class] = static::factory(EventManager::class);
150
    }
151
152
    /**
153
     * System de gestion de fichier
154
     */
155
    public static function fs(bool $shared = true): Filesystem
156
    {
157
        if (true === $shared && isset(static::$instances[Filesystem::class])) {
158
            return static::$instances[Filesystem::class];
159
        }
160
161
        return static::$instances[Filesystem::class] = static::factory(Filesystem::class);
162
    }
163
164
    /**
165
     * Le client HTTP fourni une interface simple pour interagir avec d'autres serveurs.
166
     * Typiquement a traver des APIs.
167
     */
168
    public static function httpclient(?string $baseUrl = null, bool $shared = true): ClientRequest
169
    {
170
        if (true === $shared && isset(static::$instances[ClientRequest::class])) {
171
            return static::$instances[ClientRequest::class]->baseUrl((string) $baseUrl);
172
        }
173
174
        return static::$instances[ClientRequest::class] = static::factory(ClientRequest::class, ['event' => static::event()])->baseUrl((string) $baseUrl);
175
    }
176
177
    /**
178
     * Responsable du chargement des traductions des chaînes de langue.
179
     */
180
    public static function language(?string $locale = null, bool $shared = true): Translate
181
    {
182
        if (empty($locale)) {
183
            if (empty($locale = static::$instances[Translate::class . 'locale'] ?? null)) {
184
                $config = Config::get('app');
185
186
                if (empty($locale = static::negotiator()->language($config['supported_locales']))) {
187
                    $locale = $config['language'];
188
                }
189
190
                static::$instances[Translate::class . 'locale'] = $locale;
191
            }
192
        }
193
194
        if (true === $shared && isset(static::$instances[Translate::class])) {
195
            return static::$instances[Translate::class]->setLocale($locale);
196
        }
197
198
        return static::$instances[Translate::class] = static::factory(Translate::class, ['locale' => $locale, 'locator' => static::locator()]);
199
    }
200
201
    /**
202
     * Le file locator fournit des methodes utilitaire pour chercher les fichiers non-classes
203
     * dans les dossiers de namespace. C'est une excelente methode pour charger les 'vues', 'helpers', et 'libraries'.
204
     */
205
    public static function locator(bool $shared = true): Locator
206
    {
207
        if ($shared && isset(static::$instances[Locator::class])) {
208
            return static::$instances[Locator::class];
209
        }
210
211
        return static::$instances[Locator::class] = static::factory(Locator::class, ['autoloader' => static::autoloader()]);
212
    }
213
214
    /**
215
     * La classe Logger est une classe Logging compatible PSR-3 qui prend en charge
216
     * plusieurs gestionnaires qui traitent la journalisation réelle.
217
     */
218
    public static function logger(bool $shared = true): Logger
219
    {
220
        if ($shared && isset(static::$instances[Logger::class])) {
221
            return static::$instances[Logger::class];
222
        }
223
224
        return static::$instances[Logger::class] = static::factory(Logger::class);
225
    }
226
227
    /**
228
     * La classe de mail vous permet d'envoyer par courrier électronique via mail, sendmail, SMTP.
229
     */
230
    public static function mail(?array $config = null, bool $shared = true): Mail
231
    {
232
        if (empty($config)) {
233
            $config = Config::get('mail');
234
        }
235
236
        if (true === $shared && isset(static::$instances[Mail::class])) {
237
            /** @var Mail $instance */
238
            $instance = static::$instances[Mail::class];
239
            if (empty(func_get_args()[0])) {
240
                return $instance;
241
            }
242
243
            return $instance->merge($config);
244
        }
245
246
        return static::$instances[Mail::class] = static::factory(Mail::class, compact('config'));
247
    }
248
249
    /**
250
     * La classe Input générale modélise une requête HTTP.
251
     */
252
    public static function negotiator(?ServerRequest $request = null, bool $shared = true): Negotiator
253
    {
254
        if (empty($request)) {
255
            $request = static::request(true);
256
        }
257
258
        if (true === $shared && isset(static::$instances[Negotiator::class])) {
259
            $instance = static::$instances[Negotiator::class];
260
            if (empty(func_get_args()[0])) {
261
                return $instance;
262
            }
263
264
            return $instance->setRequest($request);
265
        }
266
267
        return static::$instances[Negotiator::class] = static::factory(Negotiator::class, compact('request'));
268
    }
269
270
    /**
271
     * La classe des redirections HTTP
272
     */
273
    public static function redirection(bool $shared = true): Redirection
274
    {
275
        if (true === $shared && isset(static::$instances[Redirection::class])) {
276
            return static::$instances[Redirection::class];
277
        }
278
279
        return static::$instances[Redirection::class] = static::factory(Redirection::class);
280
    }
281
282
    /**
283
     * La classe Resquest modélise une reqûete HTTP.
284
     */
285
    public static function request(bool $shared = true): Request
286
    {
287
        if (true === $shared && isset(static::$instances[Request::class])) {
288
            return static::$instances[Request::class];
289
        }
290
291
        return static::$instances[Request::class] = static::factory(Request::class);
292
    }
293
294
    /**
295
     * La classe Response modélise une réponse HTTP.
296
     */
297
    public static function response(bool $shared = true): Response
298
    {
299
        if (true === $shared && isset(static::$instances[Response::class])) {
300
            return static::$instances[Response::class];
301
        }
302
303
        return static::$instances[Response::class] = static::factory(Response::class);
304
    }
305
306
    /**
307
     * Le service Routes est une classe qui permet de construire facilement
308
     * une collection d'itinéraires.
309
     */
310
    public static function routes(bool $shared = true): RouteCollection
311
    {
312
        if (true === $shared && isset(static::$instances[RouteCollection::class])) {
313
            return static::$instances[RouteCollection::class];
314
        }
315
316
        return static::$instances[RouteCollection::class] = static::factory(RouteCollection::class);
317
    }
318
319
    /**
320
     * La classe Router utilise le tableau de routes d'une RouteCollection et détermine
321
     * le contrôleur et la méthode corrects à exécuter.
322
     */
323
    public static function router(?RouteCollection $routes = null, ?ServerRequest $request = null, bool $shared = true): Router
324
    {
325
        if (true === $shared) {
326
            return static::singleton(Router::class);
327
        }
328
        if (empty($routes)) {
329
            $routes = static::routes(true);
330
        }
331
        if (empty($request)) {
332
            $request = static::request(true);
333
        }
334
335
        return static::factory(Router::class, compact('routes', 'request'));
336
    }
337
338
    /**
339
     * Retourne le gestionnaire de session.
340
     */
341
    public static function session(bool $shared = true): Session
342
    {
343
        if (true === $shared && isset(static::$instances[Session::class])) {
344
            return static::$instances[Session::class];
345
        }
346
347
        $config = Config::get('session');
348
        $db     = null;
349
350
        if (Text::contains($config['handler'], [DatabaseSessionHandler::class, 'database'])) {
351
            $group = $config['group'] ?? Config::get('database.connection');
352
            $db    = DatabaseConfig::connect($group);
353
354
            $driver = $db->getPlatform();
355
356
            if (Text::contains($driver, ['mysql', MySQLSessionHandler::class])) {
357
                $config['handler'] = MySQLSessionHandler::class;
358
            } elseif (Text::contains($driver, ['postgre', PostgreSessionHandler::class])) {
359
                $config['handler'] = PostgreSessionHandler::class;
360
            }
361
        }
362
363
        Cookie::setDefaults($cookies = Config::get('cookie'));
364
        $session = new Session($config, $cookies, Helpers::ipAddress());
365
        $session->setLogger(static::logger());
366
        $session->setDatabase($db);
367
368
        if (session_status() === PHP_SESSION_NONE) {
369
            $session->start();
370
        }
371
372
        return static::$instances[Session::class] = $session;
373
    }
374
375
    /**
376
     * System de gestion de fichier par disque
377
     */
378
    public static function storage(bool $shared = true): FilesystemManager
379
    {
380
        if ($shared && isset(static::$instances[FilesystemManager::class])) {
381
            return static::$instances[FilesystemManager::class];
382
        }
383
384
        return static::$instances[FilesystemManager::class] = new FilesystemManager(Config::get('filesystems'));
385
    }
386
387
    /**
388
     * La classe Timer fournit un moyen simple d'évaluer des parties de votre application.
389
     */
390
    public static function timer(bool $shared = true): Timer
391
    {
392
        if (true === $shared && isset(static::$instances[Timer::class])) {
393
            return static::$instances[Timer::class];
394
        }
395
396
        return static::$instances[Timer::class] = static::factory(Timer::class);
397
    }
398
399
    /**
400
     * Renvoie la barre d'outils de débogage.
401
     */
402
    public static function toolbar(?stdClass $config = null, bool $shared = true): Toolbar
403
    {
404
        if ($shared && isset(static::$instances[Toolbar::class])) {
405
            return static::$instances[Toolbar::class];
406
        }
407
408
        $config ??= (object) config('toolbar');
409
410
        return static::$instances[Toolbar::class] = static::factory(Toolbar::class, compact('config'));
411
    }
412
413
    /**
414
     * La classe URI fournit un moyen de modéliser et de manipuler les URI.
415
     */
416
    public static function uri(?string $uri = null, bool $shared = true): Uri
417
    {
418
        if (true === $shared && isset(static::$instances[Uri::class])) {
419
            return static::$instances[Uri::class]->setURI($uri);
420
        }
421
422
        return static::$instances[Uri::class] = static::factory(Uri::class, compact('uri'));
423
    }
424
425
    /**
426
     * La classe Renderer est la classe qui affiche réellement un fichier à l'utilisateur.
427
     * La classe View par défaut dans BlitzPHP est intentionnellement simple, mais
428
     * le service peut facilement être remplacé par un moteur de modèle si l'utilisateur en a besoin.
429
     */
430
    public static function viewer(bool $shared = true): View
431
    {
432
        if (true === $shared && isset(static::$instances[View::class])) {
433
            return static::$instances[View::class];
434
        }
435
436
        return static::$instances[View::class] = static::factory(View::class);
437
    }
438
439
    /**
440
     * Offre la possibilité d'effectuer des appels insensibles à la casse des noms de service.
441
     *
442
     * @return mixed
443
     */
444
    public static function __callStatic(string $name, array $arguments)
445
    {
446
        if (method_exists(static::class, $name)) {
447
            return static::$name(...$arguments);
448
        }
449
450
        return static::discoverServices($name, $arguments);
451
    }
452
453
    /**
454
     * Essaie d'obtenir un service à partir du conteneur
455
     *
456
     * @return mixed
457
     */
458
    protected static function discoverServices(string $name, array $arguments)
459
    {
460
        $shared = array_pop($arguments);
461
        if ($shared !== true) {
462
            return static::discoverServiceFactory($name, $arguments);
463
        }
464
465
        return static::discoverServiceSingleton($name, ...$arguments);
466
    }
467
468
    /**
469
     * Essaie d'obtenir un service à partir du conteneur
470
     *
471
     * @return mixed
472
     */
473
    private static function discoverServiceFactory(string $name, array $arguments)
474
    {
475
        try {
476
            return static::factory($name, $arguments);
477
        } catch (NotFoundException $e) {
478
            try {
479
                return static::factory($name . 'Service', $arguments);
480
            } catch (NotFoundException $ex) {
481
                throw $e;
482
            }
483
        }
484
    }
485
486
    /**
487
     * Essaie de trouver un seul service
488
     *
489
     * @return mixed
490
     */
491
    private static function discoverServiceSingleton(string $name)
492
    {
493
        $arguments = func_get_args();
494
        $name      = array_shift($arguments);
495
496
        try {
497
            return static::singleton($name, ...$arguments);
498
        } catch (NotFoundException $e) {
499
            try {
500
                return static::singleton($name . 'Service', ...$arguments);
501
            } catch (NotFoundException $ex) {
502
                throw $e;
503
            }
504
        }
505
    }
506
507
    /**
508
     * Injecter une seule instance de la classe donnée
509
     *
510
     * @return mixed
511
     */
512
    public static function singleton(string $name)
513
    {
514
        $arguments = func_get_args();
515
        $name      = array_shift($arguments);
516
517
        if (empty(static::$instances[$name])) {
518
            if (! empty($arguments)) {
519
                static::$instances[$name] = static::factory($name, $arguments);
520
            } else {
521
                static::$instances[$name] = static::injector()->get($name);
522
            }
523
        }
524
525
        return static::$instances[$name];
526
    }
527
528
    /**
529
     * Injecter une nouvelle instance de la classe donnée
530
     *
531
     * @return mixed
532
     */
533
    public static function factory(string $name, array $arguments = [])
534
    {
535
        return static::injector()->make($name, $arguments);
536
    }
537
538
    /**
539
     * Définissez un objet ou une valeur dans le conteneur.
540
     *
541
     * @param string $name  Nom de l'entrée
542
     * @param mixed  $value utilisez les aides à la définition pour définir les objets
543
     */
544
    public static function set(string $name, $value)
545
    {
546
        static::$instances[$name] = $value;
547
        static::container()->set($name, $value);
548
    }
549
}
550