Skip to content

Commit 86bcdac

Browse files
authored
Merge pull request #188 from patchlevel/1.23.x-merge-up-into-2.0.x_1WFnzs6Q
Merge release 1.23.1 into 2.0.x
2 parents dd19036 + db27fe6 commit 86bcdac

11 files changed

Lines changed: 121 additions & 17 deletions

.github/workflows/benchmark.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ jobs:
5959
cat bench.txt >> $GITHUB_ENV
6060
echo 'EOF' >> $GITHUB_ENV
6161
62-
- uses: actions/github-script@v8
62+
- uses: actions/github-script@v9
6363
with:
6464
script: |
6565
// Get the existing comments.

phpstan-baseline.neon

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,12 @@ parameters:
132132
count: 3
133133
path: src/StackHydrator.php
134134

135+
-
136+
message: '#^Parameter \#1 \$middlewares of class Patchlevel\\Hydrator\\Middleware\\Stack constructor expects non\-empty\-list\<Patchlevel\\Hydrator\\Middleware\\Middleware\>, list\<Patchlevel\\Hydrator\\Middleware\\Middleware\> given\.$#'
137+
identifier: argument.type
138+
count: 4
139+
path: src/StackHydrator.php
140+
135141
-
136142
message: '#^Property Patchlevel\\Hydrator\\Tests\\Unit\\Extension\\Cryptography\\Fixture\\ChildWithSensitiveDataWithIdentifierDto\:\:\$email is never read, only written\.$#'
137143
identifier: property.onlyWritten

src/Middleware/NoMoreMiddleware.php

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,22 @@
77
use Patchlevel\Hydrator\HydratorException;
88
use RuntimeException;
99

10+
use function array_map;
11+
use function count;
12+
use function implode;
13+
use function sprintf;
14+
1015
final class NoMoreMiddleware extends RuntimeException implements HydratorException
1116
{
12-
public function __construct()
17+
/** @param non-empty-list<Middleware> $middlewares */
18+
public function __construct(array $middlewares)
1319
{
14-
parent::__construct('no more middlewares');
20+
parent::__construct(
21+
sprintf(
22+
'The next middleware in %s was requested, but no further middleware exists. The following middlewares were executed: %s',
23+
$middlewares[count($middlewares) - 1]::class,
24+
implode(', ', array_map(static fn (Middleware $middleware): string => $middleware::class, $middlewares)),
25+
),
26+
);
1527
}
1628
}

src/Middleware/Stack.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ final class Stack
88
{
99
private int $index = 0;
1010

11-
/** @param list<Middleware> $middlewares */
11+
/** @param non-empty-list<Middleware> $middlewares */
1212
public function __construct(
1313
private readonly array $middlewares,
1414
) {
@@ -19,7 +19,7 @@ public function next(): Middleware
1919
$next = $this->middlewares[$this->index] ?? null;
2020

2121
if ($next === null) {
22-
throw new NoMoreMiddleware();
22+
throw new NoMoreMiddleware($this->middlewares);
2323
}
2424

2525
$this->index++;

src/MissingMiddlewares.php

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Patchlevel\Hydrator;
6+
7+
use RuntimeException;
8+
9+
/** @experimental */
10+
final class MissingMiddlewares extends RuntimeException implements HydratorException
11+
{
12+
public function __construct()
13+
{
14+
parent::__construct('Missing middlewares.');
15+
}
16+
}

src/StackHydrator.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,9 @@ public function __construct(
3030
private readonly array $middlewares = [new TransformMiddleware()],
3131
private readonly bool $defaultLazy = false,
3232
) {
33+
if ($middlewares === []) {
34+
throw new MissingMiddlewares();
35+
}
3336
}
3437

3538
/**
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Patchlevel\Hydrator\Tests\Unit\Fixture;
6+
7+
use Patchlevel\Hydrator\Metadata\ClassMetadata;
8+
use Patchlevel\Hydrator\Middleware\Middleware;
9+
use Patchlevel\Hydrator\Middleware\Stack;
10+
11+
final class DummyMiddleware implements Middleware
12+
{
13+
/**
14+
* @param ClassMetadata<T> $metadata
15+
* @param array<string, mixed> $data
16+
* @param array<string, mixed> $context
17+
*
18+
* @return T
19+
*
20+
* @template T of object
21+
*/
22+
public function hydrate(ClassMetadata $metadata, array $data, array $context, Stack $stack): object
23+
{
24+
return $stack->next()->hydrate($metadata, $data, $context, $stack);
25+
}
26+
27+
/**
28+
* @param array<string, mixed> $context
29+
*
30+
* @return array<string, mixed>
31+
*/
32+
public function extract(ClassMetadata $metadata, object $object, array $context, Stack $stack): array
33+
{
34+
return $stack->next()->extract($metadata, $object, $context, $stack);
35+
}
36+
}

tests/Unit/Middleware/StackTest.php

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,31 +4,41 @@
44

55
namespace Patchlevel\Hydrator\Tests\Unit\Middleware;
66

7-
use Patchlevel\Hydrator\Middleware\Middleware;
87
use Patchlevel\Hydrator\Middleware\NoMoreMiddleware;
98
use Patchlevel\Hydrator\Middleware\Stack;
9+
use Patchlevel\Hydrator\Tests\Unit\Fixture\DummyMiddleware;
1010
use PHPUnit\Framework\Attributes\CoversClass;
1111
use PHPUnit\Framework\TestCase;
1212

1313
#[CoversClass(Stack::class)]
1414
final class StackTest extends TestCase
1515
{
16-
public function testEmptyStack(): void
16+
public function testStack(): void
1717
{
18-
$this->expectException(NoMoreMiddleware::class);
18+
$middleware1 = new DummyMiddleware();
19+
$middleware2 = new DummyMiddleware();
1920

20-
$stack = new Stack([]);
21-
$stack->next();
21+
$stack = new Stack([$middleware1, $middleware2]);
22+
23+
self::assertSame($middleware1, $stack->next());
24+
self::assertSame($middleware2, $stack->next());
2225
}
2326

24-
public function testStack(): void
27+
public function testStackThrowsExceptionWhenNoMoreMiddlewareIsAvailable(): void
2528
{
26-
$middleware1 = $this->createStub(Middleware::class);
27-
$middleware2 = $this->createStub(Middleware::class);
29+
$middleware1 = new DummyMiddleware();
30+
$middleware2 = new DummyMiddleware();
2831

2932
$stack = new Stack([$middleware1, $middleware2]);
3033

31-
self::assertSame($middleware1, $stack->next());
32-
self::assertSame($middleware2, $stack->next());
34+
$stack->next();
35+
$stack->next();
36+
37+
$this->expectException(NoMoreMiddleware::class);
38+
$this->expectExceptionMessage(
39+
'The next middleware in Patchlevel\Hydrator\Tests\Unit\Fixture\DummyMiddleware was requested, but no further middleware exists. The following middlewares were executed: Patchlevel\Hydrator\Tests\Unit\Fixture\DummyMiddleware, Patchlevel\Hydrator\Tests\Unit\Fixture\DummyMiddleware',
40+
);
41+
42+
$stack->next();
3343
}
3444
}

tests/Unit/Middleware/TransformerMiddlewareTest.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ public function testHydrate(): void
3030
$this->classMetadata(ProfileCreated::class),
3131
['profileId' => '1', 'email' => 'info@patchlevel.de'],
3232
[],
33-
new Stack([]),
33+
new Stack([$middleware]),
3434
);
3535

3636
self::assertEquals($expected, $event);
@@ -49,7 +49,7 @@ public function testExtract(): void
4949
Email::fromString('info@patchlevel.de'),
5050
),
5151
[],
52-
new Stack([]),
52+
new Stack([$middleware]),
5353
);
5454

5555
self::assertEquals($expected, $data);

tests/Unit/StackHydratorBuilderTest.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,8 @@ public function testAddMetadataEnricherWithPriority(): void
5151
$builder->addMetadataEnricher($enricher1, 10);
5252
$builder->addMetadataEnricher($enricher2, 20);
5353

54+
$builder->addMiddleware($this->createMock(Middleware::class));
55+
5456
$hydrator = $builder->build();
5557

5658
$reflection = new ReflectionProperty(StackHydrator::class, 'metadataFactory');
@@ -74,6 +76,8 @@ public function testAddGuesserWithPriority(): void
7476
$builder->addGuesser($guesser1, 10);
7577
$builder->addGuesser($guesser2, 20);
7678

79+
$builder->addMiddleware($this->createMock(Middleware::class));
80+
7781
$hydrator = $builder->build();
7882

7983
$reflection = new ReflectionProperty(StackHydrator::class, 'metadataFactory');
@@ -103,6 +107,8 @@ public function testEnableDefaultLazy(): void
103107
$builder = new StackHydratorBuilder();
104108
$builder->enableDefaultLazy();
105109

110+
$builder->addMiddleware($this->createMock(Middleware::class));
111+
106112
$hydrator = $builder->build();
107113

108114
$reflection = new ReflectionProperty(StackHydrator::class, 'defaultLazy');
@@ -128,6 +134,7 @@ public function testCachePsr6(): void
128134

129135
$builder = new StackHydratorBuilder();
130136
$builder->setCache($cache);
137+
$builder->addMiddleware($this->createMock(Middleware::class));
131138

132139
$hydrator = $builder->build();
133140

@@ -143,6 +150,7 @@ public function testCachePsr16(): void
143150

144151
$builder = new StackHydratorBuilder();
145152
$builder->setCache($cache);
153+
$builder->addMiddleware($this->createMock(Middleware::class));
146154

147155
$hydrator = $builder->build();
148156

0 commit comments

Comments
 (0)