Subversion-Projekte lars-tiefland.laravel_shop

Revision

Revision 148 | Details | Vergleich mit vorheriger | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
148 lars 1
<?php
2
 
3
/*
4
 * This file is part of the Symfony package.
5
 *
6
 * (c) Fabien Potencier <fabien@symfony.com>
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\VarDumper\Caster;
13
 
14
use Symfony\Component\VarDumper\Cloner\Stub;
15
 
16
/**
17
 * Casts Reflector related classes to array representation.
18
 *
19
 * @author Nicolas Grekas <p@tchwork.com>
20
 *
21
 * @final
22
 */
23
class ReflectionCaster
24
{
25
    public const UNSET_CLOSURE_FILE_INFO = ['Closure' => __CLASS__.'::unsetClosureFileInfo'];
26
 
27
    private const EXTRA_MAP = [
28
        'docComment' => 'getDocComment',
29
        'extension' => 'getExtensionName',
30
        'isDisabled' => 'isDisabled',
31
        'isDeprecated' => 'isDeprecated',
32
        'isInternal' => 'isInternal',
33
        'isUserDefined' => 'isUserDefined',
34
        'isGenerator' => 'isGenerator',
35
        'isVariadic' => 'isVariadic',
36
    ];
37
 
38
    public static function castClosure(\Closure $c, array $a, Stub $stub, bool $isNested, int $filter = 0)
39
    {
40
        $prefix = Caster::PREFIX_VIRTUAL;
41
        $c = new \ReflectionFunction($c);
42
 
43
        $a = static::castFunctionAbstract($c, $a, $stub, $isNested, $filter);
44
 
45
        if (!str_contains($c->name, '{closure}')) {
46
            $stub->class = isset($a[$prefix.'class']) ? $a[$prefix.'class']->value.'::'.$c->name : $c->name;
47
            unset($a[$prefix.'class']);
48
        }
49
        unset($a[$prefix.'extra']);
50
 
51
        $stub->class .= self::getSignature($a);
52
 
53
        if ($f = $c->getFileName()) {
54
            $stub->attr['file'] = $f;
55
            $stub->attr['line'] = $c->getStartLine();
56
        }
57
 
58
        unset($a[$prefix.'parameters']);
59
 
60
        if ($filter & Caster::EXCLUDE_VERBOSE) {
61
            $stub->cut += ($c->getFileName() ? 2 : 0) + \count($a);
62
 
63
            return [];
64
        }
65
 
66
        if ($f) {
67
            $a[$prefix.'file'] = new LinkStub($f, $c->getStartLine());
68
            $a[$prefix.'line'] = $c->getStartLine().' to '.$c->getEndLine();
69
        }
70
 
71
        return $a;
72
    }
73
 
74
    public static function unsetClosureFileInfo(\Closure $c, array $a)
75
    {
76
        unset($a[Caster::PREFIX_VIRTUAL.'file'], $a[Caster::PREFIX_VIRTUAL.'line']);
77
 
78
        return $a;
79
    }
80
 
81
    public static function castGenerator(\Generator $c, array $a, Stub $stub, bool $isNested)
82
    {
83
        // Cannot create ReflectionGenerator based on a terminated Generator
84
        try {
85
            $reflectionGenerator = new \ReflectionGenerator($c);
86
        } catch (\Exception) {
87
            $a[Caster::PREFIX_VIRTUAL.'closed'] = true;
88
 
89
            return $a;
90
        }
91
 
92
        return self::castReflectionGenerator($reflectionGenerator, $a, $stub, $isNested);
93
    }
94
 
95
    public static function castType(\ReflectionType $c, array $a, Stub $stub, bool $isNested)
96
    {
97
        $prefix = Caster::PREFIX_VIRTUAL;
98
 
99
        if ($c instanceof \ReflectionNamedType) {
100
            $a += [
101
                $prefix.'name' => $c instanceof \ReflectionNamedType ? $c->getName() : (string) $c,
102
                $prefix.'allowsNull' => $c->allowsNull(),
103
                $prefix.'isBuiltin' => $c->isBuiltin(),
104
            ];
105
        } elseif ($c instanceof \ReflectionUnionType || $c instanceof \ReflectionIntersectionType) {
106
            $a[$prefix.'allowsNull'] = $c->allowsNull();
107
            self::addMap($a, $c, [
108
                'types' => 'getTypes',
109
            ]);
110
        } else {
111
            $a[$prefix.'allowsNull'] = $c->allowsNull();
112
        }
113
 
114
        return $a;
115
    }
116
 
117
    public static function castAttribute(\ReflectionAttribute $c, array $a, Stub $stub, bool $isNested)
118
    {
119
        self::addMap($a, $c, [
120
            'name' => 'getName',
121
            'arguments' => 'getArguments',
122
        ]);
123
 
124
        return $a;
125
    }
126
 
127
    public static function castReflectionGenerator(\ReflectionGenerator $c, array $a, Stub $stub, bool $isNested)
128
    {
129
        $prefix = Caster::PREFIX_VIRTUAL;
130
 
131
        if ($c->getThis()) {
132
            $a[$prefix.'this'] = new CutStub($c->getThis());
133
        }
134
        $function = $c->getFunction();
135
        $frame = [
136
            'class' => $function->class ?? null,
137
            'type' => isset($function->class) ? ($function->isStatic() ? '::' : '->') : null,
138
            'function' => $function->name,
139
            'file' => $c->getExecutingFile(),
140
            'line' => $c->getExecutingLine(),
141
        ];
142
        if ($trace = $c->getTrace(\DEBUG_BACKTRACE_IGNORE_ARGS)) {
143
            $function = new \ReflectionGenerator($c->getExecutingGenerator());
144
            array_unshift($trace, [
145
                'function' => 'yield',
146
                'file' => $function->getExecutingFile(),
147
                'line' => $function->getExecutingLine(),
148
            ]);
149
            $trace[] = $frame;
150
            $a[$prefix.'trace'] = new TraceStub($trace, false, 0, -1, -1);
151
        } else {
152
            $function = new FrameStub($frame, false, true);
153
            $function = ExceptionCaster::castFrameStub($function, [], $function, true);
154
            $a[$prefix.'executing'] = $function[$prefix.'src'];
155
        }
156
 
157
        $a[Caster::PREFIX_VIRTUAL.'closed'] = false;
158
 
159
        return $a;
160
    }
161
 
162
    public static function castClass(\ReflectionClass $c, array $a, Stub $stub, bool $isNested, int $filter = 0)
163
    {
164
        $prefix = Caster::PREFIX_VIRTUAL;
165
 
166
        if ($n = \Reflection::getModifierNames($c->getModifiers())) {
167
            $a[$prefix.'modifiers'] = implode(' ', $n);
168
        }
169
 
170
        self::addMap($a, $c, [
171
            'extends' => 'getParentClass',
172
            'implements' => 'getInterfaceNames',
173
            'constants' => 'getReflectionConstants',
174
        ]);
175
 
176
        foreach ($c->getProperties() as $n) {
177
            $a[$prefix.'properties'][$n->name] = $n;
178
        }
179
 
180
        foreach ($c->getMethods() as $n) {
181
            $a[$prefix.'methods'][$n->name] = $n;
182
        }
183
 
184
        self::addAttributes($a, $c, $prefix);
185
 
186
        if (!($filter & Caster::EXCLUDE_VERBOSE) && !$isNested) {
187
            self::addExtra($a, $c);
188
        }
189
 
190
        return $a;
191
    }
192
 
193
    public static function castFunctionAbstract(\ReflectionFunctionAbstract $c, array $a, Stub $stub, bool $isNested, int $filter = 0)
194
    {
195
        $prefix = Caster::PREFIX_VIRTUAL;
196
 
197
        self::addMap($a, $c, [
198
            'returnsReference' => 'returnsReference',
199
            'returnType' => 'getReturnType',
200
            'class' => \PHP_VERSION_ID >= 80111 ? 'getClosureCalledClass' : 'getClosureScopeClass',
201
            'this' => 'getClosureThis',
202
        ]);
203
 
204
        if (isset($a[$prefix.'returnType'])) {
205
            $v = $a[$prefix.'returnType'];
206
            $v = $v instanceof \ReflectionNamedType ? $v->getName() : (string) $v;
207
            $a[$prefix.'returnType'] = new ClassStub($a[$prefix.'returnType'] instanceof \ReflectionNamedType && $a[$prefix.'returnType']->allowsNull() && 'mixed' !== $v ? '?'.$v : $v, [class_exists($v, false) || interface_exists($v, false) || trait_exists($v, false) ? $v : '', '']);
208
        }
209
        if (isset($a[$prefix.'class'])) {
210
            $a[$prefix.'class'] = new ClassStub($a[$prefix.'class']);
211
        }
212
        if (isset($a[$prefix.'this'])) {
213
            $a[$prefix.'this'] = new CutStub($a[$prefix.'this']);
214
        }
215
 
216
        foreach ($c->getParameters() as $v) {
217
            $k = '$'.$v->name;
218
            if ($v->isVariadic()) {
219
                $k = '...'.$k;
220
            }
221
            if ($v->isPassedByReference()) {
222
                $k = '&'.$k;
223
            }
224
            $a[$prefix.'parameters'][$k] = $v;
225
        }
226
        if (isset($a[$prefix.'parameters'])) {
227
            $a[$prefix.'parameters'] = new EnumStub($a[$prefix.'parameters']);
228
        }
229
 
230
        self::addAttributes($a, $c, $prefix);
231
 
232
        if (!($filter & Caster::EXCLUDE_VERBOSE) && $v = $c->getStaticVariables()) {
233
            foreach ($v as $k => &$v) {
234
                if (\is_object($v)) {
235
                    $a[$prefix.'use']['$'.$k] = new CutStub($v);
236
                } else {
237
                    $a[$prefix.'use']['$'.$k] = &$v;
238
                }
239
            }
240
            unset($v);
241
            $a[$prefix.'use'] = new EnumStub($a[$prefix.'use']);
242
        }
243
 
244
        if (!($filter & Caster::EXCLUDE_VERBOSE) && !$isNested) {
245
            self::addExtra($a, $c);
246
        }
247
 
248
        return $a;
249
    }
250
 
251
    public static function castClassConstant(\ReflectionClassConstant $c, array $a, Stub $stub, bool $isNested)
252
    {
253
        $a[Caster::PREFIX_VIRTUAL.'modifiers'] = implode(' ', \Reflection::getModifierNames($c->getModifiers()));
254
        $a[Caster::PREFIX_VIRTUAL.'value'] = $c->getValue();
255
 
256
        self::addAttributes($a, $c);
257
 
258
        return $a;
259
    }
260
 
261
    public static function castMethod(\ReflectionMethod $c, array $a, Stub $stub, bool $isNested)
262
    {
263
        $a[Caster::PREFIX_VIRTUAL.'modifiers'] = implode(' ', \Reflection::getModifierNames($c->getModifiers()));
264
 
265
        return $a;
266
    }
267
 
268
    public static function castParameter(\ReflectionParameter $c, array $a, Stub $stub, bool $isNested)
269
    {
270
        $prefix = Caster::PREFIX_VIRTUAL;
271
 
272
        self::addMap($a, $c, [
273
            'position' => 'getPosition',
274
            'isVariadic' => 'isVariadic',
275
            'byReference' => 'isPassedByReference',
276
            'allowsNull' => 'allowsNull',
277
        ]);
278
 
279
        self::addAttributes($a, $c, $prefix);
280
 
281
        if ($v = $c->getType()) {
282
            $a[$prefix.'typeHint'] = $v instanceof \ReflectionNamedType ? $v->getName() : (string) $v;
283
        }
284
 
285
        if (isset($a[$prefix.'typeHint'])) {
286
            $v = $a[$prefix.'typeHint'];
287
            $a[$prefix.'typeHint'] = new ClassStub($v, [class_exists($v, false) || interface_exists($v, false) || trait_exists($v, false) ? $v : '', '']);
288
        } else {
289
            unset($a[$prefix.'allowsNull']);
290
        }
291
 
292
        if ($c->isOptional()) {
293
            try {
294
                $a[$prefix.'default'] = $v = $c->getDefaultValue();
688 lars 295
                if ($c->isDefaultValueConstant() && !\is_object($v)) {
148 lars 296
                    $a[$prefix.'default'] = new ConstStub($c->getDefaultValueConstantName(), $v);
297
                }
298
                if (null === $v) {
299
                    unset($a[$prefix.'allowsNull']);
300
                }
301
            } catch (\ReflectionException) {
302
            }
303
        }
304
 
305
        return $a;
306
    }
307
 
308
    public static function castProperty(\ReflectionProperty $c, array $a, Stub $stub, bool $isNested)
309
    {
310
        $a[Caster::PREFIX_VIRTUAL.'modifiers'] = implode(' ', \Reflection::getModifierNames($c->getModifiers()));
311
 
312
        self::addAttributes($a, $c);
313
        self::addExtra($a, $c);
314
 
315
        return $a;
316
    }
317
 
318
    public static function castReference(\ReflectionReference $c, array $a, Stub $stub, bool $isNested)
319
    {
320
        $a[Caster::PREFIX_VIRTUAL.'id'] = $c->getId();
321
 
322
        return $a;
323
    }
324
 
325
    public static function castExtension(\ReflectionExtension $c, array $a, Stub $stub, bool $isNested)
326
    {
327
        self::addMap($a, $c, [
328
            'version' => 'getVersion',
329
            'dependencies' => 'getDependencies',
330
            'iniEntries' => 'getIniEntries',
331
            'isPersistent' => 'isPersistent',
332
            'isTemporary' => 'isTemporary',
333
            'constants' => 'getConstants',
334
            'functions' => 'getFunctions',
335
            'classes' => 'getClasses',
336
        ]);
337
 
338
        return $a;
339
    }
340
 
341
    public static function castZendExtension(\ReflectionZendExtension $c, array $a, Stub $stub, bool $isNested)
342
    {
343
        self::addMap($a, $c, [
344
            'version' => 'getVersion',
345
            'author' => 'getAuthor',
346
            'copyright' => 'getCopyright',
347
            'url' => 'getURL',
348
        ]);
349
 
350
        return $a;
351
    }
352
 
353
    public static function getSignature(array $a)
354
    {
355
        $prefix = Caster::PREFIX_VIRTUAL;
356
        $signature = '';
357
 
358
        if (isset($a[$prefix.'parameters'])) {
359
            foreach ($a[$prefix.'parameters']->value as $k => $param) {
360
                $signature .= ', ';
361
                if ($type = $param->getType()) {
362
                    if (!$type instanceof \ReflectionNamedType) {
363
                        $signature .= $type.' ';
364
                    } else {
365
                        if (!$param->isOptional() && $param->allowsNull() && 'mixed' !== $type->getName()) {
366
                            $signature .= '?';
367
                        }
368
                        $signature .= substr(strrchr('\\'.$type->getName(), '\\'), 1).' ';
369
                    }
370
                }
371
                $signature .= $k;
372
 
373
                if (!$param->isDefaultValueAvailable()) {
374
                    continue;
375
                }
376
                $v = $param->getDefaultValue();
377
                $signature .= ' = ';
378
 
379
                if ($param->isDefaultValueConstant()) {
380
                    $signature .= substr(strrchr('\\'.$param->getDefaultValueConstantName(), '\\'), 1);
381
                } elseif (null === $v) {
382
                    $signature .= 'null';
383
                } elseif (\is_array($v)) {
384
                    $signature .= $v ? '[…'.\count($v).']' : '[]';
385
                } elseif (\is_string($v)) {
386
                    $signature .= 10 > \strlen($v) && !str_contains($v, '\\') ? "'{$v}'" : "'…".\strlen($v)."'";
387
                } elseif (\is_bool($v)) {
388
                    $signature .= $v ? 'true' : 'false';
389
                } elseif (\is_object($v)) {
390
                    $signature .= 'new '.substr(strrchr('\\'.get_debug_type($v), '\\'), 1);
391
                } else {
392
                    $signature .= $v;
393
                }
394
            }
395
        }
396
        $signature = (empty($a[$prefix.'returnsReference']) ? '' : '&').'('.substr($signature, 2).')';
397
 
398
        if (isset($a[$prefix.'returnType'])) {
399
            $signature .= ': '.substr(strrchr('\\'.$a[$prefix.'returnType'], '\\'), 1);
400
        }
401
 
402
        return $signature;
403
    }
404
 
405
    private static function addExtra(array &$a, \Reflector $c)
406
    {
407
        $x = isset($a[Caster::PREFIX_VIRTUAL.'extra']) ? $a[Caster::PREFIX_VIRTUAL.'extra']->value : [];
408
 
409
        if (method_exists($c, 'getFileName') && $m = $c->getFileName()) {
410
            $x['file'] = new LinkStub($m, $c->getStartLine());
411
            $x['line'] = $c->getStartLine().' to '.$c->getEndLine();
412
        }
413
 
414
        self::addMap($x, $c, self::EXTRA_MAP, '');
415
 
416
        if ($x) {
417
            $a[Caster::PREFIX_VIRTUAL.'extra'] = new EnumStub($x);
418
        }
419
    }
420
 
421
    private static function addMap(array &$a, object $c, array $map, string $prefix = Caster::PREFIX_VIRTUAL)
422
    {
423
        foreach ($map as $k => $m) {
424
            if ('isDisabled' === $k) {
425
                continue;
426
            }
427
 
428
            if (method_exists($c, $m) && false !== ($m = $c->$m()) && null !== $m) {
429
                $a[$prefix.$k] = $m instanceof \Reflector ? $m->name : $m;
430
            }
431
        }
432
    }
433
 
434
    private static function addAttributes(array &$a, \Reflector $c, string $prefix = Caster::PREFIX_VIRTUAL): void
435
    {
436
        foreach ($c->getAttributes() as $n) {
437
            $a[$prefix.'attributes'][] = $n;
438
        }
439
    }
440
}