From 4575fa69025a90a31a3dee91a0f45000d653f744 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Sat, 23 May 2020 13:22:31 +0200 Subject: [PATCH] [VarDumper] fix PHP 8 support --- .../Component/VarDumper/Caster/Caster.php | 20 ++++++++++++++++--- .../Component/VarDumper/Caster/SplCaster.php | 16 ++++----------- .../VarDumper/Cloner/AbstractCloner.php | 7 +++---- .../VarDumper/Tests/Caster/CasterTest.php | 2 +- .../VarDumper/Tests/Caster/PdoCasterTest.php | 3 ++- .../Tests/Caster/ReflectionCasterTest.php | 4 ++-- .../VarDumper/Tests/Caster/SplCasterTest.php | 18 +++++++++++------ .../VarDumper/Tests/Dumper/CliDumperTest.php | 1 + 8 files changed, 42 insertions(+), 29 deletions(-) diff --git a/src/Symfony/Component/VarDumper/Caster/Caster.php b/src/Symfony/Component/VarDumper/Caster/Caster.php index c279249a4d660..a78410f2f792d 100644 --- a/src/Symfony/Component/VarDumper/Caster/Caster.php +++ b/src/Symfony/Component/VarDumper/Caster/Caster.php @@ -46,7 +46,7 @@ class Caster * * @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) { @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 @@ public static function castObject($obj, $class, $hasDebugInfo = false) if ($a) { 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; $prefixedKeys = []; @@ -84,8 +95,8 @@ public static function castObject($obj, $class, $hasDebugInfo = false) if (!isset($publicProperties[$class][$k])) { $prefixedKeys[$i] = self::PREFIX_DYNAMIC.$k; } - } elseif (isset($k[16]) && "\0" === $k[16] && 0 === strpos($k, "\0class@anonymous\0")) { - $prefixedKeys[$i] = "\0".get_parent_class($class).'@anonymous'.strrchr($k, "\0"); + } elseif ($debugClass !== $class && 1 === strpos($k, $class)) { + $prefixedKeys[$i] = "\0".$debugClass.strrchr($k, "\0"); } ++$i; } @@ -101,6 +112,9 @@ public static function castObject($obj, $class, $hasDebugInfo = false) if ($hasDebugInfo && \is_array($debugInfo)) { foreach ($debugInfo as $k => $v) { if (!isset($k[0]) || "\0" !== $k[0]) { + if (\array_key_exists(self::PREFIX_DYNAMIC.$k, $a)) { + continue; + } $k = self::PREFIX_VIRTUAL.$k; } diff --git a/src/Symfony/Component/VarDumper/Caster/SplCaster.php b/src/Symfony/Component/VarDumper/Caster/SplCaster.php index b557b689d3526..53df3de2392e3 100644 --- a/src/Symfony/Component/VarDumper/Caster/SplCaster.php +++ b/src/Symfony/Component/VarDumper/Caster/SplCaster.php @@ -160,15 +160,6 @@ public static function castFileObject(\SplFileObject $c, array $a, Stub $stub, $ 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) { $storage = []; @@ -200,14 +191,16 @@ public static function castOuterIterator(\OuterIterator $c, array $a, Stub $stub private static function castSplArray($c, array $a, Stub $stub, $isNested) { $prefix = Caster::PREFIX_VIRTUAL; - $class = $stub->class; $flags = $c->getFlags(); if (!($flags & \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); } + if (\PHP_VERSION_ID < 70400) { + $a[$prefix.'storage'] = $c->getArrayCopy(); + } $a += [ $prefix.'flag::STD_PROP_LIST' => (bool) ($flags & \ArrayObject::STD_PROP_LIST), $prefix.'flag::ARRAY_AS_PROPS' => (bool) ($flags & \ArrayObject::ARRAY_AS_PROPS), @@ -215,7 +208,6 @@ private static function castSplArray($c, array $a, Stub $stub, $isNested) if ($c instanceof \ArrayObject) { $a[$prefix.'iteratorClass'] = new ClassStub($c->getIteratorClass()); } - $a[$prefix.'storage'] = $c->getArrayCopy(); return $a; } diff --git a/src/Symfony/Component/VarDumper/Cloner/AbstractCloner.php b/src/Symfony/Component/VarDumper/Cloner/AbstractCloner.php index aed1a67a1ea1e..f424cc4866d21 100644 --- a/src/Symfony/Component/VarDumper/Cloner/AbstractCloner.php +++ b/src/Symfony/Component/VarDumper/Cloner/AbstractCloner.php @@ -102,7 +102,6 @@ abstract class AbstractCloner implements ClonerInterface 'SplDoublyLinkedList' => ['Symfony\Component\VarDumper\Caster\SplCaster', 'castDoublyLinkedList'], 'SplFileInfo' => ['Symfony\Component\VarDumper\Caster\SplCaster', 'castFileInfo'], 'SplFileObject' => ['Symfony\Component\VarDumper\Caster\SplCaster', 'castFileObject'], - 'SplFixedArray' => ['Symfony\Component\VarDumper\Caster\SplCaster', 'castFixedArray'], 'SplHeap' => ['Symfony\Component\VarDumper\Caster\SplCaster', 'castHeap'], 'SplObjectStorage' => ['Symfony\Component\VarDumper\Caster\SplCaster', 'castObjectStorage'], 'SplPriorityQueue' => ['Symfony\Component\VarDumper\Caster\SplCaster', 'castHeap'], @@ -266,8 +265,8 @@ protected function castObject(Stub $stub, $isNested) $obj = $stub->value; $class = $stub->class; - if (isset($class[15]) && "\0" === $class[15] && 0 === strpos($class, "class@anonymous\x00")) { - $stub->class = get_parent_class($class).'@anonymous'; + if ((\PHP_VERSION_ID >= 80000 || (isset($class[15]) && "\0" === $class[15])) && false !== strpos($class, "@anonymous\0")) { + $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])) { list($i, $parents, $hasDebugInfo) = $this->classInfo[$class]; @@ -289,7 +288,7 @@ protected function castObject(Stub $stub, $isNested) $this->classInfo[$class] = [$i, $parents, $hasDebugInfo]; } - $a = Caster::castObject($obj, $class, $hasDebugInfo); + $a = Caster::castObject($obj, $class, $hasDebugInfo, $stub->class); try { while ($i--) { diff --git a/src/Symfony/Component/VarDumper/Tests/Caster/CasterTest.php b/src/Symfony/Component/VarDumper/Tests/Caster/CasterTest.php index 728697b413c4d..73800e5f9dc46 100644 --- a/src/Symfony/Component/VarDumper/Tests/Caster/CasterTest.php +++ b/src/Symfony/Component/VarDumper/Tests/Caster/CasterTest.php @@ -171,7 +171,7 @@ public function testAnonymousClass() $this->assertDumpMatchesFormat( <<<'EOTXT' -@anonymous { +class@anonymous { -foo: "foo" } EOTXT diff --git a/src/Symfony/Component/VarDumper/Tests/Caster/PdoCasterTest.php b/src/Symfony/Component/VarDumper/Tests/Caster/PdoCasterTest.php index 19bbe0f80c43b..fca242cfc6e9f 100644 --- a/src/Symfony/Component/VarDumper/Tests/Caster/PdoCasterTest.php +++ b/src/Symfony/Component/VarDumper/Tests/Caster/PdoCasterTest.php @@ -30,6 +30,7 @@ public function testCastPdo() { $pdo = new \PDO('sqlite::memory:'); $pdo->setAttribute(\PDO::ATTR_STATEMENT_CLASS, ['PDOStatement', [$pdo]]); + $pdo->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION); $cast = PdoCaster::castPdo($pdo, [], new Stub(), false); @@ -45,7 +46,7 @@ public function testCastPdo() "\x00~\x00inTransaction" => false "\x00~\x00attributes" => array:9 [ "CASE" => NATURAL - "ERRMODE" => SILENT + "ERRMODE" => EXCEPTION "PERSISTENT" => false "DRIVER_NAME" => "sqlite" "ORACLE_NULLS" => NATURAL diff --git a/src/Symfony/Component/VarDumper/Tests/Caster/ReflectionCasterTest.php b/src/Symfony/Component/VarDumper/Tests/Caster/ReflectionCasterTest.php index a0c6dc2355202..17ad5434beec2 100644 --- a/src/Symfony/Component/VarDumper/Tests/Caster/ReflectionCasterTest.php +++ b/src/Symfony/Component/VarDumper/Tests/Caster/ReflectionCasterTest.php @@ -49,8 +49,8 @@ public function testReflectionCaster() %A] methods: array:%d [ %A - "export" => ReflectionMethod { - +name: "export" + "__construct" => ReflectionMethod { + +name: "__construct" +class: "ReflectionClass" %A parameters: { $%s: ReflectionParameter { diff --git a/src/Symfony/Component/VarDumper/Tests/Caster/SplCasterTest.php b/src/Symfony/Component/VarDumper/Tests/Caster/SplCasterTest.php index 67033df091601..9fa19a812cfb4 100644 --- a/src/Symfony/Component/VarDumper/Tests/Caster/SplCasterTest.php +++ b/src/Symfony/Component/VarDumper/Tests/Caster/SplCasterTest.php @@ -175,14 +175,17 @@ public function testCastArrayObject() $expected = << 123 + ] flag::STD_PROP_LIST: false flag::ARRAY_AS_PROPS: false iteratorClass: "ArrayIterator" - storage: array:1 [ - 0 => 123 - ] } EOTXT; + if (\PHP_VERSION_ID < 70400) { + $expected = str_replace('-storage:', 'storage:', $expected); + } $this->assertDumpEquals($expected, $var); } @@ -196,13 +199,16 @@ public function testArrayIterator() $expected = << 234 ] + flag::STD_PROP_LIST: false + flag::ARRAY_AS_PROPS: false } EOTXT; + if (\PHP_VERSION_ID < 80000) { + $expected = str_replace('-storage:', 'storage:', $expected); + } $this->assertDumpEquals($expected, $var); } diff --git a/src/Symfony/Component/VarDumper/Tests/Dumper/CliDumperTest.php b/src/Symfony/Component/VarDumper/Tests/Dumper/CliDumperTest.php index 9520b4fe102e7..7656e09259264 100644 --- a/src/Symfony/Component/VarDumper/Tests/Dumper/CliDumperTest.php +++ b/src/Symfony/Component/VarDumper/Tests/Dumper/CliDumperTest.php @@ -203,6 +203,7 @@ public function provideDumpWithCommaFlagTests() /** * @requires extension xml + * @requires PHP < 8.0 */ public function testXmlResource() {