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

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