Completed
Push — master ( 193986...cdf399 )
by Andrey
11:47
created

DebugHandlersListener   A

Complexity

Total Complexity 33

Size/Duplication

Total Lines 109
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 5

Importance

Changes 0
Metric Value
dl 0
loc 109
rs 9.76
c 0
b 0
f 0
wmc 33
lcom 1
cbo 5

3 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 9 6
F configure() 0 64 25
A getSubscribedEvents() 0 10 2
1
<?php
2
3
/*
4
 * This file is part of the Symfony package.
5
 *
6
 * (c) Fabien Potencier <[email protected]>
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\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;
24
25
/**
26
 * Configures errors and exceptions handlers.
27
 *
28
 * @author Nicolas Grekas <[email protected]>
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 $firstCall = true;
39
40
    /**
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
47
     */
48
    public function __construct($exceptionHandler, LoggerInterface $logger = null, $levels = null, $throwAt = -1, $scream = true, $fileLinkFormat = null)
49
    {
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');
56
    }
57
58
    /**
59
     * Configures the error handler.
60
     *
61
     * @param Event|null $event The triggering event
62
     */
63
    public function configure(Event $event = null)
64
    {
65
        if (!$this->firstCall) {
66
            return;
67
        }
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) {
74
                if ($this->logger) {
75
                    $handler->setDefaultLogger($this->logger, $this->levels);
76
                    if (is_array($this->levels)) {
77
                        $scream = 0;
78
                        foreach ($this->levels as $type => $log) {
79
                            $scream |= $type;
80
                        }
81
                    } else {
82
                        $scream = null === $this->levels ? E_ALL | E_STRICT : $this->levels;
83
                    }
84
                    if ($this->scream) {
85
                        $handler->screamAt($scream);
86
                    }
87
                    $this->logger = $this->levels = null;
88
                }
89
                if (null !== $this->throwAt) {
90
                    $handler->throwAt($this->throwAt, true);
91
                }
92
            }
93
        }
94
        if (!$this->exceptionHandler) {
95
            if ($event instanceof KernelEvent) {
96
                if (method_exists($event->getKernel(), 'terminateWithException')) {
97
                    $this->exceptionHandler = array($event->getKernel(), 'terminateWithException');
98
                }
99
            } elseif ($event instanceof ConsoleEvent && $app = $event->getCommand()->getApplication()) {
100
                $output = $event->getOutput();
101
                if ($output instanceof ConsoleOutputInterface) {
102
                    $output = $output->getErrorOutput();
103
                }
104
                $this->exceptionHandler = function ($e) use ($app, $output) {
105
                    $app->renderException($e, $output);
106
                };
107
            }
108
        }
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;
117
            }
118
            if ($handler instanceof ExceptionHandler) {
119
                $handler->setHandler($this->exceptionHandler);
120
                if (null !== $this->fileLinkFormat) {
121
                    $handler->setFileLinkFormat($this->fileLinkFormat);
122
                }
123
            }
124
            $this->exceptionHandler = null;
125
        }
126
    }
127
128
    public static function getSubscribedEvents()
129
    {
130
        $events = array(KernelEvents::REQUEST => array('configure', 2048));
131
132
        if (defined('Symfony\Component\Console\ConsoleEvents::COMMAND')) {
133
            $events[ConsoleEvents::COMMAND] = array('configure', 2048);
134
        }
135
136
        return $events;
137
    }
138
}
139