Verzeichnisstruktur phpBB-3.3.15
- Veröffentlicht
- 28.08.2024
So funktioniert es
|
Auf das letzte Element klicken. Dies geht jeweils ein Schritt zurück |
Auf das Icon klicken, dies öffnet das Verzeichnis. Nochmal klicken schließt das Verzeichnis. |
|
(Beispiel Datei-Icons)
|
Auf das Icon klicken um den Quellcode anzuzeigen |
ControllerResolver.php
001 <?php
002
003 /*
004 * This file is part of the Symfony package.
005 *
006 * (c) Fabien Potencier <fabien@symfony.com>
007 *
008 * For the full copyright and license information, please view the LICENSE
009 * file that was distributed with this source code.
010 */
011
012 namespace Symfony\Component\HttpKernel\Controller;
013
014 use Psr\Log\LoggerInterface;
015 use Symfony\Component\HttpFoundation\Request;
016
017 /**
018 * This implementation uses the '_controller' request attribute to determine
019 * the controller to execute and uses the request attributes to determine
020 * the controller method arguments.
021 *
022 * @author Fabien Potencier <fabien@symfony.com>
023 */
024 class ControllerResolver implements ArgumentResolverInterface, ControllerResolverInterface
025 {
026 private $logger;
027
028 /**
029 * If the ...$arg functionality is available.
030 *
031 * Requires at least PHP 5.6.0 or HHVM 3.9.1
032 *
033 * @var bool
034 */
035 private $supportsVariadic;
036
037 /**
038 * If scalar types exists.
039 *
040 * @var bool
041 */
042 private $supportsScalarTypes;
043
044 public function __construct(LoggerInterface $logger = null)
045 {
046 $this->logger = $logger;
047
048 $this->supportsVariadic = method_exists('ReflectionParameter', 'isVariadic');
049 $this->supportsScalarTypes = method_exists('ReflectionParameter', 'getType');
050 }
051
052 /**
053 * {@inheritdoc}
054 *
055 * This method looks for a '_controller' request attribute that represents
056 * the controller name (a string like ClassName::MethodName).
057 */
058 public function getController(Request $request)
059 {
060 if (!$controller = $request->attributes->get('_controller')) {
061 if (null !== $this->logger) {
062 $this->logger->warning('Unable to look for the controller as the "_controller" parameter is missing.');
063 }
064
065 return false;
066 }
067
068 if (\is_array($controller)) {
069 return $controller;
070 }
071
072 if (\is_object($controller)) {
073 if (method_exists($controller, '__invoke')) {
074 return $controller;
075 }
076
077 throw new \InvalidArgumentException(sprintf('Controller "%s" for URI "%s" is not callable.', \get_class($controller), $request->getPathInfo()));
078 }
079
080 if (\is_string($controller) && false === strpos($controller, ':')) {
081 if (method_exists($controller, '__invoke')) {
082 return $this->instantiateController($controller);
083 } elseif (\function_exists($controller)) {
084 return $controller;
085 }
086 }
087
088 try {
089 $callable = $this->createController($controller);
090 } catch (\InvalidArgumentException $e) {
091 throw new \InvalidArgumentException(sprintf('The controller for URI "%s" is not callable: ', $request->getPathInfo()).$e->getMessage(), 0, $e);
092 }
093
094 return $callable;
095 }
096
097 /**
098 * {@inheritdoc}
099 *
100 * @deprecated This method is deprecated as of 3.1 and will be removed in 4.0. Implement the ArgumentResolverInterface and inject it in the HttpKernel instead.
101 */
102 public function getArguments(Request $request, $controller)
103 {
104 @trigger_error(sprintf('The "%s()" method is deprecated as of 3.1 and will be removed in 4.0. Implement the %s and inject it in the HttpKernel instead.', __METHOD__, ArgumentResolverInterface::class), \E_USER_DEPRECATED);
105
106 if (\is_array($controller)) {
107 $r = new \ReflectionMethod($controller[0], $controller[1]);
108 } elseif (\is_object($controller) && !$controller instanceof \Closure) {
109 $r = new \ReflectionObject($controller);
110 $r = $r->getMethod('__invoke');
111 } else {
112 $r = new \ReflectionFunction($controller);
113 }
114
115 return $this->doGetArguments($request, $controller, $r->getParameters());
116 }
117
118 /**
119 * @param callable $controller
120 * @param \ReflectionParameter[] $parameters
121 *
122 * @return array The arguments to use when calling the action
123 *
124 * @deprecated This method is deprecated as of 3.1 and will be removed in 4.0. Implement the ArgumentResolverInterface and inject it in the HttpKernel instead.
125 */
126 protected function doGetArguments(Request $request, $controller, array $parameters)
127 {
128 @trigger_error(sprintf('The "%s()" method is deprecated as of 3.1 and will be removed in 4.0. Implement the %s and inject it in the HttpKernel instead.', __METHOD__, ArgumentResolverInterface::class), \E_USER_DEPRECATED);
129
130 $attributes = $request->attributes->all();
131 $arguments = [];
132 foreach ($parameters as $param) {
133 if (\array_key_exists($param->name, $attributes)) {
134 if ($this->supportsVariadic && $param->isVariadic() && \is_array($attributes[$param->name])) {
135 $arguments = array_merge($arguments, array_values($attributes[$param->name]));
136 } else {
137 $arguments[] = $attributes[$param->name];
138 }
139 } elseif ($this->typeMatchesRequestClass($param, $request)) {
140 $arguments[] = $request;
141 } elseif ($param->isDefaultValueAvailable()) {
142 $arguments[] = $param->getDefaultValue();
143 } elseif ($this->supportsScalarTypes && $param->hasType() && $param->allowsNull()) {
144 $arguments[] = null;
145 } else {
146 if (\is_array($controller)) {
147 $repr = sprintf('%s::%s()', \get_class($controller[0]), $controller[1]);
148 } elseif (\is_object($controller)) {
149 $repr = \get_class($controller);
150 } else {
151 $repr = $controller;
152 }
153
154 throw new \RuntimeException(sprintf('Controller "%s" requires that you provide a value for the "$%s" argument (because there is no default value or because there is a non optional argument after this one).', $repr, $param->name));
155 }
156 }
157
158 return $arguments;
159 }
160
161 /**
162 * Returns a callable for the given controller.
163 *
164 * @param string $controller A Controller string
165 *
166 * @return callable A PHP callable
167 *
168 * @throws \InvalidArgumentException When the controller cannot be created
169 */
170 protected function createController($controller)
171 {
172 if (false === strpos($controller, '::')) {
173 throw new \InvalidArgumentException(sprintf('Unable to find controller "%s".', $controller));
174 }
175
176 list($class, $method) = explode('::', $controller, 2);
177
178 if (!class_exists($class)) {
179 throw new \InvalidArgumentException(sprintf('Class "%s" does not exist.', $class));
180 }
181
182 $controller = [$this->instantiateController($class), $method];
183
184 if (!\is_callable($controller)) {
185 throw new \InvalidArgumentException($this->getControllerError($controller));
186 }
187
188 return $controller;
189 }
190
191 /**
192 * Returns an instantiated controller.
193 *
194 * @param string $class A class name
195 *
196 * @return object
197 */
198 protected function instantiateController($class)
199 {
200 return new $class();
201 }
202
203 private function getControllerError($callable)
204 {
205 if (\is_string($callable)) {
206 if (false !== strpos($callable, '::')) {
207 $callable = explode('::', $callable);
208 }
209
210 if (class_exists($callable) && !method_exists($callable, '__invoke')) {
211 return sprintf('Class "%s" does not have a method "__invoke".', $callable);
212 }
213
214 if (!\function_exists($callable)) {
215 return sprintf('Function "%s" does not exist.', $callable);
216 }
217 }
218
219 if (!\is_array($callable)) {
220 return sprintf('Invalid type for controller given, expected string or array, got "%s".', \gettype($callable));
221 }
222
223 if (2 !== \count($callable)) {
224 return 'Invalid format for controller, expected [controller, method] or controller::method.';
225 }
226
227 list($controller, $method) = $callable;
228
229 if (\is_string($controller) && !class_exists($controller)) {
230 return sprintf('Class "%s" does not exist.', $controller);
231 }
232
233 $className = \is_object($controller) ? \get_class($controller) : $controller;
234
235 if (method_exists($controller, $method)) {
236 return sprintf('Method "%s" on class "%s" should be public and non-abstract.', $method, $className);
237 }
238
239 $collection = get_class_methods($controller);
240
241 $alternatives = [];
242
243 foreach ($collection as $item) {
244 $lev = levenshtein($method, $item);
245
246 if ($lev <= \strlen($method) / 3 || false !== strpos($item, $method)) {
247 $alternatives[] = $item;
248 }
249 }
250
251 asort($alternatives);
252
253 $message = sprintf('Expected method "%s" on class "%s"', $method, $className);
254
255 if (\count($alternatives) > 0) {
256 $message .= sprintf(', did you mean "%s"?', implode('", "', $alternatives));
257 } else {
258 $message .= sprintf('. Available methods: "%s".', implode('", "', $collection));
259 }
260
261 return $message;
262 }
263
264 /**
265 * @return bool
266 */
267 private function typeMatchesRequestClass(\ReflectionParameter $param, Request $request)
268 {
269 if (!method_exists($param, 'getType')) {
270 return $param->getClass() && $param->getClass()->isInstance($request);
271 }
272
273 if (!($type = $param->getType()) || $type->isBuiltin()) {
274 return false;
275 }
276
277 $class = new \ReflectionClass($type instanceof \ReflectionNamedType ? $type->getName() : (string) $type);
278
279 return $class && $class->isInstance($request);
280 }
281 }
282