vendor/sensio/framework-extra-bundle/src/EventListener/TemplateListener.php line 79

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 Psr\Container\ContainerInterface;
  12. use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
  13. use Sensio\Bundle\FrameworkExtraBundle\Templating\TemplateGuesser;
  14. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  15. use Symfony\Component\HttpFoundation\Request;
  16. use Symfony\Component\HttpFoundation\Response;
  17. use Symfony\Component\HttpFoundation\StreamedResponse;
  18. use Symfony\Component\HttpKernel\Event\KernelEvent;
  19. use Symfony\Component\HttpKernel\KernelEvents;
  20. use Symfony\Contracts\Service\ServiceSubscriberInterface;
  21. use Twig\Environment;
  22. /**
  23.  * Handles the Template annotation for actions.
  24.  *
  25.  * Depends on pre-processing of the ControllerListener.
  26.  *
  27.  * @author Fabien Potencier <fabien@symfony.com>
  28.  */
  29. class TemplateListener implements EventSubscriberInterfaceServiceSubscriberInterface
  30. {
  31.     private $templateGuesser;
  32.     private $twig;
  33.     private $container;
  34.     public function __construct(TemplateGuesser $templateGuesserEnvironment $twig null)
  35.     {
  36.         $this->templateGuesser $templateGuesser;
  37.         $this->twig $twig;
  38.     }
  39.     public function setContainer(ContainerInterface $container): void
  40.     {
  41.         $this->container $container;
  42.     }
  43.     /**
  44.      * Guesses the template name to render and its variables and adds them to
  45.      * the request object.
  46.      */
  47.     public function onKernelController(KernelEvent $event)
  48.     {
  49.         $request $event->getRequest();
  50.         $template $request->attributes->get('_template');
  51.         if (!$template instanceof Template) {
  52.             return;
  53.         }
  54.         $controller $event->getController();
  55.         if (!\is_array($controller) && method_exists($controller'__invoke')) {
  56.             $controller = [$controller'__invoke'];
  57.         }
  58.         $template->setOwner($controller);
  59.         // when no template has been given, try to resolve it based on the controller
  60.         if (null === $template->getTemplate()) {
  61.             $template->setTemplate($this->templateGuesser->guessTemplateName($controller$request));
  62.         }
  63.     }
  64.     /**
  65.      * Renders the template and initializes a new response object with the
  66.      * rendered template content.
  67.      */
  68.     public function onKernelView(KernelEvent $event)
  69.     {
  70.         /* @var Template $template */
  71.         $request $event->getRequest();
  72.         $template $request->attributes->get('_template');
  73.         if (!$template instanceof Template) {
  74.             return;
  75.         }
  76.         if (null === $this->twig) {
  77.             if (!$this->container || !$this->container->has('twig')) {
  78.                 throw new \LogicException('You can not use the "@Template" annotation if the Twig Bundle is not available.');
  79.             }
  80.             $this->twig $this->container->get('twig');
  81.         }
  82.         $parameters $event->getControllerResult();
  83.         $owner $template->getOwner();
  84.         list($controller$action) = $owner;
  85.         // when the annotation declares no default vars and the action returns
  86.         // null, all action method arguments are used as default vars
  87.         if (null === $parameters) {
  88.             $parameters $this->resolveDefaultParameters($request$template$controller$action);
  89.         }
  90.         // attempt to render the actual response
  91.         if ($template->isStreamable()) {
  92.             $callback = function () use ($template$parameters) {
  93.                 $this->twig->display($template->getTemplate(), $parameters);
  94.             };
  95.             $event->setResponse(new StreamedResponse($callback));
  96.         } else {
  97.             $event->setResponse(new Response($this->twig->render($template->getTemplate(), $parameters)));
  98.         }
  99.         // make sure the owner (controller+dependencies) is not cached or stored elsewhere
  100.         $template->setOwner([]);
  101.     }
  102.     /**
  103.      * @return array
  104.      */
  105.     public static function getSubscribedEvents()
  106.     {
  107.         return [
  108.             KernelEvents::CONTROLLER => ['onKernelController', -128],
  109.             KernelEvents::VIEW => 'onKernelView',
  110.         ];
  111.     }
  112.     public static function getSubscribedServices(): array
  113.     {
  114.         return ['twig' => '?'.Environment::class];
  115.     }
  116.     private function resolveDefaultParameters(Request $requestTemplate $template$controller$action)
  117.     {
  118.         $parameters = [];
  119.         $arguments $template->getVars();
  120.         if (=== \count($arguments)) {
  121.             $r = new \ReflectionObject($controller);
  122.             $arguments = [];
  123.             foreach ($r->getMethod($action)->getParameters() as $param) {
  124.                 $arguments[] = $param;
  125.             }
  126.         }
  127.         // fetch the arguments of @Template.vars or everything if desired
  128.         // and assign them to the designated template
  129.         foreach ($arguments as $argument) {
  130.             if ($argument instanceof \ReflectionParameter) {
  131.                 $parameters[$name $argument->getName()] = !$request->attributes->has($name) && $argument->isDefaultValueAvailable() ? $argument->getDefaultValue() : $request->attributes->get($name);
  132.             } else {
  133.                 $parameters[$argument] = $request->attributes->get($argument);
  134.             }
  135.         }
  136.         return $parameters;
  137.     }
  138. }