PluginProbe
Fluent Forms – Customizable Contact Forms, Survey, Quiz, & Conversational Form Builder / 3.6.67
Fluent Forms – Customizable Contact Forms, Survey, Quiz, & Conversational Form Builder v3.6.67
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.67, at framework/Foundation/Container.php

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