Skip to content

Commit 41b6ea2

Browse files
committed
hydrator builder variant
1 parent 774a87d commit 41b6ea2

9 files changed

Lines changed: 120 additions & 112 deletions

src/CoreExtension.php

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,21 +5,13 @@
55
namespace Patchlevel\Hydrator;
66

77
use Patchlevel\Hydrator\Guesser\BuiltInGuesser;
8-
use Patchlevel\Hydrator\Guesser\Guesser;
9-
use Patchlevel\Hydrator\Middleware\Middleware;
108
use Patchlevel\Hydrator\Middleware\TransformMiddleware;
119

12-
final class CoreExtension extends Extension
10+
final class CoreExtension implements Extension
1311
{
14-
/** @return iterable<Middleware|array{0: Middleware, 1?: int}> */
15-
public function middlewares(): iterable
12+
public function configure(HydratorBuilder $builder): void
1613
{
17-
yield new TransformMiddleware();
18-
}
19-
20-
/** @return iterable<Guesser|array{0: Guesser, 1?: int}> */
21-
public function guesser(): iterable
22-
{
23-
yield new BuiltInGuesser();
14+
$builder->addMiddleware(new TransformMiddleware());
15+
$builder->addGuesser(new BuiltInGuesser());
2416
}
2517
}

src/Cryptography/CryptographyExtension.php

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,25 +5,18 @@
55
namespace Patchlevel\Hydrator\Cryptography;
66

77
use Patchlevel\Hydrator\Extension;
8-
use Patchlevel\Hydrator\Metadata\MetadataEnricher;
9-
use Patchlevel\Hydrator\Middleware\Middleware;
8+
use Patchlevel\Hydrator\HydratorBuilder;
109

11-
final class CryptographyExtension extends Extension
10+
final class CryptographyExtension implements Extension
1211
{
1312
public function __construct(
1413
private readonly PayloadCryptographer $cryptography,
1514
) {
1615
}
1716

18-
/** @return iterable<Middleware|array{0: Middleware, 1?: int}> */
19-
public function middlewares(): iterable
17+
public function configure(HydratorBuilder $builder): void
2018
{
21-
yield [new CryptographyMiddleware($this->cryptography), 64];
22-
}
23-
24-
/** @return iterable<MetadataEnricher|array{0: MetadataEnricher, 1?: int}> */
25-
public function metadataEnrichers(): iterable
26-
{
27-
yield [new CryptographyMetadataEnricher(), 64];
19+
$builder->addMetadataEnricher(new CryptographyMetadataEnricher(), 64);
20+
$builder->addMiddleware(new CryptographyMiddleware($this->cryptography), 64);
2821
}
2922
}

src/Extension.php

Lines changed: 2 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -4,27 +4,7 @@
44

55
namespace Patchlevel\Hydrator;
66

7-
use Patchlevel\Hydrator\Guesser\Guesser;
8-
use Patchlevel\Hydrator\Metadata\MetadataEnricher;
9-
use Patchlevel\Hydrator\Middleware\Middleware;
10-
11-
abstract class Extension
7+
interface Extension
128
{
13-
/** @return iterable<Middleware|array{0: Middleware, 1?: int}> */
14-
public function middlewares(): iterable
15-
{
16-
return [];
17-
}
18-
19-
/** @return iterable<MetadataEnricher|array{0: MetadataEnricher, 1?: int}> */
20-
public function metadataEnrichers(): iterable
21-
{
22-
return [];
23-
}
24-
25-
/** @return iterable<Guesser|array{0: Guesser, 1?: int}> */
26-
public function guesser(): iterable
27-
{
28-
return [];
29-
}
9+
public function configure(HydratorBuilder $builder): void;
3010
}

src/HydratorBuilder.php

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
<?php
2+
3+
namespace Patchlevel\Hydrator;
4+
5+
use Patchlevel\Hydrator\Guesser\ChainGuesser;
6+
use Patchlevel\Hydrator\Guesser\Guesser;
7+
use Patchlevel\Hydrator\Metadata\AttributeMetadataFactory;
8+
use Patchlevel\Hydrator\Metadata\MetadataEnricher;
9+
use Patchlevel\Hydrator\Middleware\Middleware;
10+
11+
final class HydratorBuilder
12+
{
13+
private bool $defaultLazy = false;
14+
15+
/**
16+
* @var array<int, list<Middleware>>
17+
*/
18+
private array $middlewares = [];
19+
20+
/**
21+
* @var array<int, list<MetadataEnricher>>
22+
*/
23+
private array $metadataEnrichers = [];
24+
25+
/**
26+
* @var array<int, list<Guesser>>
27+
*/
28+
private array $guessers = [];
29+
30+
/**
31+
* @return $this
32+
*/
33+
public function addMiddleware(Middleware $middleware, int $priority = 0): static
34+
{
35+
$this->middlewares[$priority][] = $middleware;
36+
37+
return $this;
38+
}
39+
40+
/**
41+
* @return $this
42+
*/
43+
public function addMetadataEnricher(MetadataEnricher $enricher, int $priority = 0): static
44+
{
45+
$this->metadataEnrichers[$priority][] = $enricher;
46+
47+
return $this;
48+
}
49+
50+
/**
51+
* @return $this
52+
*/
53+
public function addGuesser(Guesser $guesser, int $priority = 0): static
54+
{
55+
$this->guessers[$priority][] = $guesser;
56+
57+
return $this;
58+
}
59+
60+
public function enableDefaultLazy(bool $lazy = true): static
61+
{
62+
$this->defaultLazy = $lazy;
63+
64+
return $this;
65+
}
66+
67+
public function useExtension(Extension $extension): static
68+
{
69+
$extension->configure($this);
70+
71+
return $this;
72+
}
73+
74+
public function build(): Hydrator
75+
{
76+
krsort($this->middlewares);
77+
krsort($this->metadataEnrichers);
78+
krsort($this->guessers);
79+
80+
return new MetadataHydrator(
81+
new AttributeMetadataFactory(
82+
guesser: new ChainGuesser([...array_merge(...$this->guessers)]),
83+
),
84+
[...array_merge(...$this->middlewares)],
85+
[...array_merge(...$this->metadataEnrichers)],
86+
$this->defaultLazy,
87+
);
88+
}
89+
}

src/MetadataHydrator.php

Lines changed: 0 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@
44

55
namespace Patchlevel\Hydrator;
66

7-
use Patchlevel\Hydrator\Guesser\ChainGuesser;
8-
use Patchlevel\Hydrator\Guesser\Guesser;
97
use Patchlevel\Hydrator\Metadata\AttributeMetadataFactory;
108
use Patchlevel\Hydrator\Metadata\ClassMetadata;
119
use Patchlevel\Hydrator\Metadata\ClassNotFound;
@@ -17,8 +15,6 @@
1715
use ReflectionClass;
1816

1917
use function array_key_exists;
20-
use function array_merge;
21-
use function krsort;
2218

2319
use const PHP_VERSION_ID;
2420

@@ -121,55 +117,4 @@ private function metadata(string $class): ClassMetadata
121117

122118
return $metadata;
123119
}
124-
125-
/** @param iterable<Extension> $extensions */
126-
public static function create(
127-
iterable $extensions = [],
128-
bool $defaultLazy = false,
129-
): self {
130-
$extensions = [...$extensions, new CoreExtension()];
131-
132-
$middlewares = [];
133-
$enrichers = [];
134-
$guessers = [];
135-
136-
foreach ($extensions as $extension) {
137-
foreach ($extension->middlewares() as $entry) {
138-
if ($entry instanceof Middleware) {
139-
$middlewares[0][] = $entry;
140-
} else {
141-
$middlewares[$entry[1] ?? 0][] = $entry[0];
142-
}
143-
}
144-
145-
foreach ($extension->metadataEnrichers() as $entry) {
146-
if ($entry instanceof MetadataEnricher) {
147-
$enrichers[0][] = $entry;
148-
} else {
149-
$enrichers[$entry[1] ?? 0][] = $entry[0];
150-
}
151-
}
152-
153-
foreach ($extension->guesser() as $entry) {
154-
if ($entry instanceof Guesser) {
155-
$guessers[0][] = $entry;
156-
} else {
157-
$guessers[$entry[1] ?? 0][] = $entry[0];
158-
}
159-
}
160-
}
161-
162-
krsort($middlewares);
163-
krsort($enrichers);
164-
krsort($guessers);
165-
166-
return new self(
167-
new AttributeMetadataFactory(
168-
guesser: new ChainGuesser([...array_merge(...$guessers)]),
169-
),
170-
[...array_merge(...$middlewares)],
171-
[...array_merge(...$enrichers)],
172-
$defaultLazy,
173-
);
174-
}
175120
}

tests/Benchmark/HydratorBench.php

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,9 @@
44

55
namespace Patchlevel\Hydrator\Tests\Benchmark;
66

7+
use Patchlevel\Hydrator\CoreExtension;
78
use Patchlevel\Hydrator\Hydrator;
8-
use Patchlevel\Hydrator\MetadataHydrator;
9+
use Patchlevel\Hydrator\HydratorBuilder;
910
use Patchlevel\Hydrator\Tests\Benchmark\Fixture\ProfileCreated;
1011
use Patchlevel\Hydrator\Tests\Benchmark\Fixture\ProfileId;
1112
use Patchlevel\Hydrator\Tests\Benchmark\Fixture\Skill;
@@ -18,7 +19,9 @@ final class HydratorBench
1819

1920
public function __construct()
2021
{
21-
$this->hydrator = MetadataHydrator::create();
22+
$this->hydrator = (new HydratorBuilder())
23+
->useExtension(new CoreExtension())
24+
->build();
2225
}
2326

2427
public function setUp(): void

tests/Benchmark/HydratorWithCryptographyBench.php

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,12 @@
44

55
namespace Patchlevel\Hydrator\Tests\Benchmark;
66

7+
use Patchlevel\Hydrator\CoreExtension;
78
use Patchlevel\Hydrator\Cryptography\CryptographyExtension;
89
use Patchlevel\Hydrator\Cryptography\SensitiveDataPayloadCryptographer;
910
use Patchlevel\Hydrator\Cryptography\Store\InMemoryCipherKeyStore;
1011
use Patchlevel\Hydrator\Hydrator;
11-
use Patchlevel\Hydrator\MetadataHydrator;
12+
use Patchlevel\Hydrator\HydratorBuilder;
1213
use Patchlevel\Hydrator\Tests\Benchmark\Fixture\ProfileCreated;
1314
use Patchlevel\Hydrator\Tests\Benchmark\Fixture\ProfileId;
1415
use Patchlevel\Hydrator\Tests\Benchmark\Fixture\Skill;
@@ -25,11 +26,10 @@ public function __construct()
2526
{
2627
$this->store = new InMemoryCipherKeyStore();
2728

28-
$this->hydrator = MetadataHydrator::create([
29-
new CryptographyExtension(
30-
SensitiveDataPayloadCryptographer::createWithDefaultSettings($this->store),
31-
),
32-
]);
29+
$this->hydrator = (new HydratorBuilder())
30+
->useExtension(new CoreExtension())
31+
->useExtension(new CryptographyExtension(SensitiveDataPayloadCryptographer::createWithDefaultSettings($this->store)))
32+
->build();
3333
}
3434

3535
public function setUp(): void

tests/Benchmark/HydratorWithLazyBench.php

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,9 @@
44

55
namespace Patchlevel\Hydrator\Tests\Benchmark;
66

7+
use Patchlevel\Hydrator\CoreExtension;
78
use Patchlevel\Hydrator\Hydrator;
8-
use Patchlevel\Hydrator\MetadataHydrator;
9+
use Patchlevel\Hydrator\HydratorBuilder;
910
use Patchlevel\Hydrator\Tests\Benchmark\Fixture\ProfileCreated;
1011
use PhpBench\Attributes as Bench;
1112

@@ -16,7 +17,10 @@ final class HydratorWithLazyBench
1617

1718
public function __construct()
1819
{
19-
$this->hydrator = MetadataHydrator::create(defaultLazy: true);
20+
$this->hydrator = (new HydratorBuilder())
21+
->useExtension(new CoreExtension())
22+
->enableDefaultLazy()
23+
->build();
2024
}
2125

2226
public function setUp(): void

tests/Unit/MetadataHydratorTest.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,12 @@
99
use DateTimeZone;
1010
use Patchlevel\Hydrator\CircularReference;
1111
use Patchlevel\Hydrator\ClassNotSupported;
12+
use Patchlevel\Hydrator\CoreExtension;
1213
use Patchlevel\Hydrator\Cryptography\CryptographyExtension;
1314
use Patchlevel\Hydrator\Cryptography\PayloadCryptographer;
1415
use Patchlevel\Hydrator\DenormalizationFailure;
1516
use Patchlevel\Hydrator\Guesser\Guesser;
17+
use Patchlevel\Hydrator\HydratorBuilder;
1618
use Patchlevel\Hydrator\Metadata\AttributeMetadataFactory;
1719
use Patchlevel\Hydrator\Metadata\ClassMetadata;
1820
use Patchlevel\Hydrator\MetadataHydrator;
@@ -57,7 +59,7 @@ final class MetadataHydratorTest extends TestCase
5759

5860
public function setUp(): void
5961
{
60-
$this->hydrator = MetadataHydrator::create();
62+
$this->hydrator = (new HydratorBuilder())->useExtension(new CoreExtension())->build();
6163
}
6264

6365
public function testExtract(): void

0 commit comments

Comments
 (0)