diff --git a/baseline.xml b/baseline.xml index 6f24145b1..ef1f03ece 100644 --- a/baseline.xml +++ b/baseline.xml @@ -20,14 +20,6 @@ getName()]]> - - - $headers - - - Headers - - @@ -104,6 +96,11 @@ $index + + + + + $normalizedCustomHeaders @@ -193,23 +190,6 @@ $name - - - 'bar', - 'aggregateName' => 'profile', - 'aggregateId' => '1', - 'playhead' => 3, - 'recordedOn' => $recordedAt, - 'newStreamStart' => true, - 'archived' => true, - ]]]> - - - assertSame - assertSame - - $value diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index 19fe62935..dcf8c680d 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -6,7 +6,7 @@ parameters: path: src/Console/DoctrineHelper.php - - message: "#^Method Patchlevel\\\\EventSourcing\\\\EventBus\\\\Message\\:\\:headers\\(\\) should return array\\{aggregateName\\?\\: string, aggregateId\\?\\: string, playhead\\?\\: int\\<1, max\\>, recordedOn\\?\\: DateTimeImmutable, newStreamStart\\?\\: bool, archived\\?\\: bool\\} but returns non\\-empty\\-array\\\\.$#" + message: "#^Property Patchlevel\\\\EventSourcing\\\\EventBus\\\\Message\\\\:\\:\\$headers \\(array\\{aggregateName\\?\\: string, aggregateId\\?\\: string, playhead\\?\\: int\\<1, max\\>, recordedOn\\?\\: DateTimeImmutable, newStreamStart\\?\\: bool, archived\\?\\: bool\\}\\) does not accept non\\-empty\\-array\\\\.$#" count: 1 path: src/EventBus/Message.php @@ -35,6 +35,11 @@ parameters: count: 1 path: src/Store/ArrayStream.php + - + message: "#^Parameter \\#1 \\$headers of method Patchlevel\\\\EventSourcing\\\\EventBus\\\\Message\\\\:\\:withHeaders\\(\\) expects array\\{aggregateName\\?\\: string, aggregateId\\?\\: string, playhead\\?\\: int\\<1, max\\>, recordedOn\\?\\: DateTimeImmutable, newStreamStart\\?\\: bool, archived\\?\\: bool\\}, array\\ given\\.$#" + count: 1 + path: src/Store/DoctrineDbalStoreStream.php + - message: "#^Ternary operator condition is always true\\.$#" count: 1 diff --git a/src/EventBus/Message.php b/src/EventBus/Message.php index 7c98c15c0..e9899d68a 100644 --- a/src/EventBus/Message.php +++ b/src/EventBus/Message.php @@ -20,6 +20,15 @@ * archived?: bool, * ... * } + * + * @phpstan-type Headers = array{ + * aggregateName?: string, + * aggregateId?: string, + * playhead?: positive-int, + * recordedOn?: DateTimeImmutable, + * newStreamStart?: bool, + * archived?: bool + * } */ final class Message { diff --git a/src/Outbox/DoctrineOutboxStore.php b/src/Outbox/DoctrineOutboxStore.php index 970107921..46e253e7b 100644 --- a/src/Outbox/DoctrineOutboxStore.php +++ b/src/Outbox/DoctrineOutboxStore.php @@ -111,7 +111,7 @@ public function configureSchema(Schema $schema, Connection $connection): void private function extractId(Message $message): int { try { - $value = $message->customHeader(self::HEADER_OUTBOX_IDENTIFIER); + $value = $message->header(self::HEADER_OUTBOX_IDENTIFIER); } catch (HeaderNotFound) { throw OutboxHeaderIssue::missingHeader(self::HEADER_OUTBOX_IDENTIFIER); } diff --git a/src/Store/DoctrineDbalStoreStream.php b/src/Store/DoctrineDbalStoreStream.php index fdfbd255b..2c87b8e3a 100644 --- a/src/Store/DoctrineDbalStoreStream.php +++ b/src/Store/DoctrineDbalStoreStream.php @@ -87,7 +87,7 @@ private function buildGenerator( EventSerializer $serializer, AbstractPlatform $platform, ): Generator { - /** @var array{id: positive-int, aggregate: string, aggregate_id: string, playhead: int|string, event: string, payload: string, recorded_on: string, custom_headers: string} $data */ + /** @var array{id: positive-int, aggregate: string, aggregate_id: string, playhead: int|string, event: string, payload: string, recorded_on: string, archived: int|string, new_stream_start: int|string, custom_headers: string} $data */ foreach ($result->iterateAssociative() as $data) { if ($this->position === null) { $this->position = 0; diff --git a/src/Store/DoctrineHelper.php b/src/Store/DoctrineHelper.php index 30e766f6c..42f682851 100644 --- a/src/Store/DoctrineHelper.php +++ b/src/Store/DoctrineHelper.php @@ -9,7 +9,9 @@ use Doctrine\DBAL\Types\Type; use Doctrine\DBAL\Types\Types; +use function dd; use function is_array; +use function is_bool; use function is_int; final class DoctrineHelper diff --git a/tests/Integration/Store/StoreTest.php b/tests/Integration/Store/StoreTest.php index 8cf85a9e8..660c5a58f 100644 --- a/tests/Integration/Store/StoreTest.php +++ b/tests/Integration/Store/StoreTest.php @@ -53,12 +53,16 @@ public function testSave(): void ->withAggregateName('profile') ->withAggregateId('test') ->withPlayhead(1) - ->withRecordedOn(new DateTimeImmutable('2020-01-01 00:00:00')), + ->withRecordedOn(new DateTimeImmutable('2020-01-01 00:00:00')) + ->withArchived(false) + ->withNewStreamStart(false), Message::create(new ProfileCreated(ProfileId::fromString('test'), 'test')) ->withAggregateName('profile') ->withAggregateId('test') ->withPlayhead(2) - ->withRecordedOn(new DateTimeImmutable('2020-01-02 00:00:00')), + ->withRecordedOn(new DateTimeImmutable('2020-01-02 00:00:00')) + ->withArchived(false) + ->withNewStreamStart(false), ]; $this->store->save(...$messages); @@ -93,7 +97,9 @@ public function testLoad(): void ->withAggregateName('profile') ->withAggregateId('test') ->withPlayhead(1) - ->withRecordedOn(new DateTimeImmutable('2020-01-01 00:00:00')); + ->withRecordedOn(new DateTimeImmutable('2020-01-01 00:00:00')) + ->withArchived(false) + ->withNewStreamStart(false); $this->store->save($message); diff --git a/tests/Unit/EventBus/Serializer/EventSerializerMessageSerializerTest.php b/tests/Unit/EventBus/Serializer/EventSerializerMessageSerializerTest.php index 6b34a521f..ecbbebb01 100644 --- a/tests/Unit/EventBus/Serializer/EventSerializerMessageSerializerTest.php +++ b/tests/Unit/EventBus/Serializer/EventSerializerMessageSerializerTest.php @@ -41,7 +41,7 @@ public function testSerialize(): void $content = $serializer->serialize($message); - self::assertEquals('YToyOntzOjE1OiJzZXJpYWxpemVkRXZlbnQiO086NTE6IlBhdGNobGV2ZWxcRXZlbnRTb3VyY2luZ1xTZXJpYWxpemVyXFNlcmlhbGl6ZWRFdmVudCI6Mjp7czo0OiJuYW1lIjtzOjE1OiJwcm9maWxlX3Zpc2l0ZWQiO3M6NzoicGF5bG9hZCI7czo5OiJ7aWQ6IGZvb30iO31zOjc6ImhlYWRlcnMiO2E6Mzp7czoxMDoicmVjb3JkZWRPbiI7TzoxNzoiRGF0ZVRpbWVJbW11dGFibGUiOjM6e3M6NDoiZGF0ZSI7czoyNjoiMjAyMC0wMS0wMSAyMDowMDowMC4wMDAwMDAiO3M6MTM6InRpbWV6b25lX3R5cGUiO2k6MTtzOjg6InRpbWV6b25lIjtzOjY6IiswMTowMCI7fXM6MTQ6Im5ld1N0cmVhbVN0YXJ0IjtiOjA7czo4OiJhcmNoaXZlZCI7YjowO319', $content); + self::assertEquals('YToyOntzOjE1OiJzZXJpYWxpemVkRXZlbnQiO086NTE6IlBhdGNobGV2ZWxcRXZlbnRTb3VyY2luZ1xTZXJpYWxpemVyXFNlcmlhbGl6ZWRFdmVudCI6Mjp7czo0OiJuYW1lIjtzOjE1OiJwcm9maWxlX3Zpc2l0ZWQiO3M6NzoicGF5bG9hZCI7czo5OiJ7aWQ6IGZvb30iO31zOjc6ImhlYWRlcnMiO2E6MTp7czoxMDoicmVjb3JkZWRPbiI7TzoxNzoiRGF0ZVRpbWVJbW11dGFibGUiOjM6e3M6NDoiZGF0ZSI7czoyNjoiMjAyMC0wMS0wMSAyMDowMDowMC4wMDAwMDAiO3M6MTM6InRpbWV6b25lX3R5cGUiO2k6MTtzOjg6InRpbWV6b25lIjtzOjY6IiswMTowMCI7fX19', $content); } public function testDeserialize(): void diff --git a/tests/Unit/EventBus/Serializer/PhpNativeMessageSerializerTest.php b/tests/Unit/EventBus/Serializer/PhpNativeMessageSerializerTest.php index 05d3c16ba..d26ff2fb2 100644 --- a/tests/Unit/EventBus/Serializer/PhpNativeMessageSerializerTest.php +++ b/tests/Unit/EventBus/Serializer/PhpNativeMessageSerializerTest.php @@ -31,25 +31,23 @@ public function testSerialize(): void $content = $nativeSerializer->serialize($message); - self::assertEquals('Tzo0MToiUGF0Y2hsZXZlbFxFdmVudFNvdXJjaW5nXEV2ZW50QnVzXE1lc3NhZ2UiOjg6e3M6NTY6IgBQYXRjaGxldmVsXEV2ZW50U291cmNpbmdcRXZlbnRCdXNcTWVzc2FnZQBhZ2dyZWdhdGVOYW1lIjtOO3M6NTQ6IgBQYXRjaGxldmVsXEV2ZW50U291cmNpbmdcRXZlbnRCdXNcTWVzc2FnZQBhZ2dyZWdhdGVJZCI7TjtzOjUxOiIAUGF0Y2hsZXZlbFxFdmVudFNvdXJjaW5nXEV2ZW50QnVzXE1lc3NhZ2UAcGxheWhlYWQiO047czo1MzoiAFBhdGNobGV2ZWxcRXZlbnRTb3VyY2luZ1xFdmVudEJ1c1xNZXNzYWdlAHJlY29yZGVkT24iO086MTc6IkRhdGVUaW1lSW1tdXRhYmxlIjozOntzOjQ6ImRhdGUiO3M6MjY6IjIwMjAtMDEtMDEgMjA6MDA6MDAuMDAwMDAwIjtzOjEzOiJ0aW1lem9uZV90eXBlIjtpOjE7czo4OiJ0aW1lem9uZSI7czo2OiIrMDE6MDAiO31zOjU3OiIAUGF0Y2hsZXZlbFxFdmVudFNvdXJjaW5nXEV2ZW50QnVzXE1lc3NhZ2UAbmV3U3RyZWFtU3RhcnQiO2I6MDtzOjUxOiIAUGF0Y2hsZXZlbFxFdmVudFNvdXJjaW5nXEV2ZW50QnVzXE1lc3NhZ2UAYXJjaGl2ZWQiO2I6MDtzOjU2OiIAUGF0Y2hsZXZlbFxFdmVudFNvdXJjaW5nXEV2ZW50QnVzXE1lc3NhZ2UAY3VzdG9tSGVhZGVycyI7YTowOnt9czo0ODoiAFBhdGNobGV2ZWxcRXZlbnRTb3VyY2luZ1xFdmVudEJ1c1xNZXNzYWdlAGV2ZW50IjtPOjU4OiJQYXRjaGxldmVsXEV2ZW50U291cmNpbmdcVGVzdHNcVW5pdFxGaXh0dXJlXFByb2ZpbGVWaXNpdGVkIjoxOntzOjk6InZpc2l0b3JJZCI7Tzo1MzoiUGF0Y2hsZXZlbFxFdmVudFNvdXJjaW5nXFRlc3RzXFVuaXRcRml4dHVyZVxQcm9maWxlSWQiOjE6e3M6NTc6IgBQYXRjaGxldmVsXEV2ZW50U291cmNpbmdcVGVzdHNcVW5pdFxGaXh0dXJlXFByb2ZpbGVJZABpZCI7czozOiJmb28iO319fQ==', $content); + self::assertEquals('Tzo0MToiUGF0Y2hsZXZlbFxFdmVudFNvdXJjaW5nXEV2ZW50QnVzXE1lc3NhZ2UiOjI6e3M6NTA6IgBQYXRjaGxldmVsXEV2ZW50U291cmNpbmdcRXZlbnRCdXNcTWVzc2FnZQBoZWFkZXJzIjthOjE6e3M6MTA6InJlY29yZGVkT24iO086MTc6IkRhdGVUaW1lSW1tdXRhYmxlIjozOntzOjQ6ImRhdGUiO3M6MjY6IjIwMjAtMDEtMDEgMjA6MDA6MDAuMDAwMDAwIjtzOjEzOiJ0aW1lem9uZV90eXBlIjtpOjE7czo4OiJ0aW1lem9uZSI7czo2OiIrMDE6MDAiO319czo0ODoiAFBhdGNobGV2ZWxcRXZlbnRTb3VyY2luZ1xFdmVudEJ1c1xNZXNzYWdlAGV2ZW50IjtPOjU4OiJQYXRjaGxldmVsXEV2ZW50U291cmNpbmdcVGVzdHNcVW5pdFxGaXh0dXJlXFByb2ZpbGVWaXNpdGVkIjoxOntzOjk6InZpc2l0b3JJZCI7Tzo1MzoiUGF0Y2hsZXZlbFxFdmVudFNvdXJjaW5nXFRlc3RzXFVuaXRcRml4dHVyZVxQcm9maWxlSWQiOjE6e3M6NTc6IgBQYXRjaGxldmVsXEV2ZW50U291cmNpbmdcVGVzdHNcVW5pdFxGaXh0dXJlXFByb2ZpbGVJZABpZCI7czozOiJmb28iO319fQ==', $content); } public function testDeserialize(): void { - $event = new ProfileVisited( - ProfileId::fromString('foo'), - ); - + $event = new ProfileVisited(ProfileId::fromString('foo')); $nativeSerializer = new PhpNativeMessageSerializer(); - $message = $nativeSerializer->deserialize('Tzo0MToiUGF0Y2hsZXZlbFxFdmVudFNvdXJjaW5nXEV2ZW50QnVzXE1lc3NhZ2UiOjg6e3M6NTY6IgBQYXRjaGxldmVsXEV2ZW50U291cmNpbmdcRXZlbnRCdXNcTWVzc2FnZQBhZ2dyZWdhdGVOYW1lIjtOO3M6NTQ6IgBQYXRjaGxldmVsXEV2ZW50U291cmNpbmdcRXZlbnRCdXNcTWVzc2FnZQBhZ2dyZWdhdGVJZCI7TjtzOjUxOiIAUGF0Y2hsZXZlbFxFdmVudFNvdXJjaW5nXEV2ZW50QnVzXE1lc3NhZ2UAcGxheWhlYWQiO047czo1MzoiAFBhdGNobGV2ZWxcRXZlbnRTb3VyY2luZ1xFdmVudEJ1c1xNZXNzYWdlAHJlY29yZGVkT24iO086MTc6IkRhdGVUaW1lSW1tdXRhYmxlIjozOntzOjQ6ImRhdGUiO3M6MjY6IjIwMjAtMDEtMDEgMjA6MDA6MDAuMDAwMDAwIjtzOjEzOiJ0aW1lem9uZV90eXBlIjtpOjE7czo4OiJ0aW1lem9uZSI7czo2OiIrMDE6MDAiO31zOjU3OiIAUGF0Y2hsZXZlbFxFdmVudFNvdXJjaW5nXEV2ZW50QnVzXE1lc3NhZ2UAbmV3U3RyZWFtU3RhcnQiO2I6MDtzOjUxOiIAUGF0Y2hsZXZlbFxFdmVudFNvdXJjaW5nXEV2ZW50QnVzXE1lc3NhZ2UAYXJjaGl2ZWQiO2I6MDtzOjU2OiIAUGF0Y2hsZXZlbFxFdmVudFNvdXJjaW5nXEV2ZW50QnVzXE1lc3NhZ2UAY3VzdG9tSGVhZGVycyI7YTowOnt9czo0ODoiAFBhdGNobGV2ZWxcRXZlbnRTb3VyY2luZ1xFdmVudEJ1c1xNZXNzYWdlAGV2ZW50IjtPOjU4OiJQYXRjaGxldmVsXEV2ZW50U291cmNpbmdcVGVzdHNcVW5pdFxGaXh0dXJlXFByb2ZpbGVWaXNpdGVkIjoxOntzOjk6InZpc2l0b3JJZCI7Tzo1MzoiUGF0Y2hsZXZlbFxFdmVudFNvdXJjaW5nXFRlc3RzXFVuaXRcRml4dHVyZVxQcm9maWxlSWQiOjE6e3M6NTc6IgBQYXRjaGxldmVsXEV2ZW50U291cmNpbmdcVGVzdHNcVW5pdFxGaXh0dXJlXFByb2ZpbGVJZABpZCI7czozOiJmb28iO319fQ=='); + $message = $nativeSerializer->deserialize('Tzo0MToiUGF0Y2hsZXZlbFxFdmVudFNvdXJjaW5nXEV2ZW50QnVzXE1lc3NhZ2UiOjI6e3M6NTA6IgBQYXRjaGxldmVsXEV2ZW50U291cmNpbmdcRXZlbnRCdXNcTWVzc2FnZQBoZWFkZXJzIjthOjE6e3M6MTA6InJlY29yZGVkT24iO086MTc6IkRhdGVUaW1lSW1tdXRhYmxlIjozOntzOjQ6ImRhdGUiO3M6MjY6IjIwMjAtMDEtMDEgMjA6MDA6MDAuMDAwMDAwIjtzOjEzOiJ0aW1lem9uZV90eXBlIjtpOjE7czo4OiJ0aW1lem9uZSI7czo2OiIrMDE6MDAiO319czo0ODoiAFBhdGNobGV2ZWxcRXZlbnRTb3VyY2luZ1xFdmVudEJ1c1xNZXNzYWdlAGV2ZW50IjtPOjU4OiJQYXRjaGxldmVsXEV2ZW50U291cmNpbmdcVGVzdHNcVW5pdFxGaXh0dXJlXFByb2ZpbGVWaXNpdGVkIjoxOntzOjk6InZpc2l0b3JJZCI7Tzo1MzoiUGF0Y2hsZXZlbFxFdmVudFNvdXJjaW5nXFRlc3RzXFVuaXRcRml4dHVyZVxQcm9maWxlSWQiOjE6e3M6NTc6IgBQYXRjaGxldmVsXEV2ZW50U291cmNpbmdcVGVzdHNcVW5pdFxGaXh0dXJlXFByb2ZpbGVJZABpZCI7czozOiJmb28iO319fQ=='); self::assertEquals($event, $message->event()); - self::assertEquals([ - 'recordedOn' => new DateTimeImmutable('2020-01-01T20:00:00.000000+0100'), - 'newStreamStart' => false, - 'archived' => false, - ], $message->headers()); + self::assertEquals( + [ + 'recordedOn' => new DateTimeImmutable('2020-01-01T20:00:00.000000+0100'), + ], + $message->headers(), + ); } public function testDeserializeDecodeFailed(): void diff --git a/tests/Unit/Store/DoctrineDbalStoreTest.php b/tests/Unit/Store/DoctrineDbalStoreTest.php index 684d1b58d..3a164d749 100644 --- a/tests/Unit/Store/DoctrineDbalStoreTest.php +++ b/tests/Unit/Store/DoctrineDbalStoreTest.php @@ -102,6 +102,8 @@ public function testLoadWithOneEvent(): void 'event' => 'profile.created', 'payload' => '{"profileId": "1", "email": "s"}', 'recorded_on' => '2021-02-17 10:00:00', + 'archived' => '0', + 'new_stream_start' => '0', 'custom_headers' => '[]', ], ], @@ -124,9 +126,9 @@ public function testLoadWithOneEvent(): void $selectSqlBuilder->buildSQL(Argument::type(SelectQuery::class)) ->willReturn('SELECT * FROM eventstore WHERE (aggregate = :aggregate) AND (aggregate_id = :id) AND (playhead > :playhead) AND (archived = :archived) ORDER BY id ASC'); - $abstractPlatform->createSelectSQLBuilder() - ->willReturn($selectSqlBuilder->reveal()); - $abstractPlatform->getDateTimeTzFormatString()->willReturn('Y-m-d H:i:s'); + $abstractPlatform->createSelectSQLBuilder()->shouldBeCalledOnce()->willReturn($selectSqlBuilder->reveal()); + $abstractPlatform->getDateTimeTzFormatString()->shouldBeCalledOnce()->willReturn('Y-m-d H:i:s'); + $abstractPlatform->convertFromBoolean('0')->shouldBeCalledTimes(2)->willReturn(false); $connection->getDatabasePlatform()->willReturn($abstractPlatform->reveal());