PluginProbe
BetterDocs – AI Documentation, Knowledge Base, MCP Server, Docs, Wikis, FAQ & Chatbot / 4.8.0
BetterDocs – AI Documentation, Knowledge Base, MCP Server, Docs, Wikis, FAQ & Chatbot v4.8.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 / CallableResolver.php

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

126 lines 3.9 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 Closure;
7 use WPDeveloper\BetterDocs\Dependencies\Invoker\Exception\NotCallableException;
8 use WPDeveloper\BetterDocs\Dependencies\Psr\Container\ContainerInterface;
9 use WPDeveloper\BetterDocs\Dependencies\Psr\Container\NotFoundExceptionInterface;
10 use ReflectionException;
11 use ReflectionMethod;
12
13 /**
14 * Resolves a callable from a container.
15 */
16 class CallableResolver
17 {
18 /** @var ContainerInterface */
19 private $container;
20
21 public function __construct(ContainerInterface $container)
22 {
23 $this->container = $container;
24 }
25
26 /**
27 * Resolve the given callable into a real PHP callable.
28 *
29 * @param callable|string|array $callable
30 * @return callable Real PHP callable.
31 * @throws NotCallableException|ReflectionException
32 */
33 public function resolve($callable): callable
34 {
35 if (is_string($callable) && strpos($callable, '::') !== false) {
36 $callable = explode('::', $callable, 2);
37 }
38
39 $callable = $this->resolveFromContainer($callable);
40
41 if (! is_callable($callable)) {
42 throw NotCallableException::fromInvalidCallable($callable, true);
43 }
44
45 return $callable;
46 }
47
48 /**
49 * @param callable|string|array $callable
50 * @return callable|mixed
51 * @throws NotCallableException|ReflectionException
52 */
53 private function resolveFromContainer($callable)
54 {
55 // Shortcut for a very common use case
56 if ($callable instanceof Closure) {
57 return $callable;
58 }
59
60 // If it's already a callable there is nothing to do
61 if (is_callable($callable)) {
62 // TODO with PHP 8 that should not be necessary to check this anymore
63 if (! $this->isStaticCallToNonStaticMethod($callable)) {
64 return $callable;
65 }
66 }
67
68 // The callable is a container entry name
69 if (is_string($callable)) {
70 try {
71 return $this->container->get($callable);
72 } catch (NotFoundExceptionInterface $e) {
73 if ($this->container->has($callable)) {
74 throw $e;
75 }
76 throw NotCallableException::fromInvalidCallable($callable, true);
77 }
78 }
79
80 // The callable is an array whose first item is a container entry name
81 // e.g. ['some-container-entry', 'methodToCall']
82 if (is_array($callable) && is_string($callable[0])) {
83 try {
84 // Replace the container entry name by the actual object
85 $callable[0] = $this->container->get($callable[0]);
86 return $callable;
87 } catch (NotFoundExceptionInterface $e) {
88 if ($this->container->has($callable[0])) {
89 throw $e;
90 }
91 throw new NotCallableException(sprintf(
92 'Cannot call %s() on %s because it is not a class nor a valid container entry',
93 $callable[1],
94 $callable[0]
95 ));
96 }
97 }
98
99 // Unrecognized stuff, we let it fail later
100 return $callable;
101 }
102
103 /**
104 * Check if the callable represents a static call to a non-static method.
105 *
106 * @param mixed $callable
107 * @throws ReflectionException
108 */
109 private function isStaticCallToNonStaticMethod($callable): bool
110 {
111 if (is_array($callable) && is_string($callable[0])) {
112 [$class, $method] = $callable;
113
114 if (! method_exists($class, $method)) {
115 return false;
116 }
117
118 $reflection = new ReflectionMethod($class, $method);
119
120 return ! $reflection->isStatic();
121 }
122
123 return false;
124 }
125 }
126