Skip to content

Commit 478e9be

Browse files
committed
add context feature
1 parent 5a37a76 commit 478e9be

File tree

8 files changed

+99
-37
lines changed

8 files changed

+99
-37
lines changed

src/Cryptography/CryptographyMiddleware.php

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,33 +18,36 @@ public function __construct(
1818
/**
1919
* @param ClassMetadata<T> $metadata
2020
* @param array<string, mixed> $data
21+
* @param array<string, mixed> $context
2122
*
2223
* @return T
2324
*
2425
* @template T of object
2526
*/
26-
public function hydrate(ClassMetadata $metadata, array $data, Stack $stack): object
27+
public function hydrate(ClassMetadata $metadata, array $data, array $context, Stack $stack): object
2728
{
2829
return $stack->next()->hydrate(
2930
$metadata,
3031
$this->cryptography->decrypt($metadata, $data),
32+
$context,
3133
$stack,
3234
);
3335
}
3436

3537
/**
3638
* @param ClassMetadata<T> $metadata
3739
* @param T $object
40+
* @param array<string, mixed> $context
3841
*
3942
* @return array<string, mixed>
4043
*
4144
* @template T of object
4245
*/
43-
public function extract(ClassMetadata $metadata, object $object, Stack $stack): array
46+
public function extract(ClassMetadata $metadata, object $object, array $context, Stack $stack): array
4447
{
4548
return $this->cryptography->encrypt(
4649
$metadata,
47-
$stack->next()->extract($metadata, $object, $stack),
50+
$stack->next()->extract($metadata, $object, $context, $stack),
4851
);
4952
}
5053
}

src/Hydrator.php

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,20 @@ interface Hydrator
99
/**
1010
* @param class-string<T> $class
1111
* @param array<string, mixed> $data
12+
* @param array<string, mixed> $context
1213
*
1314
* @return T
1415
*
1516
* @throws ClassNotSupported if the class is not supported or not found.
1617
*
1718
* @template T of object
1819
*/
19-
public function hydrate(string $class, array $data): object;
20+
public function hydrate(string $class, array $data, array $context = []): object;
2021

21-
/** @return array<string, mixed> */
22-
public function extract(object $object): array;
22+
/**
23+
* @param array<string, mixed> $context
24+
*
25+
* @return array<string, mixed>
26+
*/
27+
public function extract(object $object, array $context = []): array;
2328
}

src/MetadataHydrator.php

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -37,12 +37,13 @@ public function __construct(
3737
/**
3838
* @param class-string<T> $class
3939
* @param array<string, mixed> $data
40+
* @param array<string, mixed> $context
4041
*
4142
* @return T
4243
*
4344
* @template T of object
4445
*/
45-
public function hydrate(string $class, array $data): object
46+
public function hydrate(string $class, array $data, array $context = []): object
4647
{
4748
try {
4849
$metadata = $this->metadata($class);
@@ -53,33 +54,37 @@ public function hydrate(string $class, array $data): object
5354
if (PHP_VERSION_ID < 80400) {
5455
$stack = new Stack($this->middlewares);
5556

56-
return $stack->next()->hydrate($metadata, $data, $stack);
57+
return $stack->next()->hydrate($metadata, $data, $context, $stack);
5758
}
5859

5960
$lazy = $metadata->lazy ?? $this->defaultLazy;
6061

6162
if (!$lazy) {
6263
$stack = new Stack($this->middlewares);
6364

64-
return $stack->next()->hydrate($metadata, $data, $stack);
65+
return $stack->next()->hydrate($metadata, $data, $context, $stack);
6566
}
6667

6768
return (new ReflectionClass($class))->newLazyProxy(
68-
function () use ($metadata, $data): object {
69+
function () use ($metadata, $data, $context): object {
6970
$stack = new Stack($this->middlewares);
7071

71-
return $stack->next()->hydrate($metadata, $data, $stack);
72+
return $stack->next()->hydrate($metadata, $data, $context, $stack);
7273
},
7374
);
7475
}
7576

76-
/** @return array<string, mixed> */
77-
public function extract(object $object): array
77+
/**
78+
* @param array<string, mixed> $context
79+
*
80+
* @return array<string, mixed>
81+
*/
82+
public function extract(object $object, array $context = []): array
7883
{
7984
$metadata = $this->metadata($object::class);
8085
$stack = new Stack($this->middlewares);
8186

82-
return $stack->next()->extract($metadata, $object, $stack);
87+
return $stack->next()->extract($metadata, $object, $context, $stack);
8388
}
8489

8590
/**

src/Middleware/Middleware.php

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,20 +11,22 @@ interface Middleware
1111
/**
1212
* @param ClassMetadata<T> $metadata
1313
* @param array<string, mixed> $data
14+
* @param array<string, mixed> $context
1415
*
1516
* @return T
1617
*
1718
* @template T of object
1819
*/
19-
public function hydrate(ClassMetadata $metadata, array $data, Stack $stack): object;
20+
public function hydrate(ClassMetadata $metadata, array $data, array $context, Stack $stack): object;
2021

2122
/**
22-
* @param ClassMetadata<T> $metadata
23-
* @param T $object
23+
* @param ClassMetadata<T> $metadata
24+
* @param T $object
25+
* @param array<string, mixed> $context
2426
*
2527
* @return array<string, mixed>
2628
*
2729
* @template T of object
2830
*/
29-
public function extract(ClassMetadata $metadata, object $object, Stack $stack): array;
31+
public function extract(ClassMetadata $metadata, object $object, array $context, Stack $stack): array;
3032
}

src/Middleware/TransformMiddleware.php

Lines changed: 29 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
use Patchlevel\Hydrator\DenormalizationFailure;
99
use Patchlevel\Hydrator\Metadata\ClassMetadata;
1010
use Patchlevel\Hydrator\NormalizationFailure;
11+
use Patchlevel\Hydrator\Normalizer\ContextAwareNormalizer;
1112
use Patchlevel\Hydrator\TypeMismatch;
1213
use ReflectionParameter;
1314
use Throwable;
@@ -25,12 +26,13 @@ final class TransformMiddleware implements Middleware
2526
/**
2627
* @param ClassMetadata<T> $metadata
2728
* @param array<string, mixed> $data
29+
* @param array<string, mixed> $context
2830
*
2931
* @return T
3032
*
3133
* @template T of object
3234
*/
33-
public function hydrate(ClassMetadata $metadata, array $data, Stack $stack): object
35+
public function hydrate(ClassMetadata $metadata, array $data, array $context, Stack $stack): object
3436
{
3537
$object = $metadata->newInstance();
3638

@@ -62,8 +64,14 @@ public function hydrate(ClassMetadata $metadata, array $data, Stack $stack): obj
6264

6365
if ($normalizer) {
6466
try {
65-
/** @psalm-suppress MixedAssignment */
66-
$value = $normalizer->denormalize($data[$propertyMetadata->fieldName]);
67+
if ($propertyMetadata->normalizer instanceof ContextAwareNormalizer) {
68+
/** @psalm-suppress MixedAssignment */
69+
$value = $normalizer->denormalize($data[$propertyMetadata->fieldName], $context);
70+
71+
} else {
72+
/** @psalm-suppress MixedAssignment */
73+
$value = $normalizer->denormalize($data[$propertyMetadata->fieldName]);
74+
}
6775
} catch (Throwable $e) {
6876
throw new DenormalizationFailure(
6977
$metadata->className,
@@ -90,8 +98,12 @@ public function hydrate(ClassMetadata $metadata, array $data, Stack $stack): obj
9098
return $object;
9199
}
92100

93-
/** @return array<string, mixed> */
94-
public function extract(ClassMetadata $metadata, object $object, Stack $stack): array
101+
/**
102+
* @param array<string, mixed> $context
103+
*
104+
* @return array<string, mixed>
105+
*/
106+
public function extract(ClassMetadata $metadata, object $object, array $context, Stack $stack): array
95107
{
96108
$objectId = spl_object_id($object);
97109

@@ -110,10 +122,18 @@ public function extract(ClassMetadata $metadata, object $object, Stack $stack):
110122
foreach ($metadata->properties as $propertyMetadata) {
111123
if ($propertyMetadata->normalizer) {
112124
try {
113-
/** @psalm-suppress MixedAssignment */
114-
$data[$propertyMetadata->fieldName] = $propertyMetadata->normalizer->normalize(
115-
$propertyMetadata->getValue($object),
116-
);
125+
if ($propertyMetadata->normalizer instanceof ContextAwareNormalizer) {
126+
/** @psalm-suppress MixedAssignment */
127+
$data[$propertyMetadata->fieldName] = $propertyMetadata->normalizer->normalize(
128+
$propertyMetadata->getValue($object),
129+
$context,
130+
);
131+
} else {
132+
/** @psalm-suppress MixedAssignment */
133+
$data[$propertyMetadata->fieldName] = $propertyMetadata->normalizer->normalize(
134+
$propertyMetadata->getValue($object),
135+
);
136+
}
117137
} catch (CircularReference $e) {
118138
throw $e;
119139
} catch (Throwable $e) {
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<?php
2+
3+
namespace Patchlevel\Hydrator\Normalizer;
4+
5+
interface ContextAwareNormalizer extends Normalizer
6+
{
7+
/**
8+
* @param array<string, mixed> $context
9+
*
10+
* @throws InvalidArgument
11+
*/
12+
public function normalize(mixed $value, array $context = []): mixed;
13+
14+
/**
15+
* @param array<string, mixed> $context
16+
*
17+
* @throws InvalidArgument
18+
*/
19+
public function denormalize(mixed $value, array $context = []): mixed;
20+
}

src/Normalizer/ObjectNormalizer.php

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
use function is_array;
1616

1717
#[Attribute(Attribute::TARGET_PROPERTY | Attribute::TARGET_CLASS)]
18-
final class ObjectNormalizer implements Normalizer, TypeAwareNormalizer, HydratorAwareNormalizer
18+
final class ObjectNormalizer implements ContextAwareNormalizer, TypeAwareNormalizer, HydratorAwareNormalizer
1919
{
2020
private Hydrator|null $hydrator = null;
2121

@@ -25,8 +25,12 @@ public function __construct(
2525
) {
2626
}
2727

28-
/** @return array<string, mixed>|null */
29-
public function normalize(mixed $value): array|null
28+
/**
29+
* @param array<string, mixed> $context
30+
*
31+
* @return array<string, mixed>|null
32+
*/
33+
public function normalize(mixed $value, array $context = []): array|null
3034
{
3135
if (!$this->hydrator) {
3236
throw new MissingHydrator();
@@ -42,10 +46,13 @@ public function normalize(mixed $value): array|null
4246
throw InvalidArgument::withWrongType($className . '|null', $value);
4347
}
4448

45-
return $this->hydrator->extract($value);
49+
return $this->hydrator->extract($value, $context);
4650
}
4751

48-
public function denormalize(mixed $value): object|null
52+
/**
53+
* @param array<string, mixed> $context
54+
*/
55+
public function denormalize(mixed $value, array $context = []): object|null
4956
{
5057
if (!$this->hydrator) {
5158
throw new MissingHydrator();
@@ -61,7 +68,7 @@ public function denormalize(mixed $value): object|null
6168

6269
$className = $this->getClassName();
6370

64-
return $this->hydrator->hydrate($className, $value);
71+
return $this->hydrator->hydrate($className, $value, $context);
6572
}
6673

6774
public function setHydrator(Hydrator $hydrator): void

tests/Unit/MetadataHydratorTest.php

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -491,9 +491,9 @@ public function testCreate(): void
491491
*
492492
* @template T of object
493493
*/
494-
public function hydrate(ClassMetadata $metadata, array $data, Stack $stack): object
494+
public function hydrate(ClassMetadata $metadata, array $data, array $context, Stack $stack): object
495495
{
496-
return $stack->next()->hydrate($metadata, $data, $stack);
496+
return $stack->next()->hydrate($metadata, $data, $context, $stack);
497497
}
498498

499499
/**
@@ -504,9 +504,9 @@ public function hydrate(ClassMetadata $metadata, array $data, Stack $stack): obj
504504
*
505505
* @template T of object
506506
*/
507-
public function extract(ClassMetadata $metadata, object $object, Stack $stack): array
507+
public function extract(ClassMetadata $metadata, object $object, array $context, Stack $stack): array
508508
{
509-
return $stack->next()->extract($metadata, $object, $stack);
509+
return $stack->next()->extract($metadata, $object, $context, $stack);
510510
}
511511
},
512512
],

0 commit comments

Comments
 (0)