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

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