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

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