1 | <?php |
||
12 | class Container implements ContainerInterface |
||
13 | { |
||
14 | |||
15 | /** |
||
16 | * Holds all bindings defined. |
||
17 | * |
||
18 | * @var Bindings |
||
19 | */ |
||
20 | private $bindings; |
||
21 | |||
22 | /** |
||
23 | * Holds instances of all singletons. |
||
24 | * |
||
25 | * @var array |
||
26 | */ |
||
27 | private $singletons = []; |
||
28 | |||
29 | 19 | public function __construct() |
|
33 | |||
34 | /** |
||
35 | * Resolves names of items requested from the container to their correct binding definition. |
||
36 | * |
||
37 | * @param string $class |
||
38 | * @return array|null The name of the class detected or null |
||
39 | */ |
||
40 | 17 | private function getResolvedBinding(string $class) |
|
50 | |||
51 | /** |
||
52 | * Starts the process of defining a binding. |
||
53 | * This method selects an active binding for the internal bindings object. |
||
54 | * |
||
55 | * @param string $type |
||
56 | * @return \ntentan\panie\Bindings |
||
57 | */ |
||
58 | 10 | public function bind(string $type) : Bindings |
|
62 | |||
63 | /** |
||
64 | * Returns true if type is found in container otherwise it returns false. |
||
65 | * |
||
66 | * @param string $type |
||
67 | * @return bool |
||
68 | */ |
||
69 | 2 | public function has($type) : bool |
|
73 | |||
74 | /** |
||
75 | * Pass an array of bindings to the container. |
||
76 | * |
||
77 | * @param array $bindings |
||
78 | */ |
||
79 | 5 | public function setup(array $bindings) : void |
|
83 | |||
84 | /** |
||
85 | * Resolves a type and returns an instance of an object of the requested type. |
||
86 | * Optional constructor arguments could be provided to be used in initializing the object. This method throws a |
||
87 | * ResolutionException in cases where the type could not be resolved. |
||
88 | * |
||
89 | * @param string $type |
||
90 | * @param array $constructorArguments |
||
91 | * @return mixed |
||
92 | * @throws exceptions\ResolutionException |
||
93 | */ |
||
94 | 17 | public function resolve(string $type, array $constructorArguments = []) |
|
95 | { |
||
96 | 17 | $resolvedClass = $this->getResolvedBinding($type); |
|
97 | 17 | if ($resolvedClass['binding'] === null) { |
|
98 | 2 | throw new exceptions\ResolutionException("Could not resolve dependency of type [$type]"); |
|
99 | } |
||
100 | 15 | if ($resolvedClass['singleton'] ?? false) { |
|
101 | 2 | $instance = $this->getSingletonInstance($type, $resolvedClass['binding'], $constructorArguments); |
|
102 | } else { |
||
103 | 13 | $instance = $this->getInstance($resolvedClass['binding'], $constructorArguments); |
|
104 | } |
||
105 | |||
106 | 14 | foreach($resolvedClass['calls'] ?? [] as $calls) { |
|
107 | 3 | $method = new \ReflectionMethod($instance, $calls[0]); |
|
108 | 3 | $method->invokeArgs($instance, $this->getMethodArguments($method, $calls[1])); |
|
109 | } |
||
110 | |||
111 | 14 | return $instance; |
|
112 | } |
||
113 | |||
114 | /** |
||
115 | * Returns an instance of the type requested if this type (which was requested) is defined in the container. |
||
116 | * |
||
117 | * @param string $type |
||
118 | * @return mixed |
||
119 | * @throws exceptions\ResolutionException |
||
120 | */ |
||
121 | 1 | public function get($type) |
|
122 | { |
||
123 | 1 | return $this->resolve($type); |
|
124 | } |
||
125 | |||
126 | /** |
||
127 | * Resolves an argument for a method or constructor. |
||
128 | * If the argument passed is a string and the type hint of the argument points to an object, the string passed is |
||
129 | * assumed to be a class binding and it is resolved. |
||
130 | * |
||
131 | * @param mixed $argument |
||
132 | * @param string $class |
||
133 | * @return mixed |
||
134 | * @throws exceptions\ResolutionException |
||
135 | */ |
||
136 | 4 | private function resolveArgument($argument, $class) |
|
137 | { |
||
138 | 4 | if($class && is_string($argument)) { |
|
139 | 1 | return $this->resolve($argument); |
|
140 | } |
||
141 | 3 | return $argument; |
|
142 | } |
||
143 | |||
144 | /** |
||
145 | * Resolves all the arguments of a method or constructor. |
||
146 | * |
||
147 | * @param \ReflectionMethod $method |
||
148 | * @param array $methodArguments |
||
149 | * @return array |
||
150 | * @throws exceptions\ResolutionException |
||
151 | */ |
||
152 | 6 | private function getMethodArguments(\ReflectionMethod $method, array $methodArguments) : array |
|
168 | |||
169 | /** |
||
170 | * Returns a singleton of a given bound type. |
||
171 | * |
||
172 | * @param string $type |
||
173 | * @param mixed $class |
||
174 | * @param array $constructorArguments |
||
175 | * @return mixed |
||
176 | * @throws exceptions\ResolutionException |
||
177 | */ |
||
178 | 2 | private function getSingletonInstance(string $type, $class, array $constructorArguments) |
|
185 | |||
186 | /** |
||
187 | * Returns an instance of a class. |
||
188 | * |
||
189 | * @param string|closure $className |
||
190 | * @param array $constructorArguments |
||
191 | * @return mixed |
||
192 | * @throws exceptions\ResolutionException |
||
193 | */ |
||
194 | 15 | private function getInstance($className, array $constructorArguments = []) |
|
209 | } |
||
210 |