8000 [VarExporter] Fix exporting classes with __serialize() but not __unse… · symfony/symfony@6d8a363 · GitHub
[go: up one dir, main page]

Skip to content

Commit 6d8a363

Browse files
fancywebnicolas-grekas
authored andcommitted
[VarExporter] Fix exporting classes with __serialize() but not __unserialize()
1 parent 0c1e73e commit 6d8a363

File tree

3 files changed

+47
-2
lines changed

3 files changed

+47
-2
lines changed

src/Symfony/Component/VarExporter/Internal/Exporter.php

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,20 +73,29 @@ public static function prepare($values, $objectsPool, &$refsPool, &$objectsCount
7373

7474
$class = \get_class($value);
7575
$reflector = Registry::$reflectors[$class] ?? Registry::getClassReflector($class);
76+
$properties = [];
7677

7778
if ($reflector->hasMethod('__serialize')) {
7879
if (!$reflector->getMethod('__serialize')->isPublic()) {
7980
throw new \Error(sprintf('Call to %s method "%s::__serialize()".', $reflector->getMethod('__serialize')->isProtected() ? 'protected' : 'private', $class));
8081
}
8182

82-
if (!\is_array($properties = $value->__serialize())) {
83+
if (!\is_array($serializeProperties = $value->__serialize())) {
8384
throw new \TypeError($class.'::__serialize() must return an array');
8485
}
8586

87+
if ($reflector->hasMethod('__unserialize')) {
88+
$properties = $serializeProperties;
89+
} else {
90+
foreach ($serializeProperties as $n => $v) {
91+
$c = \PHP_VERSION_ID >= 80100 && $reflector->hasProperty($n) && ($p = $reflector->getProperty($n))->isReadOnly() ? $p->class : 'stdClass';
92+
$properties[$c][$n] = $v;
93+
}
94+
}
95+
8696
goto prepare_value;
8797
}
8898

89-
$properties = [];
9099
$sleep = null;
91100
$proto = Registry::$prototypes[$class];
92101

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<?php
2+
3+
return \Symfony\Component\VarExporter\Internal\Hydrator::hydrate(
4+
$o = [
5+
clone (\Symfony\Component\VarExporter\Internal\Registry::$prototypes['Symfony\\Component\\VarExporter\\Tests\\__SerializeButNo__Unserialize'] ?? \Symfony\Component\VarExporter\Internal\Registry::p('Symfony\\Component\\VarExporter\\Tests\\__SerializeButNo__Unserialize')),
6+
],
7+
null,
8+
[
9+
'stdClass' => [
10+
'foo' => [
11+
'ccc',
12+
],
13+
],
14+
],
15+
$o[0],
16+
[]
17+
);

src/Symfony/Component/VarExporter/Tests/VarExporterTest.php

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,8 @@ public static function provideExport()
247247

248248
yield ['__unserialize-but-no-__serialize', new __UnserializeButNo__Serialize()];
249249

250+
yield ['__serialize-but-no-__unserialize', new __SerializeButNo__Unserialize()];
251+
250252
if (\PHP_VERSION_ID < 80100) {
251253
return;
252254
}
@@ -470,3 +472,20 @@ public function __unserialize(array $data): void
470472
$this->foo = $data['foo'];
471473
}
472474
}
475+
476+
class __SerializeButNo__Unserialize
477+
{
478+
public $foo;
479+
480+
public function __construct()
481+
{
482+
$this->foo = 'ccc';
483+
}
484+
485+
public function __serialize(): array
486+
{
487+
return [
488+
'foo' => $this->foo,
489+
];
490+
}
491+
}

0 commit comments

Comments
 (0)
0