vendor/friendsofsymfony/rest-bundle/EventListener/ParamFetcherListener.php line 39

  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\EventListener;
  11. use FOS\RestBundle\FOSRestBundle;
  12. use FOS\RestBundle\Request\ParamFetcherInterface;
  13. use Symfony\Component\HttpKernel\Event\ControllerEvent;
  14. /**
  15.  * This listener handles various setup tasks related to the query fetcher.
  16.  *
  17.  * Setting the controller callable on the query fetcher
  18.  * Setting the query fetcher as a request attribute
  19.  *
  20.  * @author Lukas Kahwe Smith <smith@pooteeweet.org>
  21.  *
  22.  * @internal
  23.  */
  24. class ParamFetcherListener
  25. {
  26.     private $paramFetcher;
  27.     private $setParamsAsAttributes;
  28.     public function __construct(ParamFetcherInterface $paramFetcherbool $setParamsAsAttributes false)
  29.     {
  30.         $this->paramFetcher $paramFetcher;
  31.         $this->setParamsAsAttributes $setParamsAsAttributes;
  32.     }
  33.     public function onKernelController(ControllerEvent $event): void
  34.     {
  35.         $request $event->getRequest();
  36.         if (!$request->attributes->get(FOSRestBundle::ZONE_ATTRIBUTEtrue)) {
  37.             return;
  38.         }
  39.         $controller $event->getController();
  40.         if (is_callable($controller) && (is_object($controller) || is_string($controller)) && method_exists($controller'__invoke')) {
  41.             $controller = [$controller'__invoke'];
  42.         }
  43.         $this->paramFetcher->setController($controller);
  44.         $attributeName $this->getAttributeName($controller);
  45.         $request->attributes->set($attributeName$this->paramFetcher);
  46.         if ($this->setParamsAsAttributes) {
  47.             $params $this->paramFetcher->all();
  48.             foreach ($params as $name => $param) {
  49.                 if ($request->attributes->has($name) && null !== $request->attributes->get($name)) {
  50.                     $msg sprintf("ParamFetcher parameter conflicts with a path parameter '$name' for route '%s'"$request->attributes->get('_route'));
  51.                     throw new \InvalidArgumentException($msg);
  52.                 }
  53.                 $request->attributes->set($name$param);
  54.             }
  55.         }
  56.     }
  57.     private function getAttributeName(callable $controller): string
  58.     {
  59.         list($object$name) = $controller;
  60.         $method = new \ReflectionMethod($object$name);
  61.         foreach ($method->getParameters() as $param) {
  62.             if ($this->isParamFetcherType($param)) {
  63.                 return $param->getName();
  64.             }
  65.         }
  66.         // If there is no typehint, inject the ParamFetcher using a default name.
  67.         return 'paramFetcher';
  68.     }
  69.     private function isParamFetcherType(\ReflectionParameter $controllerParam): bool
  70.     {
  71.         $type $controllerParam->getType();
  72.         foreach ($type instanceof \ReflectionUnionType $type->getTypes() : [$type] as $type) {
  73.             if (null === $type || $type->isBuiltin() || !$type instanceof \ReflectionNamedType) {
  74.                 continue;
  75.             }
  76.             $class = new \ReflectionClass($type->getName());
  77.             if ($class->implementsInterface(ParamFetcherInterface::class)) {
  78.                 return true;
  79.             }
  80.         }
  81.         return false;
  82.     }
  83. }