From 7a3c92f2634a4a3cca2bab5a3803552bbbac0739 Mon Sep 17 00:00:00 2001 From: Matthias Schmidt Date: Thu, 19 Jun 2025 11:03:54 +0200 Subject: [PATCH] [ObjectMapper] Fix parameter passed to class level transform Fixes #60827 --- .../Component/ObjectMapper/ObjectMapper.php | 2 +- .../InstanceCallbackWithArguments/A.php | 19 +++++++++++++ .../InstanceCallbackWithArguments/B.php | 27 +++++++++++++++++++ .../ObjectMapper/Tests/ObjectMapperTest.php | 12 +++++++++ 4 files changed, 59 insertions(+), 1 deletion(-) create mode 100644 src/Symfony/Component/ObjectMapper/Tests/Fixtures/InstanceCallbackWithArguments/A.php create mode 100644 src/Symfony/Component/ObjectMapper/Tests/Fixtures/InstanceCallbackWithArguments/B.php diff --git a/src/Symfony/Component/ObjectMapper/ObjectMapper.php b/src/Symfony/Component/ObjectMapper/ObjectMapper.php index d78bc3ce8d216..69f02fb7f1160 100644 --- a/src/Symfony/Component/ObjectMapper/ObjectMapper.php +++ b/src/Symfony/Component/ObjectMapper/ObjectMapper.php @@ -70,7 +70,7 @@ public function map(object $source, object|string|null $target = null): object $mappedTarget = $mappingToObject ? $target : $targetRefl->newInstanceWithoutConstructor(); if ($map && $map->transform) { - $mappedTarget = $this->applyTransforms($map, $mappedTarget, $mappedTarget, null); + $mappedTarget = $this->applyTransforms($map, $mappedTarget, $source, null); if (!\is_object($mappedTarget)) { throw new MappingTransformException(\sprintf('Cannot map "%s" to a non-object target of type "%s".', get_debug_type($source), get_debug_type($mappedTarget))); diff --git a/src/Symfony/Component/ObjectMapper/Tests/Fixtures/InstanceCallbackWithArguments/A.php b/src/Symfony/Component/ObjectMapper/Tests/Fixtures/InstanceCallbackWithArguments/A.php new file mode 100644 index 0000000000000..77ab0c3a3a76e --- /dev/null +++ b/src/Symfony/Component/ObjectMapper/Tests/Fixtures/InstanceCallbackWithArguments/A.php @@ -0,0 +1,19 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\ObjectMapper\Tests\Fixtures\InstanceCallbackWithArguments; + +use Symfony\Component\ObjectMapper\Attribute\Map; + +#[Map(target: B::class, transform: [B::class, 'newInstance'])] +class A +{ +} diff --git a/src/Symfony/Component/ObjectMapper/Tests/Fixtures/InstanceCallbackWithArguments/B.php b/src/Symfony/Component/ObjectMapper/Tests/Fixtures/InstanceCallbackWithArguments/B.php new file mode 100644 index 0000000000000..b5ea60066b59f --- /dev/null +++ b/src/Symfony/Component/ObjectMapper/Tests/Fixtures/InstanceCallbackWithArguments/B.php @@ -0,0 +1,27 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\ObjectMapper\Tests\Fixtures\InstanceCallbackWithArguments; + +class B +{ + public mixed $transformValue; + public object $transformSource; + + public static function newInstance(mixed $value, object $source): self + { + $b = new self(); + $b->transformValue = $value; + $b->transformSource = $source; + + return $b; + } +} diff --git a/src/Symfony/Component/ObjectMapper/Tests/ObjectMapperTest.php b/src/Symfony/Component/ObjectMapper/Tests/ObjectMapperTest.php index a416abd47933b..ab8aa7f74aaa3 100644 --- a/src/Symfony/Component/ObjectMapper/Tests/ObjectMapperTest.php +++ b/src/Symfony/Component/ObjectMapper/Tests/ObjectMapperTest.php @@ -34,6 +34,8 @@ use Symfony\Component\ObjectMapper\Tests\Fixtures\HydrateObject\SourceOnly; use Symfony\Component\ObjectMapper\Tests\Fixtures\InstanceCallback\A as InstanceCallbackA; use Symfony\Component\ObjectMapper\Tests\Fixtures\InstanceCallback\B as InstanceCallbackB; +use Symfony\Component\ObjectMapper\Tests\Fixtures\InstanceCallbackWithArguments\A as InstanceCallbackWithArgumentsA; +use Symfony\Component\ObjectMapper\Tests\Fixtures\InstanceCallbackWithArguments\B as InstanceCallbackWithArgumentsB; use Symfony\Component\ObjectMapper\Tests\Fixtures\MapStruct\AToBMapper; use Symfony\Component\ObjectMapper\Tests\Fixtures\MapStruct\MapStructMapperMetadataFactory; use Symfony\Component\ObjectMapper\Tests\Fixtures\MapStruct\Source; @@ -155,6 +157,16 @@ public function testMapToWithInstanceHook() $this->assertSame($b->name, 'test'); } + public function testMapToWithInstanceHookWithArguments() + { + $a = new InstanceCallbackWithArgumentsA(); + $mapper = new ObjectMapper(); + $b = $mapper->map($a); + $this->assertInstanceOf(InstanceCallbackWithArgumentsB::class, $b); + $this->assertSame($a, $b->transformSource); + $this->assertInstanceOf(InstanceCallbackWithArgumentsB::class, $b->transformValue); + } + public function testMapStruct() { $a = new Source('a', 'b', 'c');