PluginProbe
Fluent Forms – Customizable Contact Forms, Survey, Quiz, & Conversational Form Builder / 3.6.64
Fluent Forms – Customizable Contact Forms, Survey, Quiz, & Conversational Form Builder v3.6.64
6.2.14 6.2.13 6.2.12 6.2.10 6.2.11 6.2.9 6.2.8 6.2.7 6.2.6 6.2.5 6.2.4 6.2.3 6.2.2 3.6.22 3.6.31 3.6.40 3.6.41 3.6.42 3.6.50 3.6.51 3.6.60 3.6.61 3.6.62 3.6.64 3.6.65 All 196 releases
fluentform / framework / Foundation / Container.php

Container.php in Fluent Forms – Customizable Contact Forms, Survey, Quiz, & Conversational Form Builder 3.6.64, at framework/Foundation/Container.php

445 lines 11.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace FluentForm\Framework\Foundation;
4
5 use Closure;
6 use Exception;
7 use ArrayAccess;
8 use ReflectionClass;
9 use ReflectionParameter;
10 use FluentForm\Framework\Exception\UnResolveableEntityException;
11
12 class Container implements ArrayAccess
13 {
14 /**
15 * $container The service container
16 * @var array
17 */
18 protected static $container = array(
19 'facades' => array(),
20 'aliases' => array(),
21 'resolved' => array(),
22 'bindings' => array(),
23 'singletons' => array(),
24 );
25
26 /**
27 * Bind an instance into service container
28 * @param string $key identifier
29 * @param mixed $concrete
30 * @param string $facade [optional facade]
31 * @param string $alias [optional alias]
32 * @return void
33 */
34 public function bind($key, $concrete = null, $facade = null, $alias = null, $shared = false)
35 {
36 $concrete = is_null($concrete) ? $key : $concrete;
37
38 if (!$shared) {
39 static::$container['bindings'][$key] = $concrete;
40 } else {
41 static::$container['singletons'][$key] = $concrete;
42 if ($this->resolved($key)) {
43 $this->clearResolved($key);
44 }
45 }
46
47 if ($facade) {
48 $this->facade($key, $facade);
49 }
50
51 if ($alias) {
52 $this->alias($key, $alias);
53 }
54 }
55
56 /**
57 * Bind a singleton instance into service container
58 * @param string $key identifier
59 * @param mixed $concrete
60 * @param string $facade [optional facade]
61 * @param string $alias [optional alias]
62 * @return void
63 */
64 public function bindSingleton($key, $concrete = null, $facade = null, $alias = null)
65 {
66 $this->bind($key, $concrete, $facade, $alias, true);
67 }
68
69 /**
70 * Bind a singleton instance into service container
71 * @param string $key identifier
72 * @param mixed $concrete
73 * @param string $facade [optional facade]
74 * @param string $alias [optional alias]
75 * @return void
76 */
77 public function bindInstance($key, $concrete, $facade = null, $alias = null)
78 {
79 $this->bind($key, function() use ($concrete) {
80 return $concrete;
81 }, $facade, $alias, true);
82 }
83
84 /**
85 * Register a facade for a registered instance
86 * @param string $key
87 * @param string $facade
88 * @return string
89 */
90 public function facade($key, $facade)
91 {
92 static::$container['facades'][$facade] = $key;
93 }
94
95 /**
96 * Register an alias for a registered instance
97 * @param string $key
98 * @param string $alias
99 * @return string
100 */
101 public function alias($key, $aliases)
102 {
103 foreach ((array) $aliases as $alias) {
104 static::$container['aliases'][$alias] = $key;
105 }
106 }
107
108 /**
109 * Resolve an instance from container
110 * @param string $key
111 * @return mixed
112 * @throws \FluentForm\Framework\Exception\UnResolveableEntityException
113 */
114 public function make($key = null, array $params = [])
115 {
116 if (is_null($key)) {
117 return AppFacade::getApplication();
118 }
119
120 $key = $this->getAlias($key);
121
122 if (isset(static::$container['resolved'][$key])) {
123 return static::$container['resolved'][$key];
124 }
125
126 if (isset(static::$container['singletons'][$key])) {
127 return static::$container['resolved'][$key] = $this->resolve(
128 static::$container['singletons'][$key], $params
129 );
130 }
131
132 if (isset(static::$container['bindings'][$key])) {
133 return $this->resolve(static::$container['bindings'][$key], $params);
134 }
135
136 if ($this->classExists($key)) {
137 return $this->resolve($key, $params);
138 }
139
140 throw new UnResolveableEntityException('The service ['.$key.'] doesn\'t exist.');
141 }
142
143 /**
144 * Resolve an item from the container
145 * @param mixed $value
146 * @return mixed
147 */
148 protected function resolve($value, $params = [])
149 {
150 if ($value instanceof Closure) {
151 return $value($this, $params);
152 }
153
154 return $this->build($value, $params);
155 }
156
157 /**
158 * Build a concrete class with all dependencies
159 * @param string $value FQN class name
160 * @return mixed resolved instance
161 */
162 protected function build($value, $params = [])
163 {
164 if (is_object($value)) return $value;
165
166 $reflector = new ReflectionClass($value);
167
168 if (!$reflector->isInstantiable()) {
169 throw new UnResolveableEntityException(
170 "The [$value] is not instantiable."
171 );
172 }
173
174 if (!($constructor = $reflector->getConstructor())) {
175 return new $value;
176 }
177
178 $dependencies = $params ? $params : $this->resolveDependencies(
179 $constructor->getParameters()
180 );
181
182 return $reflector->newInstanceArgs($dependencies);
183 }
184
185 /**
186 * Resolve all dependencies of a single class
187 * @param array $dependencies Constructor Parameters
188 * @return array An array of all the resolved dependencies of one class
189 */
190 protected function resolveDependencies(array $dependencies)
191 {
192 $results = [];
193
194 foreach ($dependencies as $dependency) {
195 $results[] = $this->resolveClass($dependency);
196 }
197
198 return $results;
199 }
200
201 /**
202 * Resolves a single class instance
203 * @param ReflectionParameter $parameter
204 * @return mixed
205 * @throws Exception
206 */
207 protected function resolveClass(ReflectionParameter $parameter)
208 {
209 $types = ['bool', 'int', 'float', 'string', 'array', 'resource'];
210
211 try {
212 if ($class = $this->getParameterType($parameter)) {
213 $class = $class->getName();
214 if ($class && in_array($class, $types)) {
215 $class = null;
216 }
217 }
218
219 if ($class) {
220 return $this->make($class);
221 }
222
223 throw new Exception("The [".$parameter->name."] is not instantiable.");
224 } catch (Exception $exception) {
225 if ($parameter->isOptional()) {
226 return $parameter->getDefaultValue();
227 } elseif (!$class) {
228 $name = $parameter->getName();
229 $cls = $parameter->getDeclaringClass();
230 throw new UnResolveableEntityException(
231 "The [".$cls->name."] is not instantiable, $".$name." is required."
232 );
233 }
234
235 throw $exception;
236 }
237 }
238
239 /**
240 * Get the parameter type for the given parameter.
241 *
242 * @return object ReflectionClass|ReflectionNamedType
243 */
244 protected function getParameterType($parameter)
245 {
246 if (method_exists($parameter, 'getType')) {
247 return $parameter->getType();
248 }
249
250 return $parameter->getClass();
251 }
252
253 /**
254 * Get the parameter name for the given parameter.
255 *
256 * @return string
257 */
258 protected function getParameterName($parameter)
259 {
260 return $this->getParameterType($parameter)->getName();
261 }
262
263 /**
264 * Get the alias for a key if available.
265 * @param string $key
266 * @return string
267 */
268 public function getAlias($key)
269 {
270 if (isset(static::$container['aliases'][$key])) {
271 return static::$container['aliases'][$key];
272 }
273
274 return $key;
275 }
276
277 /**
278 * Check if a given class/interface exists
279 * @param string $key
280 * @return bool
281 */
282 protected function classExists($key)
283 {
284 return is_string($key) && (class_exists($key) || interface_exists($key));
285 }
286
287 /**
288 * Check if an item exists at a given offset
289 * @param string $offset
290 * @return bool
291 */
292 public function bound($offset)
293 {
294 return isset(static::$container['resolved'][$offset]) ||
295 isset(static::$container['singletons'][$offset]) ||
296 isset(static::$container['bindings'][$offset]);
297 }
298
299 /**
300 * Check if an item exists at a given offset
301 * @param string $offset
302 * @return bool
303 */
304 public function has($offset)
305 {
306 return $this->bound($offset);
307 }
308
309 /**
310 * Check if an item exists at a given offset
311 * @param string $offset
312 * @return bool
313 */
314 public function offsetExists($offset)
315 {
316 return $this->bound($offset);
317 }
318
319 /**
320 * Get the value from given offset
321 * @param string $offset
322 * @param mixed $value
323 * @return void
324 */
325 public function offsetGet($offset)
326 {
327 return $this->make($offset);
328 }
329
330 /**
331 * Set the value at a given offset
332 * @param string $offset
333 * @param mixed $value
334 * @return void
335 */
336 public function offsetSet($offset, $value)
337 {
338 $this->bindInstance($offset, $value);
339 }
340
341 /**
342 * Unset the value at a given offset
343 * @param string $offset
344 * @return void
345 */
346 public function offsetUnset($offset)
347 {
348 unset(
349 static::$container['bindings'][$offset],
350 static::$container['resolved'][$offset],
351 static::$container['singletons'][$offset]
352 );
353
354 if(array_key_exists($offset, $aliases = array_flip(static::$container['aliases']))) {
355 unset(static::$container['aliases'][$aliases[$offset]]);
356 }
357
358 if(array_key_exists($offset, $facades = array_flip(static::$container['facades']))) {
359 unset(static::$container['facades'][$facades[$offset]]);
360 }
361 }
362
363 /**
364 * Determine whether a shared entity is resolved.
365 * @param string $key
366 * @return bool
367 */
368 public function resolved($key)
369 {
370 return array_key_exists($key, static::$container['resolved']);
371 }
372
373 /**
374 * Get one or all resolved instance(s)
375 * @param string $key
376 * @return mixed
377 */
378 public function getResolved($key = null)
379 {
380 return static::$container['resolved'];
381 }
382
383 /**
384 * Clear one or all resolved instance(s)
385 * @param string $key
386 * @return void
387 */
388 public function clearResolved($key = null)
389 {
390 if (!$key) {
391 static::$container['resolved'] = [];
392 } else {
393 unset(static::$container['resolved'][$key]);
394 }
395 }
396
397 /**
398 * Get one or all binding(s)
399 * @param string $key
400 * @return void
401 */
402 public function getBindings($key = null)
403 {
404 return static::$container['bindings'];
405 }
406
407 /**
408 * Clear one or all binding(s)
409 * @param string $key
410 * @return void
411 */
412 public function clearBindings($key = null)
413 {
414 if (!$key) {
415 static::$container['bindings'] = [];
416 } else {
417 unset(static::$container['bindings'][$key]);
418 }
419 }
420
421 /**
422 * Get one or all singletons(s)
423 * @param string $key
424 * @return void
425 */
426 public function getSingletons($key = null)
427 {
428 return static::$container['singletons'];
429 }
430
431 /**
432 * Clear one or all singletons(s)
433 * @param string $key
434 * @return void
435 */
436 public function clearSingletons($key = null)
437 {
438 if (!$key) {
439 static::$container['singletons'] = [];
440 } else {
441 unset(static::$container['singletons'][$key]);
442 }
443 }
444 }
445