Skip to content

Commit 079f8b3

Browse files
Merge branch '7.4' into 8.0
* 7.4: Fix merge [WebProfiler] fix the security profiler template add tests for bypassed headers [Scheduler] Array to string conversion when using AsCronTask with array options [Config] Fix merging node that canBeDisable()/canBeEnabled() [ObjectMapper] error when multiple targets and no condition
2 parents ffb1dbc + 4429481 commit 079f8b3

File tree

6 files changed

+66
-4
lines changed

6 files changed

+66
-4
lines changed

ObjectMapper.php

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ public function map(object $source, object|string|null $target = null): object
6060
private function doMap(object $source, object|string|null $target, \WeakMap $objectMap, bool $rootCall): object
6161
{
6262
$metadata = $this->metadataFactory->create($source);
63-
$map = $this->getMapTarget($metadata, null, $source, null);
63+
$map = $this->getMapTarget($metadata, null, $source, null, null === $target);
6464
$target ??= $map?->target;
6565
$mappingToObject = \is_object($target);
6666

@@ -82,7 +82,7 @@ private function doMap(object $source, object|string|null $target, \WeakMap $obj
8282

8383
if (!$metadata && $targetMetadata = $this->metadataFactory->create($mappedTarget)) {
8484
$metadata = $targetMetadata;
85-
$map = $this->getMapTarget($metadata, null, $source, null);
85+
$map = $this->getMapTarget($metadata, null, $source, null, false);
8686
}
8787

8888
if ($map && $map->transform) {
@@ -243,7 +243,7 @@ private function getSourceValue(object $source, object $target, mixed $value, \W
243243
if (
244244
\is_object($value)
245245
&& ($innerMetadata = $this->metadataFactory->create($value))
246-
&& ($mapTo = $this->getMapTarget($innerMetadata, $value, $source, $target))
246+
&& ($mapTo = $this->getMapTarget($innerMetadata, $value, $source, $target, true))
247247
&& (\is_string($mapTo->target) && class_exists($mapTo->target))
248248
) {
249249
$value = $this->applyTransforms($mapTo, $value, $source, $target);
@@ -307,14 +307,18 @@ private function call(callable $fn, mixed $value, object $source, ?object $targe
307307
/**
308308
* @param Mapping[] $metadata
309309
*/
310-
private function getMapTarget(array $metadata, mixed $value, object $source, ?object $target): ?Mapping
310+
private function getMapTarget(array $metadata, mixed $value, object $source, ?object $target, bool $enforceUnique = false): ?Mapping
311311
{
312312
$mapTo = null;
313313
foreach ($metadata as $mapAttribute) {
314314
if (($if = $mapAttribute->if) && ($fn = $this->getCallable($if, $this->conditionCallableLocator)) && !$this->call($fn, $value, $source, $target)) {
315315
continue;
316316
}
317317

318+
if ($enforceUnique && null !== $mapTo) {
319+
throw new MappingException(\sprintf('Ambiguous mapping for "%s". Multiple #[Map] attributes match. Use the "if" parameter to specify conditions.', get_debug_type($value ?? $source)));
320+
}
321+
318322
$mapTo = $mapAttribute;
319323
}
320324

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<?php
2+
3+
namespace Symfony\Component\ObjectMapper\Tests\Fixtures\NestedMapping;
4+
5+
use Symfony\Component\ObjectMapper\Attribute\Map;
6+
7+
#[Map(target: NestedSourceB::class)]
8+
class NestedSourceA
9+
{
10+
public function __construct(
11+
public string $foo,
12+
public string $bar,
13+
) {
14+
}
15+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<?php
2+
3+
namespace Symfony\Component\ObjectMapper\Tests\Fixtures\NestedMapping;
4+
5+
class NestedSourceB
6+
{
7+
public function __construct(
8+
public string $foo,
9+
) {
10+
}
11+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<?php
2+
3+
namespace Symfony\Component\ObjectMapper\Tests\Fixtures\NestedMapping;
4+
5+
class Source
6+
{
7+
public function __construct(
8+
public NestedSourceA $item,
9+
) {
10+
}
11+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<?php
2+
3+
namespace Symfony\Component\ObjectMapper\Tests\Fixtures\NestedMapping;
4+
5+
class TargetUnion
6+
{
7+
public function __construct(
8+
public NestedSourceA|NestedSourceB $item,
9+
) {
10+
}
11+
}

Tests/ObjectMapperTest.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -669,4 +669,14 @@ public function testMissingSourcePropertiesAreIgnored()
669669
'Property without default value should remain uninitialized'
670670
);
671671
}
672+
673+
public function testMultipleTargetsWithoutConditionThrowsExceptionWhenNoTargetProvided()
674+
{
675+
$this->expectException(MappingException::class);
676+
$this->expectExceptionMessage('Ambiguous mapping');
677+
678+
$source = new MultipleTargetPropertyA();
679+
$mapper = new ObjectMapper();
680+
$mapper->map($source);
681+
}
672682
}

0 commit comments

Comments
 (0)