From df043be3e74f124094030e6bf550c2066eab61d0 Mon Sep 17 00:00:00 2001 From: Nicolas PHILIPPE Date: Tue, 3 Oct 2023 12:31:57 +0200 Subject: [PATCH] fix: handle when input key does not exist --- .gitignore | 1 + src/Transformer/NullableTransformer.php | 18 +++++++++++++++--- tests/AutoMapperTest.php | 9 +++++++++ .../ClassWithNullablePropertyInConstructor.php | 12 ++++++++++++ 4 files changed, 37 insertions(+), 3 deletions(-) create mode 100644 tests/Fixtures/ClassWithNullablePropertyInConstructor.php diff --git a/.gitignore b/.gitignore index c3e33b77..07b75b44 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ vendor/ composer.lock .php-cs-fixer.cache .phpunit.result.cache +tests/cache/ diff --git a/src/Transformer/NullableTransformer.php b/src/Transformer/NullableTransformer.php index c52fbc98..5158f406 100644 --- a/src/Transformer/NullableTransformer.php +++ b/src/Transformer/NullableTransformer.php @@ -49,9 +49,21 @@ public function transform(Expr $input, Expr $target, PropertyMapping $propertyMa $itemStatements[] = new Stmt\Expression(new $assignClass($newOutput, $output)); } - $statements[] = new Stmt\If_(new Expr\BinaryOp\NotIdentical(new Expr\ConstFetch(new Name('null')), $input), [ - 'stmts' => $itemStatements, - ]); + if ($input instanceof Expr\ArrayDimFetch) { + /** + * if `$input` is an array access, let's validate if the array key exists and is not null: + * + * if (isset($value['key'])) { + */ + $statements[] = new Stmt\If_(new Expr\Isset_([$input]), ['stmts' => $itemStatements]); + } else { + /** + * otherwise, let's check the value is not null: + * + * if ($input !== null) { + */ + $statements[] = new Stmt\If_(new Expr\BinaryOp\NotIdentical(new Expr\ConstFetch(new Name('null')), $input), ['stmts' => $itemStatements]); + } return [$newOutput ?? $output, $statements]; } diff --git a/tests/AutoMapperTest.php b/tests/AutoMapperTest.php index 1568b9c3..b40f4d2c 100644 --- a/tests/AutoMapperTest.php +++ b/tests/AutoMapperTest.php @@ -17,6 +17,7 @@ use AutoMapper\Tests\Fixtures\AddressType; use AutoMapper\Tests\Fixtures\AddressWithEnum; use AutoMapper\Tests\Fixtures\ClassWithMapToContextAttribute; +use AutoMapper\Tests\Fixtures\ClassWithNullablePropertyInConstructor; use AutoMapper\Tests\Fixtures\ClassWithPrivateProperty; use AutoMapper\Tests\Fixtures\Fish; use AutoMapper\Tests\Fixtures\ObjectWithDateTime; @@ -1207,4 +1208,12 @@ public function testItCanDisablePrivatePropertiesMapping(): void $this->autoMapper->map(new ClassWithPrivateProperty('foo'), 'array') ); } + + public function testItCanMapFromArrayWithMissingNullableProperty(): void + { + self::assertEquals( + new ClassWithNullablePropertyInConstructor(foo: 1), + $this->autoMapper->map(['foo' => 1], ClassWithNullablePropertyInConstructor::class) + ); + } } diff --git a/tests/Fixtures/ClassWithNullablePropertyInConstructor.php b/tests/Fixtures/ClassWithNullablePropertyInConstructor.php new file mode 100644 index 00000000..e82e59e1 --- /dev/null +++ b/tests/Fixtures/ClassWithNullablePropertyInConstructor.php @@ -0,0 +1,12 @@ +