These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | |||
3 | namespace Anax\Route; |
||
4 | |||
5 | use Anax\Commons\ContainerInjectableInterface; |
||
6 | use Anax\Route\Exception\ConfigurationException; |
||
7 | use Anax\Route\Exception\NotFoundException; |
||
8 | |||
9 | /** |
||
10 | * Call a routes handler and return the results. |
||
11 | */ |
||
12 | class RouteHandler |
||
13 | { |
||
14 | /** |
||
15 | * Handle the action for a route and return the results. |
||
16 | * |
||
17 | * @param string $method the request method. |
||
18 | * @param string $path that was matched. |
||
19 | * @param string|array $action base for the callable. |
||
20 | * @param array $arguments optional arguments. |
||
21 | * @param ContainerInjectableInterface $di container with services. |
||
22 | * |
||
23 | * @return mixed as the result from the route handler. |
||
24 | */ |
||
25 | 110 | public function handle( |
|
26 | string $method = null, |
||
27 | string $path = null, |
||
28 | $action, |
||
29 | array $arguments = [], |
||
30 | ContainerInjectableInterface $di = null |
||
31 | ) { |
||
32 | 110 | if (is_null($action)) { |
|
33 | 1 | return; |
|
34 | } |
||
35 | |||
36 | 109 | if (is_callable($action)) { |
|
37 | 92 | return $this->handleAsCallable($action, $arguments); |
|
38 | } |
||
39 | |||
40 | 17 | if (is_string($action) && class_exists($action)) { |
|
41 | 16 | $callable = $this->isControllerAction($method, $path, $action); |
|
42 | 16 | if ($callable) { |
|
43 | 16 | return $this->handleAsControllerAction($callable); |
|
44 | } |
||
45 | } |
||
46 | |||
47 | // if ($di |
||
48 | // && is_array($action) |
||
49 | // && isset($action[0]) |
||
50 | // && isset($action[1]) |
||
51 | // && is_string($action[0]) |
||
52 | // ) { |
||
53 | // // Try to load service from app/di injected container |
||
54 | // return $this->handleUsingDi($action, $arguments, $di); |
||
55 | // } |
||
56 | // |
||
57 | 1 | throw new ConfigurationException("Handler for route does not seem to be a callable action."); |
|
58 | } |
||
59 | |||
60 | |||
61 | |||
62 | /** |
||
63 | * Check if items can be used to call a controller action, verify |
||
64 | * that the controller exists, the action has a class-method to call. |
||
65 | * |
||
66 | * @param string $method the request method. |
||
67 | * @param string $path the matched path, base for the controller action |
||
68 | * and the arguments. |
||
69 | * @param string $class the controller class |
||
70 | * |
||
71 | * @return array with callable details. |
||
72 | */ |
||
73 | 16 | protected function isControllerAction( |
|
74 | string $method = null, |
||
75 | string $path = null, |
||
76 | string $class |
||
77 | ) { |
||
78 | 16 | $args = explode("/", $path); |
|
79 | 16 | $action = array_shift($args); |
|
80 | 16 | $action = empty($action) ? "index" : $action; |
|
81 | 16 | $action1 = "${action}Action${method}"; |
|
82 | 16 | $action2 = "${action}Action"; |
|
83 | |||
84 | 16 | $refl = null; |
|
85 | 16 | foreach ([$action1, $action2] as $action) { |
|
86 | try { |
||
87 | 16 | $refl = new \ReflectionMethod($class, $action); |
|
88 | 16 | if (!$refl->isPublic()) { |
|
89 | throw new NotFoundException("Controller method '$class::$action' is not a public method."); |
||
90 | } |
||
91 | |||
92 | 16 | return [$class, $action, $args]; |
|
93 | 13 | } catch (\ReflectionException $e) { |
|
0 ignored issues
–
show
Coding Style
Comprehensibility
introduced
by
Loading history...
|
|||
94 | ; |
||
95 | } |
||
96 | } |
||
97 | |||
98 | return false; |
||
99 | } |
||
100 | |||
101 | |||
102 | |||
103 | /** |
||
104 | * Call the controller action with optional arguments and call |
||
105 | * initialisation methods if available. |
||
106 | * |
||
107 | * @param string $callable with details on what controller action to call. |
||
108 | * |
||
109 | * @return mixed result from the handler. |
||
110 | */ |
||
111 | protected function handleAsControllerAction(array $callable) |
||
112 | { |
||
113 | 16 | $class = $callable[0]; |
|
114 | 16 | $action = $callable[1]; |
|
115 | 16 | $args = $callable[2]; |
|
116 | |||
117 | 16 | $obj = new $class(); |
|
118 | 16 | $refl = new \ReflectionMethod($class, "initialize"); |
|
119 | 16 | if ($refl->isPublic()) { |
|
120 | 16 | $obj->initialize(); |
|
121 | } |
||
122 | |||
123 | try { |
||
124 | 16 | $res = $obj->$action(...$args); |
|
125 | 2 | } catch (\ArgumentCountError $e) { |
|
126 | 1 | throw new NotFoundException($e->getMessage()); |
|
127 | 1 | } catch (\TypeError $e) { |
|
128 | 1 | throw new NotFoundException($e->getMessage()); |
|
129 | } |
||
130 | |||
131 | 14 | return $res; |
|
132 | } |
||
133 | |||
134 | |||
135 | |||
136 | /** |
||
137 | * Handle as callable support callables where the method is not static. |
||
138 | * |
||
139 | * @param string|array $action base for the callable |
||
140 | * @param array $arguments optional arguments |
||
141 | * @param ContainerInjectableInterface $di container with services |
||
142 | * |
||
143 | * @return mixed as the result from the route handler. |
||
144 | */ |
||
145 | protected function handleAsCallable( |
||
146 | $action, |
||
147 | array $arguments |
||
148 | ) { |
||
149 | 92 | if (is_array($action) |
|
150 | 92 | && isset($action[0]) |
|
151 | 92 | && isset($action[1]) |
|
152 | 92 | && is_string($action[0]) |
|
153 | 92 | && is_string($action[1]) |
|
154 | 92 | && class_exists($action[0]) |
|
155 | ) { |
||
156 | // ["SomeClass", "someMethod"] but not static |
||
157 | 2 | $refl = new \ReflectionMethod($action[0], $action[1]); |
|
158 | 2 | if ($refl->isPublic() && !$refl->isStatic()) { |
|
159 | 1 | $obj = new $action[0](); |
|
160 | 1 | return $obj->{$action[1]}(); |
|
161 | } |
||
162 | } |
||
163 | |||
164 | 91 | return call_user_func($action, ...$arguments); |
|
165 | } |
||
166 | |||
167 | |||
168 | |||
169 | // /** |
||
170 | // * Load callable as a service from the $di container. |
||
171 | // * |
||
172 | // * @param string|array $action base for the callable |
||
173 | // * @param array $arguments optional arguments |
||
174 | // * @param ContainerInjectableInterface $di container with services |
||
175 | // * |
||
176 | // * @return mixed as the result from the route handler. |
||
177 | // */ |
||
178 | // protected function handleUsingDi( |
||
179 | // $action, |
||
180 | // array $arguments, |
||
181 | // ContainerInjectableInterface $di |
||
182 | // ) { |
||
183 | // if (!$di->has($action[0])) { |
||
184 | // throw new ConfigurationException("Routehandler '{$action[0]}' not loaded in di."); |
||
185 | // } |
||
186 | // |
||
187 | // $service = $di->get($action[0]); |
||
188 | // if (!is_callable([$service, $action[1]])) { |
||
189 | // throw new ConfigurationException( |
||
190 | // "Routehandler '{$action[0]}' does not have a callable method '{$action[1]}'." |
||
191 | // ); |
||
192 | // } |
||
193 | // |
||
194 | // return call_user_func( |
||
195 | // [$service, $action[1]], |
||
196 | // ...$arguments |
||
197 | // ); |
||
198 | // } |
||
199 | } |
||
200 |