Skip to content

Commit b6e9cb4

Browse files
authored
feat(mapper): set deep populate to true if passing an existing value (#265)
I think having this to true by default if we pass an existing value is better for DX, i kind of expect that by default when passing a value (having to set this value should be only opt out)
2 parents 0f2fd2d + b71be23 commit b6e9cb4

File tree

5 files changed

+44
-8
lines changed

5 files changed

+44
-8
lines changed

src/AutoMapper.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,9 +103,11 @@ public function map(array|object $source, string|array|object $target, array $co
103103
if (\is_object($target)) {
104104
$targetType = $target::class;
105105
$context[MapperContext::TARGET_TO_POPULATE] = $target;
106+
$context[MapperContext::DEEP_TARGET_TO_POPULATE] ??= true;
106107
} elseif (\is_array($target)) {
107108
$targetType = 'array';
108109
$context[MapperContext::TARGET_TO_POPULATE] = $target;
110+
$context[MapperContext::DEEP_TARGET_TO_POPULATE] ??= true;
109111
} elseif (\is_string($target)) {
110112
$targetType = $target;
111113
}

src/Transformer/AbstractArrayTransformer.php

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,13 +36,24 @@ public function transform(Expr $input, Expr $target, PropertyMetadata $propertyM
3636
$baseAssign = new Expr\Array_();
3737

3838
if ($propertyMapping->target->readAccessor !== null) {
39+
$isDefined = $propertyMapping->target->readAccessor->getIsDefinedExpression(new Expr\Variable('result'));
40+
$existingValue = $propertyMapping->target->readAccessor->getExpression(new Expr\Variable('result'));
41+
42+
if (null !== $isDefined) {
43+
$existingValue = new Expr\Ternary(
44+
$isDefined,
45+
$existingValue,
46+
$baseAssign
47+
);
48+
}
49+
3950
$baseAssign = new Expr\Ternary(
4051
new Expr\BinaryOp\Coalesce(
4152
new Expr\ArrayDimFetch(new Expr\Variable('context'), new Scalar\String_(MapperContext::DEEP_TARGET_TO_POPULATE)),
4253
new Expr\ConstFetch(new Name('false'))
4354
),
44-
$propertyMapping->target->readAccessor->getExpression(new Expr\Variable('result')),
45-
new Expr\Array_()
55+
$existingValue,
56+
$baseAssign
4657
);
4758
}
4859

src/Transformer/ArrayToDoctrineCollectionTransformer.php

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,12 +36,23 @@ public function transform(Expr $input, Expr $target, PropertyMetadata $propertyM
3636
$baseAssign = new Expr\New_(new Name(ArrayCollection::class));
3737

3838
if ($propertyMapping->target->readAccessor !== null) {
39+
$isDefined = $propertyMapping->target->readAccessor->getIsDefinedExpression(new Expr\Variable('result'));
40+
$existingValue = $propertyMapping->target->readAccessor->getExpression(new Expr\Variable('result'));
41+
42+
if (null !== $isDefined) {
43+
$existingValue = new Expr\Ternary(
44+
$isDefined,
45+
$existingValue,
46+
$baseAssign
47+
);
48+
}
49+
3950
$baseAssign = new Expr\Ternary(
4051
new Expr\BinaryOp\Coalesce(
4152
new Expr\ArrayDimFetch(new Expr\Variable('context'), new Scalar\String_(MapperContext::DEEP_TARGET_TO_POPULATE)),
4253
new Expr\ConstFetch(new Name('false'))
4354
),
44-
$propertyMapping->target->readAccessor->getExpression(new Expr\Variable('result')),
55+
$existingValue,
4556
$baseAssign,
4657
);
4758
}

src/Transformer/ObjectTransformer.php

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,13 +40,24 @@ public function transform(Expr $input, Expr $target, PropertyMetadata $propertyM
4040

4141
// ($context['deep_target_to_populate'] ?? false) ? $source->property : null
4242
if ($propertyMapping->target->readAccessor !== null && $this->deepTargetToPopulate) {
43+
$isDefined = $propertyMapping->target->readAccessor->getIsDefinedExpression(new Expr\Variable('result'));
44+
$existingValue = $propertyMapping->target->readAccessor->getExpression(new Expr\Variable('result'));
45+
46+
if (null !== $isDefined) {
47+
$existingValue = new Expr\Ternary(
48+
$isDefined,
49+
$existingValue,
50+
new Expr\ConstFetch(new Name('null'))
51+
);
52+
}
53+
4354
$newContextArgs[] = new Arg(
4455
new Expr\Ternary(
4556
new Expr\BinaryOp\Coalesce(
4657
new Expr\ArrayDimFetch(new Expr\Variable('context'), new Scalar\String_(MapperContext::DEEP_TARGET_TO_POPULATE)),
4758
new Expr\ConstFetch(new Name('false'))
4859
),
49-
$propertyMapping->target->readAccessor->getExpression(new Expr\Variable('result')),
60+
$existingValue,
5061
new Expr\ConstFetch(new Name('null'))
5162
)
5263
);

tests/AutoMapperTest/ArrayConsistency/map.php

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
namespace AutoMapper\Tests\AutoMapperTest\ArrayConsistency;
66

7+
use AutoMapper\MapperContext;
78
use AutoMapper\Tests\AutoMapperBuilder;
89
use Doctrine\Common\Collections\ArrayCollection;
910
use Doctrine\Common\Collections\Collection;
@@ -102,11 +103,11 @@ public function getValues(): Collection
102103
$toCollection->values->add(5);
103104
$toCollection->values->add(6);
104105

105-
yield 'to' => $autoMapper->map($from, $to);
106+
yield 'to' => $autoMapper->map($from, $to, [MapperContext::DEEP_TARGET_TO_POPULATE => false]);
106107

107-
yield 'toAdder' => $autoMapper->map($from, $toAdder);
108+
yield 'toAdder' => $autoMapper->map($from, $toAdder, [MapperContext::DEEP_TARGET_TO_POPULATE => false]);
108109

109-
yield 'toAdderCollection' => $autoMapper->map($from, $toAdderCollection);
110+
yield 'toAdderCollection' => $autoMapper->map($from, $toAdderCollection, [MapperContext::DEEP_TARGET_TO_POPULATE => false]);
110111

111-
yield 'toCollection' => $autoMapper->map($from, $toCollection);
112+
yield 'toCollection' => $autoMapper->map($from, $toCollection, [MapperContext::DEEP_TARGET_TO_POPULATE => false]);
112113
})();

0 commit comments

Comments
 (0)