PluginProbe
Fluent Forms – Customizable Contact Forms, Survey, Quiz, & Conversational Form Builder / 4.3.21
Fluent Forms – Customizable Contact Forms, Survey, Quiz, & Conversational Form Builder v4.3.21
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 3.6.66 All 195 releases
fluentform / framework / Foundation / Container.php

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

447 lines 11.5 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
214 $phpVersion = phpversion();
215 if (version_compare($phpVersion, '7', '>=') && version_compare($phpVersion, '7.1', '<')) {
216 if ($class instanceof \ReflectionType) {
217 $class = (string)$class;
218 return $this->make($class);
219 }
220 }
221
222 $class = $class->getName();
223 if ($class && in_array($class, $types)) {
224 $class = null;
225 }
226 }
227
228 if ($class) {
229 return $this->make($class);
230 }
231
232 throw new Exception("The [" . $parameter->name . "] is not instantiable.");
233 } catch (Exception $exception) {
234 if ($parameter->isOptional()) {
235 return $parameter->getDefaultValue();
236 } elseif (!$class) {
237 $name = $parameter->getName();
238 $cls = $parameter->getDeclaringClass();
239 throw new UnResolveableEntityException(
240 "The [" . $cls->name . "] is not instantiable, $" . $name . " is required."
241 );
242 }
243
244 throw $exception;
245 }
246 }
247
248 /**
249 * Get the parameter type for the given parameter.
250 *
251 * @return object ReflectionClass|ReflectionNamedType
252 */
253 protected function getParameterType($parameter)
254 {
255 if (method_exists($parameter, 'getType')) {
256 return $parameter->getType();
257 }
258
259 return $parameter->getClass();
260 }
261
262 /**
263 * Get the alias for a key if available.
264 * @param string $key
265 * @return string
266 */
267 public function getAlias($key)
268 {
269 if (isset(static::$container['aliases'][$key])) {
270 return static::$container['aliases'][$key];
271 }
272
273 return $key;
274 }
275
276 /**
277 * Check if a given class/interface exists
278 * @param string $key
279 * @return bool
280 */
281 protected function classExists($key)
282 {
283 return is_string($key) && (class_exists($key) || interface_exists($key));
284 }
285
286 /**
287 * Check if an item exists at a given offset
288 * @param string $offset
289 * @return bool
290 */
291 public function bound($offset)
292 {
293 return isset(static::$container['resolved'][$offset]) ||
294 isset(static::$container['singletons'][$offset]) ||
295 isset(static::$container['bindings'][$offset]);
296 }
297
298 /**
299 * Check if an item exists at a given offset
300 * @param string $offset
301 * @return bool
302 */
303 public function has($offset)
304 {
305 return $this->bound($offset);
306 }
307
308 /**
309 * Check if an item exists at a given offset
310 * @param string $offset
311 * @return bool
312 */
313 #[\ReturnTypeWillChange]
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 #[\ReturnTypeWillChange]
326 public function offsetGet($offset)
327 {
328 return $this->make($offset);
329 }
330
331 /**
332 * Set the value at a given offset
333 * @param string $offset
334 * @param mixed $value
335 * @return void
336 */
337 #[\ReturnTypeWillChange]
338 public function offsetSet($offset, $value)
339 {
340 $this->bindInstance($offset, $value);
341 }
342
343 /**
344 * Unset the value at a given offset
345 * @param string $offset
346 * @return void
347 */
348 #[\ReturnTypeWillChange]
349 public function offsetUnset($offset)
350 {
351 unset(
352 static::$container['bindings'][$offset],
353 static::$container['resolved'][$offset],
354 static::$container['singletons'][$offset]
355 );
356
357 if (array_key_exists($offset, $aliases = array_flip(static::$container['aliases']))) {
358 unset(static::$container['aliases'][$aliases[$offset]]);
359 }
360
361 if (array_key_exists($offset, $facades = array_flip(static::$container['facades']))) {
362 unset(static::$container['facades'][$facades[$offset]]);
363 }
364 }
365
366 /**
367 * Determine whether a shared entity is resolved.
368 * @param string $key
369 * @return bool
370 */
371 public function resolved($key)
372 {
373 return array_key_exists($key, static::$container['resolved']);
374 }
375
376 /**
377 * Get one or all resolved instance(s)
378 * @param string $key
379 * @return mixed
380 */
381 public function getResolved($key = null)
382 {
383 return static::$container['resolved'];
384 }
385
386 /**
387 * Clear one or all resolved instance(s)
388 * @param string $key
389 * @return void
390 */
391 public function clearResolved($key = null)
392 {
393 if (!$key) {
394 static::$container['resolved'] = [];
395 } else {
396 unset(static::$container['resolved'][$key]);
397 }
398 }
399
400 /**
401 * Get one or all binding(s)
402 * @param string $key
403 * @return void
404 */
405 public function getBindings($key = null)
406 {
407 return static::$container['bindings'];
408 }
409
410 /**
411 * Clear one or all binding(s)
412 * @param string $key
413 * @return void
414 */
415 public function clearBindings($key = null)
416 {
417 if (!$key) {
418 static::$container['bindings'] = [];
419 } else {
420 unset(static::$container['bindings'][$key]);
421 }
422 }
423
424 /**
425 * Get one or all singletons(s)
426 * @param string $key
427 * @return void
428 */
429 public function getSingletons($key = null)
430 {
431 return static::$container['singletons'];
432 }
433
434 /**
435 * Clear one or all singletons(s)
436 * @param string $key
437 * @return void
438 */
439 public function clearSingletons($key = null)
440 {
441 if (!$key) {
442 static::$container['singletons'] = [];
443 } else {
444 unset(static::$container['singletons'][$key]);
445 }
446 }
447 }