[VarDumper] fix PHP 8 support

This commit is contained in:
Nicolas Grekas 2020-05-23 13:22:31 +02:00
parent d12b3b6a72
commit 9bc1ab62cf
8 changed files with 42 additions and 29 deletions

View File

@ -46,7 +46,7 @@ class Caster
* *
* @return array The array-cast of the object, with prefixed dynamic properties * @return array The array-cast of the object, with prefixed dynamic properties
*/ */
public static function castObject($obj, $class, $hasDebugInfo = false) public static function castObject($obj, $class, $hasDebugInfo = false, $debugClass = null)
{ {
if ($class instanceof \ReflectionClass) { if ($class instanceof \ReflectionClass) {
@trigger_error(sprintf('Passing a ReflectionClass to "%s()" is deprecated since Symfony 3.3 and will be unsupported in 4.0. Pass the class name as string instead.', __METHOD__), E_USER_DEPRECATED); @trigger_error(sprintf('Passing a ReflectionClass to "%s()" is deprecated since Symfony 3.3 and will be unsupported in 4.0. Pass the class name as string instead.', __METHOD__), E_USER_DEPRECATED);
@ -71,6 +71,17 @@ class Caster
if ($a) { if ($a) {
static $publicProperties = []; static $publicProperties = [];
if (null === $debugClass) {
if (\PHP_VERSION_ID >= 80000) {
$debugClass = get_debug_type($obj);
} else {
$debugClass = $class;
if (isset($debugClass[15]) && "\0" === $debugClass[15]) {
$debugClass = (get_parent_class($debugClass) ?: key(class_implements($debugClass)) ?: 'class').'@anonymous';
}
}
}
$i = 0; $i = 0;
$prefixedKeys = []; $prefixedKeys = [];
@ -84,8 +95,8 @@ class Caster
if (!isset($publicProperties[$class][$k])) { if (!isset($publicProperties[$class][$k])) {
$prefixedKeys[$i] = self::PREFIX_DYNAMIC.$k; $prefixedKeys[$i] = self::PREFIX_DYNAMIC.$k;
} }
} elseif (isset($k[16]) && "\0" === $k[16] && 0 === strpos($k, "\0class@anonymous\0")) { } elseif ($debugClass !== $class && 1 === strpos($k, $class)) {
$prefixedKeys[$i] = "\0".get_parent_class($class).'@anonymous'.strrchr($k, "\0"); $prefixedKeys[$i] = "\0".$debugClass.strrchr($k, "\0");
} }
++$i; ++$i;
} }
@ -101,6 +112,9 @@ class Caster
if ($hasDebugInfo && \is_array($debugInfo)) { if ($hasDebugInfo && \is_array($debugInfo)) {
foreach ($debugInfo as $k => $v) { foreach ($debugInfo as $k => $v) {
if (!isset($k[0]) || "\0" !== $k[0]) { if (!isset($k[0]) || "\0" !== $k[0]) {
if (\array_key_exists(self::PREFIX_DYNAMIC.$k, $a)) {
continue;
}
$k = self::PREFIX_VIRTUAL.$k; $k = self::PREFIX_VIRTUAL.$k;
} }

View File

@ -160,15 +160,6 @@ class SplCaster
return $a; return $a;
} }
public static function castFixedArray(\SplFixedArray $c, array $a, Stub $stub, $isNested)
{
$a += [
Caster::PREFIX_VIRTUAL.'storage' => $c->toArray(),
];
return $a;
}
public static function castObjectStorage(\SplObjectStorage $c, array $a, Stub $stub, $isNested) public static function castObjectStorage(\SplObjectStorage $c, array $a, Stub $stub, $isNested)
{ {
$storage = []; $storage = [];
@ -200,14 +191,16 @@ class SplCaster
private static function castSplArray($c, array $a, Stub $stub, $isNested) private static function castSplArray($c, array $a, Stub $stub, $isNested)
{ {
$prefix = Caster::PREFIX_VIRTUAL; $prefix = Caster::PREFIX_VIRTUAL;
$class = $stub->class;
$flags = $c->getFlags(); $flags = $c->getFlags();
if (!($flags & \ArrayObject::STD_PROP_LIST)) { if (!($flags & \ArrayObject::STD_PROP_LIST)) {
$c->setFlags(\ArrayObject::STD_PROP_LIST); $c->setFlags(\ArrayObject::STD_PROP_LIST);
$a = Caster::castObject($c, $class); $a = Caster::castObject($c, \get_class($c), method_exists($c, '__debugInfo'), $stub->class);
$c->setFlags($flags); $c->setFlags($flags);
} }
if (\PHP_VERSION_ID < 70400) {
$a[$prefix.'storage'] = $c->getArrayCopy();
}
$a += [ $a += [
$prefix.'flag::STD_PROP_LIST' => (bool) ($flags & \ArrayObject::STD_PROP_LIST), $prefix.'flag::STD_PROP_LIST' => (bool) ($flags & \ArrayObject::STD_PROP_LIST),
$prefix.'flag::ARRAY_AS_PROPS' => (bool) ($flags & \ArrayObject::ARRAY_AS_PROPS), $prefix.'flag::ARRAY_AS_PROPS' => (bool) ($flags & \ArrayObject::ARRAY_AS_PROPS),
@ -215,7 +208,6 @@ class SplCaster
if ($c instanceof \ArrayObject) { if ($c instanceof \ArrayObject) {
$a[$prefix.'iteratorClass'] = new ClassStub($c->getIteratorClass()); $a[$prefix.'iteratorClass'] = new ClassStub($c->getIteratorClass());
} }
$a[$prefix.'storage'] = $c->getArrayCopy();
return $a; return $a;
} }

View File

@ -102,7 +102,6 @@ abstract class AbstractCloner implements ClonerInterface
'SplDoublyLinkedList' => ['Symfony\Component\VarDumper\Caster\SplCaster', 'castDoublyLinkedList'], 'SplDoublyLinkedList' => ['Symfony\Component\VarDumper\Caster\SplCaster', 'castDoublyLinkedList'],
'SplFileInfo' => ['Symfony\Component\VarDumper\Caster\SplCaster', 'castFileInfo'], 'SplFileInfo' => ['Symfony\Component\VarDumper\Caster\SplCaster', 'castFileInfo'],
'SplFileObject' => ['Symfony\Component\VarDumper\Caster\SplCaster', 'castFileObject'], 'SplFileObject' => ['Symfony\Component\VarDumper\Caster\SplCaster', 'castFileObject'],
'SplFixedArray' => ['Symfony\Component\VarDumper\Caster\SplCaster', 'castFixedArray'],
'SplHeap' => ['Symfony\Component\VarDumper\Caster\SplCaster', 'castHeap'], 'SplHeap' => ['Symfony\Component\VarDumper\Caster\SplCaster', 'castHeap'],
'SplObjectStorage' => ['Symfony\Component\VarDumper\Caster\SplCaster', 'castObjectStorage'], 'SplObjectStorage' => ['Symfony\Component\VarDumper\Caster\SplCaster', 'castObjectStorage'],
'SplPriorityQueue' => ['Symfony\Component\VarDumper\Caster\SplCaster', 'castHeap'], 'SplPriorityQueue' => ['Symfony\Component\VarDumper\Caster\SplCaster', 'castHeap'],
@ -266,8 +265,8 @@ abstract class AbstractCloner implements ClonerInterface
$obj = $stub->value; $obj = $stub->value;
$class = $stub->class; $class = $stub->class;
if (isset($class[15]) && "\0" === $class[15] && 0 === strpos($class, "class@anonymous\x00")) { if ((\PHP_VERSION_ID >= 80000 || (isset($class[15]) && "\0" === $class[15])) && false !== strpos($class, "@anonymous\0")) {
$stub->class = get_parent_class($class).'@anonymous'; $stub->class = \PHP_VERSION_ID < 80000 ? (get_parent_class($class) ?: key(class_implements($class)) ?: 'class').'@anonymous' : get_debug_type($obj);
} }
if (isset($this->classInfo[$class])) { if (isset($this->classInfo[$class])) {
list($i, $parents, $hasDebugInfo) = $this->classInfo[$class]; list($i, $parents, $hasDebugInfo) = $this->classInfo[$class];
@ -289,7 +288,7 @@ abstract class AbstractCloner implements ClonerInterface
$this->classInfo[$class] = [$i, $parents, $hasDebugInfo]; $this->classInfo[$class] = [$i, $parents, $hasDebugInfo];
} }
$a = Caster::castObject($obj, $class, $hasDebugInfo); $a = Caster::castObject($obj, $class, $hasDebugInfo, $stub->class);
try { try {
while ($i--) { while ($i--) {

View File

@ -171,7 +171,7 @@ EOTXT
$this->assertDumpMatchesFormat( $this->assertDumpMatchesFormat(
<<<'EOTXT' <<<'EOTXT'
@anonymous { class@anonymous {
-foo: "foo" -foo: "foo"
} }
EOTXT EOTXT

View File

@ -30,6 +30,7 @@ class PdoCasterTest extends TestCase
{ {
$pdo = new \PDO('sqlite::memory:'); $pdo = new \PDO('sqlite::memory:');
$pdo->setAttribute(\PDO::ATTR_STATEMENT_CLASS, ['PDOStatement', [$pdo]]); $pdo->setAttribute(\PDO::ATTR_STATEMENT_CLASS, ['PDOStatement', [$pdo]]);
$pdo->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
$cast = PdoCaster::castPdo($pdo, [], new Stub(), false); $cast = PdoCaster::castPdo($pdo, [], new Stub(), false);
@ -45,7 +46,7 @@ array:2 [
"\x00~\x00inTransaction" => false "\x00~\x00inTransaction" => false
"\x00~\x00attributes" => array:9 [ "\x00~\x00attributes" => array:9 [
"CASE" => NATURAL "CASE" => NATURAL
"ERRMODE" => SILENT "ERRMODE" => EXCEPTION
"PERSISTENT" => false "PERSISTENT" => false
"DRIVER_NAME" => "sqlite" "DRIVER_NAME" => "sqlite"
"ORACLE_NULLS" => NATURAL "ORACLE_NULLS" => NATURAL

View File

@ -49,8 +49,8 @@ ReflectionClass {
%A] %A]
methods: array:%d [ methods: array:%d [
%A %A
"export" => ReflectionMethod { "__construct" => ReflectionMethod {
+name: "export" +name: "__construct"
+class: "ReflectionClass" +class: "ReflectionClass"
%A parameters: { %A parameters: {
$%s: ReflectionParameter { $%s: ReflectionParameter {

View File

@ -175,14 +175,17 @@ EOTXT;
$expected = <<<EOTXT $expected = <<<EOTXT
ArrayObject { ArrayObject {
+"foo": 234 +"foo": 234
-storage: array:1 [
0 => 123
]
flag::STD_PROP_LIST: false flag::STD_PROP_LIST: false
flag::ARRAY_AS_PROPS: false flag::ARRAY_AS_PROPS: false
iteratorClass: "ArrayIterator" iteratorClass: "ArrayIterator"
storage: array:1 [
0 => 123
]
} }
EOTXT; EOTXT;
if (\PHP_VERSION_ID < 70400) {
$expected = str_replace('-storage:', 'storage:', $expected);
}
$this->assertDumpEquals($expected, $var); $this->assertDumpEquals($expected, $var);
} }
@ -196,13 +199,16 @@ EOTXT;
$expected = <<<EOTXT $expected = <<<EOTXT
Symfony\Component\VarDumper\Tests\Caster\MyArrayIterator { Symfony\Component\VarDumper\Tests\Caster\MyArrayIterator {
-foo: 123 -foo: 123
flag::STD_PROP_LIST: false -storage: array:1 [
flag::ARRAY_AS_PROPS: false
storage: array:1 [
0 => 234 0 => 234
] ]
flag::STD_PROP_LIST: false
flag::ARRAY_AS_PROPS: false
} }
EOTXT; EOTXT;
if (\PHP_VERSION_ID < 70400) {
$expected = str_replace('-storage:', 'storage:', $expected);
}
$this->assertDumpEquals($expected, $var); $this->assertDumpEquals($expected, $var);
} }

View File

@ -203,6 +203,7 @@ EOTXT;
/** /**
* @requires extension xml * @requires extension xml
* @requires PHP < 8.0
*/ */
public function testXmlResource() public function testXmlResource()
{ {