1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace PhpConsole\Dispatcher; |
4
|
|
|
use PhpConsole\Dispatcher; |
5
|
|
|
use PhpConsole\ErrorMessage; |
6
|
|
|
use PhpConsole\Message; |
7
|
|
|
|
8
|
|
|
/** |
9
|
|
|
* Sends system errors and exceptions to connector as client expected messages |
10
|
|
|
* |
11
|
|
|
* @package PhpConsole |
12
|
|
|
* @version 3.1 |
13
|
|
|
* @link http://consle.com |
14
|
|
|
* @author Sergey Barbushin http://linkedin.com/in/barbushin |
15
|
|
|
* @copyright © Sergey Barbushin, 2011-2013. All rights reserved. |
16
|
|
|
* @license http://www.opensource.org/licenses/BSD-3-Clause "The BSD 3-Clause License" |
17
|
|
|
*/ |
18
|
|
|
class Errors extends Dispatcher { |
19
|
|
|
|
20
|
|
|
/** @var array PHP errors constants values => names(will be initialized in first call) */ |
21
|
|
|
protected static $errorsConstantsValues = array(); |
22
|
|
|
/** @var array PHP errors constants names */ |
23
|
|
|
protected static $errorsConstantsNames = array( |
24
|
|
|
'E_STRICT', |
25
|
|
|
'E_DEPRECATED', |
26
|
|
|
'E_RECOVERABLE_ERROR', |
27
|
|
|
'E_NOTICE', |
28
|
|
|
'E_WARNING', |
29
|
|
|
'E_ERROR', |
30
|
|
|
'E_PARSE', |
31
|
|
|
'E_USER_DEPRECATED', |
32
|
|
|
'E_USER_NOTICE', |
33
|
|
|
'E_USER_WARNING', |
34
|
|
|
'E_USER_ERROR', |
35
|
|
|
'E_CORE_WARNING', |
36
|
|
|
'E_CORE_ERROR', |
37
|
|
|
'E_COMPILE_ERROR', |
38
|
|
|
'E_COMPILE_WARNING', |
39
|
|
|
); |
40
|
|
|
|
41
|
|
|
/** @var bool Don't send errors messages with same file, line & class */ |
42
|
|
|
public $ignoreRepeatedSource = true; |
43
|
|
|
/** @var bool Dispatch $exception->getPrevious() if not empty */ |
44
|
|
|
public $dispatchPreviousExceptions = true; |
45
|
|
|
|
46
|
|
|
/** @var ErrorMessage[] */ |
47
|
|
|
protected $sentMessages = array(); |
48
|
|
|
|
49
|
|
|
/** |
50
|
|
|
* Send error message to client |
51
|
|
|
* @param null|integer $code |
52
|
|
|
* @param null|string $text |
53
|
|
|
* @param null|string $file |
54
|
|
|
* @param null|integer $line |
55
|
|
|
* @param int|array $ignoreTraceCalls Ignore tracing classes by name prefix `array('PhpConsole')` or fixed number of calls to ignore |
56
|
|
|
*/ |
57
|
18 |
|
public function dispatchError($code = null, $text = null, $file = null, $line = null, $ignoreTraceCalls = 0) { |
58
|
18 |
|
if($this->isActive()) { |
59
|
17 |
|
$message = new ErrorMessage(); |
60
|
17 |
|
$message->code = $code; |
61
|
17 |
|
$message->class = $this->getErrorTypeByCode($code); |
62
|
17 |
|
$message->data = $this->dumper->dump($text); |
63
|
17 |
|
$message->file = $file; |
64
|
17 |
|
$message->line = $line; |
65
|
17 |
|
if($ignoreTraceCalls !== null) { |
66
|
17 |
|
$message->trace = $this->fetchTrace(debug_backtrace(), $file, $line, is_array($ignoreTraceCalls) ? $ignoreTraceCalls : $ignoreTraceCalls + 1); |
67
|
|
|
} |
68
|
17 |
|
$this->sendMessage($message); |
69
|
|
|
} |
70
|
18 |
|
} |
71
|
|
|
|
72
|
|
|
/** |
73
|
|
|
* Send exception message to client |
74
|
|
|
* @param \Exception|\Throwable $exception |
75
|
|
|
*/ |
76
|
14 |
|
public function dispatchException($exception) { |
77
|
14 |
|
if($this->isActive()) { |
78
|
14 |
|
if($this->dispatchPreviousExceptions && $exception->getPrevious()) { |
79
|
1 |
|
$this->dispatchException($exception->getPrevious()); |
80
|
|
|
} |
81
|
14 |
|
$message = new ErrorMessage(); |
82
|
14 |
|
$message->code = $exception->getCode(); |
83
|
14 |
|
$message->class = get_class($exception); |
84
|
14 |
|
$message->data = $this->dumper->dump($exception->getMessage()); |
85
|
14 |
|
$message->file = $exception->getFile(); |
86
|
14 |
|
$message->line = $exception->getLine(); |
87
|
14 |
|
$message->trace = self::fetchTrace($exception->getTrace(), $message->file, $message->line); |
88
|
14 |
|
$this->sendMessage($message); |
89
|
|
|
} |
90
|
14 |
|
} |
91
|
|
|
|
92
|
|
|
/** |
93
|
|
|
* Send message to PHP Console connector |
94
|
|
|
* @param Message $message |
95
|
|
|
*/ |
96
|
31 |
|
protected function sendMessage(Message $message) { |
97
|
31 |
|
if(!$this->isIgnored($message)) { |
98
|
31 |
|
parent::sendMessage($message); |
99
|
31 |
|
$this->sentMessages[] = $message; |
100
|
|
|
} |
101
|
31 |
|
} |
102
|
|
|
|
103
|
|
|
/** |
104
|
|
|
* Get PHP error constant name by value |
105
|
|
|
* @param int $code |
106
|
|
|
* @return string |
107
|
|
|
*/ |
108
|
17 |
|
protected function getErrorTypeByCode($code) { |
109
|
17 |
|
if(!static::$errorsConstantsValues) { |
|
|
|
|
110
|
17 |
|
foreach(static::$errorsConstantsNames as $constantName) { |
111
|
17 |
|
if(defined($constantName)) { |
112
|
17 |
|
static::$errorsConstantsValues[constant($constantName)] = $constantName; |
113
|
|
|
} |
114
|
|
|
} |
115
|
|
|
} |
116
|
17 |
|
if(isset(static::$errorsConstantsValues[$code])) { |
117
|
5 |
|
return static::$errorsConstantsValues[$code]; |
118
|
|
|
} |
119
|
12 |
|
return (string)$code; |
120
|
|
|
} |
121
|
|
|
|
122
|
|
|
/** |
123
|
|
|
* Return true if message with same file, line & class was already sent |
124
|
|
|
* @param ErrorMessage $message |
125
|
|
|
* @return bool |
126
|
|
|
*/ |
127
|
31 |
|
protected function isIgnored(ErrorMessage $message) { |
128
|
31 |
|
if($this->ignoreRepeatedSource && $message->file) { |
129
|
18 |
|
foreach($this->sentMessages as $sentMessage) { |
130
|
4 |
|
if($message->file == $sentMessage->file && $message->line == $sentMessage->line && $message->class == $sentMessage->class) { |
131
|
4 |
|
return true; |
132
|
|
|
} |
133
|
|
|
} |
134
|
|
|
} |
135
|
31 |
|
return false; |
136
|
|
|
} |
137
|
|
|
} |
138
|
|
|
|
This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.
Consider making the comparison explicit by using
empty(..)
or! empty(...)
instead.