vendor/symfony/http-kernel/EventListener/DebugHandlersListener.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 Symfony\Component\HttpKernel\EventListener;
  11. use Psr\Log\LoggerInterface;
  12. use Symfony\Component\Console\ConsoleEvents;
  13. use Symfony\Component\Console\Event\ConsoleEvent;
  14. use Symfony\Component\Console\Output\ConsoleOutputInterface;
  15. use Symfony\Component\Debug\ErrorHandler;
  16. use Symfony\Component\Debug\ExceptionHandler;
  17. use Symfony\Component\EventDispatcher\Event;
  18. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  19. use Symfony\Component\HttpFoundation\Request;
  20. use Symfony\Component\HttpFoundation\Response;
  21. use Symfony\Component\HttpKernel\Debug\FileLinkFormatter;
  22. use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
  23. use Symfony\Component\HttpKernel\Event\KernelEvent;
  24. use Symfony\Component\HttpKernel\KernelEvents;
  25. /**
  26.  * Configures errors and exceptions handlers.
  27.  *
  28.  * @author Nicolas Grekas <p@tchwork.com>
  29.  */
  30. class DebugHandlersListener implements EventSubscriberInterface
  31. {
  32.     private $exceptionHandler;
  33.     private $logger;
  34.     private $levels;
  35.     private $throwAt;
  36.     private $scream;
  37.     private $fileLinkFormat;
  38.     private $scope;
  39.     private $charset;
  40.     private $firstCall true;
  41.     private $hasTerminatedWithException;
  42.     /**
  43.      * @param callable|null                 $exceptionHandler A handler that will be called on Exception
  44.      * @param LoggerInterface|null          $logger           A PSR-3 logger
  45.      * @param array|int                     $levels           An array map of E_* to LogLevel::* or an integer bit field of E_* constants
  46.      * @param int|null                      $throwAt          Thrown errors in a bit field of E_* constants, or null to keep the current value
  47.      * @param bool                          $scream           Enables/disables screaming mode, where even silenced errors are logged
  48.      * @param string|FileLinkFormatter|null $fileLinkFormat   The format for links to source files
  49.      * @param bool                          $scope            Enables/disables scoping mode
  50.      */
  51.     public function __construct(callable $exceptionHandler nullLoggerInterface $logger null$levels E_ALL, ?int $throwAt E_ALLbool $scream true$fileLinkFormat nullbool $scope truestring $charset null)
  52.     {
  53.         $this->exceptionHandler $exceptionHandler;
  54.         $this->logger $logger;
  55.         $this->levels null === $levels E_ALL $levels;
  56.         $this->throwAt = \is_int($throwAt) ? $throwAt : (null === $throwAt null : ($throwAt E_ALL null));
  57.         $this->scream $scream;
  58.         $this->fileLinkFormat $fileLinkFormat;
  59.         $this->scope $scope;
  60.         $this->charset $charset;
  61.     }
  62.     /**
  63.      * Configures the error handler.
  64.      */
  65.     public function configure(Event $event null)
  66.     {
  67.         if (!$event instanceof KernelEvent ? !$this->firstCall : !$event->isMasterRequest()) {
  68.             return;
  69.         }
  70.         $this->firstCall $this->hasTerminatedWithException false;
  71.         $handler set_exception_handler('var_dump');
  72.         $handler = \is_array($handler) ? $handler[0] : null;
  73.         restore_exception_handler();
  74.         if ($this->logger || null !== $this->throwAt) {
  75.             if ($handler instanceof ErrorHandler) {
  76.                 if ($this->logger) {
  77.                     $handler->setDefaultLogger($this->logger$this->levels);
  78.                     if (\is_array($this->levels)) {
  79.                         $levels 0;
  80.                         foreach ($this->levels as $type => $log) {
  81.                             $levels |= $type;
  82.                         }
  83.                     } else {
  84.                         $levels $this->levels;
  85.                     }
  86.                     if ($this->scream) {
  87.                         $handler->screamAt($levels);
  88.                     }
  89.                     if ($this->scope) {
  90.                         $handler->scopeAt($levels & ~E_USER_DEPRECATED & ~E_DEPRECATED);
  91.                     } else {
  92.                         $handler->scopeAt(0true);
  93.                     }
  94.                     $this->logger $this->levels null;
  95.                 }
  96.                 if (null !== $this->throwAt) {
  97.                     $handler->throwAt($this->throwAttrue);
  98.                 }
  99.             }
  100.         }
  101.         if (!$this->exceptionHandler) {
  102.             if ($event instanceof KernelEvent) {
  103.                 if (method_exists($kernel $event->getKernel(), 'terminateWithException')) {
  104.                     $request $event->getRequest();
  105.                     $hasRun = &$this->hasTerminatedWithException;
  106.                     $this->exceptionHandler = static function (\Exception $e) use ($kernel$request, &$hasRun) {
  107.                         if ($hasRun) {
  108.                             throw $e;
  109.                         }
  110.                         $hasRun true;
  111.                         $kernel->terminateWithException($e$request);
  112.                     };
  113.                 }
  114.             } elseif ($event instanceof ConsoleEvent && $app $event->getCommand()->getApplication()) {
  115.                 $output $event->getOutput();
  116.                 if ($output instanceof ConsoleOutputInterface) {
  117.                     $output $output->getErrorOutput();
  118.                 }
  119.                 $this->exceptionHandler = function ($e) use ($app$output) {
  120.                     $app->renderException($e$output);
  121.                 };
  122.             }
  123.         }
  124.         if ($this->exceptionHandler) {
  125.             if ($handler instanceof ErrorHandler) {
  126.                 $h $handler->setExceptionHandler('var_dump');
  127.                 if (\is_array($h) && $h[0] instanceof ExceptionHandler) {
  128.                     $handler->setExceptionHandler($h);
  129.                     $handler $h[0];
  130.                 } else {
  131.                     $handler->setExceptionHandler($this->exceptionHandler);
  132.                 }
  133.             }
  134.             if ($handler instanceof ExceptionHandler) {
  135.                 $handler->setHandler($this->exceptionHandler);
  136.                 if (null !== $this->fileLinkFormat) {
  137.                     $handler->setFileLinkFormat($this->fileLinkFormat);
  138.                 }
  139.             }
  140.             $this->exceptionHandler null;
  141.         }
  142.     }
  143.     /**
  144.      * @internal
  145.      */
  146.     public function onKernelException(GetResponseForExceptionEvent $event)
  147.     {
  148.         if (!$this->hasTerminatedWithException || !$event->isMasterRequest()) {
  149.             return;
  150.         }
  151.         $debug $this->scream && $this->scope;
  152.         $controller = function (Request $request) use ($debug) {
  153.             $e $request->attributes->get('exception');
  154.             $handler = new ExceptionHandler($debug$this->charset$this->fileLinkFormat);
  155.             return new Response($handler->getHtml($e), $e->getStatusCode(), $e->getHeaders());
  156.         };
  157.         (new ExceptionListener($controller$this->logger$debug))->onKernelException($event);
  158.     }
  159.     public static function getSubscribedEvents()
  160.     {
  161.         $events = [KernelEvents::REQUEST => ['configure'2048]];
  162.         if ('cli' === \PHP_SAPI && \defined('Symfony\Component\Console\ConsoleEvents::COMMAND')) {
  163.             $events[ConsoleEvents::COMMAND] = ['configure'2048];
  164.         }
  165.         $events[KernelEvents::EXCEPTION] = ['onKernelException', -2048];
  166.         return $events;
  167.     }
  168. }