ArgumentResolver.php 3.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. <?php
  2. /*
  3. * This file is part of the Symfony package.
  4. *
  5. * (c) Fabien Potencier <fabien@symfony.com>
  6. *
  7. * For the full copyright and license information, please view the LICENSE
  8. * file that was distributed with this source code.
  9. */
  10. namespace Symfony\Component\HttpKernel\Controller;
  11. use Symfony\Component\HttpFoundation\Request;
  12. use Symfony\Component\HttpKernel\Controller\ArgumentResolver\DefaultValueResolver;
  13. use Symfony\Component\HttpKernel\Controller\ArgumentResolver\RequestAttributeValueResolver;
  14. use Symfony\Component\HttpKernel\Controller\ArgumentResolver\RequestValueResolver;
  15. use Symfony\Component\HttpKernel\Controller\ArgumentResolver\SessionValueResolver;
  16. use Symfony\Component\HttpKernel\Controller\ArgumentResolver\VariadicValueResolver;
  17. use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadataFactory;
  18. use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadataFactoryInterface;
  19. /**
  20. * Responsible for resolving the arguments passed to an action.
  21. *
  22. * @author Iltar van der Berg <kjarli@gmail.com>
  23. */
  24. final class ArgumentResolver implements ArgumentResolverInterface
  25. {
  26. private $argumentMetadataFactory;
  27. /**
  28. * @var iterable|ArgumentValueResolverInterface[]
  29. */
  30. private $argumentValueResolvers;
  31. public function __construct(ArgumentMetadataFactoryInterface $argumentMetadataFactory = null, iterable $argumentValueResolvers = [])
  32. {
  33. $this->argumentMetadataFactory = $argumentMetadataFactory ?: new ArgumentMetadataFactory();
  34. $this->argumentValueResolvers = $argumentValueResolvers ?: self::getDefaultArgumentValueResolvers();
  35. }
  36. /**
  37. * {@inheritdoc}
  38. */
  39. public function getArguments(Request $request, $controller)
  40. {
  41. $arguments = [];
  42. foreach ($this->argumentMetadataFactory->createArgumentMetadata($controller) as $metadata) {
  43. foreach ($this->argumentValueResolvers as $resolver) {
  44. if (!$resolver->supports($request, $metadata)) {
  45. continue;
  46. }
  47. $resolved = $resolver->resolve($request, $metadata);
  48. if (!$resolved instanceof \Generator) {
  49. throw new \InvalidArgumentException(sprintf('%s::resolve() must yield at least one value.', \get_class($resolver)));
  50. }
  51. foreach ($resolved as $append) {
  52. $arguments[] = $append;
  53. }
  54. // continue to the next controller argument
  55. continue 2;
  56. }
  57. $representative = $controller;
  58. if (\is_array($representative)) {
  59. $representative = sprintf('%s::%s()', \get_class($representative[0]), $representative[1]);
  60. } elseif (\is_object($representative)) {
  61. $representative = \get_class($representative);
  62. }
  63. 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()));
  64. }
  65. return $arguments;
  66. }
  67. public static function getDefaultArgumentValueResolvers(): iterable
  68. {
  69. return [
  70. new RequestAttributeValueResolver(),
  71. new RequestValueResolver(),
  72. new SessionValueResolver(),
  73. new DefaultValueResolver(),
  74. new VariadicValueResolver(),
  75. ];
  76. }
  77. }