Completed
Branch master (421f75)
by Alex
03:24 queued 01:26
created
src/ContainerAwareInterface.php 1 patch
Indentation   +12 added lines, -12 removed lines patch added patch discarded remove patch
@@ -19,18 +19,18 @@
 block discarded – undo
19 19
 interface ContainerAwareInterface
20 20
 {
21 21
 
22
-    /**
23
-     * Inject the container instance into the class.
24
-     *
25
-     * @param \Codeburner\Container\Container $container
26
-     */
27
-    public function setContainer(Container $container);
22
+	/**
23
+	 * Inject the container instance into the class.
24
+	 *
25
+	 * @param \Codeburner\Container\Container $container
26
+	 */
27
+	public function setContainer(Container $container);
28 28
 
29
-    /**
30
-     * get the container instance.
31
-     *
32
-     * @return \Codeburner\Container\Container $container
33
-     */
34
-    public function getContainer();
29
+	/**
30
+	 * get the container instance.
31
+	 *
32
+	 * @return \Codeburner\Container\Container $container
33
+	 */
34
+	public function getContainer();
35 35
 
36 36
 }
Please login to merge, or discard this patch.
src/ContainerAwareTrait.php 1 patch
Indentation   +29 added lines, -29 removed lines patch added patch discarded remove patch
@@ -19,34 +19,34 @@
 block discarded – undo
19 19
 trait ContainerAwareTrait
20 20
 {
21 21
 
22
-    /**
23
-     * The instance of container.
24
-     *
25
-     * @var \Codeburner\Container\Container
26
-     */
27
-    protected $container;
28
-
29
-    /**
30
-     * Set a container.
31
-     *
32
-     * @param \Codeburner\Container\Container $container
33
-     * @return mixed
34
-     */
35
-    public function setContainer(Container $container)
36
-    {
37
-        $this->container = $container;
38
-
39
-        return $this;
40
-    }
41
-
42
-    /**
43
-     * Get the container.
44
-     *
45
-     * @return \Codeburner\Container\Container
46
-     */
47
-    public function getContainer()
48
-    {
49
-        return $this->container;
50
-    }
22
+	/**
23
+	 * The instance of container.
24
+	 *
25
+	 * @var \Codeburner\Container\Container
26
+	 */
27
+	protected $container;
28
+
29
+	/**
30
+	 * Set a container.
31
+	 *
32
+	 * @param \Codeburner\Container\Container $container
33
+	 * @return mixed
34
+	 */
35
+	public function setContainer(Container $container)
36
+	{
37
+		$this->container = $container;
38
+
39
+		return $this;
40
+	}
41
+
42
+	/**
43
+	 * Get the container.
44
+	 *
45
+	 * @return \Codeburner\Container\Container
46
+	 */
47
+	public function getContainer()
48
+	{
49
+		return $this->container;
50
+	}
51 51
 
52 52
 }
Please login to merge, or discard this patch.
src/Container.php 2 patches
Spacing   +15 added lines, -15 removed lines patch added patch discarded remove patch
@@ -134,7 +134,7 @@  discard block
 block discarded – undo
134 134
         if ($constructor  = $inspector->getConstructor()) {
135 135
             $dependencies = $constructor->getParameters();
136 136
 
137
-            return function ($abstract, $parameters) use ($inspector, $dependencies, $force) {
137
+            return function($abstract, $parameters) use ($inspector, $dependencies, $force) {
138 138
                 $resolvedClassParameters = [];
139 139
 
140 140
                 foreach ($dependencies as $dependency) {
@@ -147,7 +147,7 @@  discard block
 block discarded – undo
147 147
             };
148 148
         }
149 149
 
150
-        return function ($abstract) {
150
+        return function($abstract) {
151 151
             return new $abstract;
152 152
         };
153 153
     }
@@ -166,7 +166,7 @@  discard block
 block discarded – undo
166 166
     {
167 167
         $key = $abstract.$dependency->name;
168 168
 
169
-        if (! isset($this->resolved[$key]) || $force === true) {
169
+        if (!isset($this->resolved[$key]) || $force === true) {
170 170
             $this->resolved[$key] = $this->generate($abstract, $dependency);
171 171
         }
172 172
 
@@ -192,7 +192,7 @@  discard block
 block discarded – undo
192 192
                 return $this->dependencies[$key];
193 193
             }
194 194
 
195
-            return function () use ($classname) {
195
+            return function() use ($classname) {
196 196
                 return $this->make($classname);
197 197
             };
198 198
         }
@@ -226,7 +226,7 @@  discard block
 block discarded – undo
226 226
      */
227 227
     public function get($abstract)
228 228
     {
229
-        if (! isset($this->collection[$abstract])) {
229
+        if (!isset($this->collection[$abstract])) {
230 230
             throw new Exceptions\NotFoundException("Element '$abstract' not found");
231 231
         }
232 232
 
@@ -283,7 +283,7 @@  discard block
 block discarded – undo
283 283
     public function set(string $abstract, $concrete, bool $shared = false) : self
284 284
     {
285 285
         if ($concrete instanceof Closure === false) {
286
-            $concrete = function (Container $container) use ($concrete) {
286
+            $concrete = function(Container $container) use ($concrete) {
287 287
                 return $container->make($concrete);
288 288
             };
289 289
         }
@@ -307,7 +307,7 @@  discard block
 block discarded – undo
307 307
 
308 308
     public function setIf(string $abstract, $concrete, bool $shared = false) : self
309 309
     {
310
-        if (! isset($this->collection[$abstract])) {
310
+        if (!isset($this->collection[$abstract])) {
311 311
             $this->set($abstract, $concrete, $shared);
312 312
         }
313 313
 
@@ -328,11 +328,11 @@  discard block
 block discarded – undo
328 328
     {
329 329
         if ($dependency instanceof Closure === false) {
330 330
             if (is_object($dependency)) {
331
-                $dependency = function () use ($dependency) {
331
+                $dependency = function() use ($dependency) {
332 332
                     return $dependency;
333 333
                 };
334 334
             } else {
335
-                $dependency = function () use ($dependency) {
335
+                $dependency = function() use ($dependency) {
336 336
                     return $this->get($dependency);
337 337
                 };
338 338
             }
@@ -372,8 +372,8 @@  discard block
 block discarded – undo
372 372
 
373 373
     public function instance(string $abstract, $instance) : self
374 374
     {
375
-        if (! is_object($instance)) {
376
-            throw new Exceptions\ContainerException('Trying to store ' . gettype($type) . ' as object.');
375
+        if (!is_object($instance)) {
376
+            throw new Exceptions\ContainerException('Trying to store '.gettype($type).' as object.');
377 377
         }
378 378
 
379 379
         $this->collection[$abstract] = $instance;
@@ -393,14 +393,14 @@  discard block
 block discarded – undo
393 393
 
394 394
     public function extend(string $abstract, closure $extension) : self
395 395
     {
396
-        if (! isset($this->collection[$abstract])) {
396
+        if (!isset($this->collection[$abstract])) {
397 397
             throw new Exceptions\NotFoundException;
398 398
         }
399 399
 
400 400
         $object = $this->collection[$abstract];
401 401
 
402 402
         if ($object instanceof Closure) {
403
-            $this->collection[$abstract] = function () use ($object, $extension) {
403
+            $this->collection[$abstract] = function() use ($object, $extension) {
404 404
                 return $extension($object($this), $this);
405 405
             };
406 406
         } else {
@@ -423,11 +423,11 @@  discard block
 block discarded – undo
423 423
 
424 424
     public function share(string $abstract) : self
425 425
     {
426
-        if (! isset($this->collection[$abstract])) {
426
+        if (!isset($this->collection[$abstract])) {
427 427
             throw new Exceptions\NotFoundException("Element '$abstract' not found");
428 428
         }
429 429
 
430
-        if (! $this->collection[$abstract] instanceof Closure) {
430
+        if (!$this->collection[$abstract] instanceof Closure) {
431 431
             throw new Exceptions\ContainerException("'$abstract' must be a resolvable element");
432 432
         }
433 433
 
Please login to merge, or discard this patch.
Indentation   +402 added lines, -402 removed lines patch added patch discarded remove patch
@@ -29,407 +29,407 @@
 block discarded – undo
29 29
 class Container implements ContainerInterface
30 30
 {
31 31
 
32
-    /**
33
-     * Holds all resolved or resolvable instances into the container.
34
-     *
35
-     * @var array
36
-     */
37
-
38
-    protected $collection;
39
-
40
-    /**
41
-     * Class specific defined dependencies.
42
-     *
43
-     * @var array
44
-     */
45
-
46
-    protected $dependencies;
47
-
48
-    /**
49
-     * Cache of classes inspector and resolver.
50
-     *
51
-     * @var array
52
-     */
53
-
54
-    protected $resolving;
55
-
56
-    /**
57
-     * Cache of classes dependencies in callbacks ready for resolution.
58
-     *
59
-     * @var array
60
-     */
61
-
62
-    protected $resolved;
63
-
64
-    /**
65
-     * Call a user function injecting the dependencies.
66
-     *
67
-     * @param string|Closure $function   The function or the user function name.
68
-     * @param array          $parameters The predefined dependencies.
69
-     *
70
-     * @return mixed
71
-     */
72
-
73
-    public function call($function, array $parameters = [])
74
-    {
75
-        $inspector = new ReflectionFunction($function);
76
-        $dependencies = $inspector->getParameters();
77
-        $resolvedClosureDependencies = [];
78
-
79
-        foreach ($dependencies as $dependency) {
80
-            if (isset($parameters[$dependency->name])) {
81
-                $resolvedClosureDependencies[] = $parameters[$dependency->name];
82
-            } else {
83
-                if (($class = $dependency->getClass()) === null) {
84
-                       $resolvedClosureDependencies[] = $dependency->getDefaultValue();
85
-                } else $resolvedClosureDependencies[] = $this->make($class->name);
86
-            }
87
-        }
88
-
89
-        return call_user_func_array($function, $resolvedClosureDependencies);
90
-    }
91
-
92
-    /**
93
-     * Makes an element or class injecting automatically all the dependencies.
94
-     *
95
-     * @param string $abstract   The class name or container element name to make.
96
-     * @param array  $parameters Specific parameters definition.
97
-     * @param bool   $force      Specify if a new element must be given and the dependencies must have be recalculated.
98
-     *
99
-     * @throws \Psr\Container\Exception\ContainerException
100
-     * @return object|null
101
-     */
102
-
103
-    public function make($abstract, array $parameters = [], bool $force = false)
104
-    {
105
-        if ($force === false && isset($this->collection[$abstract])) {
106
-            return $this->get($abstract);
107
-        }
108
-
109
-        if (isset($this->resolving[$abstract])) {
110
-            return $this->resolving[$abstract]($abstract, $parameters);
111
-        }
112
-
113
-        return ($this->resolving[$abstract] = $this->construct($abstract, $force))($abstract, $parameters);
114
-    }
115
-
116
-    /**
117
-     * Construct a class and all the dependencies using the reflection library of PHP.
118
-     *
119
-     * @param string $abstract The class name or container element name to make.
120
-     * @param bool   $force    Specify if a new element must be given and the dependencies must have be recalculated.
121
-     *
122
-     * @throws ReflectionException
123
-     * @return Closure
124
-     */
125
-
126
-    protected function construct(string $abstract, bool $force) : Closure
127
-    {
128
-        $inspector = new ReflectionClass($abstract);
129
-
130
-        if ($constructor  = $inspector->getConstructor()) {
131
-            $dependencies = $constructor->getParameters();
132
-
133
-            return function ($abstract, $parameters) use ($inspector, $dependencies, $force) {
134
-                $resolvedClassParameters = [];
135
-
136
-                foreach ($dependencies as $dependency) {
137
-                    if (isset($parameters[$dependency->name])) {
138
-                           $resolvedClassParameters[] = $parameters[$dependency->name];
139
-                    } else $resolvedClassParameters[] = $this->resolve($abstract, $dependency, $force);
140
-                }
141
-
142
-                return $inspector->newInstanceArgs($resolvedClassParameters);
143
-            };
144
-        }
145
-
146
-        return function ($abstract) {
147
-            return new $abstract;
148
-        };
149
-    }
150
-
151
-    /**
152
-     * Resolve all the given class reflected dependencies.
153
-     *
154
-     * @param string               $abstract   The class name or container element name to resolve dependencies.
155
-     * @param ReflectionParameter  $dependency The class dependency to be resolved.
156
-     * @param bool                 $force      Specify if the dependencies must be recalculated.
157
-     *
158
-     * @return Object
159
-     */
160
-
161
-    protected function resolve(string $abstract, ReflectionParameter $dependency, bool $force)
162
-    {
163
-        $key = $abstract.$dependency->name;
164
-
165
-        if (! isset($this->resolved[$key]) || $force === true) {
166
-            $this->resolved[$key] = $this->generate($abstract, $dependency);
167
-        }
168
-
169
-        return $this->resolved[$key]($this);
170
-    }
171
-
172
-    /**
173
-     * Generate the dependencies callbacks to jump some conditions in every dependency creation.
174
-     *
175
-     * @param string               $abstract   The class name or container element name to resolve dependencies.
176
-     * @param ReflectionParameter  $dependency The class dependency to be resolved.
177
-     *
178
-     * @return Closure
179
-     */
180
-
181
-    protected function generate(string $abstract, ReflectionParameter $dependency) : Closure
182
-    {
183
-        if ($class = $dependency->getClass()) {
184
-            $classname = $class->name;
185
-            $key = $abstract.$classname;
186
-
187
-            if (isset($this->dependencies[$key])) {
188
-                return $this->dependencies[$key];
189
-            }
190
-
191
-            return function () use ($classname) {
192
-                return $this->make($classname);
193
-            };
194
-        }
195
-
196
-        return $class->getDefaultValue();
197
-    }
198
-
199
-    /**
200
-     * Reset the container, removing all the elements, cache and options.
201
-     *
202
-     * @return void
203
-     */
204
-
205
-    public function flush()
206
-    {
207
-        $this->collection = [];
208
-        $this->dependencies = [];
209
-        $this->resolving = [];
210
-        $this->resolved = [];
211
-    }
212
-
213
-    /**
214
-     * Finds an entry of the container by its identifier and returns it.
215
-     *
216
-     * @param string $abstract Identifier of the entry to look for.
217
-     *
218
-     * @throws \Psr\Container\Exception\NotFoundException  No entry was found for this identifier.
219
-     * @throws \Psr\Container\Exception\ContainerException Error while retrieving the entry.
220
-     *
221
-     * @return mixed Entry.
222
-     */
223
-    public function get($abstract)
224
-    {
225
-        if (! isset($this->collection[$abstract])) {
226
-            throw new Exceptions\NotFoundException("Element '$abstract' not found");
227
-        }
228
-
229
-        if ($this->collection[$abstract] instanceof Closure) {
230
-            try {
231
-                return $this->collection[$abstract]($this);
232
-            } catch (Exception $e) {
233
-                throw new Exceptions\ContainerException($e->getMessage());
234
-            }
235
-        }
236
-
237
-        return $this->collection[$abstract];
238
-    }
239
-
240
-    /**
241
-     * Returns true if the container can return an entry for the given identifier.
242
-     * Returns false otherwise.
243
-     *
244
-     * `has($abstract)` returning true does not mean that `get($abstract)` will not throw an exception.
245
-     * It does however mean that `get($abstract)` will not throw a `NotFoundException`.
246
-     *
247
-     * @param string $abstract Identifier of the entry to look for.
248
-     *
249
-     * @return boolean
250
-     */
251
-
252
-    public function has($abstract)
253
-    {
254
-        return isset($this->collection[$abstract]);
255
-    }
256
-
257
-    /**
258
-     * Verify if an element has a singleton instance.
259
-     *
260
-     * @param  string The class name or container element name to resolve dependencies.
261
-     * @return bool
262
-     */
263
-
264
-    public function isSingleton(string $abstract) : bool
265
-    {
266
-        return isset($this->collection[$abstract]);
267
-    }
268
-
269
-    /**
270
-     * Bind a new element to the container.
271
-     *
272
-     * @param string         $abstract The alias name that will be used to call the element.
273
-     * @param string|closure $concrete The element class name, or an closure that makes the element.
274
-     * @param bool           $shared   Define if the element will be a singleton instance.
275
-     *
276
-     * @return \Codeburner\Container\Container
277
-     */
278
-
279
-    public function set(string $abstract, $concrete, bool $shared = false) : self
280
-    {
281
-        if ($concrete instanceof Closure === false) {
282
-            $concrete = function (Container $container) use ($concrete) {
283
-                return $container->make($concrete);
284
-            };
285
-        }
286
-
287
-        if ($shared === true) {
288
-               $this->collection[$abstract] = $concrete($this);
289
-        } else $this->collection[$abstract] = $concrete;
290
-
291
-        return $this;
292
-    }
293
-
294
-    /**
295
-     * Bind a new element to the container IF the element name not exists in the container.
296
-     *
297
-     * @param string         $abstract The alias name that will be used to call the element.
298
-     * @param string|closure $concrete The element class name, or an closure that makes the element.
299
-     * @param bool           $shared   Define if the element will be a singleton instance.
300
-     *
301
-     * @return \Codeburner\Container\Container
302
-     */
303
-
304
-    public function setIf(string $abstract, $concrete, bool $shared = false) : self
305
-    {
306
-        if (! isset($this->collection[$abstract])) {
307
-            $this->set($abstract, $concrete, $shared);
308
-        }
309
-
310
-        return $this;
311
-    }
312
-
313
-    /**
314
-     * Bind an specific instance to a class dependency.
315
-     *
316
-     * @param string         $class          The class full name.
317
-     * @param string         $dependencyName The dependency full name.
318
-     * @param string|closure $dependency     The specific object class name or a classure that makes the element.
319
-     *
320
-     * @return \Codeburner\Container\Container
321
-     */
322
-
323
-    public function setTo(string $class, string $dependencyName, $dependency) : self
324
-    {
325
-        if ($dependency instanceof Closure === false) {
326
-            if (is_object($dependency)) {
327
-                $dependency = function () use ($dependency) {
328
-                    return $dependency;
329
-                };
330
-            } else {
331
-                $dependency = function () use ($dependency) {
332
-                    return $this->get($dependency);
333
-                };
334
-            }
335
-        }
336
-
337
-        $this->dependencies[$class.$dependencyName] = $dependency;
338
-
339
-        return $this;
340
-    }
341
-
342
-    /**
343
-     * Bind an element that will be construct only one time, and every call for the element,
344
-     * the same instance will be given.
345
-     *
346
-     * @param string         $abstract The alias name that will be used to call the element.
347
-     * @param string|closure $concrete The element class name, or an closure that makes the element.
348
-     *
349
-     * @return \Codeburner\Container\Container
350
-     */
351
-
352
-    public function singleton(string $abstract, $concrete) : self
353
-    {
354
-        $this->set($abstract, $concrete, true);
355
-
356
-        return $this;
357
-    }
358
-
359
-    /**
360
-     * Bind an object to the container.
361
-     *
362
-     * @param string $abstract The alias name that will be used to call the object.
363
-     * @param object $instance The object that will be inserted.
364
-     *
365
-     * @throws \Psr\Container\Exception\ContainerException When $instance is not an object.
366
-     * @return \Codeburner\Container\Container
367
-     */
368
-
369
-    public function instance(string $abstract, $instance) : self
370
-    {
371
-        if (! is_object($instance)) {
372
-            throw new Exceptions\ContainerException('Trying to store ' . gettype($type) . ' as object.');
373
-        }
374
-
375
-        $this->collection[$abstract] = $instance;
376
-
377
-        return $this;
378
-    }
379
-
380
-    /**
381
-     * Modify an element with a given function that receive the old element as argument.
382
-     *
383
-     * @param string  $abstract  The alias name that will be used to call the element.
384
-     * @param closure $extension The function that receives the old element and return a new or modified one.
385
-     *
386
-     * @throws \Psr\Container\Exception\NotFoundException  When no element was found with $abstract key.
387
-     * @return \Codeburner\Container\Container
388
-     */
389
-
390
-    public function extend(string $abstract, closure $extension) : self
391
-    {
392
-        if (! isset($this->collection[$abstract])) {
393
-            throw new Exceptions\NotFoundException;
394
-        }
395
-
396
-        $object = $this->collection[$abstract];
397
-
398
-        if ($object instanceof Closure) {
399
-            $this->collection[$abstract] = function () use ($object, $extension) {
400
-                return $extension($object($this), $this);
401
-            };
402
-        } else {
403
-            $this->collection[$abstract] = $extension($object, $this);
404
-        }
405
-
406
-        return $this;
407
-    }
408
-
409
-    /**
410
-     * Makes an resolvable element an singleton.
411
-     *
412
-     * @param  string $abstract The alias name that will be used to call the element.
413
-     *
414
-     * @throws \Psr\Container\Exception\NotFoundException  When no element was found with $abstract key.
415
-     * @throws \Psr\Container\Exception\ContainerException When the element on $abstract key is not resolvable.
416
-     *
417
-     * @return \Codeburner\Container\Container
418
-     */
419
-
420
-    public function share(string $abstract) : self
421
-    {
422
-        if (! isset($this->collection[$abstract])) {
423
-            throw new Exceptions\NotFoundException("Element '$abstract' not found");
424
-        }
425
-
426
-        if (! $this->collection[$abstract] instanceof Closure) {
427
-            throw new Exceptions\ContainerException("'$abstract' must be a resolvable element");
428
-        }
429
-
430
-        $this->collection[$abstract] = $this->collection[$abstract]($this);
431
-
432
-        return $this;
433
-    }
32
+	/**
33
+	 * Holds all resolved or resolvable instances into the container.
34
+	 *
35
+	 * @var array
36
+	 */
37
+
38
+	protected $collection;
39
+
40
+	/**
41
+	 * Class specific defined dependencies.
42
+	 *
43
+	 * @var array
44
+	 */
45
+
46
+	protected $dependencies;
47
+
48
+	/**
49
+	 * Cache of classes inspector and resolver.
50
+	 *
51
+	 * @var array
52
+	 */
53
+
54
+	protected $resolving;
55
+
56
+	/**
57
+	 * Cache of classes dependencies in callbacks ready for resolution.
58
+	 *
59
+	 * @var array
60
+	 */
61
+
62
+	protected $resolved;
63
+
64
+	/**
65
+	 * Call a user function injecting the dependencies.
66
+	 *
67
+	 * @param string|Closure $function   The function or the user function name.
68
+	 * @param array          $parameters The predefined dependencies.
69
+	 *
70
+	 * @return mixed
71
+	 */
72
+
73
+	public function call($function, array $parameters = [])
74
+	{
75
+		$inspector = new ReflectionFunction($function);
76
+		$dependencies = $inspector->getParameters();
77
+		$resolvedClosureDependencies = [];
78
+
79
+		foreach ($dependencies as $dependency) {
80
+			if (isset($parameters[$dependency->name])) {
81
+				$resolvedClosureDependencies[] = $parameters[$dependency->name];
82
+			} else {
83
+				if (($class = $dependency->getClass()) === null) {
84
+					   $resolvedClosureDependencies[] = $dependency->getDefaultValue();
85
+				} else $resolvedClosureDependencies[] = $this->make($class->name);
86
+			}
87
+		}
88
+
89
+		return call_user_func_array($function, $resolvedClosureDependencies);
90
+	}
91
+
92
+	/**
93
+	 * Makes an element or class injecting automatically all the dependencies.
94
+	 *
95
+	 * @param string $abstract   The class name or container element name to make.
96
+	 * @param array  $parameters Specific parameters definition.
97
+	 * @param bool   $force      Specify if a new element must be given and the dependencies must have be recalculated.
98
+	 *
99
+	 * @throws \Psr\Container\Exception\ContainerException
100
+	 * @return object|null
101
+	 */
102
+
103
+	public function make($abstract, array $parameters = [], bool $force = false)
104
+	{
105
+		if ($force === false && isset($this->collection[$abstract])) {
106
+			return $this->get($abstract);
107
+		}
108
+
109
+		if (isset($this->resolving[$abstract])) {
110
+			return $this->resolving[$abstract]($abstract, $parameters);
111
+		}
112
+
113
+		return ($this->resolving[$abstract] = $this->construct($abstract, $force))($abstract, $parameters);
114
+	}
115
+
116
+	/**
117
+	 * Construct a class and all the dependencies using the reflection library of PHP.
118
+	 *
119
+	 * @param string $abstract The class name or container element name to make.
120
+	 * @param bool   $force    Specify if a new element must be given and the dependencies must have be recalculated.
121
+	 *
122
+	 * @throws ReflectionException
123
+	 * @return Closure
124
+	 */
125
+
126
+	protected function construct(string $abstract, bool $force) : Closure
127
+	{
128
+		$inspector = new ReflectionClass($abstract);
129
+
130
+		if ($constructor  = $inspector->getConstructor()) {
131
+			$dependencies = $constructor->getParameters();
132
+
133
+			return function ($abstract, $parameters) use ($inspector, $dependencies, $force) {
134
+				$resolvedClassParameters = [];
135
+
136
+				foreach ($dependencies as $dependency) {
137
+					if (isset($parameters[$dependency->name])) {
138
+						   $resolvedClassParameters[] = $parameters[$dependency->name];
139
+					} else $resolvedClassParameters[] = $this->resolve($abstract, $dependency, $force);
140
+				}
141
+
142
+				return $inspector->newInstanceArgs($resolvedClassParameters);
143
+			};
144
+		}
145
+
146
+		return function ($abstract) {
147
+			return new $abstract;
148
+		};
149
+	}
150
+
151
+	/**
152
+	 * Resolve all the given class reflected dependencies.
153
+	 *
154
+	 * @param string               $abstract   The class name or container element name to resolve dependencies.
155
+	 * @param ReflectionParameter  $dependency The class dependency to be resolved.
156
+	 * @param bool                 $force      Specify if the dependencies must be recalculated.
157
+	 *
158
+	 * @return Object
159
+	 */
160
+
161
+	protected function resolve(string $abstract, ReflectionParameter $dependency, bool $force)
162
+	{
163
+		$key = $abstract.$dependency->name;
164
+
165
+		if (! isset($this->resolved[$key]) || $force === true) {
166
+			$this->resolved[$key] = $this->generate($abstract, $dependency);
167
+		}
168
+
169
+		return $this->resolved[$key]($this);
170
+	}
171
+
172
+	/**
173
+	 * Generate the dependencies callbacks to jump some conditions in every dependency creation.
174
+	 *
175
+	 * @param string               $abstract   The class name or container element name to resolve dependencies.
176
+	 * @param ReflectionParameter  $dependency The class dependency to be resolved.
177
+	 *
178
+	 * @return Closure
179
+	 */
180
+
181
+	protected function generate(string $abstract, ReflectionParameter $dependency) : Closure
182
+	{
183
+		if ($class = $dependency->getClass()) {
184
+			$classname = $class->name;
185
+			$key = $abstract.$classname;
186
+
187
+			if (isset($this->dependencies[$key])) {
188
+				return $this->dependencies[$key];
189
+			}
190
+
191
+			return function () use ($classname) {
192
+				return $this->make($classname);
193
+			};
194
+		}
195
+
196
+		return $class->getDefaultValue();
197
+	}
198
+
199
+	/**
200
+	 * Reset the container, removing all the elements, cache and options.
201
+	 *
202
+	 * @return void
203
+	 */
204
+
205
+	public function flush()
206
+	{
207
+		$this->collection = [];
208
+		$this->dependencies = [];
209
+		$this->resolving = [];
210
+		$this->resolved = [];
211
+	}
212
+
213
+	/**
214
+	 * Finds an entry of the container by its identifier and returns it.
215
+	 *
216
+	 * @param string $abstract Identifier of the entry to look for.
217
+	 *
218
+	 * @throws \Psr\Container\Exception\NotFoundException  No entry was found for this identifier.
219
+	 * @throws \Psr\Container\Exception\ContainerException Error while retrieving the entry.
220
+	 *
221
+	 * @return mixed Entry.
222
+	 */
223
+	public function get($abstract)
224
+	{
225
+		if (! isset($this->collection[$abstract])) {
226
+			throw new Exceptions\NotFoundException("Element '$abstract' not found");
227
+		}
228
+
229
+		if ($this->collection[$abstract] instanceof Closure) {
230
+			try {
231
+				return $this->collection[$abstract]($this);
232
+			} catch (Exception $e) {
233
+				throw new Exceptions\ContainerException($e->getMessage());
234
+			}
235
+		}
236
+
237
+		return $this->collection[$abstract];
238
+	}
239
+
240
+	/**
241
+	 * Returns true if the container can return an entry for the given identifier.
242
+	 * Returns false otherwise.
243
+	 *
244
+	 * `has($abstract)` returning true does not mean that `get($abstract)` will not throw an exception.
245
+	 * It does however mean that `get($abstract)` will not throw a `NotFoundException`.
246
+	 *
247
+	 * @param string $abstract Identifier of the entry to look for.
248
+	 *
249
+	 * @return boolean
250
+	 */
251
+
252
+	public function has($abstract)
253
+	{
254
+		return isset($this->collection[$abstract]);
255
+	}
256
+
257
+	/**
258
+	 * Verify if an element has a singleton instance.
259
+	 *
260
+	 * @param  string The class name or container element name to resolve dependencies.
261
+	 * @return bool
262
+	 */
263
+
264
+	public function isSingleton(string $abstract) : bool
265
+	{
266
+		return isset($this->collection[$abstract]);
267
+	}
268
+
269
+	/**
270
+	 * Bind a new element to the container.
271
+	 *
272
+	 * @param string         $abstract The alias name that will be used to call the element.
273
+	 * @param string|closure $concrete The element class name, or an closure that makes the element.
274
+	 * @param bool           $shared   Define if the element will be a singleton instance.
275
+	 *
276
+	 * @return \Codeburner\Container\Container
277
+	 */
278
+
279
+	public function set(string $abstract, $concrete, bool $shared = false) : self
280
+	{
281
+		if ($concrete instanceof Closure === false) {
282
+			$concrete = function (Container $container) use ($concrete) {
283
+				return $container->make($concrete);
284
+			};
285
+		}
286
+
287
+		if ($shared === true) {
288
+			   $this->collection[$abstract] = $concrete($this);
289
+		} else $this->collection[$abstract] = $concrete;
290
+
291
+		return $this;
292
+	}
293
+
294
+	/**
295
+	 * Bind a new element to the container IF the element name not exists in the container.
296
+	 *
297
+	 * @param string         $abstract The alias name that will be used to call the element.
298
+	 * @param string|closure $concrete The element class name, or an closure that makes the element.
299
+	 * @param bool           $shared   Define if the element will be a singleton instance.
300
+	 *
301
+	 * @return \Codeburner\Container\Container
302
+	 */
303
+
304
+	public function setIf(string $abstract, $concrete, bool $shared = false) : self
305
+	{
306
+		if (! isset($this->collection[$abstract])) {
307
+			$this->set($abstract, $concrete, $shared);
308
+		}
309
+
310
+		return $this;
311
+	}
312
+
313
+	/**
314
+	 * Bind an specific instance to a class dependency.
315
+	 *
316
+	 * @param string         $class          The class full name.
317
+	 * @param string         $dependencyName The dependency full name.
318
+	 * @param string|closure $dependency     The specific object class name or a classure that makes the element.
319
+	 *
320
+	 * @return \Codeburner\Container\Container
321
+	 */
322
+
323
+	public function setTo(string $class, string $dependencyName, $dependency) : self
324
+	{
325
+		if ($dependency instanceof Closure === false) {
326
+			if (is_object($dependency)) {
327
+				$dependency = function () use ($dependency) {
328
+					return $dependency;
329
+				};
330
+			} else {
331
+				$dependency = function () use ($dependency) {
332
+					return $this->get($dependency);
333
+				};
334
+			}
335
+		}
336
+
337
+		$this->dependencies[$class.$dependencyName] = $dependency;
338
+
339
+		return $this;
340
+	}
341
+
342
+	/**
343
+	 * Bind an element that will be construct only one time, and every call for the element,
344
+	 * the same instance will be given.
345
+	 *
346
+	 * @param string         $abstract The alias name that will be used to call the element.
347
+	 * @param string|closure $concrete The element class name, or an closure that makes the element.
348
+	 *
349
+	 * @return \Codeburner\Container\Container
350
+	 */
351
+
352
+	public function singleton(string $abstract, $concrete) : self
353
+	{
354
+		$this->set($abstract, $concrete, true);
355
+
356
+		return $this;
357
+	}
358
+
359
+	/**
360
+	 * Bind an object to the container.
361
+	 *
362
+	 * @param string $abstract The alias name that will be used to call the object.
363
+	 * @param object $instance The object that will be inserted.
364
+	 *
365
+	 * @throws \Psr\Container\Exception\ContainerException When $instance is not an object.
366
+	 * @return \Codeburner\Container\Container
367
+	 */
368
+
369
+	public function instance(string $abstract, $instance) : self
370
+	{
371
+		if (! is_object($instance)) {
372
+			throw new Exceptions\ContainerException('Trying to store ' . gettype($type) . ' as object.');
373
+		}
374
+
375
+		$this->collection[$abstract] = $instance;
376
+
377
+		return $this;
378
+	}
379
+
380
+	/**
381
+	 * Modify an element with a given function that receive the old element as argument.
382
+	 *
383
+	 * @param string  $abstract  The alias name that will be used to call the element.
384
+	 * @param closure $extension The function that receives the old element and return a new or modified one.
385
+	 *
386
+	 * @throws \Psr\Container\Exception\NotFoundException  When no element was found with $abstract key.
387
+	 * @return \Codeburner\Container\Container
388
+	 */
389
+
390
+	public function extend(string $abstract, closure $extension) : self
391
+	{
392
+		if (! isset($this->collection[$abstract])) {
393
+			throw new Exceptions\NotFoundException;
394
+		}
395
+
396
+		$object = $this->collection[$abstract];
397
+
398
+		if ($object instanceof Closure) {
399
+			$this->collection[$abstract] = function () use ($object, $extension) {
400
+				return $extension($object($this), $this);
401
+			};
402
+		} else {
403
+			$this->collection[$abstract] = $extension($object, $this);
404
+		}
405
+
406
+		return $this;
407
+	}
408
+
409
+	/**
410
+	 * Makes an resolvable element an singleton.
411
+	 *
412
+	 * @param  string $abstract The alias name that will be used to call the element.
413
+	 *
414
+	 * @throws \Psr\Container\Exception\NotFoundException  When no element was found with $abstract key.
415
+	 * @throws \Psr\Container\Exception\ContainerException When the element on $abstract key is not resolvable.
416
+	 *
417
+	 * @return \Codeburner\Container\Container
418
+	 */
419
+
420
+	public function share(string $abstract) : self
421
+	{
422
+		if (! isset($this->collection[$abstract])) {
423
+			throw new Exceptions\NotFoundException("Element '$abstract' not found");
424
+		}
425
+
426
+		if (! $this->collection[$abstract] instanceof Closure) {
427
+			throw new Exceptions\ContainerException("'$abstract' must be a resolvable element");
428
+		}
429
+
430
+		$this->collection[$abstract] = $this->collection[$abstract]($this);
431
+
432
+		return $this;
433
+	}
434 434
 
435 435
 }
Please login to merge, or discard this patch.