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