Skip to content

Commit fb2bf2b

Browse files
committed
add inline normalizer
1 parent a2f2cc9 commit fb2bf2b

File tree

3 files changed

+112
-1
lines changed

3 files changed

+112
-1
lines changed
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Patchlevel\Hydrator\Normalizer;
6+
7+
use Attribute;
8+
use Closure;
9+
10+
/**
11+
* @template N of mixed
12+
* @template D of mixed
13+
*/
14+
#[Attribute(Attribute::TARGET_PROPERTY | Attribute::TARGET_CLASS)]
15+
class InlineNormalizer implements Normalizer
16+
{
17+
/**
18+
* @param Closure(D):N $normalize
19+
* @param Closure(N):D $denormalize
20+
*/
21+
public function __construct(
22+
private readonly Closure $normalize,
23+
private readonly Closure $denormalize,
24+
private readonly bool $passNull = false,
25+
) {
26+
}
27+
28+
/**
29+
* @param D $value
30+
*
31+
* @return N
32+
*/
33+
public function normalize(mixed $value): mixed
34+
{
35+
if (!$this->passNull && $value === null) {
36+
return null;
37+
}
38+
39+
return ($this->normalize)($value);
40+
}
41+
42+
/**
43+
* @param N $value
44+
*
45+
* @return D
46+
*/
47+
public function denormalize(mixed $value): mixed
48+
{
49+
if (!$this->passNull && $value === null) {
50+
return null;
51+
}
52+
53+
return ($this->denormalize)($value);
54+
}
55+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Patchlevel\Hydrator\Tests\Unit\Fixture;
6+
7+
use Patchlevel\Hydrator\Normalizer\InlineNormalizer;
8+
9+
final class ProfileCreatedWithInlineNormalizer
10+
{
11+
public function __construct(
12+
#[IdNormalizer]
13+
public ProfileId $profileId,
14+
#[InlineNormalizer(
15+
normalize: static function (Email $email): string {
16+
return $email->toString();
17+
},
18+
denormalize: static function (string $value): Email {
19+
return Email::fromString($value);
20+
},
21+
)]
22+
public Email $email,
23+
) {
24+
}
25+
}

tests/Unit/MetadataHydratorTest.php

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
use Patchlevel\Hydrator\Tests\Unit\Fixture\NormalizerInBaseClassDefinedDto;
3434
use Patchlevel\Hydrator\Tests\Unit\Fixture\ParentDto;
3535
use Patchlevel\Hydrator\Tests\Unit\Fixture\ProfileCreated;
36+
use Patchlevel\Hydrator\Tests\Unit\Fixture\ProfileCreatedWithInlineNormalizer;
3637
use Patchlevel\Hydrator\Tests\Unit\Fixture\ProfileCreatedWithNormalizer;
3738
use Patchlevel\Hydrator\Tests\Unit\Fixture\ProfileCreatedWrapper;
3839
use Patchlevel\Hydrator\Tests\Unit\Fixture\ProfileId;
@@ -113,7 +114,7 @@ public function testExtractCircularReference(): void
113114
$this->hydrator->extract($dto1);
114115
}
115116

116-
public function testExtractWithInferNormalizer2(): void
117+
public function testExtractWithInferNormalizer(): void
117118
{
118119
$result = $this->hydrator->extract(
119120
new InferNormalizerWithNullableDto(
@@ -148,6 +149,20 @@ public function testExtractWithInferNormalizerFailed(): void
148149
);
149150
}
150151

152+
#[RequiresPhp('>=8.5')]
153+
public function testExtractWithInlineNormalizer(): void
154+
{
155+
$event = new ProfileCreatedWithInlineNormalizer(
156+
ProfileId::fromString('1'),
157+
Email::fromString('info@patchlevel.de'),
158+
);
159+
160+
self::assertEquals(
161+
['profileId' => '1', 'email' => 'info@patchlevel.de'],
162+
$this->hydrator->extract($event),
163+
);
164+
}
165+
151166
public function testExtractWithHooks(): void
152167
{
153168
$data = $this->hydrator->extract(new DtoWithHooks());
@@ -236,6 +251,22 @@ public function testHydrateWithTypeMismatch(): void
236251
);
237252
}
238253

254+
#[RequiresPhp('>=8.5')]
255+
public function testHydrateWithInlineNormalizer(): void
256+
{
257+
$expected = new ProfileCreatedWithInlineNormalizer(
258+
ProfileId::fromString('1'),
259+
Email::fromString('info@patchlevel.de'),
260+
);
261+
262+
$event = $this->hydrator->hydrate(
263+
ProfileCreatedWithInlineNormalizer::class,
264+
['profileId' => '1', 'email' => 'info@patchlevel.de'],
265+
);
266+
267+
self::assertEquals($expected, $event);
268+
}
269+
239270
public function testDenormalizationFailure(): void
240271
{
241272
$this->expectException(DenormalizationFailure::class);

0 commit comments

Comments
 (0)