vendor/symfony/twig-bridge/ErrorRenderer/TwigErrorRenderer.php line 51

Open in your IDE?
  1. <?php
  2. /*
  3.  * This file is part of the Symfony package.
  4.  *
  5.  * (c) Fabien Potencier <[email protected]>
  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\Bridge\Twig\ErrorRenderer;
  11. use Symfony\Component\ErrorHandler\ErrorRenderer\ErrorRendererInterface;
  12. use Symfony\Component\ErrorHandler\ErrorRenderer\HtmlErrorRenderer;
  13. use Symfony\Component\ErrorHandler\Exception\FlattenException;
  14. use Symfony\Component\HttpFoundation\RequestStack;
  15. use Twig\Environment;
  16. use Twig\Error\LoaderError;
  17. use Twig\Loader\ExistsLoaderInterface;
  18. /**
  19.  * Provides the ability to render custom Twig-based HTML error pages
  20.  * in non-debug mode, otherwise falls back to HtmlErrorRenderer.
  21.  *
  22.  * @author Yonel Ceruto <[email protected]>
  23.  */
  24. class TwigErrorRenderer implements ErrorRendererInterface
  25. {
  26.     private $twig;
  27.     private $fallbackErrorRenderer;
  28.     private $debug;
  29.     /**
  30.      * @param bool|callable $debug The debugging mode as a boolean or a callable that should return it
  31.      */
  32.     public function __construct(Environment $twigHtmlErrorRenderer $fallbackErrorRenderer null$debug false)
  33.     {
  34.         if (!\is_bool($debug) && !\is_callable($debug)) {
  35.             throw new \TypeError(sprintf('Argument 3 passed to "%s()" must be a boolean or a callable, "%s" given.'__METHOD__, \is_object($debug) ? \get_class($debug) : \gettype($debug)));
  36.         }
  37.         $this->twig $twig;
  38.         $this->fallbackErrorRenderer $fallbackErrorRenderer ?? new HtmlErrorRenderer();
  39.         $this->debug $debug;
  40.     }
  41.     /**
  42.      * {@inheritdoc}
  43.      */
  44.     public function render(\Throwable $exception): FlattenException
  45.     {
  46.         $exception $this->fallbackErrorRenderer->render($exception);
  47.         $debug = \is_bool($this->debug) ? $this->debug : ($this->debug)($exception);
  48.         if ($debug || !$template $this->findTemplate($exception->getStatusCode())) {
  49.             return $exception;
  50.         }
  51.         return $exception->setAsString($this->twig->render($template, [
  52.             'legacy' => false// to be removed in 5.0
  53.             'exception' => $exception,
  54.             'status_code' => $exception->getStatusCode(),
  55.             'status_text' => $exception->getStatusText(),
  56.         ]));
  57.     }
  58.     public static function isDebug(RequestStack $requestStackbool $debug): \Closure
  59.     {
  60.         return static function () use ($requestStack$debug): bool {
  61.             if (!$request $requestStack->getCurrentRequest()) {
  62.                 return $debug;
  63.             }
  64.             return $debug && $request->attributes->getBoolean('showException'true);
  65.         };
  66.     }
  67.     private function findTemplate(int $statusCode): ?string
  68.     {
  69.         $template sprintf('@Twig/Exception/error%s.html.twig'$statusCode);
  70.         if ($this->templateExists($template)) {
  71.             return $template;
  72.         }
  73.         $template '@Twig/Exception/error.html.twig';
  74.         if ($this->templateExists($template)) {
  75.             return $template;
  76.         }
  77.         return null;
  78.     }
  79.     /**
  80.      * To be removed in 5.0.
  81.      *
  82.      * Use instead:
  83.      *
  84.      *   $this->twig->getLoader()->exists($template)
  85.      */
  86.     private function templateExists(string $template): bool
  87.     {
  88.         $loader $this->twig->getLoader();
  89.         if ($loader instanceof ExistsLoaderInterface || method_exists($loader'exists')) {
  90.             return $loader->exists($template);
  91.         }
  92.         try {
  93.             $loader->getSourceContext($template);
  94.             return true;
  95.         } catch (LoaderError $e) {
  96.         }
  97.         return false;
  98.     }
  99. }