Skip to content

Commit 2f87dc4

Browse files
committed
[Serializer] Fix readonly property initialization from incorrect scope
1 parent bd60612 commit 2f87dc4

File tree

4 files changed

+70
-1
lines changed

4 files changed

+70
-1
lines changed

‎src/Symfony/Component/Serializer/Normalizer/PropertyNormalizer.php

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
use Symfony\Component\PropertyAccess\Exception\UninitializedPropertyException;
1515
use Symfony\Component\PropertyInfo\PropertyTypeExtractorInterface;
16+
use Symfony\Component\Serializer\Exception\LogicException;
1617
use Symfony\Component\Serializer\Mapping\ClassDiscriminatorResolverInterface;
1718
use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactoryInterface;
1819
use Symfony\Component\Serializer\NameConverter\NameConverterInterface;
@@ -202,7 +203,24 @@ protected function setAttributeValue(object $object, string $attribute, mixed $v
202203
return;
203204
}
204205

205-
$reflectionProperty->setValue($object, $value);
206+
if (!$reflectionProperty->isReadOnly()) {
207+
$reflectionProperty->setValue($object, $value);
208+
209+
return;
210+
}
211+
212+
if (!$reflectionProperty->isInitialized($object)) {
213+
$declaringClass = $reflectionProperty->getDeclaringClass();
214+
$declaringClass->getProperty($reflectionProperty->getName())->setValue($object, $value);
215+
216+
return;
217+
}
218+
219+
if ($reflectionProperty->getValue($object) === $value) {
220+
return;
221+
}
222+
223+
throw new LogicException(\sprintf('Attempting to change readonly property "%s"::$%s.', $object::class, $reflectionProperty->getName()));
206224
}
207225

208226
/**
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\Serializer\Tests\Fixtures;
13+
14+
readonly class ChildClassDummy extends ParentClassDummy
15+
{
16+
public string $childProp;
17+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\Serializer\Tests\Fixtures;
13+
14+
readonly class ParentClassDummy
15+
{
16+
public string $parentProp;
17+
}

‎src/Symfony/Component/Serializer/Tests/Normalizer/PropertyNormalizerTest.php

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
use Symfony\Component\Serializer\SerializerInterface;
3131
use Symfony\Component\Serializer\Tests\Fixtures\Attributes\GroupDummy;
3232
use Symfony\Component\Serializer\Tests\Fixtures\Attributes\GroupDummyChild;
33+
use Symfony\Component\Serializer\Tests\Fixtures\ChildClassDummy;
3334
use Symfony\Component\Serializer\Tests\Fixtures\Dummy;
3435
use Symfony\Component\Serializer\Tests\Fixtures\Php74Dummy;
3536
use Symfony\Component\Serializer\Tests\Fixtures\PropertyCircularReferenceDummy;
@@ -174,6 +175,22 @@ public function testDenormalize()
174175
$this->assertEquals('bar', $obj->getBar());
175176
}
176177

178+
/**
179+
* @requires PHP 8.2
180+
*/
181+
public function testDenormalizeWithReadOnlyClass()
182+
{
183+
/** @var ChildClassDummy $object */
184+
$object = $this->normalizer->denormalize(
185+
['parentProp' => 'parentProp', 'childProp' => 'childProp'],
186+
ChildClassDummy::class,
187+
'any'
188+
);
189+
190+
$this->assertEquals('parentProp', $object->parentProp);
191+
$this->assertEquals('childProp', $object->childProp);
192+
}
193+
177194
public function testNormalizeWithParentClass()
178195
{
179196
$group = new GroupDummyChild();

0 commit comments

Comments
 (0)