Skip to content

Commit d6ff8d1

Browse files
committed
[ObjectMapper] allow owning ObjectMapper object
1 parent 501ec09 commit d6ff8d1

File tree

4 files changed

+83
-2
lines changed

4 files changed

+83
-2
lines changed

src/Symfony/Component/ObjectMapper/CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
CHANGELOG
22
=========
33

4+
7.4
5+
---
6+
7+
* Add `ObjectMapperAwareInterface` to set the owning object mapper instance
8+
49
7.3
510
---
611

src/Symfony/Component/ObjectMapper/ObjectMapper.php

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
*
2929
* @author Antoine Bluchet <[email protected]>
3030
*/
31-
final class ObjectMapper implements ObjectMapperInterface
31+
final class ObjectMapper implements ObjectMapperInterface, ObjectMapperAwareInterface
3232
{
3333
/**
3434
* Tracks recursive references.
@@ -40,6 +40,7 @@ public function __construct(
4040
private readonly ?PropertyAccessorInterface $propertyAccessor = null,
4141
private readonly ?ContainerInterface $transformCallableLocator = null,
4242
private readonly ?ContainerInterface $conditionCallableLocator = null,
43+
private ?ObjectMapperInterface $objectMapper = null,
4344
) {
4445
}
4546

@@ -211,7 +212,7 @@ private function getSourceValue(object $source, object $target, mixed $value, \S
211212
} elseif ($objectMap->contains($value)) {
212213
$value = $objectMap[$value];
213214
} else {
214-
$value = $this->map($value, $mapTo->target);
215+
$value = ($this->objectMapper ?? $this)->map($value, $mapTo->target);
215216
}
216217
}
217218

@@ -327,4 +328,12 @@ private function getSourceReflectionClass(object $source, \ReflectionClass $targ
327328

328329
return $targetRefl;
329330
}
331+
332+
public function withObjectMapper(ObjectMapperInterface $objectMapper): static
333+
{
334+
$clone = clone $this;
335+
$clone->objectMapper = $objectMapper;
336+
337+
return $clone;
338+
}
330339
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\ObjectMapper;
13+
14+
/**
15+
* @experimental
16+
*
17+
* @author Antoine Bluchet <[email protected]>
18+
*/
19+
interface ObjectMapperAwareInterface
20+
{
21+
/**
22+
* Sets the owning ObjectMapper object.
23+
*/
24+
public function withObjectMapper(ObjectMapperInterface $objectMapper): static;
25+
}

src/Symfony/Component/ObjectMapper/Tests/ObjectMapperTest.php

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -368,4 +368,46 @@ public static function objectMapperProvider(): iterable
368368
yield [new ObjectMapper()];
369369
yield [new ObjectMapper(new ReflectionObjectMapperMetadataFactory(), PropertyAccess::createPropertyAccessor())];
370370
}
371+
372+
public function testDecorateObjectMapper()
373+
{
374+
$mapper = new ObjectMapper();
375+
$myMapper = new class($mapper) implements ObjectMapperInterface {
376+
private ?\SplObjectStorage $embededMap = null;
377+
378+
public function __construct(private readonly ObjectMapperInterface $mapper)
379+
{
380+
$this->embededMap = new \SplObjectStorage();
381+
}
382+
383+
public function map(object $source, object|string|null $target = null): object
384+
{
385+
if (isset($this->embededMap[$source])) {
386+
$target = $this->embededMap[$source];
387+
}
388+
389+
$mapped = $this->mapper->map($source, $target);
390+
$this->embededMap[$source] = $mapped;
391+
392+
return $mapped;
393+
}
394+
};
395+
396+
$mapper = $mapper->withObjectMapper($myMapper);
397+
398+
$d = new D(baz: 'foo', bat: 'bar');
399+
$c = new C(foo: 'foo', bar: 'bar');
400+
$myNewD = $myMapper->map($c);
401+
402+
$a = new A();
403+
$a->foo = 'test';
404+
$a->transform = 'test';
405+
$a->baz = 'me';
406+
$a->notinb = 'test';
407+
$a->relation = $c;
408+
$a->relationNotMapped = $d;
409+
410+
$b = $mapper->map($a);
411+
$this->assertSame($myNewD, $b->relation);
412+
}
371413
}

0 commit comments

Comments
 (0)