vendor/symfony/http-kernel/Controller/ArgumentResolver.php line 54

  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\TraceableValueResolver;
  17. use Symfony\Component\HttpKernel\Controller\ArgumentResolver\VariadicValueResolver;
  18. use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadataFactory;
  19. use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadataFactoryInterface;
  20. /**
  21.  * Responsible for resolving the arguments passed to an action.
  22.  *
  23.  * @author Iltar van der Berg <kjarli@gmail.com>
  24.  */
  25. final class ArgumentResolver implements ArgumentResolverInterface
  26. {
  27.     private ArgumentMetadataFactoryInterface $argumentMetadataFactory;
  28.     private iterable $argumentValueResolvers;
  29.     /**
  30.      * @param iterable<mixed, ArgumentValueResolverInterface|ValueResolverInterface> $argumentValueResolvers
  31.      */
  32.     public function __construct(ArgumentMetadataFactoryInterface $argumentMetadataFactory nulliterable $argumentValueResolvers = [])
  33.     {
  34.         $this->argumentMetadataFactory $argumentMetadataFactory ?? new ArgumentMetadataFactory();
  35.         $this->argumentValueResolvers $argumentValueResolvers ?: self::getDefaultArgumentValueResolvers();
  36.     }
  37.     public function getArguments(Request $request, callable $controller\ReflectionFunctionAbstract $reflector null): array
  38.     {
  39.         $arguments = [];
  40.         foreach ($this->argumentMetadataFactory->createArgumentMetadata($controller$reflector) as $metadata) {
  41.             foreach ($this->argumentValueResolvers as $resolver) {
  42.                 if ((!$resolver instanceof ValueResolverInterface || $resolver instanceof TraceableValueResolver) && !$resolver->supports($request$metadata)) {
  43.                     continue;
  44.                 }
  45.                 $count 0;
  46.                 foreach ($resolver->resolve($request$metadata) as $argument) {
  47.                     ++$count;
  48.                     $arguments[] = $argument;
  49.                 }
  50.                 if ($count && !$metadata->isVariadic()) {
  51.                     throw new \InvalidArgumentException(sprintf('"%s::resolve()" must yield at most one value for non-variadic arguments.'get_debug_type($resolver)));
  52.                 }
  53.                 if ($count) {
  54.                     // continue to the next controller argument
  55.                     continue 2;
  56.                 }
  57.                 if (!$resolver instanceof ValueResolverInterface) {
  58.                     throw new \InvalidArgumentException(sprintf('"%s::resolve()" must yield at least one value.'get_debug_type($resolver)));
  59.                 }
  60.             }
  61.             $representative $controller;
  62.             if (\is_array($representative)) {
  63.                 $representative sprintf('%s::%s()'\get_class($representative[0]), $representative[1]);
  64.             } elseif (\is_object($representative)) {
  65.                 $representative get_debug_type($representative);
  66.             }
  67.             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()));
  68.         }
  69.         return $arguments;
  70.     }
  71.     /**
  72.      * @return iterable<int, ArgumentValueResolverInterface>
  73.      */
  74.     public static function getDefaultArgumentValueResolvers(): iterable
  75.     {
  76.         return [
  77.             new RequestAttributeValueResolver(),
  78.             new RequestValueResolver(),
  79.             new SessionValueResolver(),
  80.             new DefaultValueResolver(),
  81.             new VariadicValueResolver(),
  82.         ];
  83.     }
  84. }