Skip to content

Commit 91ab23c

Browse files
committed
fix(discriminator): don't use target to populate when there is a discriminator on target
1 parent 946a77e commit 91ab23c

File tree

5 files changed

+74
-10
lines changed

5 files changed

+74
-10
lines changed

src/Generator/CreateTargetStatementsGenerator.php

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,10 @@ public function __construct(
4040
* ... // create object statements
4141
* }
4242
* ```
43+
*
44+
* @return list<Stmt>
4345
*/
44-
public function generate(GeneratorMetadata $metadata, VariableRegistry $variableRegistry): Stmt
46+
public function generate(GeneratorMetadata $metadata, VariableRegistry $variableRegistry): array
4547
{
4648
$createObjectStatements = [];
4749

@@ -56,9 +58,18 @@ public function generate(GeneratorMetadata $metadata, VariableRegistry $variable
5658

5759
$createObjectStatements = array_values(array_filter($createObjectStatements));
5860

59-
return new Stmt\If_(new Expr\BinaryOp\Identical(new Expr\ConstFetch(new Name('null')), $variableRegistry->getResult()), [
60-
'stmts' => $createObjectStatements,
61-
]);
61+
if ($this->canUseTargetToPopulate($metadata)) {
62+
return [new Stmt\If_(new Expr\BinaryOp\Identical(new Expr\ConstFetch(new Name('null')), $variableRegistry->getResult()), [
63+
'stmts' => $createObjectStatements,
64+
])];
65+
}
66+
67+
return $createObjectStatements;
68+
}
69+
70+
public function canUseTargetToPopulate(GeneratorMetadata $metadata): bool
71+
{
72+
return !$this->discriminatorStatementsGeneratorTarget->supports($metadata);
6273
}
6374

6475
private function targetAsArray(GeneratorMetadata $metadata): ?Stmt

src/Generator/MapMethodStatementsGenerator.php

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -52,9 +52,13 @@ public function getStatements(GeneratorMetadata $metadata): array
5252

5353
$statements = [$this->ifSourceIsNullReturnNull($metadata)];
5454
$statements = [...$statements, ...$this->handleCircularReference($metadata)];
55-
$statements = [...$statements, ...$this->initializeTargetToPopulate($metadata)];
56-
$statements = [...$statements, ...$this->initializeTargetFromProvider($metadata)];
57-
$statements[] = $this->createObjectStatementsGenerator->generate($metadata, $variableRegistry);
55+
56+
if ($this->createObjectStatementsGenerator->canUseTargetToPopulate($metadata)) {
57+
$statements = [...$statements, ...$this->initializeTargetToPopulate($metadata)];
58+
$statements = [...$statements, ...$this->initializeTargetFromProvider($metadata)];
59+
}
60+
61+
$statements = [...$statements, ...$this->createObjectStatementsGenerator->generate($metadata, $variableRegistry)];
5862

5963
$addedDependenciesStatements = $this->handleDependencies($metadata);
6064

src/Generator/Shared/DiscriminatorStatementsGenerator.php

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -122,8 +122,7 @@ public function createTargetStatements(GeneratorMetadata $metadata): array
122122
if (!$isDefinedExpression) {
123123
return $discriminateStatements;
124124
}
125-
$cannotCreateTarget = ($metadata->mapperMetadata->targetReflectionClass?->isAbstract()
126-
|| $metadata->mapperMetadata->targetReflectionClass?->isInterface()) ?? false;
125+
$cannotCreateTarget = !($metadata->mapperMetadata->targetReflectionClass === null) && !$metadata->mapperMetadata->targetReflectionClass->isInstantiable();
127126

128127
$if = new Stmt\If_($isDefinedExpression, [
129128
'stmts' => $discriminateStatements,
@@ -140,7 +139,7 @@ public function createTargetStatements(GeneratorMetadata $metadata): array
140139
return $statements;
141140
}
142141

143-
private function supports(GeneratorMetadata $metadata): bool
142+
public function supports(GeneratorMetadata $metadata): bool
144143
{
145144
if (!$this->classDiscriminatorResolver->hasClassDiscriminator($metadata, $this->fromSource)) {
146145
return false;
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
AutoMapper\Tests\AutoMapperTest\DiscriminatorPopulate\LinkWrapper {
2+
+link: AutoMapper\Tests\AutoMapperTest\DiscriminatorPopulate\DefaultLinkType {
3+
+link: "https://example.com/new"
4+
+description: "description"
5+
}
6+
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace AutoMapper\Tests\AutoMapperTest\DiscriminatorPopulate;
6+
7+
use AutoMapper\MapperContext;
8+
use AutoMapper\Tests\AutoMapperBuilder;
9+
use Symfony\Component\Serializer\Attribute\DiscriminatorMap;
10+
11+
#[DiscriminatorMap('linkType', [
12+
'default' => DefaultLinkType::class,
13+
])]
14+
abstract class LinkType
15+
{
16+
}
17+
18+
class DefaultLinkType extends LinkType
19+
{
20+
public function __construct(
21+
public string $link,
22+
public string $description = 'default',
23+
) {
24+
}
25+
}
26+
27+
class LinkWrapper
28+
{
29+
public function __construct(
30+
public LinkType $link,
31+
) {
32+
}
33+
}
34+
35+
$source = [
36+
'link' => [
37+
'linkType' => 'default',
38+
'link' => 'https://example.com/new',
39+
],
40+
];
41+
42+
$existingData = new LinkWrapper(new DefaultLinkType('https://example.com/old', 'description'));
43+
44+
return AutoMapperBuilder::buildAutoMapper()->map($source, $existingData, [MapperContext::DEEP_TARGET_TO_POPULATE => true]);

0 commit comments

Comments
 (0)