4 * This file is part of the Symfony package.
6 * (c) Fabien Potencier <fabien@symfony.com>
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
12 namespace Symfony\Component\HttpKernel\EventListener;
14 use Psr\Log\LoggerInterface;
15 use Symfony\Component\Console\ConsoleEvents;
16 use Symfony\Component\Console\Event\ConsoleEvent;
17 use Symfony\Component\Console\Output\ConsoleOutputInterface;
18 use Symfony\Component\Debug\ErrorHandler;
19 use Symfony\Component\Debug\ExceptionHandler;
20 use Symfony\Component\EventDispatcher\Event;
21 use Symfony\Component\EventDispatcher\EventSubscriberInterface;
22 use Symfony\Component\HttpKernel\Event\KernelEvent;
23 use Symfony\Component\HttpKernel\KernelEvents;
26 * Configures errors and exceptions handlers.
28 * @author Nicolas Grekas <p@tchwork.com>
30 class DebugHandlersListener implements EventSubscriberInterface
32 private $exceptionHandler;
37 private $fileLinkFormat;
39 private $firstCall = true;
40 private $hasTerminatedWithException;
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|array $fileLinkFormat The format for links to source files
49 * @param bool $scope Enables/disables scoping mode
51 public function __construct(callable $exceptionHandler = null, LoggerInterface $logger = null, $levels = E_ALL, $throwAt = E_ALL, $scream = true, $fileLinkFormat = null, $scope = true)
53 $this->exceptionHandler = $exceptionHandler;
54 $this->logger = $logger;
55 $this->levels = null === $levels ? E_ALL : $levels;
56 $this->throwAt = is_numeric($throwAt) ? (int) $throwAt : (null === $throwAt ? null : ($throwAt ? E_ALL : null));
57 $this->scream = (bool) $scream;
58 $this->fileLinkFormat = $fileLinkFormat;
59 $this->scope = (bool) $scope;
63 * Configures the error handler.
65 public function configure(Event $event = null)
67 if (!$event instanceof KernelEvent ? !$this->firstCall : !$event->isMasterRequest()) {
70 $this->firstCall = $this->hasTerminatedWithException = false;
72 $handler = set_exception_handler('var_dump');
73 $handler = \is_array($handler) ? $handler[0] : null;
74 restore_exception_handler();
76 if ($this->logger || null !== $this->throwAt) {
77 if ($handler instanceof ErrorHandler) {
79 $handler->setDefaultLogger($this->logger, $this->levels);
80 if (\is_array($this->levels)) {
82 foreach ($this->levels as $type => $log) {
86 $levels = $this->levels;
89 $handler->screamAt($levels);
92 $handler->scopeAt($levels & ~E_USER_DEPRECATED & ~E_DEPRECATED);
94 $handler->scopeAt(0, true);
96 $this->logger = $this->levels = null;
98 if (null !== $this->throwAt) {
99 $handler->throwAt($this->throwAt, true);
103 if (!$this->exceptionHandler) {
104 if ($event instanceof KernelEvent) {
105 if (method_exists($kernel = $event->getKernel(), 'terminateWithException')) {
106 $request = $event->getRequest();
107 $hasRun = &$this->hasTerminatedWithException;
108 $this->exceptionHandler = function (\Exception $e) use ($kernel, $request, &$hasRun) {
113 $kernel->terminateWithException($e, $request);
116 } elseif ($event instanceof ConsoleEvent && $app = $event->getCommand()->getApplication()) {
117 $output = $event->getOutput();
118 if ($output instanceof ConsoleOutputInterface) {
119 $output = $output->getErrorOutput();
121 $this->exceptionHandler = function ($e) use ($app, $output) {
122 $app->renderException($e, $output);
126 if ($this->exceptionHandler) {
127 if ($handler instanceof ErrorHandler) {
128 $h = $handler->setExceptionHandler('var_dump');
129 if (\is_array($h) && $h[0] instanceof ExceptionHandler) {
130 $handler->setExceptionHandler($h);
133 $handler->setExceptionHandler($this->exceptionHandler);
136 if ($handler instanceof ExceptionHandler) {
137 $handler->setHandler($this->exceptionHandler);
138 if (null !== $this->fileLinkFormat) {
139 $handler->setFileLinkFormat($this->fileLinkFormat);
142 $this->exceptionHandler = null;
146 public static function getSubscribedEvents()
148 $events = array(KernelEvents::REQUEST => array('configure', 2048));
150 if ('cli' === \PHP_SAPI && \defined('Symfony\Component\Console\ConsoleEvents::COMMAND')) {
151 $events[ConsoleEvents::COMMAND] = array('configure', 2048);