1 | <?php |
||||
2 | |||||
3 | namespace Nip\Container\ServiceProviders; |
||||
4 | |||||
5 | use Nip\Container\ContainerAwareInterface; |
||||
6 | use Nip\Container\ContainerAwareTrait; |
||||
7 | use Nip\Container\ServiceProviders\Providers\AbstractServiceProvider; |
||||
8 | use Nip\Container\ServiceProviders\Providers\BootableServiceProviderInterface; |
||||
9 | use Nip\Container\ServiceProviders\Providers\ServiceProviderInterface; |
||||
10 | |||||
11 | /** |
||||
12 | * Class ServiceProviderAggregate |
||||
13 | * @package Nip\Container\ServiceProvider |
||||
14 | */ |
||||
15 | class ProviderRepository implements ProviderRepositoryInterface |
||||
16 | { |
||||
17 | use ContainerAwareTrait; |
||||
18 | |||||
19 | /** |
||||
20 | * @var array |
||||
21 | */ |
||||
22 | protected $services = []; |
||||
23 | |||||
24 | /** |
||||
25 | * @var AbstractServiceProvider[] |
||||
26 | */ |
||||
27 | protected $providers = []; |
||||
28 | |||||
29 | /** |
||||
30 | * @var array Array of registered providers class names |
||||
31 | */ |
||||
32 | protected $registeredProviders = []; |
||||
33 | |||||
34 | /** |
||||
35 | * The deferred services and their providers. |
||||
36 | * |
||||
37 | * @var array |
||||
38 | */ |
||||
39 | protected $deferredServices = []; |
||||
40 | |||||
41 | /** |
||||
42 | * Indicates if the application has "booted". |
||||
43 | * |
||||
44 | * @var bool |
||||
45 | */ |
||||
46 | protected $booted = false; |
||||
47 | |||||
48 | /** |
||||
49 | * Adds a new Service Provider |
||||
50 | * {@inheritdoc} |
||||
51 | */ |
||||
52 | public function add($provider) |
||||
53 | 2 | { |
|||
54 | if (is_string($provider) && class_exists($provider)) { |
||||
55 | 2 | $provider = $this->resolveProvider($provider); |
|||
56 | 1 | } |
|||
57 | |||||
58 | if ($provider instanceof ContainerAwareInterface) { |
||||
59 | 2 | $provider->setContainer($this->getContainer()); |
|||
60 | 2 | } |
|||
61 | |||||
62 | if ($provider instanceof ServiceProviderInterface) { |
||||
63 | 2 | foreach ($provider->provides() as $service) { |
|||
64 | 2 | $this->services[$service] = get_class($provider); |
|||
65 | 2 | } |
|||
66 | $this->providers[] = $provider; |
||||
67 | 2 | return $this; |
|||
68 | 2 | } |
|||
69 | |||||
70 | throw new \InvalidArgumentException( |
||||
71 | 'A service provider must be a fully qualified class name or instance ' . |
||||
72 | 'of (\Nip\Container\ServiceProvider\ServiceProviderInterface)' |
||||
73 | ); |
||||
74 | } |
||||
75 | |||||
76 | /** |
||||
77 | * Resolve a service provider instance from the class name. |
||||
78 | * |
||||
79 | * @param string $provider |
||||
80 | * @return AbstractServiceProvider |
||||
81 | */ |
||||
82 | public function resolveProvider($provider) |
||||
83 | 1 | { |
|||
84 | return new $provider($this); |
||||
85 | 1 | } |
|||
86 | |||||
87 | public function register() |
||||
88 | { |
||||
89 | foreach ($this->providers as $provider) { |
||||
90 | $this->registerProvider($provider); |
||||
91 | } |
||||
92 | } |
||||
93 | |||||
94 | /** |
||||
95 | * Register a service provider with the application. |
||||
96 | * |
||||
97 | * @param AbstractServiceProvider|string $provider |
||||
98 | * @return AbstractServiceProvider |
||||
99 | */ |
||||
100 | public function registerProvider($provider) |
||||
101 | { |
||||
102 | if (($provider = $this->getProvider($provider))) { |
||||
103 | } elseif (is_string($provider)) { |
||||
0 ignored issues
–
show
introduced
by
![]() |
|||||
104 | $provider = $this->resolveProvider($provider); |
||||
105 | } |
||||
106 | |||||
107 | if ($this->registeredProvider($provider)) { |
||||
108 | return $provider; |
||||
0 ignored issues
–
show
|
|||||
109 | } |
||||
110 | |||||
111 | if (method_exists($provider, 'register')) { |
||||
112 | $provider->register(); |
||||
113 | } |
||||
114 | |||||
115 | $this->markAsRegistered($provider); |
||||
116 | |||||
117 | // If the application has already booted, we will call this boot method on |
||||
118 | // the provider class so it has an opportunity to do its boot logic and |
||||
119 | // will be ready for any usage by this developer's application logic. |
||||
120 | if ($this->booted) { |
||||
121 | $this->bootProvider($provider); |
||||
0 ignored issues
–
show
It seems like
$provider can also be of type null ; however, parameter $provider of Nip\Container\ServicePro...ository::bootProvider() does only seem to accept Nip\Container\ServicePro...AbstractServiceProvider , 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
![]() |
|||||
122 | } |
||||
123 | return $provider; |
||||
0 ignored issues
–
show
|
|||||
124 | } |
||||
125 | |||||
126 | /** |
||||
127 | * Get the registered service provider instance if it exists. |
||||
128 | * |
||||
129 | * @param AbstractServiceProvider|string $provider |
||||
130 | * @return AbstractServiceProvider|null |
||||
131 | */ |
||||
132 | public function getProvider($provider) |
||||
133 | 3 | { |
|||
134 | $name = is_string($provider) ? $provider : get_class($provider); |
||||
135 | 3 | ||||
136 | foreach ($this->providers as $key => $value) { |
||||
137 | 2 | if ($value instanceof $name) { |
|||
138 | 3 | return $value; |
|||
139 | } |
||||
140 | } |
||||
141 | return null; |
||||
142 | } |
||||
143 | |||||
144 | /** |
||||
145 | * @param AbstractServiceProvider $provider |
||||
146 | * @return bool |
||||
147 | */ |
||||
148 | public function registeredProvider($provider) |
||||
149 | { |
||||
150 | $providerClass = get_class($provider); |
||||
151 | if (isset($this->registeredProviders[$providerClass]) && $this->registeredProviders[$providerClass] === true) { |
||||
152 | return true; |
||||
153 | } |
||||
154 | return false; |
||||
155 | } |
||||
156 | |||||
157 | /** |
||||
158 | * Mark the given provider as registered. |
||||
159 | * |
||||
160 | * @param AbstractServiceProvider $provider |
||||
161 | * @return void |
||||
162 | */ |
||||
163 | protected function markAsRegistered($provider) |
||||
164 | { |
||||
165 | $this->registeredProviders[get_class($provider)] = true; |
||||
166 | } |
||||
167 | |||||
168 | /** |
||||
169 | * Boot the given service provider. |
||||
170 | * |
||||
171 | * @param AbstractServiceProvider $provider |
||||
172 | * @return mixed |
||||
173 | */ |
||||
174 | protected function bootProvider(AbstractServiceProvider $provider) |
||||
175 | { |
||||
176 | if ($provider instanceof BootableServiceProviderInterface) { |
||||
177 | return $provider->boot(); |
||||
0 ignored issues
–
show
Are you sure the usage of
$provider->boot() targeting Nip\Container\ServicePro...oviderInterface::boot() seems to always return null.
This check looks for function or method calls that always return null and whose return value is used. class A
{
function getObject()
{
return null;
}
}
$a = new A();
if ($a->getObject()) {
The method The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes. ![]() |
|||||
178 | } |
||||
179 | return null; |
||||
180 | } |
||||
181 | |||||
182 | /** |
||||
183 | * @return array |
||||
184 | */ |
||||
185 | public function getProviders(): array |
||||
186 | { |
||||
187 | return $this->providers; |
||||
188 | } |
||||
189 | |||||
190 | /** |
||||
191 | * Check to see if the services is registered |
||||
192 | * {@inheritdoc} |
||||
193 | */ |
||||
194 | public function provides($service) |
||||
195 | { |
||||
196 | return array_key_exists($service, $this->providers); |
||||
197 | } |
||||
198 | |||||
199 | public function boot() |
||||
200 | { |
||||
201 | foreach ($this->providers as $provider) { |
||||
202 | $this->bootProvider($provider); |
||||
203 | } |
||||
204 | |||||
205 | $this->setBooted(true); |
||||
206 | } |
||||
207 | |||||
208 | /** |
||||
209 | * @param bool $booted |
||||
210 | */ |
||||
211 | public function setBooted($booted) |
||||
212 | { |
||||
213 | $this->booted = $booted; |
||||
214 | } |
||||
215 | |||||
216 | /** |
||||
217 | * Load and boot all of the remaining deferred providers. |
||||
218 | * |
||||
219 | * @return void |
||||
220 | */ |
||||
221 | public function loadDeferredProviders() |
||||
222 | { |
||||
223 | // We will simply spin through each of the deferred providers and register each |
||||
224 | // one and boot them if the application has booted. This should make each of |
||||
225 | // the remaining services available to this application for immediate use. |
||||
226 | foreach ($this->deferredServices as $service => $provider) { |
||||
227 | $this->loadDeferredProvider($service); |
||||
228 | } |
||||
229 | $this->deferredServices = []; |
||||
230 | } |
||||
231 | |||||
232 | /** |
||||
233 | * Load the provider for a deferred service. |
||||
234 | * |
||||
235 | * @param string $service |
||||
236 | * @return void |
||||
237 | */ |
||||
238 | public function loadDeferredProvider($service) |
||||
239 | { |
||||
240 | if (!isset($this->deferredServices[$service])) { |
||||
241 | return; |
||||
242 | } |
||||
243 | $provider = $this->deferredServices[$service]; |
||||
244 | |||||
245 | // If the service provider has not already been loaded and registered we can |
||||
246 | // register it with the application and remove the service from this list |
||||
247 | // of deferred services, since it will already be loaded on subsequent. |
||||
248 | if (!isset($this->registeredProviders[$provider])) { |
||||
249 | $this->registerDeferredProvider($provider, $service); |
||||
250 | } |
||||
251 | } |
||||
252 | |||||
253 | /** |
||||
254 | * Register a deferred provider and service. |
||||
255 | * |
||||
256 | * @param string $provider |
||||
257 | * @param string $service |
||||
258 | * @return void |
||||
259 | */ |
||||
260 | public function registerDeferredProvider($provider, $service = null) |
||||
261 | { |
||||
262 | // Once the provider that provides the deferred service has been registered we |
||||
263 | // will remove it from our local list of the deferred services with related |
||||
264 | // providers so that this container does not try to resolve it out again. |
||||
265 | if ($service) { |
||||
266 | unset($this->deferredServices[$service]); |
||||
267 | } |
||||
268 | $this->registerProvider($instance = new $provider($this)); |
||||
269 | } |
||||
270 | } |
||||
271 |