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\Debug\ErrorHandler;
16 use Symfony\Component\Debug\ExceptionHandler;
17 use Symfony\Component\EventDispatcher\Event;
18 use Symfony\Component\EventDispatcher\EventSubscriberInterface;
19 use Symfony\Component\HttpKernel\Event\KernelEvent;
20 use Symfony\Component\HttpKernel\KernelEvents;
21 use Symfony\Component\Console\ConsoleEvents;
22 use Symfony\Component\Console\Event\ConsoleEvent;
23 use Symfony\Component\Console\Output\ConsoleOutputInterface;
26 * Configures errors and exceptions handlers.
28 * @author Nicolas Grekas <p@tchwork.com>
30 class DebugHandlersListener implements EventSubscriberInterface
32 private $exceptionHandler;
37 private $fileLinkFormat;
38 private $firstCall = true;
41 * @param callable|null $exceptionHandler A handler that will be called on Exception
42 * @param LoggerInterface|null $logger A PSR-3 logger
43 * @param array|int $levels An array map of E_* to LogLevel::* or an integer bit field of E_* constants
44 * @param int|null $throwAt Thrown errors in a bit field of E_* constants, or null to keep the current value
45 * @param bool $scream Enables/disables screaming mode, where even silenced errors are logged
46 * @param string $fileLinkFormat The format for links to source files
48 public function __construct($exceptionHandler, LoggerInterface $logger = null, $levels = null, $throwAt = -1, $scream = true, $fileLinkFormat = null)
50 $this->exceptionHandler = $exceptionHandler;
51 $this->logger = $logger;
52 $this->levels = $levels;
53 $this->throwAt = is_numeric($throwAt) ? (int) $throwAt : (null === $throwAt ? null : ($throwAt ? -1 : null));
54 $this->scream = (bool) $scream;
55 $this->fileLinkFormat = $fileLinkFormat ?: ini_get('xdebug.file_link_format') ?: get_cfg_var('xdebug.file_link_format');
59 * Configures the error handler.
61 * @param Event|null $event The triggering event
63 public function configure(Event $event = null)
65 if (!$this->firstCall) {
68 $this->firstCall = false;
69 if ($this->logger || null !== $this->throwAt) {
70 $handler = set_error_handler('var_dump');
71 $handler = is_array($handler) ? $handler[0] : null;
72 restore_error_handler();
73 if ($handler instanceof ErrorHandler) {
75 $handler->setDefaultLogger($this->logger, $this->levels);
76 if (is_array($this->levels)) {
78 foreach ($this->levels as $type => $log) {
82 $scream = null === $this->levels ? E_ALL | E_STRICT : $this->levels;
85 $handler->screamAt($scream);
87 $this->logger = $this->levels = null;
89 if (null !== $this->throwAt) {
90 $handler->throwAt($this->throwAt, true);
94 if (!$this->exceptionHandler) {
95 if ($event instanceof KernelEvent) {
96 if (method_exists($event->getKernel(), 'terminateWithException')) {
97 $this->exceptionHandler = array($event->getKernel(), 'terminateWithException');
99 } elseif ($event instanceof ConsoleEvent && $app = $event->getCommand()->getApplication()) {
100 $output = $event->getOutput();
101 if ($output instanceof ConsoleOutputInterface) {
102 $output = $output->getErrorOutput();
104 $this->exceptionHandler = function ($e) use ($app, $output) {
105 $app->renderException($e, $output);
109 if ($this->exceptionHandler) {
110 $handler = set_exception_handler('var_dump');
111 $handler = is_array($handler) ? $handler[0] : null;
112 restore_exception_handler();
113 if ($handler instanceof ErrorHandler) {
114 $h = $handler->setExceptionHandler('var_dump') ?: $this->exceptionHandler;
115 $handler->setExceptionHandler($h);
116 $handler = is_array($h) ? $h[0] : null;
118 if ($handler instanceof ExceptionHandler) {
119 $handler->setHandler($this->exceptionHandler);
120 if (null !== $this->fileLinkFormat) {
121 $handler->setFileLinkFormat($this->fileLinkFormat);
124 $this->exceptionHandler = null;
128 public static function getSubscribedEvents()
130 $events = array(KernelEvents::REQUEST => array('configure', 2048));
132 if (defined('Symfony\Component\Console\ConsoleEvents::COMMAND')) {
133 $events[ConsoleEvents::COMMAND] = array('configure', 2048);