1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace Dazzle\Throwable; |
4
|
|
|
|
5
|
|
|
/** |
6
|
|
|
* Throwables were designed to handle exceptional states that can occur in application during execution. They were not |
7
|
|
|
* meant to be used in business logic, however in practice, many design patterns emerged that used Throwables as a type |
8
|
|
|
* representation of failure, for which application needed to react. In other programming languages Throwables are |
9
|
|
|
* populated with data not on creation but while throwing. In PHP it works differently, and Throwables are populated |
10
|
|
|
* on creation. This can lead to major problems with memory and performance with usage of previously mentioned design |
11
|
|
|
* patterns. In those cases the valuable pieces of information are Throwable class, message, code and previous element, |
12
|
|
|
* but not stack trace that requires most of memory allocation. For this exclusive need ThrowableProxy has been created. |
13
|
|
|
* Its main purpose is to create a placeholders for Throwable most needed data discarding all not needed traces. |
14
|
|
|
* |
15
|
|
|
* TLDR: This class should be used in design patterns which logic represents failures as throwables, and does not |
16
|
|
|
* necessarily need stack information. |
17
|
|
|
*/ |
18
|
|
|
class ThrowableProxy |
19
|
|
|
{ |
20
|
|
|
/** |
21
|
|
|
* @var string |
22
|
|
|
*/ |
23
|
|
|
protected $class; |
24
|
|
|
|
25
|
|
|
/** |
26
|
|
|
* @var string |
27
|
|
|
*/ |
28
|
|
|
protected $message; |
29
|
|
|
|
30
|
|
|
/** |
31
|
|
|
* @var \Error|\Exception|ThrowableProxy|null |
32
|
|
|
*/ |
33
|
|
|
protected $prev; |
34
|
|
|
|
35
|
|
|
/** |
36
|
|
|
* @var mixed[] |
37
|
|
|
*/ |
38
|
|
|
protected $context; |
39
|
|
|
|
40
|
|
|
/** |
41
|
|
|
* @param \Error|\Exception|string[]|string $throwableOrMessage |
42
|
|
|
*/ |
43
|
14 |
|
public function __construct($throwableOrMessage) |
44
|
|
|
{ |
45
|
14 |
|
if ($throwableOrMessage instanceof \Error || $throwableOrMessage instanceof \Exception) |
|
|
|
|
46
|
|
|
{ |
47
|
10 |
|
$prev = $throwableOrMessage->getPrevious(); |
48
|
|
|
|
49
|
10 |
|
$this->class = get_class($throwableOrMessage); |
50
|
10 |
|
$this->message = $throwableOrMessage->getMessage(); |
51
|
10 |
|
$this->prev = $prev === null ? null : new ThrowableProxy($prev); |
52
|
|
|
} |
53
|
4 |
|
else if (is_array($throwableOrMessage)) |
54
|
|
|
{ |
55
|
1 |
|
$this->class = $throwableOrMessage[0]; |
56
|
1 |
|
$this->message = $throwableOrMessage[1]; |
57
|
1 |
|
$this->prev = null; |
58
|
|
|
} |
59
|
|
|
else |
60
|
|
|
{ |
61
|
3 |
|
$this->class = 'Exception'; |
62
|
3 |
|
$this->message = $throwableOrMessage; |
63
|
3 |
|
$this->prev = null; |
64
|
|
|
} |
65
|
14 |
|
} |
66
|
|
|
|
67
|
|
|
/** |
68
|
|
|
* |
69
|
|
|
*/ |
70
|
19 |
|
public function __destruct() |
71
|
|
|
{ |
72
|
19 |
|
unset($this->class); |
73
|
19 |
|
unset($this->message); |
74
|
19 |
|
unset($this->prev); |
75
|
19 |
|
} |
76
|
|
|
|
77
|
|
|
/** |
78
|
|
|
* @param mixed[] $context |
79
|
|
|
*/ |
80
|
|
|
public function setContext(array $context = []) |
81
|
|
|
{ |
82
|
|
|
$this->context = $context; |
83
|
|
|
} |
84
|
|
|
|
85
|
|
|
/** |
86
|
|
|
* @return mixed[] |
87
|
|
|
*/ |
88
|
|
|
public function getContext() |
89
|
|
|
{ |
90
|
|
|
return $this->context; |
91
|
|
|
} |
92
|
|
|
|
93
|
|
|
/** |
94
|
|
|
* Format proxied Throwable as string. |
95
|
|
|
* |
96
|
|
|
* @return string |
97
|
|
|
*/ |
98
|
1 |
|
public function __toString() |
99
|
|
|
{ |
100
|
1 |
|
return Exception::toString($this->toThrowable()); |
101
|
|
|
} |
102
|
|
|
|
103
|
|
|
/** |
104
|
|
|
* Return proxied Throwable. |
105
|
|
|
* |
106
|
|
|
* @return \Error|\Exception |
107
|
|
|
*/ |
108
|
10 |
|
public function toThrowable() |
109
|
|
|
{ |
110
|
10 |
|
$class = $this->class; |
111
|
10 |
|
$prev = $this->prev !== null ? $this->prev->toThrowable() : $this->prev; |
|
|
|
|
112
|
|
|
|
113
|
10 |
|
return new $class($this->message, 0, $prev); |
114
|
|
|
} |
115
|
|
|
|
116
|
|
|
/** |
117
|
|
|
* Return proxied Throwable message. |
118
|
|
|
* |
119
|
|
|
* @return string |
120
|
|
|
*/ |
121
|
1 |
|
final public function getMessage() |
122
|
|
|
{ |
123
|
1 |
|
return $this->message; |
124
|
|
|
} |
125
|
|
|
|
126
|
|
|
/** |
127
|
|
|
* Return proxied Throwable code. |
128
|
|
|
* |
129
|
|
|
* @return int |
130
|
|
|
*/ |
131
|
1 |
|
final public function getCode() |
132
|
|
|
{ |
133
|
1 |
|
return $this->toThrowable()->getCode(); |
134
|
|
|
} |
135
|
|
|
|
136
|
|
|
/** |
137
|
|
|
* Return proxied Throwable file. |
138
|
|
|
* |
139
|
|
|
* @return string |
140
|
|
|
*/ |
141
|
1 |
|
final public function getFile() |
142
|
|
|
{ |
143
|
1 |
|
return $this->toThrowable()->getFile(); |
144
|
|
|
} |
145
|
|
|
|
146
|
|
|
/** |
147
|
|
|
* Return proxied Throwable code. |
148
|
|
|
* |
149
|
|
|
* @return int |
150
|
|
|
*/ |
151
|
1 |
|
final public function getLine() |
152
|
|
|
{ |
153
|
1 |
|
return $this->toThrowable()->getLine(); |
154
|
|
|
} |
155
|
|
|
|
156
|
|
|
/** |
157
|
|
|
* Return proxied Throwable trace. |
158
|
|
|
* |
159
|
|
|
* @return array |
160
|
|
|
*/ |
161
|
1 |
|
final public function getTrace() |
162
|
|
|
{ |
163
|
1 |
|
return $this->toThrowable()->getTrace(); |
164
|
|
|
} |
165
|
|
|
|
166
|
|
|
/** |
167
|
|
|
* Return proxied Throwable previous element. |
168
|
|
|
* |
169
|
|
|
* @return \Error|\Exception|null |
170
|
|
|
*/ |
171
|
2 |
|
final public function getPrevious() |
172
|
|
|
{ |
173
|
2 |
|
return $this->prev !== null ? $this->prev->toThrowable() : $this->prev; |
|
|
|
|
174
|
|
|
} |
175
|
|
|
|
176
|
|
|
/** |
177
|
|
|
* Return proxied Throwable trace in string format. |
178
|
|
|
* |
179
|
|
|
* @return string |
180
|
|
|
*/ |
181
|
1 |
|
final public function getTraceAsString() |
182
|
|
|
{ |
183
|
1 |
|
return $this->toThrowable()->getTraceAsString(); |
184
|
|
|
} |
185
|
|
|
} |
186
|
|
|
|
This error could be the result of:
1. Missing dependencies
PHP Analyzer uses your
composer.json
file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects thecomposer.json
to be in the root folder of your repository.Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the
require
orrequire-dev
section?2. Missing use statement
PHP does not complain about undefined classes in
ìnstanceof
checks. For example, the following PHP code will work perfectly fine:If you have not tested against this specific condition, such errors might go unnoticed.