vendor/friendsofsymfony/rest-bundle/Request/ParamFetcher.php line 36

Open in your IDE?
  1. <?php
  2. /*
  3.  * This file is part of the FOSRestBundle package.
  4.  *
  5.  * (c) FriendsOfSymfony <http://friendsofsymfony.github.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 FOS\RestBundle\Request;
  11. use FOS\RestBundle\Controller\Annotations\ParamInterface;
  12. use FOS\RestBundle\Exception\InvalidParameterException;
  13. use FOS\RestBundle\Util\ResolverTrait;
  14. use FOS\RestBundle\Validator\Constraints\ResolvableConstraintInterface;
  15. use Symfony\Component\DependencyInjection\ContainerInterface;
  16. use Symfony\Component\HttpFoundation\Request;
  17. use Symfony\Component\HttpFoundation\RequestStack;
  18. use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
  19. use Symfony\Component\Validator\Constraint;
  20. use Symfony\Component\Validator\ConstraintViolationList;
  21. use Symfony\Component\Validator\Validator\ValidatorInterface;
  22. use Symfony\Component\Validator\Exception\ValidatorException;
  23. use Symfony\Component\Validator\ConstraintViolation;
  24. /**
  25.  * Helper to validate parameters of the active request.
  26.  *
  27.  * @author Alexander <[email protected]>
  28.  * @author Lukas Kahwe Smith <[email protected]>
  29.  * @author Jordi Boggiano <[email protected]>
  30.  * @author Boris GuĂ©ry <[email protected]>
  31.  */
  32. final class ParamFetcher implements ParamFetcherInterface
  33. {
  34.     use ResolverTrait;
  35.     private $container;
  36.     private $parameterBag;
  37.     private $requestStack;
  38.     private $validator;
  39.     public function __construct(ContainerInterface $containerParamReaderInterface $paramReaderRequestStack $requestStackValidatorInterface $validator)
  40.     {
  41.         $this->container $container;
  42.         $this->requestStack $requestStack;
  43.         $this->validator $validator;
  44.         $this->parameterBag = new ParameterBag($paramReader);
  45.     }
  46.     /**
  47.      * {@inheritdoc}
  48.      */
  49.     public function setController(callable $controller): void
  50.     {
  51.         $this->parameterBag->setController($this->getRequest(), $controller);
  52.     }
  53.     /**
  54.      * Add additional params to the ParamFetcher during runtime.
  55.      *
  56.      * Note that adding a param that has the same name as an existing param will override that param.
  57.      */
  58.     public function addParam(ParamInterface $param): void
  59.     {
  60.         $this->parameterBag->addParam($this->getRequest(), $param);
  61.     }
  62.     /**
  63.      * @return ParamInterface[]
  64.      */
  65.     public function getParams(): array
  66.     {
  67.         return $this->parameterBag->getParams($this->getRequest());
  68.     }
  69.     /**
  70.      * {@inheritdoc}
  71.      */
  72.     public function get(string $name, ?bool $strict null)
  73.     {
  74.         $params $this->getParams();
  75.         
  76.         if (!array_key_exists($name$params)) {
  77.             throw new \InvalidArgumentException(sprintf("No @ParamInterface configuration for parameter '%s'."$name));
  78.         }
  79.         /** @var ParamInterface $param */
  80.         $param $params[$name];
  81.         
  82.         $default $param->getDefault();
  83.         
  84.         $default $this->resolveValue($this->container$default);
  85.         $strict = (null !== $strict $strict $param->isStrict());
  86.         
  87.         $paramValue $param->getValue($this->getRequest(), $default);
  88.         return $this->cleanParamWithRequirements($param$paramValue$strict$default);
  89.     }
  90.     private function cleanParamWithRequirements(ParamInterface $param$paramValuebool $strict$default)
  91.     {
  92.         $this->checkNotIncompatibleParams($param);
  93.         if (null !== $default && $default === $paramValue) {
  94.             return $paramValue;
  95.         }
  96.         $constraints $param->getConstraints();
  97.         $this->resolveConstraints($constraints);
  98.         if (empty($constraints)) {
  99.             return $paramValue;
  100.         }
  101.         try {
  102.             $errors $this->validator->validate($paramValue$constraints);
  103.         } catch (ValidatorException $e) {
  104.             $violation = new ConstraintViolation(
  105.                 $e->getMessage(),
  106.                 $e->getMessage(),
  107.                 [],
  108.                 $paramValue,
  109.                 '',
  110.                 null,
  111.                 null,
  112.                 $e->getCode()
  113.             );
  114.             $errors = new ConstraintViolationList([$violation]);
  115.         }
  116.         if (count($errors)) {
  117.             if ($strict) {
  118.                 throw InvalidParameterException::withViolations($param$errors);
  119.             }
  120.             return null === $default '' $default;
  121.         }
  122.         return $paramValue;
  123.     }
  124.     /**
  125.      * {@inheritdoc}
  126.      */
  127.     public function all(?bool $strict null): array
  128.     {
  129.         $configuredParams $this->getParams();
  130.         $params = [];
  131.         foreach ($configuredParams as $name => $param) {
  132.             $params[$name] = $this->get($name$strict);
  133.         }
  134.         return $params;
  135.     }
  136.     private function checkNotIncompatibleParams(ParamInterface $param): void
  137.     {
  138.         if (null === $param->getValue($this->getRequest(), null)) {
  139.             return;
  140.         }
  141.         $params $this->getParams();
  142.         foreach ($param->getIncompatibilities() as $incompatibleParamName) {
  143.             if (!array_key_exists($incompatibleParamName$params)) {
  144.                 throw new \InvalidArgumentException(sprintf("No @ParamInterface configuration for parameter '%s'."$incompatibleParamName));
  145.             }
  146.             $incompatibleParam $params[$incompatibleParamName];
  147.             if (null !== $incompatibleParam->getValue($this->getRequest(), null)) {
  148.                 $exceptionMessage sprintf(
  149.                     '"%s" param is incompatible with %s param.',
  150.                     $param->getName(),
  151.                     $incompatibleParam->getName()
  152.                 );
  153.                 throw new BadRequestHttpException($exceptionMessage);
  154.             }
  155.         }
  156.     }
  157.     /**
  158.      * @param Constraint[] $constraints
  159.      */
  160.     private function resolveConstraints(array $constraints): void
  161.     {
  162.         foreach ($constraints as $constraint) {
  163.             if ($constraint instanceof ResolvableConstraintInterface) {
  164.                 $constraint->resolve($this->container);
  165.             }
  166.         }
  167.     }
  168.     private function getRequest(): Request
  169.     {
  170.         $request $this->requestStack->getCurrentRequest();
  171.         if (null === $request) {
  172.             throw new \RuntimeException('There is no current request.');
  173.         }
  174.         return $request;
  175.     }
  176. }