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\Exception; |
13
|
|
|
|
14
|
|
|
use Symfony\Component\Debug\Exception\FlattenException as DebugFlattenException; |
15
|
|
|
|
16
|
|
|
/** |
17
|
|
|
* FlattenException wraps a PHP Exception to be able to serialize it. |
18
|
|
|
* |
19
|
|
|
* Basically, this class removes all objects from the trace. |
20
|
|
|
* |
21
|
|
|
* @author Fabien Potencier <[email protected]> |
22
|
|
|
* |
23
|
|
|
* @deprecated Deprecated in 2.3, to be removed in 3.0. Use the same class from the Debug component instead. |
24
|
|
|
*/ |
25
|
|
|
class FlattenException |
26
|
|
|
{ |
27
|
|
|
private $handler; |
28
|
|
|
|
29
|
|
|
public static function __callStatic($method, $args) |
30
|
|
|
{ |
31
|
|
|
if (!method_exists('Symfony\Component\Debug\Exception\FlattenException', $method)) { |
32
|
|
|
throw new \BadMethodCallException(sprintf('Call to undefined method %s::%s()', get_called_class(), $method)); |
33
|
|
|
} |
34
|
|
|
|
35
|
|
|
return call_user_func_array(array('Symfony\Component\Debug\Exception\FlattenException', $method), $args); |
36
|
|
|
} |
37
|
|
|
|
38
|
|
|
public function __call($method, $args) |
39
|
|
|
{ |
40
|
|
|
if (!isset($this->handler)) { |
41
|
|
|
$this->handler = new DebugFlattenException(); |
42
|
|
|
} |
43
|
|
|
|
44
|
|
|
if (!method_exists($this->handler, $method)) { |
45
|
|
|
throw new \BadMethodCallException(sprintf('Call to undefined method %s::%s()', get_class($this), $method)); |
46
|
|
|
} |
47
|
|
|
|
48
|
|
|
return call_user_func_array(array($this->handler, $method), $args); |
49
|
|
|
} |
50
|
|
|
} |
51
|
|
|
|
52
|
|
|
namespace Symfony\Component\Debug\Exception; |
53
|
|
|
|
54
|
|
|
use Symfony\Component\HttpKernel\Exception\FlattenException as LegacyFlattenException; |
55
|
|
|
use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface; |
56
|
|
|
|
57
|
|
|
/** |
58
|
|
|
* FlattenException wraps a PHP Exception to be able to serialize it. |
59
|
|
|
* |
60
|
|
|
* Basically, this class removes all objects from the trace. |
61
|
|
|
* |
62
|
|
|
* @author Fabien Potencier <[email protected]> |
63
|
|
|
*/ |
64
|
|
|
class FlattenException extends LegacyFlattenException |
|
|
|
|
65
|
|
|
{ |
66
|
|
|
private $message; |
67
|
|
|
private $code; |
68
|
|
|
private $previous; |
69
|
|
|
private $trace; |
70
|
|
|
private $class; |
71
|
|
|
private $statusCode; |
72
|
|
|
private $headers; |
73
|
|
|
private $file; |
74
|
|
|
private $line; |
75
|
|
|
|
76
|
|
|
public static function create(\Exception $exception, $statusCode = null, array $headers = array()) |
77
|
|
|
{ |
78
|
|
|
$e = new static(); |
79
|
|
|
$e->setMessage($exception->getMessage()); |
80
|
|
|
$e->setCode($exception->getCode()); |
81
|
|
|
|
82
|
|
|
if ($exception instanceof HttpExceptionInterface) { |
83
|
|
|
$statusCode = $exception->getStatusCode(); |
84
|
|
|
$headers = array_merge($headers, $exception->getHeaders()); |
85
|
|
|
} |
86
|
|
|
|
87
|
|
|
if (null === $statusCode) { |
88
|
|
|
$statusCode = 500; |
89
|
|
|
} |
90
|
|
|
|
91
|
|
|
$e->setStatusCode($statusCode); |
92
|
|
|
$e->setHeaders($headers); |
93
|
|
|
$e->setTraceFromException($exception); |
94
|
|
|
$e->setClass(get_class($exception)); |
95
|
|
|
$e->setFile($exception->getFile()); |
96
|
|
|
$e->setLine($exception->getLine()); |
97
|
|
|
|
98
|
|
|
$previous = $exception->getPrevious(); |
99
|
|
|
|
100
|
|
|
if ($previous instanceof \Exception) { |
101
|
|
|
$e->setPrevious(static::create($previous)); |
102
|
|
|
} elseif ($previous instanceof \Throwable) { |
103
|
|
|
$e->setPrevious(static::create(new FatalThrowableError($previous))); |
104
|
|
|
} |
105
|
|
|
|
106
|
|
|
return $e; |
107
|
|
|
} |
108
|
|
|
|
109
|
|
|
public function toArray() |
110
|
|
|
{ |
111
|
|
|
$exceptions = array(); |
112
|
|
|
foreach (array_merge(array($this), $this->getAllPrevious()) as $exception) { |
113
|
|
|
$exceptions[] = array( |
114
|
|
|
'message' => $exception->getMessage(), |
115
|
|
|
'class' => $exception->getClass(), |
116
|
|
|
'trace' => $exception->getTrace(), |
117
|
|
|
); |
118
|
|
|
} |
119
|
|
|
|
120
|
|
|
return $exceptions; |
121
|
|
|
} |
122
|
|
|
|
123
|
|
|
public function getStatusCode() |
124
|
|
|
{ |
125
|
|
|
return $this->statusCode; |
126
|
|
|
} |
127
|
|
|
|
128
|
|
|
public function setStatusCode($code) |
129
|
|
|
{ |
130
|
|
|
$this->statusCode = $code; |
131
|
|
|
} |
132
|
|
|
|
133
|
|
|
public function getHeaders() |
134
|
|
|
{ |
135
|
|
|
return $this->headers; |
136
|
|
|
} |
137
|
|
|
|
138
|
|
|
public function setHeaders(array $headers) |
139
|
|
|
{ |
140
|
|
|
$this->headers = $headers; |
141
|
|
|
} |
142
|
|
|
|
143
|
|
|
public function getClass() |
144
|
|
|
{ |
145
|
|
|
return $this->class; |
146
|
|
|
} |
147
|
|
|
|
148
|
|
|
public function setClass($class) |
149
|
|
|
{ |
150
|
|
|
$this->class = $class; |
151
|
|
|
} |
152
|
|
|
|
153
|
|
|
public function getFile() |
154
|
|
|
{ |
155
|
|
|
return $this->file; |
156
|
|
|
} |
157
|
|
|
|
158
|
|
|
public function setFile($file) |
159
|
|
|
{ |
160
|
|
|
$this->file = $file; |
161
|
|
|
} |
162
|
|
|
|
163
|
|
|
public function getLine() |
164
|
|
|
{ |
165
|
|
|
return $this->line; |
166
|
|
|
} |
167
|
|
|
|
168
|
|
|
public function setLine($line) |
169
|
|
|
{ |
170
|
|
|
$this->line = $line; |
171
|
|
|
} |
172
|
|
|
|
173
|
|
|
public function getMessage() |
174
|
|
|
{ |
175
|
|
|
return $this->message; |
176
|
|
|
} |
177
|
|
|
|
178
|
|
|
public function setMessage($message) |
179
|
|
|
{ |
180
|
|
|
$this->message = $message; |
181
|
|
|
} |
182
|
|
|
|
183
|
|
|
public function getCode() |
184
|
|
|
{ |
185
|
|
|
return $this->code; |
186
|
|
|
} |
187
|
|
|
|
188
|
|
|
public function setCode($code) |
189
|
|
|
{ |
190
|
|
|
$this->code = $code; |
191
|
|
|
} |
192
|
|
|
|
193
|
|
|
public function getPrevious() |
194
|
|
|
{ |
195
|
|
|
return $this->previous; |
196
|
|
|
} |
197
|
|
|
|
198
|
|
|
public function setPrevious(FlattenException $previous) |
199
|
|
|
{ |
200
|
|
|
$this->previous = $previous; |
201
|
|
|
} |
202
|
|
|
|
203
|
|
|
public function getAllPrevious() |
204
|
|
|
{ |
205
|
|
|
$exceptions = array(); |
206
|
|
|
$e = $this; |
207
|
|
|
while ($e = $e->getPrevious()) { |
208
|
|
|
$exceptions[] = $e; |
209
|
|
|
} |
210
|
|
|
|
211
|
|
|
return $exceptions; |
212
|
|
|
} |
213
|
|
|
|
214
|
|
|
public function getTrace() |
215
|
|
|
{ |
216
|
|
|
return $this->trace; |
217
|
|
|
} |
218
|
|
|
|
219
|
|
|
public function setTraceFromException(\Exception $exception) |
220
|
|
|
{ |
221
|
|
|
$this->setTrace($exception->getTrace(), $exception->getFile(), $exception->getLine()); |
222
|
|
|
} |
223
|
|
|
|
224
|
|
|
public function setTrace($trace, $file, $line) |
225
|
|
|
{ |
226
|
|
|
$this->trace = array(); |
227
|
|
|
$this->trace[] = array( |
228
|
|
|
'namespace' => '', |
229
|
|
|
'short_class' => '', |
230
|
|
|
'class' => '', |
231
|
|
|
'type' => '', |
232
|
|
|
'function' => '', |
233
|
|
|
'file' => $file, |
234
|
|
|
'line' => $line, |
235
|
|
|
'args' => array(), |
236
|
|
|
); |
237
|
|
|
foreach ($trace as $entry) { |
238
|
|
|
$class = ''; |
239
|
|
|
$namespace = ''; |
240
|
|
|
if (isset($entry['class'])) { |
241
|
|
|
$parts = explode('\\', $entry['class']); |
242
|
|
|
$class = array_pop($parts); |
243
|
|
|
$namespace = implode('\\', $parts); |
244
|
|
|
} |
245
|
|
|
|
246
|
|
|
$this->trace[] = array( |
247
|
|
|
'namespace' => $namespace, |
248
|
|
|
'short_class' => $class, |
249
|
|
|
'class' => isset($entry['class']) ? $entry['class'] : '', |
250
|
|
|
'type' => isset($entry['type']) ? $entry['type'] : '', |
251
|
|
|
'function' => isset($entry['function']) ? $entry['function'] : null, |
252
|
|
|
'file' => isset($entry['file']) ? $entry['file'] : null, |
253
|
|
|
'line' => isset($entry['line']) ? $entry['line'] : null, |
254
|
|
|
'args' => isset($entry['args']) ? $this->flattenArgs($entry['args']) : array(), |
255
|
|
|
); |
256
|
|
|
} |
257
|
|
|
} |
258
|
|
|
|
259
|
|
|
private function flattenArgs($args, $level = 0, &$count = 0) |
260
|
|
|
{ |
261
|
|
|
$result = array(); |
262
|
|
|
foreach ($args as $key => $value) { |
263
|
|
|
if (++$count > 1e4) { |
264
|
|
|
return array('array', '*SKIPPED over 10000 entries*'); |
265
|
|
|
} |
266
|
|
|
if ($value instanceof \__PHP_Incomplete_Class) { |
267
|
|
|
// is_object() returns false on PHP<=7.1 |
268
|
|
|
$result[$key] = array('incomplete-object', $this->getClassNameFromIncomplete($value)); |
269
|
|
|
} elseif (is_object($value)) { |
270
|
|
|
$result[$key] = array('object', get_class($value)); |
271
|
|
|
} elseif (is_array($value)) { |
272
|
|
|
if ($level > 10) { |
273
|
|
|
$result[$key] = array('array', '*DEEP NESTED ARRAY*'); |
274
|
|
|
} else { |
275
|
|
|
$result[$key] = array('array', $this->flattenArgs($value, $level + 1, $count)); |
276
|
|
|
} |
277
|
|
|
} elseif (null === $value) { |
278
|
|
|
$result[$key] = array('null', null); |
279
|
|
|
} elseif (is_bool($value)) { |
280
|
|
|
$result[$key] = array('boolean', $value); |
281
|
|
|
} elseif (is_resource($value)) { |
282
|
|
|
$result[$key] = array('resource', get_resource_type($value)); |
283
|
|
|
} else { |
284
|
|
|
$result[$key] = array('string', (string) $value); |
285
|
|
|
} |
286
|
|
|
} |
287
|
|
|
|
288
|
|
|
return $result; |
289
|
|
|
} |
290
|
|
|
|
291
|
|
|
private function getClassNameFromIncomplete(\__PHP_Incomplete_Class $value) |
292
|
|
|
{ |
293
|
|
|
$array = new \ArrayObject($value); |
294
|
|
|
|
295
|
|
|
return $array['__PHP_Incomplete_Class_Name']; |
296
|
|
|
} |
297
|
|
|
} |
298
|
|
|
|
This class, trait or interface has been deprecated. The supplier of the file has supplied an explanatory message.
The explanatory message should give you some clue as to whether and when the type will be removed from the class and what other constant to use instead.