vendor/symfony/http-kernel/EventListener/ExceptionListener.php line 48

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\Debug\ExceptionHandler;
  13. use Symfony\Component\Debug\Exception\FlattenException;
  14. use Symfony\Component\EventDispatcher\EventDispatcherInterface;
  15. use Symfony\Component\HttpFoundation\Request;
  16. use Symfony\Component\HttpFoundation\Response;
  17. use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
  18. use Symfony\Component\HttpKernel\Log\DebugLoggerInterface;
  19. use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
  20. use Symfony\Component\HttpKernel\KernelEvents;
  21. use Symfony\Component\HttpKernel\HttpKernelInterface;
  22. use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface;
  23. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  24. /**
  25.  * ExceptionListener.
  26.  *
  27.  * @author Fabien Potencier <fabien@symfony.com>
  28.  */
  29. class ExceptionListener implements EventSubscriberInterface
  30. {
  31.     protected $controller;
  32.     protected $logger;
  33.     protected $debug;
  34.     private $charset;
  35.     public function __construct($controllerLoggerInterface $logger null$debug false$charset null)
  36.     {
  37.         $this->controller $controller;
  38.         $this->logger $logger;
  39.         $this->debug $debug;
  40.         $this->charset $charset;
  41.     }
  42.     public function onKernelException(GetResponseForExceptionEvent $event)
  43.     {
  44.         $exception $event->getException();
  45.         $request $event->getRequest();
  46.         $eventDispatcher func_num_args() > func_get_arg(2) : null;
  47.         $this->logException($exceptionsprintf('Uncaught PHP Exception %s: "%s" at %s line %s'get_class($exception), $exception->getMessage(), $exception->getFile(), $exception->getLine()));
  48.         $request $this->duplicateRequest($exception$request);
  49.         try {
  50.             $response $event->getKernel()->handle($requestHttpKernelInterface::SUB_REQUESTfalse);
  51.         } catch (\Exception $e) {
  52.             $this->logException($esprintf('Exception thrown when handling an exception (%s: %s at %s line %s)'get_class($e), $e->getMessage(), $e->getFile(), $e->getLine()));
  53.             $wrapper $e;
  54.             while ($prev $wrapper->getPrevious()) {
  55.                 if ($exception === $wrapper $prev) {
  56.                     throw $e;
  57.                 }
  58.             }
  59.             $prev = new \ReflectionProperty('Exception''previous');
  60.             $prev->setAccessible(true);
  61.             $prev->setValue($wrapper$exception);
  62.             throw $e;
  63.         }
  64.         $event->setResponse($response);
  65.         if ($this->debug && $eventDispatcher instanceof EventDispatcherInterface) {
  66.             $cspRemovalListener = function (FilterResponseEvent $event) use (&$cspRemovalListener$eventDispatcher) {
  67.                 $event->getResponse()->headers->remove('Content-Security-Policy');
  68.                 $eventDispatcher->removeListener(KernelEvents::RESPONSE$cspRemovalListener);
  69.             };
  70.             $eventDispatcher->addListener(KernelEvents::RESPONSE$cspRemovalListener, -128);
  71.         }
  72.     }
  73.     public static function getSubscribedEvents()
  74.     {
  75.         return array(
  76.             KernelEvents::EXCEPTION => array('onKernelException', -128),
  77.         );
  78.     }
  79.     /**
  80.      * Logs an exception.
  81.      *
  82.      * @param \Exception $exception The \Exception instance
  83.      * @param string     $message   The error message to log
  84.      */
  85.     protected function logException(\Exception $exception$message)
  86.     {
  87.         if (null !== $this->logger) {
  88.             if (!$exception instanceof HttpExceptionInterface || $exception->getStatusCode() >= 500) {
  89.                 $this->logger->critical($message, array('exception' => $exception));
  90.             } else {
  91.                 $this->logger->error($message, array('exception' => $exception));
  92.             }
  93.         }
  94.     }
  95.     /**
  96.      * Clones the request for the exception.
  97.      *
  98.      * @param \Exception $exception The thrown exception
  99.      * @param Request    $request   The original request
  100.      *
  101.      * @return Request $request The cloned request
  102.      */
  103.     protected function duplicateRequest(\Exception $exceptionRequest $request)
  104.     {
  105.         $attributes = array(
  106.             'exception' => $exception FlattenException::create($exception),
  107.             '_controller' => $this->controller ?: function () use ($exception) {
  108.                 $handler = new ExceptionHandler($this->debug$this->charset);
  109.                 return new Response($handler->getHtml($exception), $exception->getStatusCode(), $exception->getHeaders());
  110.             },
  111.             'logger' => $this->logger instanceof DebugLoggerInterface $this->logger null,
  112.         );
  113.         $request $request->duplicate(nullnull$attributes);
  114.         $request->setMethod('GET');
  115.         return $request;
  116.     }
  117. }