vendor/sensio/framework-extra-bundle/src/EventListener/ControllerListener.php line 44

Open in your IDE?
  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 Sensio\Bundle\FrameworkExtraBundle\EventListener;
  11. use Doctrine\Common\Annotations\Reader;
  12. use Doctrine\Persistence\Proxy;
  13. use Sensio\Bundle\FrameworkExtraBundle\Configuration\ConfigurationInterface;
  14. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  15. use Symfony\Component\HttpKernel\Event\KernelEvent;
  16. use Symfony\Component\HttpKernel\KernelEvents;
  17. /**
  18.  * The ControllerListener class parses annotation blocks located in
  19.  * controller classes.
  20.  *
  21.  * @author Fabien Potencier <fabien@symfony.com>
  22.  */
  23. class ControllerListener implements EventSubscriberInterface
  24. {
  25.     /**
  26.      * @var Reader
  27.      */
  28.     private $reader;
  29.     public function __construct(Reader $reader)
  30.     {
  31.         $this->reader $reader;
  32.     }
  33.     /**
  34.      * Modifies the Request object to apply configuration information found in
  35.      * controllers annotations like the template to render or HTTP caching
  36.      * configuration.
  37.      */
  38.     public function onKernelController(KernelEvent $event)
  39.     {
  40.         $controller $event->getController();
  41.         if (!\is_array($controller) && method_exists($controller'__invoke')) {
  42.             $controller = [$controller'__invoke'];
  43.         }
  44.         if (!\is_array($controller)) {
  45.             return;
  46.         }
  47.         $className $this->getRealClass(\get_class($controller[0]));
  48.         $object = new \ReflectionClass($className);
  49.         $method $object->getMethod($controller[1]);
  50.         $classConfigurations $this->getConfigurations($this->reader->getClassAnnotations($object));
  51.         $methodConfigurations $this->getConfigurations($this->reader->getMethodAnnotations($method));
  52.         if (80000 <= \PHP_VERSION_ID) {
  53.             $classAttributes array_map(
  54.                 function (\ReflectionAttribute $attribute) {
  55.                     return $attribute->newInstance();
  56.                 },
  57.                 $object->getAttributes(ConfigurationInterface::class, \ReflectionAttribute::IS_INSTANCEOF)
  58.             );
  59.             $classConfigurations array_merge($classConfigurations$this->getConfigurations($classAttributes));
  60.             $methodAttributes array_map(
  61.                 function (\ReflectionAttribute $attribute) {
  62.                     return $attribute->newInstance();
  63.                 },
  64.                 $method->getAttributes(ConfigurationInterface::class, \ReflectionAttribute::IS_INSTANCEOF)
  65.             );
  66.             $methodConfigurations array_merge($methodConfigurations$this->getConfigurations($methodAttributes));
  67.         }
  68.         $configurations = [];
  69.         foreach (array_merge(array_keys($classConfigurations), array_keys($methodConfigurations)) as $key) {
  70.             if (!\array_key_exists($key$classConfigurations)) {
  71.                 $configurations[$key] = $methodConfigurations[$key];
  72.             } elseif (!\array_key_exists($key$methodConfigurations)) {
  73.                 $configurations[$key] = $classConfigurations[$key];
  74.             } else {
  75.                 if (\is_array($classConfigurations[$key])) {
  76.                     if (!\is_array($methodConfigurations[$key])) {
  77.                         throw new \UnexpectedValueException('Configurations should both be an array or both not be an array.');
  78.                     }
  79.                     $configurations[$key] = array_merge($classConfigurations[$key], $methodConfigurations[$key]);
  80.                 } else {
  81.                     // method configuration overrides class configuration
  82.                     $configurations[$key] = $methodConfigurations[$key];
  83.                 }
  84.             }
  85.         }
  86.         $request $event->getRequest();
  87.         foreach ($configurations as $key => $attributes) {
  88.             $request->attributes->set($key$attributes);
  89.         }
  90.     }
  91.     private function getConfigurations(array $annotations)
  92.     {
  93.         $configurations = [];
  94.         foreach ($annotations as $configuration) {
  95.             if ($configuration instanceof ConfigurationInterface) {
  96.                 if ($configuration->allowArray()) {
  97.                     $configurations['_'.$configuration->getAliasName()][] = $configuration;
  98.                 } elseif (!isset($configurations['_'.$configuration->getAliasName()])) {
  99.                     $configurations['_'.$configuration->getAliasName()] = $configuration;
  100.                 } else {
  101.                     throw new \LogicException(sprintf('Multiple "%s" annotations are not allowed.'$configuration->getAliasName()));
  102.                 }
  103.             }
  104.         }
  105.         return $configurations;
  106.     }
  107.     /**
  108.      * @return array
  109.      */
  110.     public static function getSubscribedEvents()
  111.     {
  112.         return [
  113.             KernelEvents::CONTROLLER => 'onKernelController',
  114.         ];
  115.     }
  116.     private static function getRealClass(string $class): string
  117.     {
  118.         if (class_exists(Proxy::class)) {
  119.             if (false === $pos strrpos($class'\\'.Proxy::MARKER.'\\')) {
  120.                 return $class;
  121.             }
  122.             return substr($class$pos Proxy::MARKER_LENGTH 2);
  123.         }
  124.         return $class;
  125.     }
  126. }