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