Skip to content

Commit c674bcd

Browse files
committed
Introduce a Mapped Guesser
There's currently no easy way to avoid adding attributes in order to configure which normalizers to use for which types. This `MappedGuesser` is a trivial Guesser implementation allowing users to specify a map of `Type::class => Normalizer::class` as an alternative to adding attributes to targets
1 parent ef787c0 commit c674bcd

File tree

3 files changed

+67
-12
lines changed

3 files changed

+67
-12
lines changed

phpstan-baseline.neon

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -168,12 +168,6 @@ parameters:
168168
count: 2
169169
path: tests/Unit/Normalizer/ArrayNormalizerTest.php
170170

171-
-
172-
message: '#^Parameter \#1 \$normalizer of class Patchlevel\\Hydrator\\Normalizer\\ArrayNormalizer constructor expects Patchlevel\\Hydrator\\Normalizer\\Normalizer, PHPUnit\\Framework\\MockObject\\MockObject given\.$#'
173-
identifier: argument.type
174-
count: 1
175-
path: tests/Unit/Normalizer/ArrayNormalizerTest.php
176-
177171
-
178172
message: '#^Cannot cast mixed to int\.$#'
179173
identifier: cast.int
@@ -185,9 +179,3 @@ parameters:
185179
identifier: cast.string
186180
count: 2
187181
path: tests/Unit/Normalizer/ArrayShapeNormalizerTest.php
188-
189-
-
190-
message: '#^Parameter \#1 \$normalizerMap of class Patchlevel\\Hydrator\\Normalizer\\ArrayShapeNormalizer constructor expects array\<Patchlevel\\Hydrator\\Normalizer\\Normalizer\>, array\<string, PHPUnit\\Framework\\MockObject\\MockObject\> given\.$#'
191-
identifier: argument.type
192-
count: 1
193-
path: tests/Unit/Normalizer/ArrayShapeNormalizerTest.php

src/Guesser/MappedGuesser.php

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Patchlevel\Hydrator\Guesser;
6+
7+
use Patchlevel\Hydrator\Normalizer\Normalizer;
8+
use Symfony\Component\TypeInfo\Type\ObjectType;
9+
10+
use function array_key_exists;
11+
12+
final readonly class MappedGuesser implements Guesser
13+
{
14+
/** @param array<class-string, class-string<Normalizer>> $map */
15+
public function __construct(private array $map)
16+
{
17+
}
18+
19+
/**
20+
* @param ObjectType<T> $type
21+
*
22+
* @template T
23+
*/
24+
public function guess(ObjectType $type): Normalizer|null
25+
{
26+
$className = $type->getClassName();
27+
if (! array_key_exists($className, $this->map)) {
28+
return null;
29+
}
30+
31+
$normalizerType = $this->map[$className];
32+
33+
return new $normalizerType();
34+
}
35+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Patchlevel\Hydrator\Tests\Unit\Guesser;
6+
7+
use Patchlevel\Hydrator\Guesser\MappedGuesser;
8+
use Patchlevel\Hydrator\Tests\Unit\Fixture\Email;
9+
use Patchlevel\Hydrator\Tests\Unit\Fixture\EmailNormalizer;
10+
use PHPUnit\Framework\TestCase;
11+
use Symfony\Component\TypeInfo\Type\ObjectType;
12+
13+
final class MappedGuesserTest extends TestCase
14+
{
15+
public function testTheNormalizerIsNullWhenTheTypeHasNotBeenMapped(): void
16+
{
17+
$guesser = new MappedGuesser([]);
18+
19+
self::assertNull($guesser->guess(new ObjectType(Email::class)));
20+
}
21+
22+
public function testTheNormalizerIsOfTheExpectedType(): void
23+
{
24+
$guesser = new MappedGuesser([
25+
Email::class => EmailNormalizer::class,
26+
]);
27+
28+
$normalizer = $guesser->guess(new ObjectType(Email::class));
29+
30+
self::assertInstanceOf(EmailNormalizer::class, $normalizer);
31+
}
32+
}

0 commit comments

Comments
 (0)