1616use Patchlevel \Hydrator \Metadata \ClassNotFound ;
1717use Patchlevel \Hydrator \Metadata \MetadataFactory ;
1818use Patchlevel \Hydrator \Normalizer \HydratorAwareNormalizer ;
19+ use Patchlevel \Hydrator \Normalizer \NormalizerWithContext ;
1920use ReflectionClass ;
2021use ReflectionParameter ;
2122use Symfony \Component \EventDispatcher \EventDispatcher ;
3031
3132use const PHP_VERSION_ID ;
3233
33- final class MetadataHydrator implements Hydrator
34+ final class MetadataHydrator implements HydratorWithContext
3435{
3536 /** @var array<int, class-string> */
3637 private array $ stack = [];
@@ -57,12 +58,13 @@ public function __construct(
5758 /**
5859 * @param class-string<T> $class
5960 * @param array<string, mixed> $data
61+ * @param array<string, mixed> $context
6062 *
6163 * @return T
6264 *
6365 * @template T of object
6466 */
65- public function hydrate (string $ class , array $ data ): object
67+ public function hydrate (string $ class , array $ data, array $ context = [] ): object
6668 {
6769 try {
6870 $ metadata = $ this ->metadataFactory ->metadata ($ class );
@@ -71,31 +73,32 @@ public function hydrate(string $class, array $data): object
7173 }
7274
7375 if (PHP_VERSION_ID < 80400 ) {
74- return $ this ->doHydrate ($ metadata , $ data );
76+ return $ this ->doHydrate ($ metadata , $ data, $ context );
7577 }
7678
7779 $ lazy = $ metadata ->lazy () ?? $ this ->defaultLazy ;
7880
7981 if (!$ lazy ) {
80- return $ this ->doHydrate ($ metadata , $ data );
82+ return $ this ->doHydrate ($ metadata , $ data, $ context );
8183 }
8284
8385 return (new ReflectionClass ($ class ))->newLazyProxy (
84- function () use ($ metadata , $ data ): object {
85- return $ this ->doHydrate ($ metadata , $ data );
86+ function () use ($ metadata , $ data, $ context ): object {
87+ return $ this ->doHydrate ($ metadata , $ data, $ context );
8688 },
8789 );
8890 }
8991
9092 /**
9193 * @param ClassMetadata<T> $metadata
9294 * @param array<string, mixed> $data
95+ * @param array<string, mixed> $context
9396 *
9497 * @return T
9598 *
9699 * @template T of object
97100 */
98- private function doHydrate (ClassMetadata $ metadata , array $ data ): object
101+ private function doHydrate (ClassMetadata $ metadata , array $ data, array $ context = [] ): object
99102 {
100103 if ($ this ->eventDispatcher ) {
101104 $ data = $ this ->eventDispatcher ->dispatch (new PreHydrate ($ data , $ metadata ))->data ;
@@ -138,7 +141,11 @@ private function doHydrate(ClassMetadata $metadata, array $data): object
138141
139142 try {
140143 /** @psalm-suppress MixedAssignment */
141- $ value = $ normalizer ->denormalize ($ value );
144+ if ($ normalizer instanceof NormalizerWithContext) {
145+ $ value = $ normalizer ->denormalize ($ value , $ context );
146+ } else {
147+ $ value = $ normalizer ->denormalize ($ value );
148+ }
142149 } catch (Throwable $ e ) {
143150 throw new DenormalizationFailure (
144151 $ metadata ->className (),
@@ -167,8 +174,12 @@ private function doHydrate(ClassMetadata $metadata, array $data): object
167174 return $ object ;
168175 }
169176
170- /** @return array<string, mixed> */
171- public function extract (object $ object ): array
177+ /**
178+ * @param array<string, mixed> $context
179+ *
180+ * @return array<string, mixed>
181+ */
182+ public function extract (object $ object , array $ context = []): array
172183 {
173184 $ objectId = spl_object_id ($ object );
174185
@@ -202,11 +213,18 @@ public function extract(object $object): array
202213 }
203214
204215 try {
205- /** @psalm-suppress MixedAssignment */
206- $ value = $ normalizer ->normalize ($ value );
207- } catch (CircularReference $ e ) {
208- throw $ e ;
216+ if ($ normalizer instanceof NormalizerWithContext) {
217+ /** @psalm-suppress MixedAssignment */
218+ $ value = $ normalizer ->normalize ($ value , $ context );
219+ } else {
220+ /** @psalm-suppress MixedAssignment */
221+ $ value = $ normalizer ->normalize ($ value );
222+ }
209223 } catch (Throwable $ e ) {
224+ if ($ e instanceof CircularReference) {
225+ throw $ e ;
226+ }
227+
210228 throw new NormalizationFailure (
211229 $ object ::class,
212230 $ propertyMetadata ->propertyName (),
0 commit comments