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 <iam.asm89@gmail.com>
  28.  * @author Lukas Kahwe Smith <smith@pooteeweet.org>
  29.  * @author Jordi Boggiano <j.boggiano@seld.be>
  30.  * @author Boris GuĂ©ry <guery.b@gmail.com>
  31.  */
  32. class ParamFetcher implements ParamFetcherInterface
  33. {
  34.     use ResolverTrait;
  35.     private $container;
  36.     private $parameterBag;
  37.     private $requestStack;
  38.     private $validator;
  39.     /**
  40.      * Initializes fetcher.
  41.      *
  42.      * @param ContainerInterface   $container
  43.      * @param ParamReaderInterface $paramReader
  44.      * @param RequestStack         $requestStack
  45.      * @param ValidatorInterface   $validator
  46.      */
  47.     public function __construct(ContainerInterface $containerParamReaderInterface $paramReaderRequestStack $requestStackValidatorInterface $validator null)
  48.     {
  49.         if (null === $validator) {
  50.             @trigger_error(sprintf('Using no validator is deprecated since FOSRestBundle 2.6. The `$validator` constructor argument of the `%s` will become mandatory in 3.0.'__CLASS__), E_USER_DEPRECATED);
  51.         }
  52.         $this->container $container;
  53.         $this->requestStack $requestStack;
  54.         $this->validator $validator;
  55.         $this->parameterBag = new ParameterBag($paramReader);
  56.     }
  57.     /**
  58.      * {@inheritdoc}
  59.      */
  60.     public function setController($controller)
  61.     {
  62.         $this->parameterBag->setController($this->getRequest(), $controller);
  63.     }
  64.     /**
  65.      * Add additional params to the ParamFetcher during runtime.
  66.      *
  67.      * Note that adding a param that has the same name as an existing param will override that param.
  68.      *
  69.      * @param ParamInterface $param
  70.      */
  71.     public function addParam(ParamInterface $param)
  72.     {
  73.         $this->parameterBag->addParam($this->getRequest(), $param);
  74.     }
  75.     /**
  76.      * @return ParamInterface[]
  77.      */
  78.     public function getParams()
  79.     {
  80.         return $this->parameterBag->getParams($this->getRequest());
  81.     }
  82.     /**
  83.      * {@inheritdoc}
  84.      */
  85.     public function get($name$strict null)
  86.     {
  87.         $params $this->getParams();
  88.         if (!array_key_exists($name$params)) {
  89.             throw new \InvalidArgumentException(sprintf("No @ParamInterface configuration for parameter '%s'."$name));
  90.         }
  91.         /** @var ParamInterface $param */
  92.         $param $params[$name];
  93.         $default $param->getDefault();
  94.         $default $this->resolveValue($this->container$default);
  95.         $strict = (null !== $strict $strict $param->isStrict());
  96.         $paramValue $param->getValue($this->getRequest(), $default);
  97.         return $this->cleanParamWithRequirements($param$paramValue$strict$default);
  98.     }
  99.     /**
  100.      * @param ParamInterface $param
  101.      * @param mixed          $paramValue
  102.      * @param bool           $strict
  103.      * @param mixed          $default
  104.      *
  105.      * @throws BadRequestHttpException
  106.      * @throws \RuntimeException
  107.      *
  108.      * @return mixed
  109.      *
  110.      * @internal
  111.      */
  112.     protected function cleanParamWithRequirements(ParamInterface $param$paramValue$strict$default)
  113.     {
  114.         $this->checkNotIncompatibleParams($param);
  115.         if (null !== $default && $default === $paramValue) {
  116.             return $paramValue;
  117.         }
  118.         if (null === $this->validator) {
  119.             throw new \RuntimeException(
  120.                 'The ParamFetcher requirements feature requires the symfony/validator component.'
  121.             );
  122.         }
  123.         $constraints $param->getConstraints();
  124.         $this->resolveConstraints($constraints);
  125.         if (empty($constraints)) {
  126.             return $paramValue;
  127.         }
  128.         try {
  129.             $errors $this->validator->validate($paramValue$constraints);
  130.         } catch (ValidatorException $e) {
  131.             $violation = new ConstraintViolation(
  132.                 $e->getMessage(),
  133.                 $e->getMessage(),
  134.                 array(),
  135.                 $paramValue,
  136.                 '',
  137.                 null,
  138.                 null,
  139.                 $e->getCode()
  140.             );
  141.             $errors = new ConstraintViolationList(array($violation));
  142.         }
  143.         if (count($errors)) {
  144.             if ($strict) {
  145.                 throw InvalidParameterException::withViolations($param$errors);
  146.             }
  147.             return null === $default '' $default;
  148.         }
  149.         return $paramValue;
  150.     }
  151.     /**
  152.      * {@inheritdoc}
  153.      */
  154.     public function all($strict null)
  155.     {
  156.         $configuredParams $this->getParams();
  157.         $params = [];
  158.         foreach ($configuredParams as $name => $param) {
  159.             $params[$name] = $this->get($name$strict);
  160.         }
  161.         return $params;
  162.     }
  163.     /**
  164.      * Check if current param is not in conflict with other parameters
  165.      * according to the "incompatibles" field.
  166.      *
  167.      * @param ParamInterface $param the configuration for the param fetcher
  168.      *
  169.      * @throws InvalidArgumentException
  170.      * @throws BadRequestHttpException
  171.      *
  172.      * @internal
  173.      */
  174.     protected function checkNotIncompatibleParams(ParamInterface $param)
  175.     {
  176.         if (null === $param->getValue($this->getRequest(), null)) {
  177.             return;
  178.         }
  179.         $params $this->getParams();
  180.         foreach ($param->getIncompatibilities() as $incompatibleParamName) {
  181.             if (!array_key_exists($incompatibleParamName$params)) {
  182.                 throw new \InvalidArgumentException(sprintf("No @ParamInterface configuration for parameter '%s'."$incompatibleParamName));
  183.             }
  184.             $incompatibleParam $params[$incompatibleParamName];
  185.             if (null !== $incompatibleParam->getValue($this->getRequest(), null)) {
  186.                 $exceptionMessage sprintf(
  187.                     "'%s' param is incompatible with %s param.",
  188.                     $param->getName(),
  189.                     $incompatibleParam->getName()
  190.                 );
  191.                 throw new BadRequestHttpException($exceptionMessage);
  192.             }
  193.         }
  194.     }
  195.     /**
  196.      * @param Constraint[] $constraints
  197.      */
  198.     private function resolveConstraints(array $constraints)
  199.     {
  200.         foreach ($constraints as $constraint) {
  201.             if ($constraint instanceof ResolvableConstraintInterface) {
  202.                 $constraint->resolve($this->container);
  203.             }
  204.         }
  205.     }
  206.     /**
  207.      * @throws \RuntimeException
  208.      *
  209.      * @return Request
  210.      */
  211.     private function getRequest()
  212.     {
  213.         $request $this->requestStack->getCurrentRequest();
  214.         if (null === $request) {
  215.             throw new \RuntimeException('There is no current request.');
  216.         }
  217.         return $request;
  218.     }
  219. }