mirror of
https://github.com/symfony/symfony.git
synced 2026-03-24 00:32:15 +01:00
[VarExporter] Fix DeepCloner crash with objects using __serialize()
This commit is contained in:
@@ -100,7 +100,7 @@ class Exporter
|
||||
throw new \TypeError($class.'::__serialize() must return an array');
|
||||
}
|
||||
|
||||
if (self::$classInfo[$class][0] ??= method_exists($class, '__unserialize')) {
|
||||
if (self::$classInfo[$class][0] ??= $reflector->hasMethod('__unserialize')) {
|
||||
$properties = $arrayValue;
|
||||
goto prepare_value;
|
||||
}
|
||||
@@ -126,7 +126,7 @@ class Exporter
|
||||
$value = new Reference($id);
|
||||
goto handle_value;
|
||||
} else {
|
||||
if (self::$classInfo[$class][3] ??= method_exists($class, '__sleep')) {
|
||||
if (self::$classInfo[$class][3] ??= $reflector->hasMethod('__sleep')) {
|
||||
if (!\is_array($sleep = $value->__sleep())) {
|
||||
trigger_error('serialize(): __sleep should return an array only containing the names of instance-variables to serialize', \E_USER_NOTICE);
|
||||
$value = null;
|
||||
@@ -188,17 +188,17 @@ class Exporter
|
||||
trigger_error(\sprintf('serialize(): "%s" returned as member variable from __sleep() but does not exist', $n), \E_USER_NOTICE);
|
||||
}
|
||||
}
|
||||
$hasUnserialize = self::$classInfo[$class][0] ??= method_exists($class, '__unserialize');
|
||||
$hasUnserialize = self::$classInfo[$class][0] ??= $reflector->hasMethod('__unserialize');
|
||||
if ($hasUnserialize) {
|
||||
$properties = $arrayValue;
|
||||
}
|
||||
|
||||
prepare_value:
|
||||
$hasUnserialize ??= self::$classInfo[$class][0] ??= method_exists($class, '__unserialize');
|
||||
$hasUnserialize ??= self::$classInfo[$class][0] ??= $reflector->hasMethod('__unserialize');
|
||||
$objectsPool[$value] = [$id = \count($objectsPool)];
|
||||
$properties = self::prepare($properties, $objectsPool, $refsPool, $objectsCount, $valueIsStatic);
|
||||
++$objectsCount;
|
||||
$objectsPool[$value] = [$id, $class, $properties, $hasUnserialize ? -$objectsCount : ((self::$classInfo[$class][1] ??= method_exists($class, '__wakeup')) ? $objectsCount : 0)];
|
||||
$objectsPool[$value] = [$id, $class, $properties, $hasUnserialize ? -$objectsCount : ((self::$classInfo[$class][1] ??= $reflector->hasMethod('__wakeup')) ? $objectsCount : 0)];
|
||||
|
||||
$value = new Reference($id);
|
||||
|
||||
|
||||
@@ -223,6 +223,31 @@ class DeepCloneTest extends TestCase
|
||||
$this->assertNotEquals($dt, $clone);
|
||||
}
|
||||
|
||||
public function testDateTimeImmutable()
|
||||
{
|
||||
$dt = new \DateTimeImmutable('2024-01-15 10:30:00', new \DateTimeZone('UTC'));
|
||||
|
||||
$clone = DeepCloner::deepClone($dt);
|
||||
|
||||
$this->assertNotSame($dt, $clone);
|
||||
$this->assertEquals($dt, $clone);
|
||||
}
|
||||
|
||||
public function testObjectContainingDateTimeImmutable()
|
||||
{
|
||||
$obj = new DeepCloneDateTimeContainer(
|
||||
'test-item',
|
||||
new \DateTimeImmutable('2024-01-15 10:30:00', new \DateTimeZone('UTC'))
|
||||
);
|
||||
|
||||
$clone = DeepCloner::deepClone($obj);
|
||||
|
||||
$this->assertNotSame($obj, $clone);
|
||||
$this->assertSame('test-item', $clone->name);
|
||||
$this->assertNotSame($obj->storedAt, $clone->storedAt);
|
||||
$this->assertEquals($obj->storedAt, $clone->storedAt);
|
||||
}
|
||||
|
||||
public function testSplObjectStorage()
|
||||
{
|
||||
$s = new \SplObjectStorage();
|
||||
@@ -442,6 +467,15 @@ class DeepCloneTest extends TestCase
|
||||
}
|
||||
}
|
||||
|
||||
class DeepCloneDateTimeContainer
|
||||
{
|
||||
public function __construct(
|
||||
public readonly string $name,
|
||||
public readonly \DateTimeImmutable $storedAt,
|
||||
) {
|
||||
}
|
||||
}
|
||||
|
||||
class DeepCloneReadonlyReference
|
||||
{
|
||||
public function __construct(
|
||||
|
||||
Reference in New Issue
Block a user