Skip to content

Commit c0c4860

Browse files
committed
replace trait with an abstract class
1 parent 898d854 commit c0c4860

12 files changed

+65
-63
lines changed

docs/pages/dynamic_consistency_boundary.md

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -92,13 +92,13 @@ Course exists:
9292

9393
```php
9494
use Patchlevel\EventSourcing\Attribute\Apply;
95-
use Patchlevel\EventSourcing\DCB\EventRouter;
95+
use Patchlevel\EventSourcing\DCB\BasicProjection;
9696
use Patchlevel\EventSourcing\DCB\Projection;
9797

9898
/** @implements Projection<bool> */
9999
final class CourseExists implements Projection
100100
{
101-
use EventRouter;
101+
use BasicProjection;
102102

103103
public function __construct(private readonly CourseId $courseId) {}
104104

@@ -125,12 +125,12 @@ Current capacity of a course:
125125

126126
```php
127127
use Patchlevel\EventSourcing\Attribute\Apply;
128-
use Patchlevel\EventSourcing\DCB\EventRouter;
128+
use Patchlevel\EventSourcing\DCB\BasicProjection;
129129
use Patchlevel\EventSourcing\DCB\Projection;
130130

131131
final class CourseCapacityProjection implements Projection
132132
{
133-
use EventRouter;
133+
use BasicProjection;
134134

135135
public function __construct(private readonly CourseId $courseId) {}
136136

@@ -163,12 +163,12 @@ Count subscriptions of a course:
163163

164164
```php
165165
use Patchlevel\EventSourcing\Attribute\Apply;
166-
use Patchlevel\EventSourcing\DCB\EventRouter;
166+
use Patchlevel\EventSourcing\DCB\BasicProjection;
167167
use Patchlevel\EventSourcing\DCB\Projection;
168168

169169
final class NumberOfCourseSubscriptionsProjection implements Projection
170170
{
171-
use EventRouter;
171+
use BasicProjection;
172172

173173
public function __construct(private readonly CourseId $courseId) {}
174174

@@ -195,12 +195,12 @@ Count subscriptions of a student:
195195

196196
```php
197197
use Patchlevel\EventSourcing\Attribute\Apply;
198-
use Patchlevel\EventSourcing\DCB\EventRouter;
198+
use Patchlevel\EventSourcing\DCB\BasicProjection;
199199
use Patchlevel\EventSourcing\DCB\Projection;
200200

201201
final class NumberOfStudentSubscriptionsProjection implements Projection
202202
{
203-
use EventRouter;
203+
use BasicProjection;
204204

205205
public function __construct(private readonly StudentId $studentId) {}
206206

@@ -227,13 +227,13 @@ Has the student already subscribed to this course:
227227

228228
```php
229229
use Patchlevel\EventSourcing\Attribute\Apply;
230-
use Patchlevel\EventSourcing\DCB\EventRouter;
230+
use Patchlevel\EventSourcing\DCB\BasicProjection;
231231
use Patchlevel\EventSourcing\DCB\Projection;
232232

233233
/** @implements Projection<bool> */
234234
final class StudentAlreadySubscribedProjection implements Projection
235235
{
236-
use EventRouter;
236+
use BasicProjection;
237237

238238
public function __construct(
239239
private readonly StudentId $studentId,
@@ -266,12 +266,12 @@ Next invoice number from the last event only:
266266

267267
```php
268268
use Patchlevel\EventSourcing\Attribute\Apply;
269-
use Patchlevel\EventSourcing\DCB\EventRouter;
269+
use Patchlevel\EventSourcing\DCB\BasicProjection;
270270
use Patchlevel\EventSourcing\DCB\Projection;
271271

272272
final class NextInvoiceNumberProjection implements Projection
273273
{
274-
use EventRouter;
274+
use BasicProjection;
275275

276276
public function initialState(): int
277277
{

src/DCB/EventRouter.php renamed to src/DCB/BasicProjection.php

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,14 +21,19 @@
2121

2222
/**
2323
* @experimental
24-
* @require-implements Projection
2524
* @template S = mixed
25+
* @implements Projection<S>
2626
*/
27-
trait EventRouter
27+
abstract class BasicProjection implements Projection, SubQueryProvider
2828
{
2929
/** @var array<class-string, string>|null $applyMethods */
3030
private array|null $applyMethods = null;
3131

32+
/**
33+
* @param S $state
34+
*
35+
* @return S
36+
*/
3237
public function apply(mixed $state, Message $message): mixed
3338
{
3439
if (!$this->subQuery()->match($message)) {
@@ -57,7 +62,7 @@ public function subQuery(): SubQuery
5762
}
5863

5964
/** @return list<class-string> */
60-
public function eventTypeFilter(): array
65+
protected function eventTypeFilter(): array
6166
{
6267
return array_keys($this->applyMethods());
6368
}
@@ -177,14 +182,14 @@ static function (ReflectionNamedType|ReflectionIntersectionType $reflectionType)
177182
}
178183

179184
/** @return list<string> */
180-
abstract public function tagFilter(): array;
185+
abstract protected function tagFilter(): array;
181186

182-
public function streamName(): string|null
187+
protected function streamName(): string|null
183188
{
184189
return null;
185190
}
186191

187-
public function lastEventIsEnough(): bool
192+
protected function lastEventIsEnough(): bool
188193
{
189194
return false;
190195
}

src/DCB/CompositeProjection.php

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
use Patchlevel\EventSourcing\Message\Message;
88
use Patchlevel\EventSourcing\Store\Query;
9+
use Patchlevel\EventSourcing\Store\SubQuery;
910

1011
use function array_map;
1112

@@ -20,12 +21,19 @@ public function __construct(
2021

2122
public function query(): Query
2223
{
23-
$query = new Query(
24-
...array_map(
25-
static fn (Projection $projection) => $projection->subQuery(),
26-
$this->projections,
27-
),
28-
);
24+
$subQueries = [];
25+
26+
foreach ($this->projections as $projection) {
27+
if ($projection instanceof SubQueryProvider) {
28+
$subQueries[] = $projection->subQuery();
29+
30+
continue;
31+
}
32+
33+
$subQueries[] = new SubQuery();
34+
}
35+
36+
$query = new Query(...$subQueries);
2937

3038
return $query->optimize();
3139
}

src/DCB/Projection.php

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
namespace Patchlevel\EventSourcing\DCB;
66

77
use Patchlevel\EventSourcing\Message\Message;
8-
use Patchlevel\EventSourcing\Store\SubQuery;
98

109
/**
1110
* @experimental
@@ -22,6 +21,4 @@ public function initialState(): mixed;
2221
* @return S
2322
*/
2423
public function apply(mixed $state, Message $message): mixed;
25-
26-
public function subQuery(): SubQuery;
2724
}

src/DCB/SubQueryProvider.php

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Patchlevel\EventSourcing\DCB;
6+
7+
use Patchlevel\EventSourcing\Store\SubQuery;
8+
9+
/** @experimental */
10+
interface SubQueryProvider
11+
{
12+
public function subQuery(): SubQuery;
13+
}

tests/Integration/DynamicConsistencyBoundary/Course/Projection/CourseCapacityProjection.php

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,13 @@
55
namespace Patchlevel\EventSourcing\Tests\Integration\DynamicConsistencyBoundary\Course\Projection;
66

77
use Patchlevel\EventSourcing\Attribute\Apply;
8-
use Patchlevel\EventSourcing\DCB\EventRouter;
9-
use Patchlevel\EventSourcing\DCB\Projection;
8+
use Patchlevel\EventSourcing\DCB\BasicProjection;
109
use Patchlevel\EventSourcing\Tests\Integration\DynamicConsistencyBoundary\Course\CourseId;
1110
use Patchlevel\EventSourcing\Tests\Integration\DynamicConsistencyBoundary\Course\Event\CourseCapacityChanged;
1211
use Patchlevel\EventSourcing\Tests\Integration\DynamicConsistencyBoundary\Course\Event\CourseDefined;
1312

14-
final class CourseCapacityProjection implements Projection
13+
final class CourseCapacityProjection extends BasicProjection
1514
{
16-
use EventRouter;
17-
1815
public function __construct(
1916
private readonly CourseId $courseId,
2017
) {

tests/Integration/DynamicConsistencyBoundary/Course/Projection/CourseExists.php

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,13 @@
55
namespace Patchlevel\EventSourcing\Tests\Integration\DynamicConsistencyBoundary\Course\Projection;
66

77
use Patchlevel\EventSourcing\Attribute\Apply;
8-
use Patchlevel\EventSourcing\DCB\EventRouter;
9-
use Patchlevel\EventSourcing\DCB\Projection;
8+
use Patchlevel\EventSourcing\DCB\BasicProjection;
109
use Patchlevel\EventSourcing\Tests\Integration\DynamicConsistencyBoundary\Course\CourseId;
1110
use Patchlevel\EventSourcing\Tests\Integration\DynamicConsistencyBoundary\Course\Event\CourseDefined;
1211

13-
/** @implements Projection<bool> */
14-
final class CourseExists implements Projection
12+
/** @extends BasicProjection<bool> */
13+
final class CourseExists extends BasicProjection
1514
{
16-
use EventRouter;
17-
1815
public function __construct(
1916
private readonly CourseId $courseId,
2017
) {

tests/Integration/DynamicConsistencyBoundary/Course/Projection/NumberOfCourseSubscriptionsProjection.php

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,12 @@
55
namespace Patchlevel\EventSourcing\Tests\Integration\DynamicConsistencyBoundary\Course\Projection;
66

77
use Patchlevel\EventSourcing\Attribute\Apply;
8-
use Patchlevel\EventSourcing\DCB\EventRouter;
9-
use Patchlevel\EventSourcing\DCB\Projection;
8+
use Patchlevel\EventSourcing\DCB\BasicProjection;
109
use Patchlevel\EventSourcing\Tests\Integration\DynamicConsistencyBoundary\Course\CourseId;
1110
use Patchlevel\EventSourcing\Tests\Integration\DynamicConsistencyBoundary\Course\Event\StudentSubscribedToCourse;
1211

13-
final class NumberOfCourseSubscriptionsProjection implements Projection
12+
final class NumberOfCourseSubscriptionsProjection extends BasicProjection
1413
{
15-
use EventRouter;
16-
1714
public function __construct(
1815
private readonly CourseId $courseId,
1916
) {

tests/Integration/DynamicConsistencyBoundary/Course/Projection/NumberOfStudentSubscriptionsProjection.php

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,12 @@
55
namespace Patchlevel\EventSourcing\Tests\Integration\DynamicConsistencyBoundary\Course\Projection;
66

77
use Patchlevel\EventSourcing\Attribute\Apply;
8-
use Patchlevel\EventSourcing\DCB\EventRouter;
9-
use Patchlevel\EventSourcing\DCB\Projection;
8+
use Patchlevel\EventSourcing\DCB\BasicProjection;
109
use Patchlevel\EventSourcing\Tests\Integration\DynamicConsistencyBoundary\Course\Event\StudentSubscribedToCourse;
1110
use Patchlevel\EventSourcing\Tests\Integration\DynamicConsistencyBoundary\Course\StudentId;
1211

13-
final class NumberOfStudentSubscriptionsProjection implements Projection
12+
final class NumberOfStudentSubscriptionsProjection extends BasicProjection
1413
{
15-
use EventRouter;
16-
1714
public function __construct(
1815
private readonly StudentId $studentId,
1916
) {

tests/Integration/DynamicConsistencyBoundary/Course/Projection/StudentAlreadySubscribedProjection.php

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,13 @@
55
namespace Patchlevel\EventSourcing\Tests\Integration\DynamicConsistencyBoundary\Course\Projection;
66

77
use Patchlevel\EventSourcing\Attribute\Apply;
8-
use Patchlevel\EventSourcing\DCB\EventRouter;
9-
use Patchlevel\EventSourcing\DCB\Projection;
8+
use Patchlevel\EventSourcing\DCB\BasicProjection;
109
use Patchlevel\EventSourcing\Tests\Integration\DynamicConsistencyBoundary\Course\CourseId;
1110
use Patchlevel\EventSourcing\Tests\Integration\DynamicConsistencyBoundary\Course\Event\StudentSubscribedToCourse;
1211
use Patchlevel\EventSourcing\Tests\Integration\DynamicConsistencyBoundary\Course\StudentId;
1312

14-
final class StudentAlreadySubscribedProjection implements Projection
13+
final class StudentAlreadySubscribedProjection extends BasicProjection
1514
{
16-
use EventRouter;
17-
1815
public function __construct(
1916
private readonly StudentId $studentId,
2017
private readonly CourseId $courseId,

0 commit comments

Comments
 (0)