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