vendor/symfony/framework-bundle/Controller/ControllerTrait.php line 224

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 Symfony\Bundle\FrameworkBundle\Controller;
  11. use Doctrine\Common\Persistence\ManagerRegistry;
  12. use Psr\Container\ContainerInterface;
  13. use Symfony\Component\HttpFoundation\BinaryFileResponse;
  14. use Symfony\Component\HttpFoundation\JsonResponse;
  15. use Symfony\Component\HttpFoundation\Response;
  16. use Symfony\Component\HttpFoundation\RedirectResponse;
  17. use Symfony\Component\HttpFoundation\ResponseHeaderBag;
  18. use Symfony\Component\HttpFoundation\StreamedResponse;
  19. use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
  20. use Symfony\Component\HttpKernel\HttpKernelInterface;
  21. use Symfony\Component\Security\Core\Exception\AccessDeniedException;
  22. use Symfony\Component\Security\Csrf\CsrfToken;
  23. use Symfony\Component\Form\Extension\Core\Type\FormType;
  24. use Symfony\Component\Form\FormInterface;
  25. use Symfony\Component\Form\FormBuilderInterface;
  26. use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
  27. /**
  28.  * Common features needed in controllers.
  29.  *
  30.  * @author Fabien Potencier <fabien@symfony.com>
  31.  *
  32.  * @internal
  33.  *
  34.  * @property ContainerInterface $container
  35.  */
  36. trait ControllerTrait
  37. {
  38.     /**
  39.      * Returns true if the service id is defined.
  40.      *
  41.      * @final
  42.      */
  43.     protected function has(string $id): bool
  44.     {
  45.         return $this->container->has($id);
  46.     }
  47.     /**
  48.      * Gets a container service by its id.
  49.      *
  50.      * @return object The service
  51.      *
  52.      * @final
  53.      */
  54.     protected function get(string $id)
  55.     {
  56.         return $this->container->get($id);
  57.     }
  58.     /**
  59.      * Generates a URL from the given parameters.
  60.      *
  61.      * @see UrlGeneratorInterface
  62.      *
  63.      * @final
  64.      */
  65.     protected function generateUrl(string $route, array $parameters = array(), int $referenceType UrlGeneratorInterface::ABSOLUTE_PATH): string
  66.     {
  67.         return $this->container->get('router')->generate($route$parameters$referenceType);
  68.     }
  69.     /**
  70.      * Forwards the request to another controller.
  71.      *
  72.      * @param string $controller The controller name (a string like Bundle\BlogBundle\Controller\PostController::indexAction)
  73.      *
  74.      * @final
  75.      */
  76.     protected function forward(string $controller, array $path = array(), array $query = array()): Response
  77.     {
  78.         $request $this->container->get('request_stack')->getCurrentRequest();
  79.         $path['_controller'] = $controller;
  80.         $subRequest $request->duplicate($querynull$path);
  81.         return $this->container->get('http_kernel')->handle($subRequestHttpKernelInterface::SUB_REQUEST);
  82.     }
  83.     /**
  84.      * Returns a RedirectResponse to the given URL.
  85.      *
  86.      * @final
  87.      */
  88.     protected function redirect(string $urlint $status 302): RedirectResponse
  89.     {
  90.         return new RedirectResponse($url$status);
  91.     }
  92.     /**
  93.      * Returns a RedirectResponse to the given route with the given parameters.
  94.      *
  95.      * @final
  96.      */
  97.     protected function redirectToRoute(string $route, array $parameters = array(), int $status 302): RedirectResponse
  98.     {
  99.         return $this->redirect($this->generateUrl($route$parameters), $status);
  100.     }
  101.     /**
  102.      * Returns a JsonResponse that uses the serializer component if enabled, or json_encode.
  103.      *
  104.      * @final
  105.      */
  106.     protected function json($dataint $status 200, array $headers = array(), array $context = array()): JsonResponse
  107.     {
  108.         if ($this->container->has('serializer')) {
  109.             $json $this->container->get('serializer')->serialize($data'json'array_merge(array(
  110.                 'json_encode_options' => JsonResponse::DEFAULT_ENCODING_OPTIONS,
  111.             ), $context));
  112.             return new JsonResponse($json$status$headerstrue);
  113.         }
  114.         return new JsonResponse($data$status$headers);
  115.     }
  116.     /**
  117.      * Returns a BinaryFileResponse object with original or customized file name and disposition header.
  118.      *
  119.      * @param \SplFileInfo|string $file File object or path to file to be sent as response
  120.      *
  121.      * @final
  122.      */
  123.     protected function file($filestring $fileName nullstring $disposition ResponseHeaderBag::DISPOSITION_ATTACHMENT): BinaryFileResponse
  124.     {
  125.         $response = new BinaryFileResponse($file);
  126.         $response->setContentDisposition($dispositionnull === $fileName $response->getFile()->getFilename() : $fileName);
  127.         return $response;
  128.     }
  129.     /**
  130.      * Adds a flash message to the current session for type.
  131.      *
  132.      * @throws \LogicException
  133.      *
  134.      * @final
  135.      */
  136.     protected function addFlash(string $typestring $message)
  137.     {
  138.         if (!$this->container->has('session')) {
  139.             throw new \LogicException('You can not use the addFlash method if sessions are disabled. Enable them in "config/packages/framework.yaml".');
  140.         }
  141.         $this->container->get('session')->getFlashBag()->add($type$message);
  142.     }
  143.     /**
  144.      * Checks if the attributes are granted against the current authentication token and optionally supplied subject.
  145.      *
  146.      * @throws \LogicException
  147.      *
  148.      * @final
  149.      */
  150.     protected function isGranted($attributes$subject null): bool
  151.     {
  152.         if (!$this->container->has('security.authorization_checker')) {
  153.             throw new \LogicException('The SecurityBundle is not registered in your application. Try running "composer require symfony/security-bundle".');
  154.         }
  155.         return $this->container->get('security.authorization_checker')->isGranted($attributes$subject);
  156.     }
  157.     /**
  158.      * Throws an exception unless the attributes are granted against the current authentication token and optionally
  159.      * supplied subject.
  160.      *
  161.      * @throws AccessDeniedException
  162.      *
  163.      * @final
  164.      */
  165.     protected function denyAccessUnlessGranted($attributes$subject nullstring $message 'Access Denied.')
  166.     {
  167.         if (!$this->isGranted($attributes$subject)) {
  168.             $exception $this->createAccessDeniedException($message);
  169.             $exception->setAttributes($attributes);
  170.             $exception->setSubject($subject);
  171.             throw $exception;
  172.         }
  173.     }
  174.     /**
  175.      * Returns a rendered view.
  176.      *
  177.      * @final
  178.      */
  179.     protected function renderView(string $view, array $parameters = array()): string
  180.     {
  181.         if ($this->container->has('templating')) {
  182.             return $this->container->get('templating')->render($view$parameters);
  183.         }
  184.         if (!$this->container->has('twig')) {
  185.             throw new \LogicException('You can not use the "renderView" method if the Templating Component or the Twig Bundle are not available. Try running "composer require symfony/twig-bundle".');
  186.         }
  187.         return $this->container->get('twig')->render($view$parameters);
  188.     }
  189.     /**
  190.      * Renders a view.
  191.      *
  192.      * @final
  193.      */
  194.     protected function render(string $view, array $parameters = array(), Response $response null): Response
  195.     {
  196.         if ($this->container->has('templating')) {
  197.             $content $this->container->get('templating')->render($view$parameters);
  198.         } elseif ($this->container->has('twig')) {
  199.             $content $this->container->get('twig')->render($view$parameters);
  200.         } else {
  201.             throw new \LogicException('You can not use the "render" method if the Templating Component or the Twig Bundle are not available. Try running "composer require symfony/twig-bundle".');
  202.         }
  203.         if (null === $response) {
  204.             $response = new Response();
  205.         }
  206.         $response->setContent($content);
  207.         return $response;
  208.     }
  209.     /**
  210.      * Streams a view.
  211.      *
  212.      * @final
  213.      */
  214.     protected function stream(string $view, array $parameters = array(), StreamedResponse $response null): StreamedResponse
  215.     {
  216.         if ($this->container->has('templating')) {
  217.             $templating $this->container->get('templating');
  218.             $callback = function () use ($templating$view$parameters) {
  219.                 $templating->stream($view$parameters);
  220.             };
  221.         } elseif ($this->container->has('twig')) {
  222.             $twig $this->container->get('twig');
  223.             $callback = function () use ($twig$view$parameters) {
  224.                 $twig->display($view$parameters);
  225.             };
  226.         } else {
  227.             throw new \LogicException('You can not use the "stream" method if the Templating Component or the Twig Bundle are not available. Try running "composer require symfony/twig-bundle".');
  228.         }
  229.         if (null === $response) {
  230.             return new StreamedResponse($callback);
  231.         }
  232.         $response->setCallback($callback);
  233.         return $response;
  234.     }
  235.     /**
  236.      * Returns a NotFoundHttpException.
  237.      *
  238.      * This will result in a 404 response code. Usage example:
  239.      *
  240.      *     throw $this->createNotFoundException('Page not found!');
  241.      *
  242.      * @final
  243.      */
  244.     protected function createNotFoundException(string $message 'Not Found', \Exception $previous null): NotFoundHttpException
  245.     {
  246.         return new NotFoundHttpException($message$previous);
  247.     }
  248.     /**
  249.      * Returns an AccessDeniedException.
  250.      *
  251.      * This will result in a 403 response code. Usage example:
  252.      *
  253.      *     throw $this->createAccessDeniedException('Unable to access this page!');
  254.      *
  255.      * @throws \LogicException If the Security component is not available
  256.      *
  257.      * @final
  258.      */
  259.     protected function createAccessDeniedException(string $message 'Access Denied.', \Exception $previous null): AccessDeniedException
  260.     {
  261.         if (!class_exists(AccessDeniedException::class)) {
  262.             throw new \LogicException('You can not use the "createAccessDeniedException" method if the Security component is not available. Try running "composer require symfony/security-bundle".');
  263.         }
  264.         return new AccessDeniedException($message$previous);
  265.     }
  266.     /**
  267.      * Creates and returns a Form instance from the type of the form.
  268.      *
  269.      * @final
  270.      */
  271.     protected function createForm(string $type$data null, array $options = array()): FormInterface
  272.     {
  273.         return $this->container->get('form.factory')->create($type$data$options);
  274.     }
  275.     /**
  276.      * Creates and returns a form builder instance.
  277.      *
  278.      * @final
  279.      */
  280.     protected function createFormBuilder($data null, array $options = array()): FormBuilderInterface
  281.     {
  282.         return $this->container->get('form.factory')->createBuilder(FormType::class, $data$options);
  283.     }
  284.     /**
  285.      * Shortcut to return the Doctrine Registry service.
  286.      *
  287.      * @throws \LogicException If DoctrineBundle is not available
  288.      *
  289.      * @final
  290.      */
  291.     protected function getDoctrine(): ManagerRegistry
  292.     {
  293.         if (!$this->container->has('doctrine')) {
  294.             throw new \LogicException('The DoctrineBundle is not registered in your application. Try running "composer require symfony/orm-pack".');
  295.         }
  296.         return $this->container->get('doctrine');
  297.     }
  298.     /**
  299.      * Get a user from the Security Token Storage.
  300.      *
  301.      * @return mixed
  302.      *
  303.      * @throws \LogicException If SecurityBundle is not available
  304.      *
  305.      * @see TokenInterface::getUser()
  306.      *
  307.      * @final
  308.      */
  309.     protected function getUser()
  310.     {
  311.         if (!$this->container->has('security.token_storage')) {
  312.             throw new \LogicException('The SecurityBundle is not registered in your application. Try running "composer require symfony/security-bundle".');
  313.         }
  314.         if (null === $token $this->container->get('security.token_storage')->getToken()) {
  315.             return;
  316.         }
  317.         if (!is_object($user $token->getUser())) {
  318.             // e.g. anonymous authentication
  319.             return;
  320.         }
  321.         return $user;
  322.     }
  323.     /**
  324.      * Checks the validity of a CSRF token.
  325.      *
  326.      * @param string      $id    The id used when generating the token
  327.      * @param string|null $token The actual token sent with the request that should be validated
  328.      *
  329.      * @final
  330.      */
  331.     protected function isCsrfTokenValid(string $id, ?string $token): bool
  332.     {
  333.         if (!$this->container->has('security.csrf.token_manager')) {
  334.             throw new \LogicException('CSRF protection is not enabled in your application. Enable it with the "csrf_protection" key in "config/packages/framework.yaml".');
  335.         }
  336.         return $this->container->get('security.csrf.token_manager')->isTokenValid(new CsrfToken($id$token));
  337.     }
  338.     /**
  339.      * Dispatches a message to the bus.
  340.      *
  341.      * @param object $message The message to dispatch
  342.      *
  343.      * @final
  344.      */
  345.     protected function dispatchMessage($message)
  346.     {
  347.         if (!$this->container->has('message_bus')) {
  348.             throw new \LogicException('The message bus is not enabled in your application. Try running "composer require symfony/messenger".');
  349.         }
  350.         return $this->container->get('message_bus')->dispatch($message);
  351.     }
  352. }