Skip to content

Commit

Permalink
bug #33292 [VarExporter] fix support for PHP 7.4 (nicolas-grekas)
Browse files Browse the repository at this point in the history
This PR was merged into the 4.3 branch.

Discussion
----------

[VarExporter] fix support for PHP 7.4

| Q             | A
| ------------- | ---
| Branch?       | 4.3
| Bug fix?      | yes
| New feature?  | no
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets | #32844
| License       | MIT
| Doc PR        | -

Commits
-------

1a036dc [VarExporter] fix support for PHP 7.4
  • Loading branch information
nicolas-grekas committed Aug 22, 2019
2 parents dd153d8 + 1a036dc commit 35673b8
Show file tree
Hide file tree
Showing 15 changed files with 201 additions and 64 deletions.
4 changes: 2 additions & 2 deletions src/Symfony/Component/VarExporter/Internal/Exporter.php
Expand Up @@ -155,7 +155,7 @@ public static function prepare($values, $objectsPool, &$refsPool, &$objectsCount
}
$sleep[$n] = false;
}
if (!\array_key_exists($name, $proto) || $proto[$name] !== $v) {
if (!\array_key_exists($name, $proto) || $proto[$name] !== $v || "\x00Error\x00trace" === $name || "\x00Exception\x00trace" === $name) {
$properties[$c][$n] = $v;
}
}
Expand Down Expand Up @@ -291,7 +291,7 @@ private static function exportRegistry(Registry $value, string $indent, string $
continue;
}
if (!Registry::$instantiableWithoutConstructor[$class]) {
if (is_subclass_of($class, 'Serializable')) {
if (is_subclass_of($class, 'Serializable') && !method_exists($class, '__unserialize')) {
$serializables[$k] = 'C:'.\strlen($class).':"'.$class.'":0:{}';
} else {
$serializables[$k] = 'O:'.\strlen($class).':"'.$class.'":0:{}';
Expand Down
4 changes: 2 additions & 2 deletions src/Symfony/Component/VarExporter/Internal/Registry.php
Expand Up @@ -75,7 +75,7 @@ public static function getClassReflector($class, $instantiableWithoutConstructor
} elseif (!$isClass || $reflector->isAbstract()) {
throw new NotInstantiableTypeException($class);
} elseif ($reflector->name !== $class) {
$reflector = self::$reflectors[$name = $reflector->name] ?? self::getClassReflector($name, $instantiableWithoutConstructor, $cloneable);
$reflector = self::$reflectors[$name = $reflector->name] ?? self::getClassReflector($name, false, $cloneable);
self::$cloneable[$class] = self::$cloneable[$name];
self::$instantiableWithoutConstructor[$class] = self::$instantiableWithoutConstructor[$name];
self::$prototypes[$class] = self::$prototypes[$name];
Expand All @@ -86,7 +86,7 @@ public static function getClassReflector($class, $instantiableWithoutConstructor
$proto = $reflector->newInstanceWithoutConstructor();
$instantiableWithoutConstructor = true;
} catch (\ReflectionException $e) {
$proto = $reflector->implementsInterface('Serializable') && (\PHP_VERSION_ID < 70400 || !method_exists($class, '__unserialize')) ? 'C:' : 'O:';
$proto = $reflector->implementsInterface('Serializable') && !method_exists($class, '__unserialize') ? 'C:' : 'O:';
if ('C:' === $proto && !$reflector->getMethod('unserialize')->isInternal()) {
$proto = null;
} elseif (false === $proto = @unserialize($proto.\strlen($class).':"'.$class.'":0:{}')) {
Expand Down
@@ -0,0 +1,22 @@
<?php

return \Symfony\Component\VarExporter\Internal\Hydrator::hydrate(
$o = [
clone (\Symfony\Component\VarExporter\Internal\Registry::$prototypes['ArrayIterator'] ?? \Symfony\Component\VarExporter\Internal\Registry::p('ArrayIterator')),
],
null,
[
'ArrayIterator' => [
"\0" => [
[
[
123,
],
1,
],
],
],
],
$o[0],
[]
);
Expand Up @@ -5,18 +5,15 @@
clone (\Symfony\Component\VarExporter\Internal\Registry::$prototypes['ArrayIterator'] ?? \Symfony\Component\VarExporter\Internal\Registry::p('ArrayIterator')),
],
null,
[],
$o[0],
[
'ArrayIterator' => [
"\0" => [
[
[
123,
],
1,
],
[
1,
[
123,
],
[],
],
],
$o[0],
[]
]
);
@@ -0,0 +1,22 @@
<?php

return \Symfony\Component\VarExporter\Internal\Hydrator::hydrate(
$o = [
clone (\Symfony\Component\VarExporter\Internal\Registry::$prototypes['Symfony\\Component\\VarExporter\\Tests\\MyArrayObject'] ?? \Symfony\Component\VarExporter\Internal\Registry::p('Symfony\\Component\\VarExporter\\Tests\\MyArrayObject')),
],
null,
[
'ArrayObject' => [
"\0" => [
[
[
234,
],
1,
],
],
],
],
$o[0],
[]
);
Expand Up @@ -5,18 +5,17 @@
clone (\Symfony\Component\VarExporter\Internal\Registry::$prototypes['Symfony\\Component\\VarExporter\\Tests\\MyArrayObject'] ?? \Symfony\Component\VarExporter\Internal\Registry::p('Symfony\\Component\\VarExporter\\Tests\\MyArrayObject')),
],
null,
[],
$o[0],
[
'ArrayObject' => [
"\0" => [
[
[
234,
],
1,
],
[
1,
[
234,
],
[
"\0".'Symfony\\Component\\VarExporter\\Tests\\MyArrayObject'."\0".'unused' => 123,
],
],
],
$o[0],
[]
]
);
@@ -0,0 +1,29 @@
<?php

return \Symfony\Component\VarExporter\Internal\Hydrator::hydrate(
$o = [
clone (($p = &\Symfony\Component\VarExporter\Internal\Registry::$prototypes)['ArrayObject'] ?? \Symfony\Component\VarExporter\Internal\Registry::p('ArrayObject')),
clone $p['ArrayObject'],
],
null,
[
'ArrayObject' => [
"\0" => [
[
[
1,
$o[0],
],
0,
],
],
],
'stdClass' => [
'foo' => [
$o[1],
],
],
],
$o[0],
[]
);
31 changes: 15 additions & 16 deletions src/Symfony/Component/VarExporter/Tests/Fixtures/array-object.php
Expand Up @@ -6,24 +6,23 @@
clone $p['ArrayObject'],
],
null,
[],
$o[0],
[
'ArrayObject' => [
"\0" => [
[
[
1,
$o[0],
],
0,
],
[
0,
[
1,
$o[0],
],
],
'stdClass' => [
'foo' => [
$o[1],
[
'foo' => $o[1],
],
],
],
$o[0],
[]
-1 => [
0,
[],
[],
],
]
);
@@ -0,0 +1,11 @@
<?php

return \Symfony\Component\VarExporter\Internal\Hydrator::hydrate(
$o = \Symfony\Component\VarExporter\Internal\Registry::unserialize([], [
'C:54:"Symfony\\Component\\VarExporter\\Tests\\FinalArrayIterator":49:{a:2:{i:0;i:123;i:1;s:21:"x:i:0;a:0:{};m:a:0:{}";}}',
]),
null,
[],
$o[0],
[]
);
@@ -1,11 +1,17 @@
<?php

return \Symfony\Component\VarExporter\Internal\Hydrator::hydrate(
$o = \Symfony\Component\VarExporter\Internal\Registry::unserialize([], [
'C:54:"Symfony\\Component\\VarExporter\\Tests\\FinalArrayIterator":49:{a:2:{i:0;i:123;i:1;s:21:"x:i:0;a:0:{};m:a:0:{}";}}',
]),
$o = [
clone (\Symfony\Component\VarExporter\Internal\Registry::$prototypes['Symfony\\Component\\VarExporter\\Tests\\FinalArrayIterator'] ?? \Symfony\Component\VarExporter\Internal\Registry::p('Symfony\\Component\\VarExporter\\Tests\\FinalArrayIterator')),
],
null,
[],
$o[0],
[]
[
[
0,
[],
[],
],
]
);
@@ -0,0 +1,27 @@
<?php

return \Symfony\Component\VarExporter\Internal\Hydrator::hydrate(
$o = \Symfony\Component\VarExporter\Internal\Registry::unserialize([], [
'O:46:"Symfony\\Component\\VarExporter\\Tests\\FinalError":1:{s:12:"'."\0".'Error'."\0".'trace";a:0:{}}',
]),
null,
[
'TypeError' => [
'file' => [
\dirname(__DIR__).\DIRECTORY_SEPARATOR.'VarExporterTest.php',
],
'line' => [
123,
],
],
'Error' => [
'trace' => [
[],
],
],
],
$o[0],
[
1 => 0,
]
);
11 changes: 8 additions & 3 deletions src/Symfony/Component/VarExporter/Tests/Fixtures/final-error.php
@@ -1,9 +1,9 @@
<?php

return \Symfony\Component\VarExporter\Internal\Hydrator::hydrate(
$o = \Symfony\Component\VarExporter\Internal\Registry::unserialize([], [
'O:46:"Symfony\\Component\\VarExporter\\Tests\\FinalError":1:{s:12:"'."\0".'Error'."\0".'trace";a:0:{}}',
]),
$o = [
(\Symfony\Component\VarExporter\Internal\Registry::$factories['Symfony\\Component\\VarExporter\\Tests\\FinalError'] ?? \Symfony\Component\VarExporter\Internal\Registry::f('Symfony\\Component\\VarExporter\\Tests\\FinalError'))(),
],
null,
[
'TypeError' => [
Expand All @@ -14,6 +14,11 @@
123,
],
],
'Error' => [
'trace' => [
[],
],
],
],
$o[0],
[
Expand Down
@@ -0,0 +1,21 @@
<?php

return \Symfony\Component\VarExporter\Internal\Hydrator::hydrate(
$o = [
clone (($p = &\Symfony\Component\VarExporter\Internal\Registry::$prototypes)['SplObjectStorage'] ?? \Symfony\Component\VarExporter\Internal\Registry::p('SplObjectStorage')),
clone ($p['stdClass'] ?? \Symfony\Component\VarExporter\Internal\Registry::p('stdClass')),
],
null,
[
'SplObjectStorage' => [
"\0" => [
[
$o[1],
345,
],
],
],
],
$o[0],
[]
);
Expand Up @@ -6,16 +6,15 @@
clone ($p['stdClass'] ?? \Symfony\Component\VarExporter\Internal\Registry::p('stdClass')),
],
null,
[],
$o[0],
[
'SplObjectStorage' => [
"\0" => [
[
$o[1],
345,
],
[
[
$o[1],
345,
],
[],
],
],
$o[0],
[]
]
);
12 changes: 6 additions & 6 deletions src/Symfony/Component/VarExporter/Tests/VarExporterTest.php
Expand Up @@ -12,7 +12,6 @@
namespace Symfony\Component\VarExporter\Tests;

use PHPUnit\Framework\TestCase;
use PHPUnit\Framework\Warning;
use Symfony\Component\VarDumper\Test\VarDumperTestTrait;
use Symfony\Component\VarExporter\Internal\Registry;
use Symfony\Component\VarExporter\VarExporter;
Expand Down Expand Up @@ -76,10 +75,6 @@ public function provideFailingSerialization()
*/
public function testExport(string $testName, $value, bool $staticValueExpected = false)
{
if (\PHP_VERSION_ID >= 70400 && \in_array($testName, ['spl-object-storage', 'array-object-custom', 'array-iterator', 'array-object', 'final-array-iterator'])) {
throw new Warning('PHP 7.4 breaks this test.');
}

$dumpedValue = $this->getDump($value);
$isStaticValue = true;
$marshalledValue = VarExporter::export($value, $isStaticValue);
Expand All @@ -91,7 +86,12 @@ public function testExport(string $testName, $value, bool $staticValueExpected =

$dump = "<?php\n\nreturn ".$marshalledValue.";\n";
$dump = str_replace(var_export(__FILE__, true), "\\dirname(__DIR__).\\DIRECTORY_SEPARATOR.'VarExporterTest.php'", $dump);
$fixtureFile = __DIR__.'/Fixtures/'.$testName.'.php';

if (\PHP_VERSION_ID < 70400 && \in_array($testName, ['array-object', 'array-iterator', 'array-object-custom', 'spl-object-storage', 'final-array-iterator', 'final-error'], true)) {
$fixtureFile = __DIR__.'/Fixtures/'.$testName.'-legacy.php';
} else {
$fixtureFile = __DIR__.'/Fixtures/'.$testName.'.php';
}
$this->assertStringEqualsFile($fixtureFile, $dump);

if ('incomplete-class' === $testName || 'external-references' === $testName) {
Expand Down

0 comments on commit 35673b8

Please sign in to comment.