PluginProbe
BetterDocs – AI Documentation, Knowledge Base, MCP Server, Docs, Wikis, FAQ & Chatbot / 4.9.0
BetterDocs – AI Documentation, Knowledge Base, MCP Server, Docs, Wikis, FAQ & Chatbot v4.9.0
4.9.1 4.9.0 4.8.2 4.8.1 4.8.0 4.7.0 4.6.2 4.6.1 4.6.0 4.5.6 4.5.5 4.5.4 4.5.3 4.5.2 4.5.1 4.5.0 4.4.1 4.4.0 3.3.4 3.4.0 3.4.1 3.4.2 3.5.0 3.5.1 3.5.2 All 199 releases
betterdocs / includes / Dependencies / Invoker / Invoker.php

Invoker.php in BetterDocs – AI Documentation, Knowledge Base, MCP Server, Docs, Wikis, FAQ & Chatbot 4.9.0, at includes/Dependencies/Invoker/Invoker.php

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