| 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 |
* Represents a PHP class identifier.
|
|
|
18 |
*
|
|
|
19 |
* @author Nicolas Grekas <p@tchwork.com>
|
|
|
20 |
*/
|
|
|
21 |
class ClassStub extends ConstStub
|
|
|
22 |
{
|
|
|
23 |
/**
|
|
|
24 |
* @param string $identifier A PHP identifier, e.g. a class, method, interface, etc. name
|
|
|
25 |
* @param callable $callable The callable targeted by the identifier when it is ambiguous or not a real PHP identifier
|
|
|
26 |
*/
|
|
|
27 |
public function __construct(string $identifier, callable|array|string $callable = null)
|
|
|
28 |
{
|
|
|
29 |
$this->value = $identifier;
|
|
|
30 |
|
|
|
31 |
try {
|
|
|
32 |
if (null !== $callable) {
|
|
|
33 |
if ($callable instanceof \Closure) {
|
|
|
34 |
$r = new \ReflectionFunction($callable);
|
|
|
35 |
} elseif (\is_object($callable)) {
|
|
|
36 |
$r = [$callable, '__invoke'];
|
|
|
37 |
} elseif (\is_array($callable)) {
|
|
|
38 |
$r = $callable;
|
|
|
39 |
} elseif (false !== $i = strpos($callable, '::')) {
|
|
|
40 |
$r = [substr($callable, 0, $i), substr($callable, 2 + $i)];
|
|
|
41 |
} else {
|
|
|
42 |
$r = new \ReflectionFunction($callable);
|
|
|
43 |
}
|
|
|
44 |
} elseif (0 < $i = strpos($identifier, '::') ?: strpos($identifier, '->')) {
|
|
|
45 |
$r = [substr($identifier, 0, $i), substr($identifier, 2 + $i)];
|
|
|
46 |
} else {
|
|
|
47 |
$r = new \ReflectionClass($identifier);
|
|
|
48 |
}
|
|
|
49 |
|
|
|
50 |
if (\is_array($r)) {
|
|
|
51 |
try {
|
|
|
52 |
$r = new \ReflectionMethod($r[0], $r[1]);
|
|
|
53 |
} catch (\ReflectionException) {
|
|
|
54 |
$r = new \ReflectionClass($r[0]);
|
|
|
55 |
}
|
|
|
56 |
}
|
|
|
57 |
|
|
|
58 |
if (str_contains($identifier, "@anonymous\0")) {
|
|
|
59 |
$this->value = $identifier = preg_replace_callback('/[a-zA-Z_\x7f-\xff][\\\\a-zA-Z0-9_\x7f-\xff]*+@anonymous\x00.*?\.php(?:0x?|:[0-9]++\$)[0-9a-fA-F]++/', function ($m) {
|
|
|
60 |
return class_exists($m[0], false) ? (get_parent_class($m[0]) ?: key(class_implements($m[0])) ?: 'class').'@anonymous' : $m[0];
|
|
|
61 |
}, $identifier);
|
|
|
62 |
}
|
|
|
63 |
|
|
|
64 |
if (null !== $callable && $r instanceof \ReflectionFunctionAbstract) {
|
|
|
65 |
$s = ReflectionCaster::castFunctionAbstract($r, [], new Stub(), true, Caster::EXCLUDE_VERBOSE);
|
|
|
66 |
$s = ReflectionCaster::getSignature($s);
|
|
|
67 |
|
|
|
68 |
if (str_ends_with($identifier, '()')) {
|
|
|
69 |
$this->value = substr_replace($identifier, $s, -2);
|
|
|
70 |
} else {
|
|
|
71 |
$this->value .= $s;
|
|
|
72 |
}
|
|
|
73 |
}
|
|
|
74 |
} catch (\ReflectionException) {
|
|
|
75 |
return;
|
|
|
76 |
} finally {
|
|
|
77 |
if (0 < $i = strrpos($this->value, '\\')) {
|
|
|
78 |
$this->attr['ellipsis'] = \strlen($this->value) - $i;
|
|
|
79 |
$this->attr['ellipsis-type'] = 'class';
|
|
|
80 |
$this->attr['ellipsis-tail'] = 1;
|
|
|
81 |
}
|
|
|
82 |
}
|
|
|
83 |
|
|
|
84 |
if ($f = $r->getFileName()) {
|
|
|
85 |
$this->attr['file'] = $f;
|
|
|
86 |
$this->attr['line'] = $r->getStartLine();
|
|
|
87 |
}
|
|
|
88 |
}
|
|
|
89 |
|
|
|
90 |
public static function wrapCallable(mixed $callable)
|
|
|
91 |
{
|
|
|
92 |
if (\is_object($callable) || !\is_callable($callable)) {
|
|
|
93 |
return $callable;
|
|
|
94 |
}
|
|
|
95 |
|
|
|
96 |
if (!\is_array($callable)) {
|
|
|
97 |
$callable = new static($callable, $callable);
|
|
|
98 |
} elseif (\is_string($callable[0])) {
|
|
|
99 |
$callable[0] = new static($callable[0], $callable);
|
|
|
100 |
} else {
|
|
|
101 |
$callable[1] = new static($callable[1], $callable);
|
|
|
102 |
}
|
|
|
103 |
|
|
|
104 |
return $callable;
|
|
|
105 |
}
|
|
|
106 |
}
|