From 3b15b2327c1005cd5dd559afcb5fba7372c3a7a1 Mon Sep 17 00:00:00 2001 From: Priyadi Iman Nurcahyo <1102197+priyadi@users.noreply.github.com> Date: Sun, 13 Oct 2024 12:51:12 +0700 Subject: [PATCH] handle invalid extra target properties --- .../ExtraTargetPropertyNotFoundException.php | 40 +++++++++++++++++++ .../ObjectToObjectTransformer.php | 17 +++++++- .../rekalogika-mapper/generated-mappings.php | 4 +- .../IntegrationTest/ExtraTargetValuesTest.php | 18 +++++++++ 4 files changed, 76 insertions(+), 3 deletions(-) create mode 100644 src/Transformer/Exception/ExtraTargetPropertyNotFoundException.php diff --git a/src/Transformer/Exception/ExtraTargetPropertyNotFoundException.php b/src/Transformer/Exception/ExtraTargetPropertyNotFoundException.php new file mode 100644 index 0000000..fcdc44f --- /dev/null +++ b/src/Transformer/Exception/ExtraTargetPropertyNotFoundException.php @@ -0,0 +1,40 @@ + + * + * For the full copyright and license information, please view the LICENSE file + * that was distributed with this source code. + */ + +namespace Rekalogika\Mapper\Transformer\Exception; + +use Rekalogika\Mapper\Context\Context; +use Rekalogika\Mapper\Exception\LogicException; + +/** + * @internal + */ +class ExtraTargetPropertyNotFoundException extends LogicException +{ + /** + * @param class-string $class + */ + public function __construct( + string $class, + string $property, + Context $context, + ) { + $message = \sprintf( + 'Mapper is called with "ExtraTargetValues", but cannot find the target property "%s" in class "%s"', + $property, + $class, + ); + + parent::__construct($message, context: $context); + } +} diff --git a/src/Transformer/Implementation/ObjectToObjectTransformer.php b/src/Transformer/Implementation/ObjectToObjectTransformer.php index 1ebcc2e..2dc8917 100644 --- a/src/Transformer/Implementation/ObjectToObjectTransformer.php +++ b/src/Transformer/Implementation/ObjectToObjectTransformer.php @@ -27,6 +27,7 @@ use Rekalogika\Mapper\ServiceMethod\ServiceMethodSpecification; use Rekalogika\Mapper\SubMapper\SubMapperFactoryInterface; use Rekalogika\Mapper\Transformer\Exception\ClassNotInstantiableException; +use Rekalogika\Mapper\Transformer\Exception\ExtraTargetPropertyNotFoundException; use Rekalogika\Mapper\Transformer\Exception\InstantiationFailureException; use Rekalogika\Mapper\Transformer\Exception\NotAClassException; use Rekalogika\Mapper\Transformer\Exception\UninitializedSourcePropertyException; @@ -205,9 +206,23 @@ private function getExtraTargetValues( ObjectToObjectMetadata $objectToObjectMetadata, Context $context, ): array { - return $context(ExtraTargetValues::class) + $extraTargetValues = $context(ExtraTargetValues::class) ?->getArgumentsForClass($objectToObjectMetadata->getAllTargetClasses()) ?? []; + + $allPropertyMappings = $objectToObjectMetadata->getPropertyMappings(); + + foreach (array_keys($extraTargetValues) as $property) { + if (!isset($allPropertyMappings[$property])) { + throw new ExtraTargetPropertyNotFoundException( + class: $objectToObjectMetadata->getTargetClass(), + property: $property, + context: $context, + ); + } + } + + return $extraTargetValues; } /** diff --git a/tests/config/rekalogika-mapper/generated-mappings.php b/tests/config/rekalogika-mapper/generated-mappings.php index 252d6e5..ab866e2 100644 --- a/tests/config/rekalogika-mapper/generated-mappings.php +++ b/tests/config/rekalogika-mapper/generated-mappings.php @@ -388,13 +388,13 @@ ); $mappingCollection->addObjectMapping( - // tests/src/IntegrationTest/ExtraTargetValuesTest.php on line 27 + // tests/src/IntegrationTest/ExtraTargetValuesTest.php on lines 28, 68 source: \Rekalogika\Mapper\Tests\Fixtures\ExtraTargetValues\SomeObject::class, target: \Rekalogika\Mapper\Tests\Fixtures\ExtraTargetValues\SomeObjectWithConstructorDto::class ); $mappingCollection->addObjectMapping( - // tests/src/IntegrationTest/ExtraTargetValuesTest.php on line 46 + // tests/src/IntegrationTest/ExtraTargetValuesTest.php on line 47 source: \Rekalogika\Mapper\Tests\Fixtures\ExtraTargetValues\SomeObject::class, target: \Rekalogika\Mapper\Tests\Fixtures\ExtraTargetValues\SomeObjectWithPropertyDto::class ); diff --git a/tests/src/IntegrationTest/ExtraTargetValuesTest.php b/tests/src/IntegrationTest/ExtraTargetValuesTest.php index 2ba5aaa..70b8353 100644 --- a/tests/src/IntegrationTest/ExtraTargetValuesTest.php +++ b/tests/src/IntegrationTest/ExtraTargetValuesTest.php @@ -19,6 +19,7 @@ use Rekalogika\Mapper\Tests\Fixtures\ExtraTargetValues\SomeObject; use Rekalogika\Mapper\Tests\Fixtures\ExtraTargetValues\SomeObjectWithConstructorDto; use Rekalogika\Mapper\Tests\Fixtures\ExtraTargetValues\SomeObjectWithPropertyDto; +use Rekalogika\Mapper\Transformer\Exception\ExtraTargetPropertyNotFoundException; class ExtraTargetValuesTest extends FrameworkTestCase { @@ -59,4 +60,21 @@ public function testExtraTargetValuesOnProperty(): void $this->assertInstanceOf(\DateTimeImmutable::class, $target->date); $this->assertSame('2021-01-01', $target->date->format('Y-m-d')); } + + public function testInvalidExtraTargetValues(): void + { + $this->expectException(ExtraTargetPropertyNotFoundException::class); + + $this->mapper->map( + source: new SomeObject(), + target: SomeObjectWithConstructorDto::class, + context: Context::create( + new ExtraTargetValues([ + SomeObjectWithConstructorDto::class => [ + 'foo' => new \DateTimeImmutable('2021-01-01'), + ], + ]), + ), + ); + } }