Passed
Push — main ( 3399b6...dd4eea )
by Dimitri
11:50
created

Injector::get()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
c 0
b 0
f 0
nc 1
nop 1
dl 0
loc 3
rs 10
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\Traits\SingletonTrait;
15
use DI\Container;
16
use DI\ContainerBuilder;
17
18
/**
19
 * Injector
20
 *
21
 *  Conteneur d'Injection de Dependences
22
 */
23
class Injector
24
{
25
    use SingletonTrait;
26
27
    /**
28
     * @var \DI\Container
29
     */
30
    private $container;
31
32
    /**
33
     * @var ContainerBuilder
34
     */
35
    private $builder;
36
37
    /**
38
     * Constructor
39
     */
40
    private function __construct()
41
    {
42
        $this->builder = new ContainerBuilder();
43
        $this->builder->useAutowiring(true);
44
        $this->builder->useAttributes(true);
45
46
        if (on_prod(true)) {
47
            if (extension_loaded('apcu')) {
48
                $this->builder->enableDefinitionCache(str_replace([' ', '/', '\\', '.'], '', APP_PATH));
49
            }
50
            $this->builder->enableCompilation(FRAMEWORK_STORAGE_PATH . 'cache');    
51
        }
52
53
        $this->container = new Container();
54
    }
55
56
    /**
57
     * Charge les definitions pour le container
58
     */
59
    private function loadProviders()
60
    {
61
        $providers = self::providers();
62
63
        $this->builder->addDefinitions(...$providers);
64
65
        $this->container = $this->builder->build();
66
    }
67
68
    /**
69
     * Initialise le container d'injection de dependences
70
     */
71
    public static function init()
72
    {
73
        self::instance()->loadProviders();
74
    }
75
76
    /**
77
     * Renvoie l'instance du conteneur
78
     */
79
    public static function container(): Container
80
    {
81
        return self::instance()->container;
82
    }
83
84
    /**
85
     * Renvoie une entrée du conteneur par son nom.
86
     *
87
     * @param string $name Entry name or a class name.
88
     *
89
     * @return mixed
90
     */
91
    public static function get(string $name)
92
    {
93
        return self::container()->get($name);
94
    }
95
96
    /**
97
     * Alias de self::get
98
     */
99
    public static function singleton(string $classname)
100
    {
101
        return self::get($classname);
102
    }
103
104
    /**
105
     * Construire une entrée du conteneur par son nom.
106
     *
107
     * Cette méthode se comporte comme singleton() sauf qu'elle résout à nouveau l'entrée à chaque fois.
108
     * Par exemple, si l'entrée est une classe, une nouvelle instance sera créée à chaque fois.
109
     *
110
     * Cette méthode fait que le conteneur se comporte comme une usine.
111
     *
112
     * @param string $name       Nom d'entrée ou nom de classe.
113
     * @param array  $parameters Paramètres facultatifs à utiliser pour construire l'entrée. Utilisez ceci pour forcer des paramètres spécifiques
114
     *                           à des valeurs spécifiques. Les paramètres non définis dans ce tableau seront résolus en utilisant le conteneur.
115
     *
116
     * @return mixed
117
     */
118
    public static function make(string $name, array $parameters = [])
119
    {
120
        return self::container()->make($name, $parameters);
121
    }
122
123
    /**
124
     * Alias de self::make
125
     */
126
    public static function factory(string $classname, array $parameters = [])
127
    {
128
        return self::make($classname, $parameters);
129
    }
130
131
    /**
132
     * Appelez la fonction donnée en utilisant les paramètres donnés.
133
     *
134
     * Les paramètres manquants seront résolus à partir du conteneur.
135
     *
136
     * @param callable $callable Fonction à appeler.
137
     * @param array    $params   Paramètres à utiliser. Peut être indexé par les noms de paramètre
138
     *                           ou non indexé (même ordre que les paramètres).
139
     *                           Le tableau peut également contenir des définitions DI, par ex. DI\get().
140
     *
141
     * @return mixed Resultat de la fonction.
142
     */
143
    public static function call($callable, array $params = [])
144
    {
145
        return self::container()->call($callable, $params);
146
    }
147
148
    /**
149
     * Testez si le conteneur peut fournir quelque chose pour le nom donné.
150
     *
151
     * @param string $name Nom d'entrée ou nom de classe
152
     */
153
    public static function has(string $name): bool
154
    {
155
        return self::container()->has($name);
156
    }
157
158
    /**
159
     * Définissez un objet ou une valeur dans le conteneur.
160
     *
161
     * @param string $name  Nom de l'entrée
162
     * @param mixed  $value utilisez les aides à la définition pour définir les objets
163
     */
164
    public static function add(string $name, $value): void
165
    {
166
        self::container()->set($name, $value);
167
    }
168
169
170
    /**
171
     * Recupere toutes les definitions des services à injecter dans le container
172
     */
173
    private static function providers(): array
174
    {
175
        $providers = [];
176
177
        $loader = Services::locator();
178
179
        // Stockez nos versions d'helpers système et d'application afin que nous puissions contrôler l'ordre de chargement.
180
        $systemProvider = null;
181
        $appProvider    = null;
182
        $localIncludes  = [];
183
184
        $paths = array_merge(
185
            $loader->search('Constants/providers'), // providers system
186
            $loader->search('Config/providers') // providers de l'application ou des fournisseurs
187
        );
188
189
        foreach ($paths as $path) {
190
            if (strpos($path, APP_PATH . 'Config' . DS) === 0) {
191
                $appProvider = $path;
192
            } elseif (strpos($path, SYST_PATH . 'Constants' . DS) === 0) {
193
                $systemProvider = $path;
194
            } else {
195
                $localIncludes[] = $path;
196
            }
197
        }
198
199
        // Les providers par défaut du système doivent être ajouté en premier pour que les autres puisse les surcharger
200
        if (! empty($systemProvider)) {
201
            $providers[] = $systemProvider;
202
        }
203
204
        // Tous les providers avec espace de noms sont ajoutés ensuite
205
        $providers = [...$providers, ...$localIncludes];
206
207
        // Enfin ceux de l'application doivent remplacer tous les autres
208
        if (! empty($appProvider)) {
209
            $providers[] = $appProvider;
210
        }
211
       
212
        return $providers;
213
    }
214
}
215