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