diff --git a/CHANGELOG.md b/CHANGELOG.md index 7f6f2ab..3fb9997 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ handle the current target value in all cases * test: test lazy constructor * fix: double mapping if a property is in the constructor and also has a setter +* fix: remove heuristics of value object detection to reduce confusion ## 1.11.0 diff --git a/src/Transformer/ObjectToObjectMetadata/ObjectToObjectMetadata.php b/src/Transformer/ObjectToObjectMetadata/ObjectToObjectMetadata.php index 8219648..68eff79 100644 --- a/src/Transformer/ObjectToObjectMetadata/ObjectToObjectMetadata.php +++ b/src/Transformer/ObjectToObjectMetadata/ObjectToObjectMetadata.php @@ -92,14 +92,6 @@ public function __construct( $constructorPropertyMappings[$propertyMapping->getTargetProperty()] = $propertyMapping; } - if ( - !$propertyMapping->isTargetReplaceable() - && !$propertyMapping->hostCanMutateTarget() - && $propertyMapping->isTargetUnalterable() - ) { - continue; - } - $propertyPropertyMappings[$propertyMapping->getTargetProperty()] = $propertyMapping; if ($propertyMapping->isSourceLazy()) { diff --git a/tests/config/rekalogika-mapper/generated-mappings.php b/tests/config/rekalogika-mapper/generated-mappings.php index 795be04..21e252b 100644 --- a/tests/config/rekalogika-mapper/generated-mappings.php +++ b/tests/config/rekalogika-mapper/generated-mappings.php @@ -93,25 +93,25 @@ ); $mappingCollection->addObjectMapping( - // tests/src/IntegrationTest/TraversableToArrayAccessMappingTest.php on lines 152, 335 + // tests/src/IntegrationTest/TraversableToArrayAccessMappingTest.php on lines 153, 336 source: \Rekalogika\Mapper\Tests\Fixtures\ArrayLike\ObjectWithArrayProperty::class, target: \Rekalogika\Mapper\Tests\Fixtures\ArrayLikeDto\ObjectWithArrayAccessPropertyDto::class ); $mappingCollection->addObjectMapping( - // tests/src/IntegrationTest/TraversableToArrayAccessMappingTest.php on line 202 + // tests/src/IntegrationTest/TraversableToArrayAccessMappingTest.php on line 203 source: \Rekalogika\Mapper\Tests\Fixtures\ArrayLike\ObjectWithArrayProperty::class, target: \Rekalogika\Mapper\Tests\Fixtures\ArrayLikeDto\ObjectWithArrayInterfacePropertyDto::class ); $mappingCollection->addObjectMapping( - // tests/src/IntegrationTest/TraversableToArrayAccessMappingTest.php on lines 238, 348 + // tests/src/IntegrationTest/TraversableToArrayAccessMappingTest.php on lines 239, 349 source: \Rekalogika\Mapper\Tests\Fixtures\ArrayLike\ObjectWithArrayProperty::class, target: \Rekalogika\Mapper\Tests\Fixtures\ArrayLikeDto\ObjectWithArrayPropertyDto::class ); $mappingCollection->addObjectMapping( - // tests/src/IntegrationTest/TraversableToArrayAccessMappingTest.php on line 51 + // tests/src/IntegrationTest/TraversableToArrayAccessMappingTest.php on line 52 source: \Rekalogika\Mapper\Tests\Fixtures\ArrayLike\ObjectWithArrayProperty::class, target: \Rekalogika\Mapper\Tests\Fixtures\ArrayLikeDto\ObjectWithArrayPropertyWithoutTypeHintDto::class ); @@ -123,7 +123,7 @@ ); $mappingCollection->addObjectMapping( - // tests/src/IntegrationTest/TraversableToArrayAccessMappingTest.php on line 253 + // tests/src/IntegrationTest/TraversableToArrayAccessMappingTest.php on line 254 source: \Rekalogika\Mapper\Tests\Fixtures\ArrayLike\ObjectWithArrayProperty::class, target: \Rekalogika\Mapper\Tests\Fixtures\ArrayLikeDto\ObjectWithCollectionPropertyDto::class ); @@ -153,19 +153,19 @@ ); $mappingCollection->addObjectMapping( - // tests/src/IntegrationTest/TraversableToArrayAccessMappingTest.php on line 367 + // tests/src/IntegrationTest/TraversableToArrayAccessMappingTest.php on line 368 source: \Rekalogika\Mapper\Tests\Fixtures\ArrayLike\ObjectWithArrayPropertyWithStringKey::class, target: \Rekalogika\Mapper\Tests\Fixtures\ArrayLikeDto\ObjectWithArrayPropertyDtoWithIntKey::class ); $mappingCollection->addObjectMapping( - // tests/src/IntegrationTest/TraversableToArrayAccessMappingTest.php on line 170 + // tests/src/IntegrationTest/TraversableToArrayAccessMappingTest.php on line 171 source: \Rekalogika\Mapper\Tests\Fixtures\ArrayLike\ObjectWithCollectionProperty::class, target: \Rekalogika\Mapper\Tests\Fixtures\ArrayLikeDto\ObjectWithArrayAccessPropertyDto::class ); $mappingCollection->addObjectMapping( - // tests/src/IntegrationTest/TraversableToArrayAccessMappingTest.php on line 220 + // tests/src/IntegrationTest/TraversableToArrayAccessMappingTest.php on line 221 source: \Rekalogika\Mapper\Tests\Fixtures\ArrayLike\ObjectWithCollectionProperty::class, target: \Rekalogika\Mapper\Tests\Fixtures\ArrayLikeDto\ObjectWithArrayInterfacePropertyDto::class ); @@ -183,7 +183,7 @@ ); $mappingCollection->addObjectMapping( - // tests/src/IntegrationTest/TraversableToArrayAccessMappingTest.php on line 188 + // tests/src/IntegrationTest/TraversableToArrayAccessMappingTest.php on line 189 source: \Rekalogika\Mapper\Tests\Fixtures\ArrayLike\ObjectWithNullCollectionProperty::class, target: \Rekalogika\Mapper\Tests\Fixtures\ArrayLikeDto\ObjectWithNotNullArrayAccessPropertyDto::class ); @@ -195,55 +195,55 @@ ); $mappingCollection->addObjectMapping( - // tests/src/IntegrationTest/TraversableToArrayAccessMappingTest.php on line 275 + // tests/src/IntegrationTest/TraversableToArrayAccessMappingTest.php on line 276 source: \Rekalogika\Mapper\Tests\Fixtures\ArrayLike\ObjectWithSplObjectStorageProperty::class, target: \Rekalogika\Mapper\Tests\Fixtures\ArrayLikeDto\ObjectWithArrayAccessPropertyWithObjectKeyDto::class ); $mappingCollection->addObjectMapping( - // tests/src/IntegrationTest/TraversableToArrayAccessMappingTest.php on line 293 + // tests/src/IntegrationTest/TraversableToArrayAccessMappingTest.php on line 294 source: \Rekalogika\Mapper\Tests\Fixtures\ArrayLike\ObjectWithSplObjectStorageProperty::class, target: \Rekalogika\Mapper\Tests\Fixtures\ArrayLikeDto\ObjectWithArrayPropertyDto::class ); $mappingCollection->addObjectMapping( - // tests/src/IntegrationTest/TraversableToArrayAccessMappingTest.php on lines 101, 306, 390 + // tests/src/IntegrationTest/TraversableToArrayAccessMappingTest.php on lines 102, 307, 391 source: \Rekalogika\Mapper\Tests\Fixtures\ArrayLike\ObjectWithTraversableProperties::class, target: \Rekalogika\Mapper\Tests\Fixtures\ArrayLikeDto\ObjectWithArrayAccessPropertyDto::class ); $mappingCollection->addObjectMapping( - // tests/src/IntegrationTest/TraversableToArrayAccessMappingTest.php on lines 115, 320 + // tests/src/IntegrationTest/TraversableToArrayAccessMappingTest.php on lines 116, 321 source: \Rekalogika\Mapper\Tests\Fixtures\ArrayLike\ObjectWithTraversableProperties::class, target: \Rekalogika\Mapper\Tests\Fixtures\ArrayLikeDto\ObjectWithArrayPropertyDto::class ); $mappingCollection->addObjectMapping( - // tests/src/IntegrationTest/TraversableToArrayAccessMappingTest.php on line 81 + // tests/src/IntegrationTest/TraversableToArrayAccessMappingTest.php on line 82 source: \Rekalogika\Mapper\Tests\Fixtures\ArrayLike\ObjectWithTraversableProperties::class, target: \Rekalogika\Mapper\Tests\Fixtures\ArrayLikeDto\ObjectWithArrayPropertyWithCompatibleHintDto::class ); $mappingCollection->addObjectMapping( - // tests/src/IntegrationTest/TraversableToArrayAccessMappingTest.php on line 66 + // tests/src/IntegrationTest/TraversableToArrayAccessMappingTest.php on line 67 source: \Rekalogika\Mapper\Tests\Fixtures\ArrayLike\ObjectWithTraversableProperties::class, target: \Rekalogika\Mapper\Tests\Fixtures\ArrayLikeDto\ObjectWithArrayPropertyWithoutTypeHintDto::class ); $mappingCollection->addObjectMapping( - // tests/src/IntegrationTest/TraversableToArrayAccessMappingTest.php on line 433 + // tests/src/IntegrationTest/TraversableToArrayAccessMappingTest.php on line 432 source: \Rekalogika\Mapper\Tests\Fixtures\ArrayLike\ObjectWithTraversableProperties::class, target: \Rekalogika\Mapper\Tests\Fixtures\ArrayLikeDto\ObjectWithArrayWithGetterNoSetterDto::class ); $mappingCollection->addObjectMapping( - // tests/src/IntegrationTest/TraversableToArrayAccessMappingTest.php on line 130 + // tests/src/IntegrationTest/TraversableToArrayAccessMappingTest.php on line 131 source: \Rekalogika\Mapper\Tests\Fixtures\ArrayLike\ObjectWithTraversableProperties::class, target: \Rekalogika\Mapper\Tests\Fixtures\ArrayLikeDto\ObjectWithCollectionPropertyDto::class ); $mappingCollection->addObjectMapping( - // tests/src/IntegrationTest/TraversableToArrayAccessMappingTest.php on line 407 + // tests/src/IntegrationTest/TraversableToArrayAccessMappingTest.php on line 408 source: \Rekalogika\Mapper\Tests\Fixtures\ArrayLike\ObjectWithTraversableProperties::class, target: \Rekalogika\Mapper\Tests\Fixtures\ArrayLikeDto\ObjectWithCollectionWithGetterNoSetterDto::class ); @@ -261,32 +261,32 @@ ); $mappingCollection->addObjectMapping( - // tests/src/IntegrationTest/BasicMappingTest.php on line 33 + // tests/src/IntegrationTest/BasicMappingTest.php on line 34 // tests/src/IntegrationTest/IterableMapperTest.php on line 24 source: \Rekalogika\Mapper\Tests\Fixtures\Basic\Person::class, target: \Rekalogika\Mapper\Tests\Fixtures\Basic\PersonDto::class ); $mappingCollection->addObjectMapping( - // tests/src/IntegrationTest/BasicMappingTest.php on line 42 + // tests/src/IntegrationTest/BasicMappingTest.php on line 43 source: \Rekalogika\Mapper\Tests\Fixtures\Basic\Person::class, target: \Rekalogika\Mapper\Tests\Fixtures\Basic\PersonWithoutAgeDto::class ); $mappingCollection->addObjectMapping( - // tests/src/IntegrationTest/BasicMappingTest.php on line 74 + // tests/src/IntegrationTest/BasicMappingTest.php on line 75 source: \Rekalogika\Mapper\Tests\Fixtures\Basic\PersonWithDogDto::class, target: \Rekalogika\Mapper\Tests\Fixtures\Basic\PersonWithDog::class ); $mappingCollection->addObjectMapping( - // tests/src/IntegrationTest/BasicMappingTest.php on line 99 + // tests/src/IntegrationTest/BasicMappingTest.php on line 103 source: \Rekalogika\Mapper\Tests\Fixtures\Basic\PersonWithDogDto::class, target: \Rekalogika\Mapper\Tests\Fixtures\Basic\PersonWithImmutableDogWithoutSetter::class ); $mappingCollection->addObjectMapping( - // tests/src/IntegrationTest/BasicMappingTest.php on line 50 + // tests/src/IntegrationTest/BasicMappingTest.php on line 51 source: \Rekalogika\Mapper\Tests\Fixtures\Basic\PersonWithoutAge::class, target: \Rekalogika\Mapper\Tests\Fixtures\Basic\PersonDto::class ); @@ -358,7 +358,7 @@ ); $mappingCollection->addObjectMapping( - // tests/src/IntegrationTest/DynamicPropertyTest.php on line 302 + // tests/src/IntegrationTest/DynamicPropertyTest.php on line 304 source: \Rekalogika\Mapper\Tests\Fixtures\DynamicProperty\ObjectExtendingStdClass::class, target: \Rekalogika\Mapper\Tests\Fixtures\DynamicProperty\ObjectWithNonNullPropertyThatCannotBeCastFromNull::class ); @@ -376,7 +376,7 @@ ); $mappingCollection->addObjectMapping( - // tests/src/IntegrationTest/DynamicPropertyTest.php on line 310 + // tests/src/IntegrationTest/DynamicPropertyTest.php on line 312 source: \Rekalogika\Mapper\Tests\Fixtures\DynamicProperty\ObjectWithNullProperty::class, target: \stdClass::class ); @@ -1067,7 +1067,7 @@ ); $mappingCollection->addObjectMapping( - // tests/src/IntegrationTest/DynamicPropertyTest.php on line 258 + // tests/src/IntegrationTest/DynamicPropertyTest.php on line 260 source: \stdClass::class, target: \Rekalogika\Mapper\Tests\Fixtures\DynamicProperty\ObjectExtendingStdClassWithProperties::class ); @@ -1079,7 +1079,7 @@ ); $mappingCollection->addObjectMapping( - // tests/src/IntegrationTest/DynamicPropertyTest.php on lines 277, 290 + // tests/src/IntegrationTest/DynamicPropertyTest.php on lines 279, 292 source: \stdClass::class, target: \stdClass::class ); diff --git a/tests/src/IntegrationTest/BasicMappingTest.php b/tests/src/IntegrationTest/BasicMappingTest.php index fe787c8..2e22ddf 100644 --- a/tests/src/IntegrationTest/BasicMappingTest.php +++ b/tests/src/IntegrationTest/BasicMappingTest.php @@ -24,6 +24,7 @@ use Rekalogika\Mapper\Tests\Fixtures\Basic\PersonWithImmutableDogWithoutSetter; use Rekalogika\Mapper\Tests\Fixtures\Basic\PersonWithoutAge; use Rekalogika\Mapper\Tests\Fixtures\Basic\PersonWithoutAgeDto; +use Rekalogika\Mapper\Transformer\Exception\NewInstanceReturnedButCannotBeSetOnTargetException; class BasicMappingTest extends FrameworkTestCase { @@ -81,6 +82,9 @@ public function testSetterNotCalledIfValueDoesntChange(): void public function testSkippingImmutableEntityWithNoSetterOnTarget(): void { + // old behavior no longer supported, this throws an exception now + $this->expectException(NewInstanceReturnedButCannotBeSetOnTargetException::class); + // source $personDto = new PersonWithDogDto(); $dogDto = new DogDto(); diff --git a/tests/src/IntegrationTest/DateTimeMappingTest.php b/tests/src/IntegrationTest/DateTimeMappingTest.php index 5d9cf86..e2349db 100644 --- a/tests/src/IntegrationTest/DateTimeMappingTest.php +++ b/tests/src/IntegrationTest/DateTimeMappingTest.php @@ -371,14 +371,15 @@ public static function dateTimeMappingProvider(): iterable null, ]; - yield - self::getDescription(ObjectWithDateTimeInterface::class, ObjectWithDateTimeImmutableGetterOnly::class) . ' 2' => - [ - ObjectWithString::class, - ObjectWithDateTimeImmutableGetterOnly::class, - '2024-01-01 13:00:00 UTC', - null, - ]; + // this no longer tolerated. this will throw an exception now + // yield + // self::getDescription(ObjectWithDateTimeInterface::class, ObjectWithDateTimeImmutableGetterOnly::class) . ' 2' => + // [ + // ObjectWithString::class, + // ObjectWithDateTimeImmutableGetterOnly::class, + // '2024-01-01 13:00:00 UTC', + // null, + // ]; } private static function getShortClass(string $class): string diff --git a/tests/src/IntegrationTest/DynamicPropertyTest.php b/tests/src/IntegrationTest/DynamicPropertyTest.php index 0ffdcce..c250bc0 100644 --- a/tests/src/IntegrationTest/DynamicPropertyTest.php +++ b/tests/src/IntegrationTest/DynamicPropertyTest.php @@ -251,7 +251,9 @@ public function testStdClassToStdClassWithExplicitProperties(): void { $source = new \stdClass(); $source->public = 'public'; - $source->private = 'private'; + // in the new behavior, this will fail, because there is no setter on + // the target side + // $source->private = 'private'; $source->constructor = 'constructor'; $source->dynamic = 'dynamic'; diff --git a/tests/src/IntegrationTest/TraversableToArrayAccessMappingTest.php b/tests/src/IntegrationTest/TraversableToArrayAccessMappingTest.php index 3e5378d..02f1aaa 100644 --- a/tests/src/IntegrationTest/TraversableToArrayAccessMappingTest.php +++ b/tests/src/IntegrationTest/TraversableToArrayAccessMappingTest.php @@ -36,6 +36,7 @@ use Rekalogika\Mapper\Tests\Fixtures\ArrayLikeDto\ObjectWithNotNullArrayAccessPropertyDto; use Rekalogika\Mapper\Tests\Fixtures\Scalar\ObjectWithScalarProperties; use Rekalogika\Mapper\Tests\Fixtures\ScalarDto\ObjectWithScalarPropertiesDto; +use Rekalogika\Mapper\Transformer\Exception\NewInstanceReturnedButCannotBeSetOnTargetException; use Rekalogika\Mapper\Transformer\Model\HashTable; use Rekalogika\Mapper\Transformer\Model\LazyArray; @@ -423,14 +424,11 @@ public function testMappingToCollectionWithGetterButNoSetter(): void public function testMappingToArrayWithGetterButNoSetter(): void { - // the property should be skipped, cannot mutate object's - // array without a setter + $this->expectException(NewInstanceReturnedButCannotBeSetOnTargetException::class); $source = new ObjectWithTraversableProperties(); $target = new ObjectWithArrayWithGetterNoSetterDto(); - $this->assertCount(0, $target->getProperty()); $result = $this->mapper->map($source, $target); - $this->assertCount(0, $result->getProperty()); } }