diff --git a/CHANGELOG.md b/CHANGELOG.md index c546d0a2..d1b1dae3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ replace with `ArrayObjectTransformer`. * fix: Fix dynamic properties in Symfony profiler panel. * fix: Fix `PresetTransformer`. +* fix: mapping to object extending `stdClass` to property with no setter. ## 1.0.0 diff --git a/src/Transformer/ObjectToObjectMetadata/Implementation/ObjectToObjectMetadataFactory.php b/src/Transformer/ObjectToObjectMetadata/Implementation/ObjectToObjectMetadataFactory.php index 071d4307..153fb476 100644 --- a/src/Transformer/ObjectToObjectMetadata/Implementation/ObjectToObjectMetadataFactory.php +++ b/src/Transformer/ObjectToObjectMetadata/Implementation/ObjectToObjectMetadataFactory.php @@ -241,13 +241,13 @@ public function createObjectToObjectMetadata( }; if ($targetWriteMode === WriteMode::None) { - if (!$targetAllowsDynamicProperties) { + if ($targetAllowsDynamicProperties && $targetReadInfo === null) { + $targetWriteMode = WriteMode::DynamicProperty; + $targetWriteName = $targetProperty; + $targetWriteVisibility = Visibility::Public; + } else { continue; } - $targetWriteMode = WriteMode::DynamicProperty; - $targetWriteName = $targetProperty; - $targetWriteVisibility = Visibility::Public; - } else { $targetWriteName = $targetWriteInfo->getName(); $targetWriteVisibility = match ($targetWriteInfo->getVisibility()) { diff --git a/tests/Fixtures/DynamicProperty/ObjectExtendingStdClassWithProperties.php b/tests/Fixtures/DynamicProperty/ObjectExtendingStdClassWithProperties.php new file mode 100644 index 00000000..f541fd8c --- /dev/null +++ b/tests/Fixtures/DynamicProperty/ObjectExtendingStdClassWithProperties.php @@ -0,0 +1,34 @@ + + * + * For the full copyright and license information, please view the LICENSE file + * that was distributed with this source code. + */ + +namespace Rekalogika\Mapper\Tests\Fixtures\DynamicProperty; + +class ObjectExtendingStdClassWithProperties extends \stdClass +{ + public ?string $public = null; + private ?string $private = null; + + public function __construct(private ?string $constructor = null) + { + } + + public function getConstructor(): ?string + { + return $this->constructor; + } + + public function getPrivate(): ?string + { + return $this->private; + } +} diff --git a/tests/IntegrationTest/DynamicPropertyTest.php b/tests/IntegrationTest/DynamicPropertyTest.php index a65b3884..e13500aa 100644 --- a/tests/IntegrationTest/DynamicPropertyTest.php +++ b/tests/IntegrationTest/DynamicPropertyTest.php @@ -15,6 +15,7 @@ use Rekalogika\Mapper\Tests\Common\FrameworkTestCase; use Rekalogika\Mapper\Tests\Fixtures\DynamicProperty\ObjectExtendingStdClass; +use Rekalogika\Mapper\Tests\Fixtures\DynamicProperty\ObjectExtendingStdClassWithProperties; use Rekalogika\Mapper\Tests\Fixtures\Scalar\ObjectWithScalarProperties; use Rekalogika\Mapper\Tests\Fixtures\ScalarDto\ObjectWithScalarPropertiesDto; @@ -140,4 +141,19 @@ public function testStdClassToStdClass(): void $this->assertTrue($target->c); $this->assertSame(1.1, $target->d); } + + public function testStdClassToStdClassWithExplicitProperties(): void + { + $source = new \stdClass(); + $source->public = 'public'; + $source->private = 'private'; + $source->constructor = 'constructor'; + + $target = $this->mapper->map($source, ObjectExtendingStdClassWithProperties::class); + + $this->assertInstanceOf(\stdClass::class, $target); + $this->assertSame('public', $target->public); + $this->assertNull($target->getPrivate()); + $this->assertEquals('constructor', $target->getConstructor()); + } }