@@ -32,7 +32,7 @@ final class ObjectMapper implements ObjectMapperInterface, ObjectMapperAwareInte
3232 /**
3333 * Tracks recursive references.
3434 */
35- private \WeakMap $ objectMap ;
35+ private ? \WeakMap $ objectMap = null ;
3636
3737 public function __construct (
3838 private readonly ObjectMapperMetadataFactoryInterface $ metadataFactory = new ReflectionObjectMapperMetadataFactory (),
@@ -41,10 +41,23 @@ public function __construct(
4141 private readonly ?ContainerInterface $ conditionCallableLocator = null ,
4242 private ?ObjectMapperInterface $ objectMapper = null ,
4343 ) {
44- $ this ->objectMap = new \WeakMap ();
4544 }
4645
4746 public function map (object $ source , object |string |null $ target = null ): object
47+ {
48+ if ($ this ->objectMap ) {
49+ return $ this ->doMap ($ source , $ target , $ this ->objectMap , false );
50+ }
51+
52+ $ this ->objectMap = new \WeakMap ();
53+ try {
54+ return $ this ->doMap ($ source , $ target , $ this ->objectMap , true );
55+ } finally {
56+ $ this ->objectMap = null ;
57+ }
58+ }
59+
60+ private function doMap (object $ source , object |string |null $ target , \WeakMap $ objectMap , bool $ rootCall ): object
4861 {
4962 $ metadata = $ this ->metadataFactory ->create ($ source );
5063 $ map = $ this ->getMapTarget ($ metadata , null , $ source , null );
@@ -84,7 +97,7 @@ public function map(object $source, object|string|null $target = null): object
8497 throw new MappingException (\sprintf ('Expected the mapped object to be an instance of "%s" but got "%s". ' , $ targetRefl ->getName (), get_debug_type ($ mappedTarget )));
8598 }
8699
87- $ this -> objectMap [$ source ] = $ mappedTarget ;
100+ $ objectMap [$ source ] = $ mappedTarget ;
88101 $ ctorArguments = [];
89102 $ targetConstructor = $ targetRefl ->getConstructor ();
90103 foreach ($ targetConstructor ?->getParameters() ?? [] as $ parameter ) {
@@ -141,7 +154,7 @@ public function map(object $source, object|string|null $target = null): object
141154 continue ;
142155 }
143156
144- $ value = $ this ->getSourceValue ($ source , $ mappedTarget , $ value , $ this -> objectMap , $ mapping );
157+ $ value = $ this ->getSourceValue ($ source , $ mappedTarget , $ value , $ objectMap , $ mapping );
145158 $ this ->storeValue ($ targetPropertyName , $ mapToProperties , $ ctorArguments , $ value );
146159 }
147160
@@ -151,7 +164,7 @@ public function map(object $source, object|string|null $target = null): object
151164 continue ;
152165 }
153166
154- $ value = $ this ->getSourceValue ($ source , $ mappedTarget , $ this ->getRawValue ($ source , $ propertyName ), $ this -> objectMap );
167+ $ value = $ this ->getSourceValue ($ source , $ mappedTarget , $ this ->getRawValue ($ source , $ propertyName ), $ objectMap );
155168 $ this ->storeValue ($ propertyName , $ mapToProperties , $ ctorArguments , $ value );
156169 }
157170 }
@@ -233,8 +246,14 @@ private function getSourceValue(object $source, object $target, mixed $value, \W
233246 $ refl = new \ReflectionClass ($ mapTo ->target );
234247 $ mapper = $ this ->objectMapper ?? $ this ;
235248
236- return $ refl ->newLazyProxy (static function () use ($ mapper , $ value , $ objectMap , $ mapTo ) {
237- return $ objectMap [$ value ] = $ mapper ->map ($ value , $ mapTo ->target );
249+ return $ refl ->newLazyProxy (function () use ($ mapper , $ value , $ objectMap , $ mapTo ) {
250+ $ previousMap = $ this ->objectMap ;
251+ $ this ->objectMap = $ objectMap ;
252+ try {
253+ return $ objectMap [$ value ] = $ mapper ->map ($ value , $ mapTo ->target );
254+ } finally {
255+ $ this ->objectMap = $ previousMap ;
256+ }
238257 });
239258 }
240259 }
0 commit comments