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.         $configurations = [];
  53.         foreach (array_merge(array_keys($classConfigurations), array_keys($methodConfigurations)) as $key) {
  54.             if (!\array_key_exists($key$classConfigurations)) {
  55.                 $configurations[$key] = $methodConfigurations[$key];
  56.             } elseif (!\array_key_exists($key$methodConfigurations)) {
  57.                 $configurations[$key] = $classConfigurations[$key];
  58.             } else {
  59.                 if (\is_array($classConfigurations[$key])) {
  60.                     if (!\is_array($methodConfigurations[$key])) {
  61.                         throw new \UnexpectedValueException('Configurations should both be an array or both not be an array.');
  62.                     }
  63.                     $configurations[$key] = array_merge($classConfigurations[$key], $methodConfigurations[$key]);
  64.                 } else {
  65.                     // method configuration overrides class configuration
  66.                     $configurations[$key] = $methodConfigurations[$key];
  67.                 }
  68.             }
  69.         }
  70.         $request $event->getRequest();
  71.         foreach ($configurations as $key => $attributes) {
  72.             $request->attributes->set($key$attributes);
  73.         }
  74.     }
  75.     private function getConfigurations(array $annotations)
  76.     {
  77.         $configurations = [];
  78.         foreach ($annotations as $configuration) {
  79.             if ($configuration instanceof ConfigurationInterface) {
  80.                 if ($configuration->allowArray()) {
  81.                     $configurations['_'.$configuration->getAliasName()][] = $configuration;
  82.                 } elseif (!isset($configurations['_'.$configuration->getAliasName()])) {
  83.                     $configurations['_'.$configuration->getAliasName()] = $configuration;
  84.                 } else {
  85.                     throw new \LogicException(sprintf('Multiple "%s" annotations are not allowed.'$configuration->getAliasName()));
  86.                 }
  87.             }
  88.         }
  89.         return $configurations;
  90.     }
  91.     /**
  92.      * {@inheritdoc}
  93.      */
  94.     public static function getSubscribedEvents()
  95.     {
  96.         return [
  97.             KernelEvents::CONTROLLER => 'onKernelController',
  98.         ];
  99.     }
  100.     private static function getRealClass(string $class): string
  101.     {
  102.         if (class_exists(Proxy::class)) {
  103.             if (false === $pos strrpos($class'\\'.Proxy::MARKER.'\\')) {
  104.                 return $class;
  105.             }
  106.             return substr($class$pos Proxy::MARKER_LENGTH 2);
  107.         }
  108.         return $class;
  109.     }
  110. }