Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit c67c521

Browse files
[VarDumper] Add casters for Reflection* classes
1 parent b1e2ded commit c67c521

File tree

5 files changed

+318
-25
lines changed

5 files changed

+318
-25
lines changed

src/Symfony/Component/VarDumper/Caster/ReflectionCaster.php

Lines changed: 205 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,19 +20,221 @@
2020
*/
2121
class ReflectionCaster
2222
{
23+
private static $extraMap = array(
24+
'docComment' => 'getDocComment',
25+
'extension' => 'getExtensionName',
26+
'isDisabled' => 'isDisabled',
27+
'isDeprecated' => 'isDeprecated',
28+
'isInternal' => 'isInternal',
29+
'isUserDefined' => 'isUserDefined',
30+
'isGenerator' => 'isGenerator',
31+
'isVariadic' => 'isVariadic',
32+
);
33+
34+
/**
35+
* @deprecated since Symfony 2.7, to be removed in 3.0.
36+
*/
2337
public static function castReflector(\Reflector $c, array $a, Stub $stub, $isNested)
2438
{
25-
$a["\0~\0reflection"] = $c->__toString();
39+
trigger_error('The '.__METHOD__.' method is deprecated since Symfony 2.7 and will be removed in 3.0.', E_USER_DEPRECATED);
40+
$a[Caster::PREFIX_VIRTUAL.'reflection'] = $c->__toString();
2641

2742
return $a;
2843
}
2944

3045
public static function castClosure(\Closure $c, array $a, Stub $stub, $isNested)
3146
{
47+
$prefix = Caster::PREFIX_VIRTUAL;
48+
$c = new \ReflectionFunction($c);
49+
3250
$stub->class = 'Closure'; // HHVM generates unique class names for closures
33-
$a = static::castReflector(new \ReflectionFunction($c), $a, $stub, $isNested);
34-
unset($a["\0+\0000"], $a['name'], $a["\0+\0this"], $a["\0+\0parameter"]);
51+
$a = static::castFunctionAbstract($c, $a, $stub, $isNested);
52+
53+
if (isset($a[$prefix.'parameters'])) {
54+
foreach ($a[$prefix.'parameters'] as &$v) {
55+
$param = $v;
56+
$v = array();
57+
foreach (static::castParameter($param, array(), $stub, true) as $k => $param) {
58+
if ("\0" === $k[0]) {
59+
$v[substr($k, 3)] = $param;
60+
}
61+
}
62+
unset($v['position'], $v['isVariadic'], $v['byReference'], $v);
63+
}
64+
}
65+
66+
if ($f = $c->getFileName()) {
67+
$a[$prefix.'file'] = $f;
68+
$a[$prefix.'line'] = $c->getStartLine().' to '.$c->getEndLine();
69+
}
70+
71+
$prefix = Caster::PREFIX_DYNAMIC;
72+
unset($a['name'], $a[$prefix.'0'], $a[$prefix.'this'], $a[$prefix.'parameter'], $a[Caster::PREFIX_VIRTUAL.'extra']);
73+
74+
return $a;
75+
}
76+
77+
public static function castClass(\ReflectionClass $c, array $a, Stub $stub, $isNested, $filter = 0)
78+
{
79+
$prefix = Caster::PREFIX_VIRTUAL;
80+
81+
if ($n = \Reflection::getModifierNames($c->getModifiers())) {
82+
$a[$prefix.'modifiers'] = implode(' ', $n);
83+
}
84+
85+
self::addMap($a, $c, array(
86+
'extends' => 'getParentClass',
87+
'implements' => 'getInterfaceNames',
88+
'constants' => 'getConstants',
89+
));
90+
91+
foreach ($c->getProperties() as $n) {
92+
$a[$prefix.'properties'][$n->name] = $n;
93+
}
94+
95+
foreach ($c->getMethods() as $n) {
96+
$a[$prefix.'methods'][$n->name] = $n;
97+
}
98+
99+
if (!($filter & Caster::EXCLUDE_VERBOSE) && !$isNested) {
100+
self::addExtra($a, $c);
101+
}
35102

36103
return $a;
37104
}
105+
106+
public static function castFunctionAbstract(\ReflectionFunctionAbstract $c, array $a, Stub $stub, $isNested, $filter = 0)
107+
{
108+
$prefix = Caster::PREFIX_VIRTUAL;
109+
110+
self::addMap($a, $c, array(
111+
'returnsReference' => 'returnsReference',
112+
'class' => 'getClosureScopeClass',
113+
'this' => 'getClosureThis',
114+
));
115+
116+
if (isset($a[$prefix.'this'])) {
117+
$a[$prefix.'this'] = new CutStub($a[$prefix.'this']);
118+
}
119+
120+
foreach ($c->getParameters() as $v) {
121+
$k = '$'.$v->name;
122+
if ($v->isPassedByReference()) {
123+
$k = '&'.$k;
124+
}
125+
if (method_exists($v, 'isVariadic') && $v->isVariadic()) {
126+
$k = '...'.$k;
127+
}
128+
$a[$prefix.'parameters'][$k] = $v;
129+
}
130+
131+
if ($v = $c->getStaticVariables()) {
132+
foreach ($v as $k => &$v) {
133+
$a[$prefix.'use']['$'.$k] =& $v;
134+
}
135+
unset($v);
136+
}
137+
138+
if (!($filter & Caster::EXCLUDE_VERBOSE) && !$isNested) {
139+
self::addExtra($a, $c);
140+
}
141+
142+
return $a;
143+
}
144+
145+
public static function castMethod(\ReflectionMethod $c, array $a, Stub $stub, $isNested)
146+
{
147+
$a[Caster::PREFIX_VIRTUAL.'modifiers'] = implode(' ', \Reflection::getModifierNames($c->getModifiers()));
148+
149+
return $a;
150+
}
151+
152+
public static function castParameter(\ReflectionParameter $c, array $a, Stub $stub, $isNested)
153+
{
154+
$prefix = Caster::PREFIX_VIRTUAL;
155+
156+
self::addMap($a, $c, array(
157+
'position' => 'getPosition',
158+
'isVariadic' => 'isVariadic',
159+
'byReference' => 'isPassedByReference',
160+
));
161+
162+
try {
163+
if ($c->isArray()) {
164+
$a[$prefix.'typeHint'] = 'array';
165+
} elseif (method_exists($c, 'isCallable') && $c->isCallable()) {
166+
$a[$prefix.'typeHint'] = 'callable';
167+
} elseif ($v = $c->getClass()) {
168+
$a[$prefix.'typeHint'] = $v->name;
169+
}
170+
} catch (\ReflectionException $e) {
171+
}
172+
173+
try {
174+
$a[$prefix.'default'] = $v = $c->getDefaultValue();
175+
if (method_exists($c, 'isDefaultValueConstant') && $c->isDefaultValueConstant()) {
176+
$a[$prefix.'default'] = new ConstStub($c->getDefaultValueConstantName(), $v);
177+
}
178+
} catch (\ReflectionException $e) {
179+
}
180+
181+
return $a;
182+
}
183+
184+
public static function castProperty(\ReflectionProperty $c, array $a, Stub $stub, $isNested)
185+
{
186+
$a[Caster::PREFIX_VIRTUAL.'modifiers'] = implode(' ', \Reflection::getModifierNames($c->getModifiers()));
187+
self::addExtra($a, $c);
188+
189+
return $a;
190+
}
191+
192+
public static function castExtension(\ReflectionExtension $c, array $a, Stub $stub, $isNested)
193+
{
194+
self::addMap($a, $c, array(
195+
'version' => 'getVersion',
196+
'dependencies' => 'getDependencies',
197+
'iniEntries' => 'getIniEntries',
198+
'isPersistent' => 'isPersistent',
199+
'isTemporary' => 'isTemporary',
200+
'constants' => 'getConstants',
201+
'functions' => 'getFunctions',
202+
'classes' => 'getClasses',
203+
));
204+
205+
return $a;
206+
}
207+
208+
public static function castZendExtension(\ReflectionZendExtension $c, array $a, Stub $stub, $isNested)
209+
{
210+
self::addMap($a, $c, array(
211+
'version' => 'getVersion',
212+
'author' => 'getAuthor',
213+
'copyright' => 'getCopyright',
214+
'url' => 'getURL',
215+
));
216+
217+
return $a;
218+
}
219+
220+
private static function addExtra(&$a, \Reflector $c)
221+
{
222+
$a =& $a[Caster::PREFIX_VIRTUAL.'extra'];
223+
224+
if (method_exists($c, 'getFileName') && $m = $c->getFileName()) {
225+
$a['file'] = $m;
226+
$a['line'] = $c->getStartLine().' to '.$c->getEndLine();
227+
}
228+
229+
self::addMap($a, $c, self::$extraMap, '');
230+
}
231+
232+
private static function addMap(&$a, \Reflector $c, $map, $prefix = Caster::PREFIX_VIRTUAL)
233+
{
234+
foreach ($map as $k => $m) {
235+
if (method_exists($c, $m) && false !== ($m = $c->$m()) && null !== $m) {
236+
$a[$prefix.$k] = $m instanceof \Reflector ? $m->name : $m;
237+
}
238+
}
239+
}
38240
}

src/Symfony/Component/VarDumper/Cloner/AbstractCloner.php

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,13 @@ abstract class AbstractCloner implements ClonerInterface
2626
'Symfony\Component\VarDumper\Caster\ConstStub' => 'Symfony\Component\VarDumper\Caster\StubCaster::castStub',
2727

2828
'Closure' => 'Symfony\Component\VarDumper\Caster\ReflectionCaster::castClosure',
29-
'Reflector' => 'Symfony\Component\VarDumper\Caster\ReflectionCaster::castReflector',
29+
'ReflectionClass' => 'Symfony\Component\VarDumper\Caster\ReflectionCaster::castClass',
30+
'ReflectionFunctionAbstract' => 'Symfony\Component\VarDumper\Caster\ReflectionCaster::castFunctionAbstract',
31+
'ReflectionMethod' => 'Symfony\Component\VarDumper\Caster\ReflectionCaster::castMethod',
32+
'ReflectionParameter' => 'Symfony\Component\VarDumper\Caster\ReflectionCaster::castParameter',
33+
'ReflectionProperty' => 'Symfony\Component\VarDumper\Caster\ReflectionCaster::castProperty',
34+
'ReflectionExtension' => 'Symfony\Component\VarDumper\Caster\ReflectionCaster::castExtension',
35+
'ReflectionZendExtension' => 'Symfony\Component\VarDumper\Caster\ReflectionCaster::castZendExtension',
3036

3137
'Doctrine\Common\Persistence\ObjectManager' => 'Symfony\Component\VarDumper\Caster\StubCaster::cutInternals',
3238
'Doctrine\Common\Proxy\Proxy' => 'Symfony\Component\VarDumper\Caster\DoctrineCaster::castCommonProxy',
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
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\VarDumper\Tests\Caster;
13+
14+
use Symfony\Component\VarDumper\Cloner\VarCloner;
15+
use Symfony\Component\VarDumper\Dumper\CliDumper;
16+
use Symfony\Component\VarDumper\Test\VarDumperTestCase;
17+
18+
/**
19+
* @author Nicolas Grekas <[email protected]>
20+
*/
21+
class ReflectionCasterTest extends VarDumperTestCase
22+
{
23+
public function testReflectionCaster()
24+
{
25+
$var = new \ReflectionClass('ReflectionClass');
26+
27+
$this->assertDumpMatchesFormat(
28+
<<<'EOTXT'
29+
ReflectionClass {
30+
+name: "ReflectionClass"
31+
implements: array:1 [
32+
0 => "Reflector"
33+
]
34+
constants: array:3 [
35+
"IS_IMPLICIT_ABSTRACT" => 16
36+
"IS_EXPLICIT_ABSTRACT" => 32
37+
"IS_FINAL" => 64
38+
]
39+
properties: array:1 [
40+
"name" => ReflectionProperty {
41+
+name: "name"
42+
+class: "ReflectionClass"
43+
modifiers: "public"
44+
extra: null
45+
}
46+
]
47+
methods: array:%d [
48+
%A
49+
"export" => ReflectionMethod {
50+
+name: "export"
51+
+class: "ReflectionClass"
52+
parameters: array:2 [
53+
"$argument" => ReflectionParameter {
54+
+name: "argument"
55+
position: 0
56+
}
57+
"$return" => ReflectionParameter {
58+
+name: "return"
59+
position: 1
60+
}
61+
]
62+
modifiers: "public static"
63+
}
64+
%A
65+
}
66+
EOTXT
67+
, $var
68+
);
69+
}
70+
}

src/Symfony/Component/VarDumper/Tests/CliDumperTest.php

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -39,11 +39,19 @@ public function testGet()
3939
ob_start();
4040
$dumper->dump($data);
4141
$out = ob_get_clean();
42-
$closureLabel = PHP_VERSION_ID >= 50400 ? 'public method' : 'function';
4342
$out = preg_replace('/[ \t]+$/m', '', $out);
4443
$intMax = PHP_INT_MAX;
4544
$res1 = (int) $var['res'];
4645
$res2 = (int) $var[8];
46+
$closure54 = '';
47+
48+
if (PHP_VERSION_ID >= 50400) {
49+
$closure54 = <<<EOTXT
50+
51+
class: "Symfony\Component\VarDumper\Tests\CliDumperTest"
52+
this: Symfony\Component\VarDumper\Tests\CliDumperTest {#%d …}
53+
EOTXT;
54+
}
4755

4856
$this->assertStringMatchesFormat(
4957
<<<EOTXT
@@ -77,16 +85,15 @@ public function testGet()
7785
+"bar": "bar"
7886
}
7987
"closure" => Closure {#%d
80-
reflection: """
81-
Closure [ <user> {$closureLabel} Symfony\Component\VarDumper\Tests\Fixture\{closure} ] {
82-
@@ {$var['file']} {$var['line']} - {$var['line']}
83-
84-
- Parameters [2] {
85-
Parameter #0 [ <required> \$a ]
86-
Parameter #1 [ <optional> PDO or NULL &\$b = NULL ]
87-
}
88-
}
89-
"""
88+
{$closure54} parameters: array:2 [
89+
"\$a" => []
90+
"&\$b" => array:2 [
91+
"typeHint" => "PDO"
92+
"default" => null
93+
]
94+
]
95+
file: "{$var['file']}"
96+
line: "{$var['line']} to {$var['line']}"
9097
}
9198
"line" => {$var['line']}
9299
"nobj" => array:1 [

src/Symfony/Component/VarDumper/Tests/HtmlDumperTest.php

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,15 @@ public function testGet()
4747
$dumpId = $dumpId[0];
4848
$res1 = (int) $var['res'];
4949
$res2 = (int) $var[8];
50+
$closure54 = '';
51+
52+
if (PHP_VERSION_ID >= 50400) {
53+
$closure54 = <<<EOTXT
54+
55+
<span class=sf-dump-meta>class</span>: "<span class=sf-dump-str title="48 characters">Symfony\Component\VarDumper\Tests\HtmlDumperTest</span>"
56+
<span class=sf-dump-meta>this</span>: <abbr title="Symfony\Component\VarDumper\Tests\HtmlDumperTest" class=sf-dump-note>HtmlDumperTest</abbr> {<a class=sf-dump-ref>#%d</a> &#8230;}
57+
EOTXT;
58+
}
5059

5160
$this->assertStringMatchesFormat(
5261
<<<EOTXT
@@ -80,16 +89,15 @@ public function testGet()
8089
+"<span class=sf-dump-public title="Runtime added dynamic property">bar</span>": "<span class=sf-dump-str title="3 characters">bar</span>"
8190
</samp>}
8291
"<span class=sf-dump-key>closure</span>" => <span class=sf-dump-note>Closure</span> {<a class=sf-dump-ref>#%d</a><samp>
83-
<span class=sf-dump-meta>reflection</span>: """
84-
<span class=sf-dump-str title="%d characters">Closure [ &lt;user&gt; {$closureLabel} Symfony\Component\VarDumper\Tests\Fixture\{closure} ] {</span>
85-
<span class=sf-dump-str title="%d characters"> @@ {$var['file']} {$var['line']} - {$var['line']}</span>
86-
87-
<span class=sf-dump-str title="%d characters"> - Parameters [2] {</span>
88-
<span class=sf-dump-str title="%d characters"> Parameter #0 [ &lt;required&gt; \$a ]</span>
89-
<span class=sf-dump-str title="%d characters"> Parameter #1 [ &lt;optional&gt; PDO or NULL &amp;\$b = NULL ]</span>
90-
<span class=sf-dump-str title="%d characters"> }</span>
91-
<span class=sf-dump-str title="%d characters">}</span>
92-
"""
92+
{$closure54} <span class=sf-dump-meta>parameters</span>: <span class=sf-dump-note>array:2</span> [<samp>
93+
"<span class=sf-dump-key>\$a</span>" => []
94+
"<span class=sf-dump-key>&amp;\$b</span>" => <span class=sf-dump-note>array:2</span> [<samp>
95+
"<span class=sf-dump-key>typeHint</span>" => "<span class=sf-dump-str title="3 characters">PDO</span>"
96+
"<span class=sf-dump-key>default</span>" => <span class=sf-dump-const>null</span>
97+
</samp>]
98+
</samp>]
99+
<span class=sf-dump-meta>file</span>: "<span class=sf-dump-str title="93 characters">{$var['file']}</span>"
100+
<span class=sf-dump-meta>line</span>: "<span class=sf-dump-str title="8 characters">{$var['line']} to {$var['line']}</span>"
93101
</samp>}
94102
"<span class=sf-dump-key>line</span>" => <span class=sf-dump-num>{$var['line']}</span>
95103
"<span class=sf-dump-key>nobj</span>" => <span class=sf-dump-note>array:1</span> [<samp>

0 commit comments

Comments
 (0)