|
1
|
|
|
<?php |
|
2
|
|
|
|
|
3
|
|
|
namespace Kint\Parser; |
|
4
|
|
|
|
|
5
|
|
|
use Exception; |
|
6
|
|
|
use Kint\Object\BasicObject; |
|
7
|
|
|
use Kint\Object\BlobObject; |
|
8
|
|
|
use Kint\Object\InstanceObject; |
|
9
|
|
|
use Kint\Object\Representation\Representation; |
|
10
|
|
|
use Kint\Object\ResourceObject; |
|
11
|
|
|
use ReflectionObject; |
|
12
|
|
|
|
|
13
|
|
|
class Parser |
|
14
|
|
|
{ |
|
15
|
|
|
protected $caller_class = null; |
|
|
|
|
|
|
16
|
|
|
protected $depth_limit = false; |
|
|
|
|
|
|
17
|
|
|
protected $marker; |
|
18
|
|
|
protected $object_hashes = array(); |
|
|
|
|
|
|
19
|
|
|
protected $parse_break = false; |
|
|
|
|
|
|
20
|
|
|
protected $plugins = array(); |
|
21
|
|
|
|
|
22
|
|
|
/** |
|
23
|
|
|
* Plugin triggers. |
|
24
|
|
|
* |
|
25
|
|
|
* These are constants indicating trigger points for plugins |
|
26
|
|
|
* |
|
27
|
|
|
* BEGIN: Before normal parsing |
|
28
|
|
|
* SUCCESS: After successful parsing |
|
29
|
|
|
* RECURSION: After parsing cancelled by recursion |
|
30
|
|
|
* DEPTH_LIMIT: After parsing cancelled by depth limit |
|
31
|
|
|
* COMPLETE: SUCCESS | RECURSION | DEPTH_LIMIT |
|
32
|
|
|
* |
|
33
|
|
|
* While a plugin's getTriggers may return any of these |
|
34
|
|
|
*/ |
|
35
|
|
|
const TRIGGER_NONE = 0; |
|
36
|
|
|
const TRIGGER_BEGIN = 1; |
|
37
|
|
|
const TRIGGER_SUCCESS = 2; |
|
38
|
|
|
const TRIGGER_RECURSION = 4; |
|
39
|
|
|
const TRIGGER_DEPTH_LIMIT = 8; |
|
40
|
|
|
const TRIGGER_COMPLETE = 14; |
|
41
|
|
|
|
|
42
|
|
|
/** |
|
43
|
|
|
* @param bool|int $depth_limit Maximum depth to parse data |
|
44
|
|
|
* @param string $caller Caller class name |
|
|
|
|
|
|
45
|
|
|
*/ |
|
46
|
|
|
public function __construct($depth_limit = false, $caller = null) |
|
|
|
|
|
|
47
|
|
|
{ |
|
48
|
|
|
$this->marker = uniqid("kint\0", true); |
|
49
|
|
|
|
|
50
|
|
|
if ($caller) { |
|
|
|
|
|
|
51
|
|
|
$this->caller_class = $caller; |
|
52
|
|
|
} |
|
53
|
|
|
|
|
54
|
|
|
if ($depth_limit) { |
|
|
|
|
|
|
55
|
|
|
$this->depth_limit = $depth_limit; |
|
|
|
|
|
|
56
|
|
|
} |
|
57
|
|
|
} |
|
58
|
|
|
|
|
59
|
|
|
/** |
|
60
|
|
|
* Disables the depth limit and parses a variable. |
|
61
|
|
|
* |
|
62
|
|
|
* This should not be used unless you know what you're doing! |
|
63
|
|
|
* |
|
64
|
|
|
* @param mixed $var The input variable |
|
65
|
|
|
* @param BasicObject $o The base object |
|
66
|
|
|
* |
|
67
|
|
|
* @return BasicObject |
|
68
|
|
|
*/ |
|
69
|
|
|
public function parseDeep(&$var, BasicObject $o) |
|
|
|
|
|
|
70
|
|
|
{ |
|
71
|
|
|
$depth_limit = $this->depth_limit; |
|
|
|
|
|
|
72
|
|
|
$this->depth_limit = false; |
|
73
|
|
|
|
|
74
|
|
|
$out = $this->parse($var, $o); |
|
75
|
|
|
|
|
76
|
|
|
$this->depth_limit = $depth_limit; |
|
|
|
|
|
|
77
|
|
|
|
|
78
|
|
|
return $out; |
|
79
|
|
|
} |
|
80
|
|
|
|
|
81
|
|
|
/** |
|
82
|
|
|
* Parses a variable into a Kint object structure. |
|
83
|
|
|
* |
|
84
|
|
|
* @param mixed $var The input variable |
|
85
|
|
|
* @param BasicObject $o The base object |
|
86
|
|
|
* |
|
87
|
|
|
* @return BasicObject |
|
88
|
|
|
*/ |
|
89
|
|
|
public function parse(&$var, BasicObject $o) |
|
|
|
|
|
|
90
|
|
|
{ |
|
91
|
|
|
$o->type = strtolower(gettype($var)); |
|
92
|
|
|
|
|
93
|
|
|
if (!$this->applyPlugins($var, $o, self::TRIGGER_BEGIN)) { |
|
94
|
|
|
return $o; |
|
95
|
|
|
} |
|
96
|
|
|
|
|
97
|
|
|
switch ($o->type) { |
|
98
|
|
|
case 'array': |
|
99
|
|
|
return $this->parseArray($var, $o); |
|
100
|
|
|
case 'boolean': |
|
101
|
|
|
case 'double': |
|
102
|
|
|
case 'integer': |
|
103
|
|
|
case 'null': |
|
104
|
|
|
return $this->parseGeneric($var, $o); |
|
105
|
|
|
case 'object': |
|
106
|
|
|
return $this->parseObject($var, $o); |
|
107
|
|
|
case 'resource': |
|
108
|
|
|
return $this->parseResource($var, $o); |
|
109
|
|
|
case 'string': |
|
110
|
|
|
return $this->parseString($var, $o); |
|
111
|
|
|
default: |
|
112
|
|
|
return $this->parseUnknown($var, $o); |
|
113
|
|
|
} |
|
114
|
|
|
} |
|
115
|
|
|
|
|
116
|
|
|
private function parseGeneric(&$var, BasicObject $o) |
|
|
|
|
|
|
117
|
|
|
{ |
|
118
|
|
|
$rep = new Representation('Contents'); |
|
119
|
|
|
$rep->contents = $var; |
|
120
|
|
|
$rep->implicit_label = true; |
|
121
|
|
|
$o->addRepresentation($rep); |
|
122
|
|
|
$o->value = $rep; |
|
123
|
|
|
|
|
124
|
|
|
$this->applyPlugins($var, $o, self::TRIGGER_SUCCESS); |
|
125
|
|
|
|
|
126
|
|
|
return $o; |
|
127
|
|
|
} |
|
128
|
|
|
|
|
129
|
|
|
/** |
|
130
|
|
|
* Parses a string into a Kint BlobObject structure. |
|
131
|
|
|
* |
|
132
|
|
|
* @param string $var The input variable |
|
133
|
|
|
* @param BasicObject $o The base object |
|
134
|
|
|
* |
|
135
|
|
|
* @return BlobObject |
|
136
|
|
|
*/ |
|
137
|
|
|
private function parseString(&$var, BasicObject $o) |
|
|
|
|
|
|
138
|
|
|
{ |
|
139
|
|
|
$string = $o->transplant(new BlobObject()); |
|
140
|
|
|
$string->encoding = BlobObject::detectEncoding($var); |
|
|
|
|
|
|
141
|
|
|
$string->size = BlobObject::strlen($var, $string->encoding); |
|
142
|
|
|
|
|
143
|
|
|
$rep = new Representation('Contents'); |
|
144
|
|
|
$rep->contents = $var; |
|
|
|
|
|
|
145
|
|
|
$rep->implicit_label = true; |
|
146
|
|
|
|
|
147
|
|
|
$string->addRepresentation($rep); |
|
148
|
|
|
$string->value = $rep; |
|
149
|
|
|
|
|
150
|
|
|
$this->applyPlugins($var, $string, self::TRIGGER_SUCCESS); |
|
151
|
|
|
|
|
152
|
|
|
return $string; |
|
153
|
|
|
} |
|
154
|
|
|
|
|
155
|
|
|
/** |
|
156
|
|
|
* Parses an array into a Kint object structure. |
|
157
|
|
|
* |
|
158
|
|
|
* @param array $var The input variable |
|
159
|
|
|
* @param BasicObject $o The base object |
|
160
|
|
|
* |
|
161
|
|
|
* @return BasicObject |
|
162
|
|
|
*/ |
|
163
|
|
|
private function parseArray(array &$var, BasicObject $o) |
|
|
|
|
|
|
164
|
|
|
{ |
|
165
|
|
|
$array = $o->transplant(new BasicObject()); |
|
166
|
|
|
$array->size = count($var); |
|
167
|
|
|
|
|
168
|
|
View Code Duplication |
if (isset($var[$this->marker])) { |
|
|
|
|
|
|
169
|
|
|
--$array->size; |
|
170
|
|
|
$array->hints[] = 'recursion'; |
|
171
|
|
|
|
|
172
|
|
|
$this->applyPlugins($var, $array, self::TRIGGER_RECURSION); |
|
173
|
|
|
|
|
174
|
|
|
return $array; |
|
175
|
|
|
} |
|
176
|
|
|
|
|
177
|
|
|
$rep = new Representation('Contents'); |
|
178
|
|
|
$rep->implicit_label = true; |
|
179
|
|
|
$array->addRepresentation($rep); |
|
180
|
|
|
$array->value = $rep; |
|
181
|
|
|
|
|
182
|
|
|
if ($array->size) { |
|
183
|
|
View Code Duplication |
if ($this->depth_limit && $o->depth >= $this->depth_limit) { |
|
|
|
|
|
|
184
|
|
|
$array->hints[] = 'depth_limit'; |
|
185
|
|
|
|
|
186
|
|
|
$this->applyPlugins($var, $array, self::TRIGGER_DEPTH_LIMIT); |
|
187
|
|
|
|
|
188
|
|
|
return $array; |
|
189
|
|
|
} |
|
190
|
|
|
|
|
191
|
|
|
$copy = array_values($var); |
|
192
|
|
|
|
|
193
|
|
|
// It's really really hard to access numeric string keys in arrays, |
|
194
|
|
|
// and it's really really hard to access integer properties in |
|
195
|
|
|
// objects, so we just use array_values and index by counter to get |
|
196
|
|
|
// at it reliably for reference testing. This also affects access |
|
197
|
|
|
// paths since it's pretty much impossible to access these things |
|
198
|
|
|
// without complicated stuff you should never need to do. |
|
199
|
|
|
$i = 0; |
|
200
|
|
|
|
|
201
|
|
|
// Set the marker for recursion |
|
202
|
|
|
$var[$this->marker] = $array->depth; |
|
203
|
|
|
|
|
204
|
|
|
foreach ($var as $key => &$val) { |
|
205
|
|
|
if ($key === $this->marker) { |
|
206
|
|
|
continue; |
|
207
|
|
|
} |
|
208
|
|
|
|
|
209
|
|
|
$child = new BasicObject(); |
|
210
|
|
|
$child->name = $key; |
|
211
|
|
|
$child->depth = $array->depth + 1; |
|
212
|
|
|
$child->access = BasicObject::ACCESS_NONE; |
|
213
|
|
|
$child->operator = BasicObject::OPERATOR_ARRAY; |
|
214
|
|
|
|
|
215
|
|
|
if ($array->access_path !== null) { |
|
216
|
|
|
if (is_string($key) && (string) (int) $key === $key) { |
|
217
|
|
|
$child->access_path = 'array_values('.$array->access_path.')['.$i.']'; |
|
218
|
|
|
} else { |
|
219
|
|
|
$child->access_path = $array->access_path.'['.var_export($key, true).']'; |
|
220
|
|
|
} |
|
221
|
|
|
} |
|
222
|
|
|
|
|
223
|
|
|
$stash = $val; |
|
224
|
|
|
$copy[$i] = $this->marker; |
|
225
|
|
|
if ($val === $this->marker) { |
|
|
|
|
|
|
226
|
|
|
$child->reference = true; |
|
227
|
|
|
$val = $stash; |
|
228
|
|
|
} |
|
229
|
|
|
|
|
230
|
|
|
$rep->contents[] = $this->parse($val, $child); |
|
231
|
|
|
++$i; |
|
232
|
|
|
} |
|
233
|
|
|
|
|
234
|
|
|
$this->applyPlugins($var, $array, self::TRIGGER_SUCCESS); |
|
235
|
|
|
unset($var[$this->marker]); |
|
236
|
|
|
|
|
237
|
|
|
return $array; |
|
238
|
|
|
} else { |
|
239
|
|
|
$this->applyPlugins($var, $array, self::TRIGGER_SUCCESS); |
|
240
|
|
|
|
|
241
|
|
|
return $array; |
|
242
|
|
|
} |
|
243
|
|
|
} |
|
244
|
|
|
|
|
245
|
|
|
/** |
|
246
|
|
|
* Parses an object into a Kint InstanceObject structure. |
|
247
|
|
|
* |
|
248
|
|
|
* @param object $var The input variable |
|
249
|
|
|
* @param BasicObject $o The base object |
|
250
|
|
|
* |
|
251
|
|
|
* @return InstanceObject |
|
252
|
|
|
*/ |
|
253
|
|
|
private function parseObject(&$var, BasicObject $o) |
|
|
|
|
|
|
254
|
|
|
{ |
|
255
|
|
|
$hash = spl_object_hash($var); |
|
256
|
|
|
$values = (array) $var; |
|
257
|
|
|
|
|
258
|
|
|
$object = $o->transplant(new InstanceObject()); |
|
259
|
|
|
$object->classname = get_class($var); |
|
|
|
|
|
|
260
|
|
|
$object->hash = $hash; |
|
|
|
|
|
|
261
|
|
|
$object->size = count($values); |
|
262
|
|
|
|
|
263
|
|
View Code Duplication |
if (isset($this->object_hashes[$hash])) { |
|
|
|
|
|
|
264
|
|
|
$object->hints[] = 'recursion'; |
|
265
|
|
|
|
|
266
|
|
|
$this->applyPlugins($var, $object, self::TRIGGER_RECURSION); |
|
267
|
|
|
|
|
268
|
|
|
return $object; |
|
269
|
|
|
} |
|
270
|
|
|
|
|
271
|
|
|
$this->object_hashes[$hash] = $object; |
|
272
|
|
|
|
|
273
|
|
View Code Duplication |
if ($this->depth_limit && $o->depth >= $this->depth_limit) { |
|
|
|
|
|
|
274
|
|
|
$object->hints[] = 'depth_limit'; |
|
275
|
|
|
|
|
276
|
|
|
$this->applyPlugins($var, $object, self::TRIGGER_DEPTH_LIMIT); |
|
277
|
|
|
unset($this->object_hashes[$hash]); |
|
278
|
|
|
|
|
279
|
|
|
return $object; |
|
280
|
|
|
} |
|
281
|
|
|
|
|
282
|
|
|
$reflector = new ReflectionObject($var); |
|
283
|
|
|
|
|
284
|
|
|
if ($reflector->isUserDefined()) { |
|
285
|
|
|
$object->filename = $reflector->getFileName(); |
|
|
|
|
|
|
286
|
|
|
$object->startline = $reflector->getStartLine(); |
|
|
|
|
|
|
287
|
|
|
} |
|
288
|
|
|
|
|
289
|
|
|
$rep = new Representation('Properties'); |
|
290
|
|
|
|
|
291
|
|
|
$copy = array_values($values); |
|
292
|
|
|
|
|
293
|
|
|
$i = 0; |
|
294
|
|
|
|
|
295
|
|
|
// Reflection will not show parent classes private properties, and if a |
|
296
|
|
|
// property was unset it will happly trigger a notice looking for it. |
|
297
|
|
|
foreach ($values as $key => &$val) { |
|
298
|
|
|
// Casting object to array: |
|
299
|
|
|
// private properties show in the form "\0$owner_class_name\0$property_name"; |
|
300
|
|
|
// protected properties show in the form "\0*\0$property_name"; |
|
301
|
|
|
// public properties show in the form "$property_name"; |
|
302
|
|
|
// http://www.php.net/manual/en/language.types.array.php#language.types.array.casting |
|
303
|
|
|
|
|
304
|
|
|
$child = new BasicObject(); |
|
305
|
|
|
$child->depth = $object->depth + 1; |
|
306
|
|
|
$child->owner_class = $object->classname; |
|
307
|
|
|
$child->operator = BasicObject::OPERATOR_OBJECT; |
|
308
|
|
|
$child->access = BasicObject::ACCESS_PUBLIC; |
|
309
|
|
|
|
|
310
|
|
|
$split_key = explode("\0", $key, 3); |
|
|
|
|
|
|
311
|
|
|
|
|
312
|
|
|
if (count($split_key) === 3 && $split_key[0] === '') { |
|
|
|
|
|
|
313
|
|
|
$child->name = $split_key[2]; |
|
|
|
|
|
|
314
|
|
|
if ($split_key[1] === '*') { |
|
|
|
|
|
|
315
|
|
|
$child->access = BasicObject::ACCESS_PROTECTED; |
|
316
|
|
|
} else { |
|
317
|
|
|
$child->access = BasicObject::ACCESS_PRIVATE; |
|
318
|
|
|
$child->owner_class = $split_key[1]; |
|
|
|
|
|
|
319
|
|
|
} |
|
320
|
|
|
} elseif (KINT_PHP72) { |
|
321
|
|
|
$child->name = (string) $key; // @codeCoverageIgnore |
|
322
|
|
|
} else { |
|
323
|
|
|
$child->name = $key; |
|
324
|
|
|
} |
|
325
|
|
|
|
|
326
|
|
|
if ($this->childHasPath($object, $child)) { |
|
|
|
|
|
|
327
|
|
|
$child->access_path = $object->access_path; |
|
328
|
|
|
|
|
329
|
|
|
if (!KINT_PHP72 && is_int($child->name)) { |
|
330
|
|
|
$child->access_path = 'array_values((array) '.$child->access_path.')['.$i.']'; |
|
331
|
|
|
} elseif (preg_match('/^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*$/', $child->name)) { |
|
332
|
|
|
$child->access_path .= '->'.$child->name; |
|
333
|
|
|
} else { |
|
334
|
|
|
$child->access_path .= '->{'.var_export((string) $child->name, true).'}'; |
|
335
|
|
|
} |
|
336
|
|
|
} |
|
337
|
|
|
|
|
338
|
|
|
$stash = $val; |
|
339
|
|
|
$copy[$i] = $this->marker; |
|
340
|
|
|
if ($val === $this->marker) { |
|
341
|
|
|
$child->reference = true; |
|
342
|
|
|
$val = $stash; |
|
343
|
|
|
} |
|
344
|
|
|
|
|
345
|
|
|
$rep->contents[] = $this->parse($val, $child); |
|
346
|
|
|
++$i; |
|
347
|
|
|
} |
|
348
|
|
|
|
|
349
|
|
|
usort($rep->contents, array($this, 'sortObjectProperties')); |
|
350
|
|
|
|
|
351
|
|
|
$object->addRepresentation($rep); |
|
352
|
|
|
$object->value = $rep; |
|
353
|
|
|
$this->applyPlugins($var, $object, self::TRIGGER_SUCCESS); |
|
354
|
|
|
unset($this->object_hashes[$hash]); |
|
355
|
|
|
|
|
356
|
|
|
return $object; |
|
357
|
|
|
} |
|
358
|
|
|
|
|
359
|
|
|
/** |
|
360
|
|
|
* Parses a resource into a Kint ResourceObject structure. |
|
361
|
|
|
* |
|
362
|
|
|
* @param resource $var The input variable |
|
363
|
|
|
* @param BasicObject $o The base object |
|
364
|
|
|
* |
|
365
|
|
|
* @return ResourceObject |
|
366
|
|
|
*/ |
|
367
|
|
|
private function parseResource(&$var, BasicObject $o) |
|
|
|
|
|
|
368
|
|
|
{ |
|
369
|
|
|
$resource = $o->transplant(new ResourceObject()); |
|
370
|
|
|
$resource->resource_type = get_resource_type($var); |
|
|
|
|
|
|
371
|
|
|
|
|
372
|
|
|
$this->applyPlugins($var, $resource, self::TRIGGER_SUCCESS); |
|
373
|
|
|
|
|
374
|
|
|
return $resource; |
|
375
|
|
|
} |
|
376
|
|
|
|
|
377
|
|
|
/** |
|
378
|
|
|
* Parses an unknown into a Kint object structure. |
|
379
|
|
|
* |
|
380
|
|
|
* @param mixed $var The input variable |
|
381
|
|
|
* @param BasicObject $o The base object |
|
382
|
|
|
* |
|
383
|
|
|
* @return BasicObject |
|
384
|
|
|
*/ |
|
385
|
|
|
private function parseUnknown(&$var, BasicObject $o) |
|
|
|
|
|
|
386
|
|
|
{ |
|
387
|
|
|
$o->type = 'unknown'; |
|
388
|
|
|
$this->applyPlugins($var, $o, self::TRIGGER_SUCCESS); |
|
389
|
|
|
|
|
390
|
|
|
return $o; |
|
391
|
|
|
} |
|
392
|
|
|
|
|
393
|
|
|
public function addPlugin(Plugin $p) |
|
|
|
|
|
|
394
|
|
|
{ |
|
395
|
|
|
if (!$types = $p->getTypes()) { |
|
396
|
|
|
return false; |
|
397
|
|
|
} |
|
398
|
|
|
|
|
399
|
|
|
if (!$triggers = $p->getTriggers()) { |
|
400
|
|
|
return false; |
|
401
|
|
|
} |
|
402
|
|
|
|
|
403
|
|
|
$p->setParser($this); |
|
404
|
|
|
|
|
405
|
|
|
foreach ($types as $type) { |
|
406
|
|
|
if (!isset($this->plugins[$type])) { |
|
407
|
|
|
$this->plugins[$type] = array( |
|
408
|
|
|
self::TRIGGER_BEGIN => array(), |
|
409
|
|
|
self::TRIGGER_SUCCESS => array(), |
|
410
|
|
|
self::TRIGGER_RECURSION => array(), |
|
411
|
|
|
self::TRIGGER_DEPTH_LIMIT => array(), |
|
412
|
|
|
); |
|
413
|
|
|
} |
|
414
|
|
|
|
|
415
|
|
|
foreach ($this->plugins[$type] as $trigger => &$pool) { |
|
416
|
|
|
if ($triggers & $trigger) { |
|
417
|
|
|
$pool[] = $p; |
|
418
|
|
|
} |
|
419
|
|
|
} |
|
420
|
|
|
} |
|
421
|
|
|
|
|
422
|
|
|
return true; |
|
423
|
|
|
} |
|
424
|
|
|
|
|
425
|
|
|
public function clearPlugins() |
|
426
|
|
|
{ |
|
427
|
|
|
$this->plugins = array(); |
|
428
|
|
|
} |
|
429
|
|
|
|
|
430
|
|
|
/** |
|
431
|
|
|
* Applies plugins for an object type. |
|
432
|
|
|
* |
|
433
|
|
|
* @param mixed $var variable |
|
434
|
|
|
* @param BasicObject $o Kint object parsed so far |
|
435
|
|
|
* @param int $trigger The trigger to check for the plugins |
|
436
|
|
|
* |
|
437
|
|
|
* @return bool Continue parsing |
|
438
|
|
|
*/ |
|
439
|
|
|
private function applyPlugins(&$var, BasicObject &$o, $trigger) |
|
|
|
|
|
|
440
|
|
|
{ |
|
441
|
|
|
$break_stash = $this->parse_break; |
|
|
|
|
|
|
442
|
|
|
$this->parse_break = false; |
|
443
|
|
|
|
|
444
|
|
|
$plugins = array(); |
|
445
|
|
|
|
|
446
|
|
|
if (isset($this->plugins[$o->type][$trigger])) { |
|
447
|
|
|
$plugins = $this->plugins[$o->type][$trigger]; |
|
448
|
|
|
} |
|
449
|
|
|
|
|
450
|
|
|
foreach ($plugins as $plugin) { |
|
451
|
|
|
try { |
|
452
|
|
|
$plugin->parse($var, $o, $trigger); |
|
453
|
|
|
} catch (Exception $e) { |
|
454
|
|
|
trigger_error( |
|
455
|
|
|
'An exception ('.get_class($e).') was thrown in '.$e->getFile().' on line '.$e->getLine().' while executing Kint Parser Plugin "'.get_class($plugin).'". Error message: '.$e->getMessage(), |
|
456
|
|
|
E_USER_WARNING |
|
457
|
|
|
); |
|
458
|
|
|
} |
|
459
|
|
|
|
|
460
|
|
|
if ($this->parse_break) { |
|
461
|
|
|
$this->parse_break = $break_stash; |
|
|
|
|
|
|
462
|
|
|
|
|
463
|
|
|
return false; |
|
464
|
|
|
} |
|
465
|
|
|
} |
|
466
|
|
|
|
|
467
|
|
|
$this->parse_break = $break_stash; |
|
|
|
|
|
|
468
|
|
|
|
|
469
|
|
|
return true; |
|
470
|
|
|
} |
|
471
|
|
|
|
|
472
|
|
|
public function haltParse() |
|
473
|
|
|
{ |
|
474
|
|
|
$this->parse_break = true; |
|
475
|
|
|
} |
|
476
|
|
|
|
|
477
|
|
|
public function childHasPath(InstanceObject $parent, BasicObject $child) |
|
|
|
|
|
|
478
|
|
|
{ |
|
479
|
|
|
if ($parent->type === 'object' && ($parent->access_path !== null || $child->static || $child->const)) { |
|
480
|
|
|
if ($child->access === BasicObject::ACCESS_PUBLIC) { |
|
481
|
|
|
return true; |
|
482
|
|
|
} elseif ($child->access === BasicObject::ACCESS_PRIVATE && $this->caller_class) { |
|
483
|
|
|
if ($this->caller_class === $child->owner_class) { |
|
484
|
|
|
return true; |
|
485
|
|
|
} |
|
486
|
|
|
} elseif ($child->access === BasicObject::ACCESS_PROTECTED && $this->caller_class) { |
|
487
|
|
|
if ($this->caller_class === $child->owner_class) { |
|
488
|
|
|
return true; |
|
489
|
|
|
} |
|
490
|
|
|
if (is_subclass_of($this->caller_class, $child->owner_class)) { |
|
491
|
|
|
return true; |
|
492
|
|
|
} |
|
493
|
|
|
if (is_subclass_of($child->owner_class, $this->caller_class)) { |
|
494
|
|
|
return true; |
|
495
|
|
|
} |
|
496
|
|
|
} |
|
497
|
|
|
} |
|
498
|
|
|
|
|
499
|
|
|
return false; |
|
500
|
|
|
} |
|
501
|
|
|
|
|
502
|
|
|
/** |
|
503
|
|
|
* Returns an array without the recursion marker in it. |
|
504
|
|
|
* |
|
505
|
|
|
* DO NOT pass an array that has had it's marker removed back |
|
506
|
|
|
* into the parser, it will result in an extra recursion |
|
507
|
|
|
* |
|
508
|
|
|
* @param array $array Array potentially containing a recursion marker |
|
509
|
|
|
* |
|
510
|
|
|
* @return array Array with recursion marker removed |
|
511
|
|
|
*/ |
|
512
|
|
|
public function getCleanArray(array $array) |
|
513
|
|
|
{ |
|
514
|
|
|
unset($array[$this->marker]); |
|
515
|
|
|
|
|
516
|
|
|
return $array; |
|
517
|
|
|
} |
|
518
|
|
|
|
|
519
|
|
|
public function getCallerClass() |
|
520
|
|
|
{ |
|
521
|
|
|
return $this->caller_class; |
|
522
|
|
|
} |
|
523
|
|
|
|
|
524
|
|
|
public function getDepthLimit() |
|
|
|
|
|
|
525
|
|
|
{ |
|
526
|
|
|
return $this->depth_limit; |
|
527
|
|
|
} |
|
528
|
|
|
|
|
529
|
|
|
private function sortObjectProperties(BasicObject $a, BasicObject $b) |
|
|
|
|
|
|
530
|
|
|
{ |
|
531
|
|
|
$sort = BasicObject::sortByAccess($a, $b); |
|
532
|
|
|
if ($sort) { |
|
533
|
|
|
return $sort; |
|
534
|
|
|
} |
|
535
|
|
|
|
|
536
|
|
|
$sort = BasicObject::sortByName($a, $b); |
|
537
|
|
|
if ($sort) { |
|
538
|
|
|
return $sort; |
|
539
|
|
|
} |
|
540
|
|
|
|
|
541
|
|
|
return InstanceObject::sortByHierarchy($a->owner_class, $b->owner_class); |
|
542
|
|
|
} |
|
543
|
|
|
} |
|
544
|
|
|
|
This check examines a number of code elements and verifies that they conform to the given naming conventions.
You can set conventions for local variables, abstract classes, utility classes, constant, properties, methods, parameters, interfaces, classes, exceptions and special methods.