1
|
|
|
<?php declare(strict_types = 1); |
2
|
|
|
|
3
|
|
|
namespace Venta\Framework\ErrorHandler; |
4
|
|
|
|
5
|
|
|
use ErrorException; |
6
|
|
|
use Throwable; |
7
|
|
|
use Venta\Contracts\ErrorHandler\ErrorHandler as ErrorHandlerContract; |
8
|
|
|
|
9
|
|
|
/** |
10
|
|
|
* Class ErrorHandler |
11
|
|
|
* |
12
|
|
|
* @package Venta\Framework\ErrorHandler |
13
|
|
|
*/ |
14
|
|
|
class ErrorHandler implements ErrorHandlerContract |
15
|
|
|
{ |
16
|
|
|
|
17
|
|
|
/** |
18
|
|
|
* PHP is shutdown flag. |
19
|
|
|
* |
20
|
|
|
* @var bool |
21
|
|
|
*/ |
22
|
|
|
protected $shutdown = false; |
23
|
|
|
|
24
|
|
|
/** |
25
|
|
|
* ThrowableHandlers to pass caught $throwable for handling. |
26
|
|
|
* |
27
|
|
|
* @var HandlerStack |
28
|
|
|
*/ |
29
|
|
|
protected $stack; |
30
|
|
|
|
31
|
|
|
/** |
32
|
|
|
* Runner constructor registers runner as soon as possible. |
33
|
|
|
* |
34
|
|
|
* @param HandlerStack $stack |
35
|
|
|
*/ |
36
|
|
|
public function __construct(HandlerStack $stack) |
37
|
|
|
{ |
38
|
|
|
$this->stack = $stack; |
39
|
|
|
$this->register(); |
40
|
|
|
} |
41
|
|
|
|
42
|
|
|
/** |
43
|
|
|
* @inheritdoc |
44
|
|
|
* @throws ErrorException |
45
|
|
|
*/ |
46
|
|
|
public function handleError(int $severity, string $message, string $filename, int $lineNumber): bool |
47
|
|
|
{ |
48
|
|
|
// Check if we should handle this error or ignore it. |
49
|
|
|
if (!(error_reporting() & $severity)) { |
50
|
|
|
// Pass error to the next handler. |
51
|
|
|
return false; |
52
|
|
|
} |
53
|
|
|
|
54
|
|
|
$exception = new ErrorException($message, 0, $severity, $filename, $lineNumber); |
55
|
|
|
if ($this->shutdown) { |
56
|
|
|
// PHP is shutdown, we can't throw exceptions at this time. |
57
|
|
|
$this->handleThrowable($exception); |
58
|
|
|
} else { |
59
|
|
|
// We must throw exception to interrupt further code execution. |
60
|
|
|
throw $exception; |
61
|
|
|
} |
62
|
|
|
|
63
|
|
|
return true; |
64
|
|
|
} |
65
|
|
|
|
66
|
|
|
/** |
67
|
|
|
* {@inheritDoc} |
68
|
|
|
*/ |
69
|
|
|
public function handleShutdown() |
70
|
|
|
{ |
71
|
|
|
$error = error_get_last(); |
72
|
|
|
if ($error && ($error['type'] & self::FATAL)) { |
|
|
|
|
73
|
|
|
// Fatal error is not passed to handleError, we need to pass it manually. |
74
|
|
|
$this->shutdown = true; |
75
|
|
|
$this->handleError($error['type'], $error['message'], $error['file'], $error['line']); |
76
|
|
|
} |
77
|
|
|
} |
78
|
|
|
|
79
|
|
|
/** |
80
|
|
|
* {@inheritDoc} |
81
|
|
|
*/ |
82
|
|
|
public function handleThrowable(Throwable $throwable) |
83
|
|
|
{ |
84
|
|
|
foreach ($this->stack as $handler) { |
85
|
|
|
$handler->handle($throwable); |
86
|
|
|
} |
87
|
|
|
} |
88
|
|
|
|
89
|
|
|
/** |
90
|
|
|
* Registers runner as error/exception handler and shutdown function. |
91
|
|
|
* |
92
|
|
|
* @return void |
93
|
|
|
*/ |
94
|
|
|
protected function register() |
95
|
|
|
{ |
96
|
|
|
register_shutdown_function([$this, 'handleShutdown']); |
97
|
|
|
set_exception_handler([$this, 'handleThrowable']); |
98
|
|
|
set_error_handler([$this, 'handleError'], error_reporting()); |
99
|
|
|
} |
100
|
|
|
|
101
|
|
|
} |
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.