diff options
Diffstat (limited to 'vendor/symfony/http-kernel/Controller')
15 files changed, 1002 insertions, 0 deletions
diff --git a/vendor/symfony/http-kernel/Controller/ArgumentResolver.php b/vendor/symfony/http-kernel/Controller/ArgumentResolver.php new file mode 100644 index 0000000000..2c17125c5a --- /dev/null +++ b/vendor/symfony/http-kernel/Controller/ArgumentResolver.php @@ -0,0 +1,94 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Controller; + +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpKernel\Controller\ArgumentResolver\DefaultValueResolver; +use Symfony\Component\HttpKernel\Controller\ArgumentResolver\RequestAttributeValueResolver; +use Symfony\Component\HttpKernel\Controller\ArgumentResolver\RequestValueResolver; +use Symfony\Component\HttpKernel\Controller\ArgumentResolver\SessionValueResolver; +use Symfony\Component\HttpKernel\Controller\ArgumentResolver\VariadicValueResolver; +use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadataFactory; +use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadataFactoryInterface; + +/** + * Responsible for resolving the arguments passed to an action. + * + * @author Iltar van der Berg <kjarli@gmail.com> + */ +final class ArgumentResolver implements ArgumentResolverInterface +{ + private $argumentMetadataFactory; + + /** + * @var iterable|ArgumentValueResolverInterface[] + */ + private $argumentValueResolvers; + + public function __construct(ArgumentMetadataFactoryInterface $argumentMetadataFactory = null, $argumentValueResolvers = array()) + { + $this->argumentMetadataFactory = $argumentMetadataFactory ?: new ArgumentMetadataFactory(); + $this->argumentValueResolvers = $argumentValueResolvers ?: self::getDefaultArgumentValueResolvers(); + } + + /** + * {@inheritdoc} + */ + public function getArguments(Request $request, $controller) + { + $arguments = array(); + + foreach ($this->argumentMetadataFactory->createArgumentMetadata($controller) as $metadata) { + foreach ($this->argumentValueResolvers as $resolver) { + if (!$resolver->supports($request, $metadata)) { + continue; + } + + $resolved = $resolver->resolve($request, $metadata); + + if (!$resolved instanceof \Generator) { + throw new \InvalidArgumentException(sprintf('%s::resolve() must yield at least one value.', get_class($resolver))); + } + + foreach ($resolved as $append) { + $arguments[] = $append; + } + + // continue to the next controller argument + continue 2; + } + + $representative = $controller; + + if (is_array($representative)) { + $representative = sprintf('%s::%s()', get_class($representative[0]), $representative[1]); + } elseif (is_object($representative)) { + $representative = get_class($representative); + } + + throw new \RuntimeException(sprintf('Controller "%s" requires that you provide a value for the "$%s" argument. Either the argument is nullable and no null value has been provided, no default value has been provided or because there is a non optional argument after this one.', $representative, $metadata->getName())); + } + + return $arguments; + } + + public static function getDefaultArgumentValueResolvers() + { + return array( + new RequestAttributeValueResolver(), + new RequestValueResolver(), + new SessionValueResolver(), + new DefaultValueResolver(), + new VariadicValueResolver(), + ); + } +} diff --git a/vendor/symfony/http-kernel/Controller/ArgumentResolver/DefaultValueResolver.php b/vendor/symfony/http-kernel/Controller/ArgumentResolver/DefaultValueResolver.php new file mode 100644 index 0000000000..e58fd3ab2b --- /dev/null +++ b/vendor/symfony/http-kernel/Controller/ArgumentResolver/DefaultValueResolver.php @@ -0,0 +1,40 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Controller\ArgumentResolver; + +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpKernel\Controller\ArgumentValueResolverInterface; +use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata; + +/** + * Yields the default value defined in the action signature when no value has been given. + * + * @author Iltar van der Berg <kjarli@gmail.com> + */ +final class DefaultValueResolver implements ArgumentValueResolverInterface +{ + /** + * {@inheritdoc} + */ + public function supports(Request $request, ArgumentMetadata $argument) + { + return $argument->hasDefaultValue() || (null !== $argument->getType() && $argument->isNullable() && !$argument->isVariadic()); + } + + /** + * {@inheritdoc} + */ + public function resolve(Request $request, ArgumentMetadata $argument) + { + yield $argument->hasDefaultValue() ? $argument->getDefaultValue() : null; + } +} diff --git a/vendor/symfony/http-kernel/Controller/ArgumentResolver/RequestAttributeValueResolver.php b/vendor/symfony/http-kernel/Controller/ArgumentResolver/RequestAttributeValueResolver.php new file mode 100644 index 0000000000..05be372d84 --- /dev/null +++ b/vendor/symfony/http-kernel/Controller/ArgumentResolver/RequestAttributeValueResolver.php @@ -0,0 +1,40 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Controller\ArgumentResolver; + +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpKernel\Controller\ArgumentValueResolverInterface; +use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata; + +/** + * Yields a non-variadic argument's value from the request attributes. + * + * @author Iltar van der Berg <kjarli@gmail.com> + */ +final class RequestAttributeValueResolver implements ArgumentValueResolverInterface +{ + /** + * {@inheritdoc} + */ + public function supports(Request $request, ArgumentMetadata $argument) + { + return !$argument->isVariadic() && $request->attributes->has($argument->getName()); + } + + /** + * {@inheritdoc} + */ + public function resolve(Request $request, ArgumentMetadata $argument) + { + yield $request->attributes->get($argument->getName()); + } +} diff --git a/vendor/symfony/http-kernel/Controller/ArgumentResolver/RequestValueResolver.php b/vendor/symfony/http-kernel/Controller/ArgumentResolver/RequestValueResolver.php new file mode 100644 index 0000000000..2a5060a612 --- /dev/null +++ b/vendor/symfony/http-kernel/Controller/ArgumentResolver/RequestValueResolver.php @@ -0,0 +1,40 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Controller\ArgumentResolver; + +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpKernel\Controller\ArgumentValueResolverInterface; +use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata; + +/** + * Yields the same instance as the request object passed along. + * + * @author Iltar van der Berg <kjarli@gmail.com> + */ +final class RequestValueResolver implements ArgumentValueResolverInterface +{ + /** + * {@inheritdoc} + */ + public function supports(Request $request, ArgumentMetadata $argument) + { + return Request::class === $argument->getType() || is_subclass_of($argument->getType(), Request::class); + } + + /** + * {@inheritdoc} + */ + public function resolve(Request $request, ArgumentMetadata $argument) + { + yield $request; + } +} diff --git a/vendor/symfony/http-kernel/Controller/ArgumentResolver/ServiceValueResolver.php b/vendor/symfony/http-kernel/Controller/ArgumentResolver/ServiceValueResolver.php new file mode 100644 index 0000000000..b1da6a9a75 --- /dev/null +++ b/vendor/symfony/http-kernel/Controller/ArgumentResolver/ServiceValueResolver.php @@ -0,0 +1,48 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Controller\ArgumentResolver; + +use Psr\Container\ContainerInterface; +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpKernel\Controller\ArgumentValueResolverInterface; +use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata; + +/** + * Yields a service keyed by _controller and argument name. + * + * @author Nicolas Grekas <p@tchwork.com> + */ +final class ServiceValueResolver implements ArgumentValueResolverInterface +{ + private $container; + + public function __construct(ContainerInterface $container) + { + $this->container = $container; + } + + /** + * {@inheritdoc} + */ + public function supports(Request $request, ArgumentMetadata $argument) + { + return is_string($controller = $request->attributes->get('_controller')) && $this->container->has($controller) && $this->container->get($controller)->has($argument->getName()); + } + + /** + * {@inheritdoc} + */ + public function resolve(Request $request, ArgumentMetadata $argument) + { + yield $this->container->get($request->attributes->get('_controller'))->get($argument->getName()); + } +} diff --git a/vendor/symfony/http-kernel/Controller/ArgumentResolver/SessionValueResolver.php b/vendor/symfony/http-kernel/Controller/ArgumentResolver/SessionValueResolver.php new file mode 100644 index 0000000000..9e656d281b --- /dev/null +++ b/vendor/symfony/http-kernel/Controller/ArgumentResolver/SessionValueResolver.php @@ -0,0 +1,46 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Controller\ArgumentResolver; + +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Session\SessionInterface; +use Symfony\Component\HttpKernel\Controller\ArgumentValueResolverInterface; +use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata; + +/** + * Yields the Session. + * + * @author Iltar van der Berg <kjarli@gmail.com> + */ +final class SessionValueResolver implements ArgumentValueResolverInterface +{ + /** + * {@inheritdoc} + */ + public function supports(Request $request, ArgumentMetadata $argument) + { + $type = $argument->getType(); + if (SessionInterface::class !== $type && !is_subclass_of($type, SessionInterface::class)) { + return false; + } + + return $request->getSession() instanceof $type; + } + + /** + * {@inheritdoc} + */ + public function resolve(Request $request, ArgumentMetadata $argument) + { + yield $request->getSession(); + } +} diff --git a/vendor/symfony/http-kernel/Controller/ArgumentResolver/VariadicValueResolver.php b/vendor/symfony/http-kernel/Controller/ArgumentResolver/VariadicValueResolver.php new file mode 100644 index 0000000000..56ae5f191c --- /dev/null +++ b/vendor/symfony/http-kernel/Controller/ArgumentResolver/VariadicValueResolver.php @@ -0,0 +1,48 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Controller\ArgumentResolver; + +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpKernel\Controller\ArgumentValueResolverInterface; +use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata; + +/** + * Yields a variadic argument's values from the request attributes. + * + * @author Iltar van der Berg <kjarli@gmail.com> + */ +final class VariadicValueResolver implements ArgumentValueResolverInterface +{ + /** + * {@inheritdoc} + */ + public function supports(Request $request, ArgumentMetadata $argument) + { + return $argument->isVariadic() && $request->attributes->has($argument->getName()); + } + + /** + * {@inheritdoc} + */ + public function resolve(Request $request, ArgumentMetadata $argument) + { + $values = $request->attributes->get($argument->getName()); + + if (!is_array($values)) { + throw new \InvalidArgumentException(sprintf('The action argument "...$%1$s" is required to be an array, the request attribute "%1$s" contains a type of "%2$s" instead.', $argument->getName(), gettype($values))); + } + + foreach ($values as $value) { + yield $value; + } + } +} diff --git a/vendor/symfony/http-kernel/Controller/ArgumentResolverInterface.php b/vendor/symfony/http-kernel/Controller/ArgumentResolverInterface.php new file mode 100644 index 0000000000..5c51230966 --- /dev/null +++ b/vendor/symfony/http-kernel/Controller/ArgumentResolverInterface.php @@ -0,0 +1,35 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Controller; + +use Symfony\Component\HttpFoundation\Request; + +/** + * An ArgumentResolverInterface instance knows how to determine the + * arguments for a specific action. + * + * @author Fabien Potencier <fabien@symfony.com> + */ +interface ArgumentResolverInterface +{ + /** + * Returns the arguments to pass to the controller. + * + * @param Request $request + * @param callable $controller + * + * @return array An array of arguments to pass to the controller + * + * @throws \RuntimeException When no value could be provided for a required argument + */ + public function getArguments(Request $request, $controller); +} diff --git a/vendor/symfony/http-kernel/Controller/ArgumentValueResolverInterface.php b/vendor/symfony/http-kernel/Controller/ArgumentValueResolverInterface.php new file mode 100644 index 0000000000..fd7b09ecf2 --- /dev/null +++ b/vendor/symfony/http-kernel/Controller/ArgumentValueResolverInterface.php @@ -0,0 +1,43 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Controller; + +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata; + +/** + * Responsible for resolving the value of an argument based on its metadata. + * + * @author Iltar van der Berg <kjarli@gmail.com> + */ +interface ArgumentValueResolverInterface +{ + /** + * Whether this resolver can resolve the value for the given ArgumentMetadata. + * + * @param Request $request + * @param ArgumentMetadata $argument + * + * @return bool + */ + public function supports(Request $request, ArgumentMetadata $argument); + + /** + * Returns the possible value(s). + * + * @param Request $request + * @param ArgumentMetadata $argument + * + * @return \Generator + */ + public function resolve(Request $request, ArgumentMetadata $argument); +} diff --git a/vendor/symfony/http-kernel/Controller/ContainerControllerResolver.php b/vendor/symfony/http-kernel/Controller/ContainerControllerResolver.php new file mode 100644 index 0000000000..1a107c62f6 --- /dev/null +++ b/vendor/symfony/http-kernel/Controller/ContainerControllerResolver.php @@ -0,0 +1,76 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Controller; + +use Psr\Container\ContainerInterface; +use Psr\Log\LoggerInterface; + +/** + * A controller resolver searching for a controller in a psr-11 container when using the "service:method" notation. + * + * @author Fabien Potencier <fabien@symfony.com> + * @author Maxime Steinhausser <maxime.steinhausser@gmail.com> + */ +class ContainerControllerResolver extends ControllerResolver +{ + protected $container; + + public function __construct(ContainerInterface $container, LoggerInterface $logger = null) + { + $this->container = $container; + + parent::__construct($logger); + } + + /** + * Returns a callable for the given controller. + * + * @param string $controller A Controller string + * + * @return mixed A PHP callable + * + * @throws \LogicException When the name could not be parsed + * @throws \InvalidArgumentException When the controller class does not exist + */ + protected function createController($controller) + { + if (false !== strpos($controller, '::')) { + return parent::createController($controller); + } + + if (1 == substr_count($controller, ':')) { + // controller in the "service:method" notation + list($service, $method) = explode(':', $controller, 2); + + return array($this->container->get($service), $method); + } + + if ($this->container->has($controller) && method_exists($service = $this->container->get($controller), '__invoke')) { + // invokable controller in the "service" notation + return $service; + } + + throw new \LogicException(sprintf('Unable to parse the controller name "%s".', $controller)); + } + + /** + * {@inheritdoc} + */ + protected function instantiateController($class) + { + if ($this->container->has($class)) { + return $this->container->get($class); + } + + return parent::instantiateController($class); + } +} diff --git a/vendor/symfony/http-kernel/Controller/ControllerReference.php b/vendor/symfony/http-kernel/Controller/ControllerReference.php new file mode 100644 index 0000000000..3d1592e83a --- /dev/null +++ b/vendor/symfony/http-kernel/Controller/ControllerReference.php @@ -0,0 +1,46 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Controller; + +use Symfony\Component\HttpKernel\Fragment\FragmentRendererInterface; + +/** + * Acts as a marker and a data holder for a Controller. + * + * Some methods in Symfony accept both a URI (as a string) or a controller as + * an argument. In the latter case, instead of passing an array representing + * the controller, you can use an instance of this class. + * + * @author Fabien Potencier <fabien@symfony.com> + * + * @see FragmentRendererInterface + */ +class ControllerReference +{ + public $controller; + public $attributes = array(); + public $query = array(); + + /** + * Constructor. + * + * @param string $controller The controller name + * @param array $attributes An array of parameters to add to the Request attributes + * @param array $query An array of parameters to add to the Request query string + */ + public function __construct($controller, array $attributes = array(), array $query = array()) + { + $this->controller = $controller; + $this->attributes = $attributes; + $this->query = $query; + } +} diff --git a/vendor/symfony/http-kernel/Controller/ControllerResolver.php b/vendor/symfony/http-kernel/Controller/ControllerResolver.php new file mode 100644 index 0000000000..f51a5a8efb --- /dev/null +++ b/vendor/symfony/http-kernel/Controller/ControllerResolver.php @@ -0,0 +1,265 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Controller; + +use Psr\Log\LoggerInterface; +use Symfony\Component\HttpFoundation\Request; + +/** + * ControllerResolver. + * + * This implementation uses the '_controller' request attribute to determine + * the controller to execute and uses the request attributes to determine + * the controller method arguments. + * + * @author Fabien Potencier <fabien@symfony.com> + */ +class ControllerResolver implements ArgumentResolverInterface, ControllerResolverInterface +{ + private $logger; + + /** + * If the ...$arg functionality is available. + * + * Requires at least PHP 5.6.0 or HHVM 3.9.1 + * + * @var bool + */ + private $supportsVariadic; + + /** + * If scalar types exists. + * + * @var bool + */ + private $supportsScalarTypes; + + /** + * Constructor. + * + * @param LoggerInterface $logger A LoggerInterface instance + */ + public function __construct(LoggerInterface $logger = null) + { + $this->logger = $logger; + + $this->supportsVariadic = method_exists('ReflectionParameter', 'isVariadic'); + $this->supportsScalarTypes = method_exists('ReflectionParameter', 'getType'); + } + + /** + * {@inheritdoc} + * + * This method looks for a '_controller' request attribute that represents + * the controller name (a string like ClassName::MethodName). + */ + public function getController(Request $request) + { + if (!$controller = $request->attributes->get('_controller')) { + if (null !== $this->logger) { + $this->logger->warning('Unable to look for the controller as the "_controller" parameter is missing.'); + } + + return false; + } + + if (is_array($controller)) { + return $controller; + } + + if (is_object($controller)) { + if (method_exists($controller, '__invoke')) { + return $controller; + } + + throw new \InvalidArgumentException(sprintf('Controller "%s" for URI "%s" is not callable.', get_class($controller), $request->getPathInfo())); + } + + if (false === strpos($controller, ':')) { + if (method_exists($controller, '__invoke')) { + return $this->instantiateController($controller); + } elseif (function_exists($controller)) { + return $controller; + } + } + + $callable = $this->createController($controller); + + if (!is_callable($callable)) { + throw new \InvalidArgumentException(sprintf('The controller for URI "%s" is not callable. %s', $request->getPathInfo(), $this->getControllerError($callable))); + } + + return $callable; + } + + /** + * {@inheritdoc} + * + * @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. + */ + public function getArguments(Request $request, $controller) + { + @trigger_error(sprintf('%s 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); + + if (is_array($controller)) { + $r = new \ReflectionMethod($controller[0], $controller[1]); + } elseif (is_object($controller) && !$controller instanceof \Closure) { + $r = new \ReflectionObject($controller); + $r = $r->getMethod('__invoke'); + } else { + $r = new \ReflectionFunction($controller); + } + + return $this->doGetArguments($request, $controller, $r->getParameters()); + } + + /** + * @param Request $request + * @param callable $controller + * @param \ReflectionParameter[] $parameters + * + * @return array The arguments to use when calling the action + * + * @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. + */ + protected function doGetArguments(Request $request, $controller, array $parameters) + { + @trigger_error(sprintf('%s 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); + + $attributes = $request->attributes->all(); + $arguments = array(); + foreach ($parameters as $param) { + if (array_key_exists($param->name, $attributes)) { + if ($this->supportsVariadic && $param->isVariadic() && is_array($attributes[$param->name])) { + $arguments = array_merge($arguments, array_values($attributes[$param->name])); + } else { + $arguments[] = $attributes[$param->name]; + } + } elseif ($param->getClass() && $param->getClass()->isInstance($request)) { + $arguments[] = $request; + } elseif ($param->isDefaultValueAvailable()) { + $arguments[] = $param->getDefaultValue(); + } elseif ($this->supportsScalarTypes && $param->hasType() && $param->allowsNull()) { + $arguments[] = null; + } else { + if (is_array($controller)) { + $repr = sprintf('%s::%s()', get_class($controller[0]), $controller[1]); + } elseif (is_object($controller)) { + $repr = get_class($controller); + } else { + $repr = $controller; + } + + 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)); + } + } + + return $arguments; + } + + /** + * Returns a callable for the given controller. + * + * @param string $controller A Controller string + * + * @return callable A PHP callable + * + * @throws \InvalidArgumentException + */ + protected function createController($controller) + { + if (false === strpos($controller, '::')) { + throw new \InvalidArgumentException(sprintf('Unable to find controller "%s".', $controller)); + } + + list($class, $method) = explode('::', $controller, 2); + + if (!class_exists($class)) { + throw new \InvalidArgumentException(sprintf('Class "%s" does not exist.', $class)); + } + + return array($this->instantiateController($class), $method); + } + + /** + * Returns an instantiated controller. + * + * @param string $class A class name + * + * @return object + */ + protected function instantiateController($class) + { + return new $class(); + } + + private function getControllerError($callable) + { + if (is_string($callable)) { + if (false !== strpos($callable, '::')) { + $callable = explode('::', $callable); + } + + if (class_exists($callable) && !method_exists($callable, '__invoke')) { + return sprintf('Class "%s" does not have a method "__invoke".', $callable); + } + + if (!function_exists($callable)) { + return sprintf('Function "%s" does not exist.', $callable); + } + } + + if (!is_array($callable)) { + return sprintf('Invalid type for controller given, expected string or array, got "%s".', gettype($callable)); + } + + if (2 !== count($callable)) { + return sprintf('Invalid format for controller, expected array(controller, method) or controller::method.'); + } + + list($controller, $method) = $callable; + + if (is_string($controller) && !class_exists($controller)) { + return sprintf('Class "%s" does not exist.', $controller); + } + + $className = is_object($controller) ? get_class($controller) : $controller; + + if (method_exists($controller, $method)) { + return sprintf('Method "%s" on class "%s" should be public and non-abstract.', $method, $className); + } + + $collection = get_class_methods($controller); + + $alternatives = array(); + + foreach ($collection as $item) { + $lev = levenshtein($method, $item); + + if ($lev <= strlen($method) / 3 || false !== strpos($item, $method)) { + $alternatives[] = $item; + } + } + + asort($alternatives); + + $message = sprintf('Expected method "%s" on class "%s"', $method, $className); + + if (count($alternatives) > 0) { + $message .= sprintf(', did you mean "%s"?', implode('", "', $alternatives)); + } else { + $message .= sprintf('. Available methods: "%s".', implode('", "', $collection)); + } + + return $message; + } +} diff --git a/vendor/symfony/http-kernel/Controller/ControllerResolverInterface.php b/vendor/symfony/http-kernel/Controller/ControllerResolverInterface.php new file mode 100644 index 0000000000..0dd7cce96d --- /dev/null +++ b/vendor/symfony/http-kernel/Controller/ControllerResolverInterface.php @@ -0,0 +1,59 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Controller; + +use Symfony\Component\HttpFoundation\Request; + +/** + * A ControllerResolverInterface implementation knows how to determine the + * controller to execute based on a Request object. + * + * It can also determine the arguments to pass to the Controller. + * + * A Controller can be any valid PHP callable. + * + * @author Fabien Potencier <fabien@symfony.com> + */ +interface ControllerResolverInterface +{ + /** + * Returns the Controller instance associated with a Request. + * + * As several resolvers can exist for a single application, a resolver must + * return false when it is not able to determine the controller. + * + * The resolver must only throw an exception when it should be able to load + * controller but cannot because of some errors made by the developer. + * + * @param Request $request A Request instance + * + * @return callable|false A PHP callable representing the Controller, + * or false if this resolver is not able to determine the controller + * + * @throws \LogicException If the controller can't be found + */ + public function getController(Request $request); + + /** + * Returns the arguments to pass to the controller. + * + * @param Request $request A Request instance + * @param callable $controller A PHP callable + * + * @return array An array of arguments to pass to the controller + * + * @throws \RuntimeException When value for argument given is not provided + * + * @deprecated This method is deprecated as of 3.1 and will be removed in 4.0. Please use the {@see ArgumentResolverInterface} instead. + */ + public function getArguments(Request $request, $controller); +} diff --git a/vendor/symfony/http-kernel/Controller/TraceableArgumentResolver.php b/vendor/symfony/http-kernel/Controller/TraceableArgumentResolver.php new file mode 100644 index 0000000000..6fb0fa66ac --- /dev/null +++ b/vendor/symfony/http-kernel/Controller/TraceableArgumentResolver.php @@ -0,0 +1,44 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Controller; + +use Symfony\Component\Stopwatch\Stopwatch; +use Symfony\Component\HttpFoundation\Request; + +/** + * @author Fabien Potencier <fabien@symfony.com> + */ +class TraceableArgumentResolver implements ArgumentResolverInterface +{ + private $resolver; + private $stopwatch; + + public function __construct(ArgumentResolverInterface $resolver, Stopwatch $stopwatch) + { + $this->resolver = $resolver; + $this->stopwatch = $stopwatch; + } + + /** + * {@inheritdoc} + */ + public function getArguments(Request $request, $controller) + { + $e = $this->stopwatch->start('controller.get_arguments'); + + $ret = $this->resolver->getArguments($request, $controller); + + $e->stop(); + + return $ret; + } +} diff --git a/vendor/symfony/http-kernel/Controller/TraceableControllerResolver.php b/vendor/symfony/http-kernel/Controller/TraceableControllerResolver.php new file mode 100644 index 0000000000..ce291b1e3e --- /dev/null +++ b/vendor/symfony/http-kernel/Controller/TraceableControllerResolver.php @@ -0,0 +1,78 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Controller; + +use Symfony\Component\Stopwatch\Stopwatch; +use Symfony\Component\HttpFoundation\Request; + +/** + * TraceableControllerResolver. + * + * @author Fabien Potencier <fabien@symfony.com> + */ +class TraceableControllerResolver implements ControllerResolverInterface, ArgumentResolverInterface +{ + private $resolver; + private $stopwatch; + private $argumentResolver; + + /** + * Constructor. + * + * @param ControllerResolverInterface $resolver A ControllerResolverInterface instance + * @param Stopwatch $stopwatch A Stopwatch instance + * @param ArgumentResolverInterface $argumentResolver Only required for BC + */ + public function __construct(ControllerResolverInterface $resolver, Stopwatch $stopwatch, ArgumentResolverInterface $argumentResolver = null) + { + $this->resolver = $resolver; + $this->stopwatch = $stopwatch; + $this->argumentResolver = $argumentResolver; + + // BC + if (null === $this->argumentResolver) { + $this->argumentResolver = $resolver; + } + + if (!$this->argumentResolver instanceof TraceableArgumentResolver) { + $this->argumentResolver = new TraceableArgumentResolver($this->argumentResolver, $this->stopwatch); + } + } + + /** + * {@inheritdoc} + */ + public function getController(Request $request) + { + $e = $this->stopwatch->start('controller.get_callable'); + + $ret = $this->resolver->getController($request); + + $e->stop(); + + return $ret; + } + + /** + * {@inheritdoc} + * + * @deprecated This method is deprecated as of 3.1 and will be removed in 4.0. + */ + public function getArguments(Request $request, $controller) + { + @trigger_error(sprintf('The %s method is deprecated as of 3.1 and will be removed in 4.0. Please use the %s instead.', __METHOD__, TraceableArgumentResolver::class), E_USER_DEPRECATED); + + $ret = $this->argumentResolver->getArguments($request, $controller); + + return $ret; + } +} |
