PluginProbe
The Innovative Form Builder – IvyForms / 0.1.2
The Innovative Form Builder – IvyForms v0.1.2
1.5.1 1.5 1.4.1 1.4 trunk 0.1.2 0.2 0.2.1 0.3 0.3.1 0.4 0.5 0.6 0.6.1 0.6.1-backup 0.6.1.1 0.7 0.8 0.8.1 0.8.2 0.9 0.9.1 1.0 1.1 1.1.1 All 27 releases
ivyforms / backend / vendor / php-di / invoker / src / Invoker.php

Invoker.php in The Innovative Form Builder – IvyForms 0.1.2, at backend/vendor/php-di/invoker/src/Invoker.php

110 lines 3.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php declare(strict_types=1);
2
3 namespace Invoker;
4
5 use Invoker\Exception\NotCallableException;
6 use Invoker\Exception\NotEnoughParametersException;
7 use Invoker\ParameterResolver\AssociativeArrayResolver;
8 use Invoker\ParameterResolver\DefaultValueResolver;
9 use Invoker\ParameterResolver\NumericArrayResolver;
10 use Invoker\ParameterResolver\ParameterResolver;
11 use Invoker\ParameterResolver\ResolverChain;
12 use Invoker\Reflection\CallableReflection;
13 use Psr\Container\ContainerInterface;
14 use ReflectionParameter;
15
16 /**
17 * Invoke a callable.
18 */
19 class Invoker implements InvokerInterface
20 {
21 /** @var CallableResolver|null */
22 private $callableResolver;
23
24 /** @var ParameterResolver */
25 private $parameterResolver;
26
27 /** @var ContainerInterface|null */
28 private $container;
29
30 public function __construct(?ParameterResolver $parameterResolver = null, ?ContainerInterface $container = null)
31 {
32 $this->parameterResolver = $parameterResolver ?: $this->createParameterResolver();
33 $this->container = $container;
34
35 if ($container) {
36 $this->callableResolver = new CallableResolver($container);
37 }
38 }
39
40 /**
41 * {@inheritdoc}
42 */
43 public function call($callable, array $parameters = [])
44 {
45 if ($this->callableResolver) {
46 $callable = $this->callableResolver->resolve($callable);
47 }
48
49 if (! is_callable($callable)) {
50 throw new NotCallableException(sprintf(
51 '%s is not a callable',
52 is_object($callable) ? 'Instance of ' . get_class($callable) : var_export($callable, true)
53 ));
54 }
55
56 $callableReflection = CallableReflection::create($callable);
57
58 $args = $this->parameterResolver->getParameters($callableReflection, $parameters, []);
59
60 // Sort by array key because call_user_func_array ignores numeric keys
61 ksort($args);
62
63 // Check all parameters are resolved
64 $diff = array_diff_key($callableReflection->getParameters(), $args);
65 $parameter = reset($diff);
66 if ($parameter && \assert($parameter instanceof ReflectionParameter) && ! $parameter->isVariadic()) {
67 throw new NotEnoughParametersException(sprintf(
68 'Unable to invoke the callable because no value was given for parameter %d ($%s)',
69 $parameter->getPosition() + 1,
70 $parameter->name
71 ));
72 }
73
74 return call_user_func_array($callable, $args);
75 }
76
77 /**
78 * Create the default parameter resolver.
79 */
80 private function createParameterResolver(): ParameterResolver
81 {
82 return new ResolverChain([
83 new NumericArrayResolver,
84 new AssociativeArrayResolver,
85 new DefaultValueResolver,
86 ]);
87 }
88
89 /**
90 * @return ParameterResolver By default it's a ResolverChain
91 */
92 public function getParameterResolver(): ParameterResolver
93 {
94 return $this->parameterResolver;
95 }
96
97 public function getContainer(): ?ContainerInterface
98 {
99 return $this->container;
100 }
101
102 /**
103 * @return CallableResolver|null Returns null if no container was given in the constructor.
104 */
105 public function getCallableResolver(): ?CallableResolver
106 {
107 return $this->callableResolver;
108 }
109 }
110