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

Skip to content

Commit 54468db

Browse files
[VarDumper] Dump uninitialized properties
1 parent deb160a commit 54468db

File tree

7 files changed

+66
-8
lines changed

7 files changed

+66
-8
lines changed

src/Symfony/Component/VarDumper/CHANGELOG.md

+5
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
CHANGELOG
22
=========
33

4+
6.4
5+
---
6+
7+
* Dump uninitialized properties
8+
49
6.3
510
---
611

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

+33-7
Original file line numberDiff line numberDiff line change
@@ -32,13 +32,16 @@ class Caster
3232
public const EXCLUDE_EMPTY = 128;
3333
public const EXCLUDE_NOT_IMPORTANT = 256;
3434
public const EXCLUDE_STRICT = 512;
35+
public const EXCLUDE_UNINITIALIZED = 1024;
3536

3637
public const PREFIX_VIRTUAL = "\0~\0";
3738
public const PREFIX_DYNAMIC = "\0+\0";
3839
public const PREFIX_PROTECTED = "\0*\0";
3940
// usage: sprintf(Caster::PATTERN_PRIVATE, $class, $property)
4041
public const PATTERN_PRIVATE = "\0%s\0%s";
4142

43+
private static array $classProperties = [];
44+
4245
/**
4346
* Casts objects to arrays and adds the dynamic property prefix.
4447
*
@@ -61,20 +64,17 @@ public static function castObject(object $obj, string $class, bool $hasDebugInfo
6164
return $a;
6265
}
6366

67+
$classProperties = self::$classProperties[$class] ??= self::getClassProperties(new \ReflectionClass($class));
68+
$a = array_replace($classProperties, $a);
69+
6470
if ($a) {
65-
static $publicProperties = [];
6671
$debugClass ??= get_debug_type($obj);
6772

6873
$i = 0;
6974
$prefixedKeys = [];
7075
foreach ($a as $k => $v) {
7176
if ("\0" !== ($k[0] ?? '')) {
72-
if (!isset($publicProperties[$class])) {
73-
foreach ((new \ReflectionClass($class))->getProperties(\ReflectionProperty::IS_PUBLIC) as $prop) {
74-
$publicProperties[$class][$prop->name] = true;
75-
}
76-
}
77-
if (!isset($publicProperties[$class][$k])) {
77+
if (!isset($classProperties[$k])) {
7878
$prefixedKeys[$i] = self::PREFIX_DYNAMIC.$k;
7979
}
8080
} elseif ($debugClass !== $class && 1 === strpos($k, $class)) {
@@ -131,6 +131,8 @@ public static function filter(array $a, int $filter, array $listedProperties = [
131131
$type |= self::EXCLUDE_EMPTY & $filter;
132132
} elseif (false === $v || '' === $v || '0' === $v || 0 === $v || 0.0 === $v || [] === $v) {
133133
$type |= self::EXCLUDE_EMPTY & $filter;
134+
} elseif ($v instanceof UninitializedStub) {
135+
$type |= self::EXCLUDE_UNINITIALIZED & $filter;
134136
}
135137
if ((self::EXCLUDE_NOT_IMPORTANT & $filter) && !\in_array($k, $listedProperties, true)) {
136138
$type |= self::EXCLUDE_NOT_IMPORTANT;
@@ -169,4 +171,28 @@ public static function castPhpIncompleteClass(\__PHP_Incomplete_Class $c, array
169171

170172
return $a;
171173
}
174+
175+
private static function getClassProperties(\ReflectionClass $class): array
176+
{
177+
$classProperties = [];
178+
$className = $class->name;
179+
180+
foreach ($class->getProperties() as $p) {
181+
if ($p->isStatic()) {
182+
continue;
183+
}
184+
185+
$classProperties[match (true) {
186+
$p->isPublic() => $p->name,
187+
$p->isProtected() => self::PREFIX_PROTECTED.$p->name,
188+
default => "\0".$className."\0".$p->name,
189+
}] = new UninitializedStub($p);
190+
}
191+
192+
if ($parent = $class->getParentClass()) {
193+
$classProperties += self::$classProperties[$parent->name] ??= self::getClassProperties($parent);
194+
}
195+
196+
return $classProperties;
197+
}
172198
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
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\Caster;
13+
14+
/**
15+
* Represents an uninitialized property.
16+
*
17+
* @author Nicolas Grekas <[email protected]>
18+
*/
19+
class UninitializedStub extends ConstStub
20+
{
21+
public function __construct(\ReflectionProperty $property)
22+
{
23+
parent::__construct('?'.($property->hasType() ? ' '.$property->getType() : ''), 'Uninitialized property');
24+
}
25+
}

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

+1
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ public static function castXmlReader(\XMLReader $reader, array $a, Stub $stub, b
8585
$info[$props]->cut = $count;
8686
}
8787

88+
$a = Caster::filter($a, Caster::EXCLUDE_UNINITIALIZED, [], $count);
8889
$info = Caster::filter($info, Caster::EXCLUDE_EMPTY, [], $count);
8990
// +2 because hasValue and hasAttributes are always filtered
9091
$stub->cut += $count + 2;

src/Symfony/Component/VarDumper/Tests/Caster/ExceptionCasterTest.php

+1
Original file line numberDiff line numberDiff line change
@@ -378,6 +378,7 @@ public function testFlattenException()
378378
-file: "%sExceptionCasterTest.php"
379379
-line: %d
380380
-asString: null
381+
-dataRepresentation: ? Symfony\Component\VarDumper\Cloner\Data
381382
}
382383
]
383384
EODUMP;

src/Symfony/Component/VarDumper/Tests/Caster/MysqliCasterTest.php

-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@ public function testNotConnected()
3030

3131
$xCast = <<<EODUMP
3232
mysqli_driver {%A
33-
+reconnect: false
3433
+report_mode: 3
3534
}
3635
EODUMP;

src/Symfony/Component/VarDumper/composer.json

+1
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
"require-dev": {
2323
"ext-iconv": "*",
2424
"symfony/console": "^5.4|^6.0|^7.0",
25+
"symfony/error-handler": "^6.3|^7.0",
2526
"symfony/http-kernel": "^5.4|^6.0|^7.0",
2627
"symfony/process": "^5.4|^6.0|^7.0",
2728
"symfony/uid": "^5.4|^6.0|^7.0",

0 commit comments

Comments
 (0)