1c50ef4acad512c181409af36a8370a6caedb618
[yaffs-website] / vendor / symfony / http-kernel / EventListener / ExceptionListener.php
1 <?php
2
3 /*
4  * This file is part of the Symfony package.
5  *
6  * (c) Fabien Potencier <fabien@symfony.com>
7  *
8  * For the full copyright and license information, please view the LICENSE
9  * file that was distributed with this source code.
10  */
11
12 namespace Symfony\Component\HttpKernel\EventListener;
13
14 use Psr\Log\LoggerInterface;
15 use Symfony\Component\Debug\Exception\FlattenException;
16 use Symfony\Component\HttpFoundation\Request;
17 use Symfony\Component\HttpKernel\Log\DebugLoggerInterface;
18 use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
19 use Symfony\Component\HttpKernel\KernelEvents;
20 use Symfony\Component\HttpKernel\HttpKernelInterface;
21 use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface;
22 use Symfony\Component\EventDispatcher\EventSubscriberInterface;
23
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
34     public function __construct($controller, LoggerInterface $logger = null)
35     {
36         $this->controller = $controller;
37         $this->logger = $logger;
38     }
39
40     public function onKernelException(GetResponseForExceptionEvent $event)
41     {
42         $exception = $event->getException();
43         $request = $event->getRequest();
44
45         $this->logException($exception, sprintf('Uncaught PHP Exception %s: "%s" at %s line %s', get_class($exception), $exception->getMessage(), $exception->getFile(), $exception->getLine()));
46
47         $request = $this->duplicateRequest($exception, $request);
48
49         try {
50             $response = $event->getKernel()->handle($request, HttpKernelInterface::SUB_REQUEST, false);
51         } catch (\Exception $e) {
52             $this->logException($e, sprintf('Exception thrown when handling an exception (%s: %s at %s line %s)', get_class($e), $e->getMessage(), $e->getFile(), $e->getLine()));
53
54             $wrapper = $e;
55
56             while ($prev = $wrapper->getPrevious()) {
57                 if ($exception === $wrapper = $prev) {
58                     throw $e;
59                 }
60             }
61
62             $prev = new \ReflectionProperty('Exception', 'previous');
63             $prev->setAccessible(true);
64             $prev->setValue($wrapper, $exception);
65
66             throw $e;
67         }
68
69         $event->setResponse($response);
70     }
71
72     public static function getSubscribedEvents()
73     {
74         return array(
75             KernelEvents::EXCEPTION => array('onKernelException', -128),
76         );
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     /**
97      * Clones the request for the exception.
98      *
99      * @param \Exception $exception The thrown exception
100      * @param Request    $request   The original request
101      *
102      * @return Request $request The cloned request
103      */
104     protected function duplicateRequest(\Exception $exception, Request $request)
105     {
106         $attributes = array(
107             '_controller' => $this->controller,
108             'exception' => FlattenException::create($exception),
109             'logger' => $this->logger instanceof DebugLoggerInterface ? $this->logger : null,
110             // keep for BC -- as $format can be an argument of the controller callable
111             // see src/Symfony/Bundle/TwigBundle/Controller/ExceptionController.php
112             // @deprecated since version 2.4, to be removed in 3.0
113             'format' => $request->getRequestFormat(),
114         );
115         $request = $request->duplicate(null, null, $attributes);
116         $request->setMethod('GET');
117
118         return $request;
119     }
120 }