diff --git a/UPGRADE-2.0.md b/UPGRADE-2.0.md deleted file mode 100644 index 938d230c0..000000000 --- a/UPGRADE-2.0.md +++ /dev/null @@ -1,402 +0,0 @@ -# Upgrading to v2 - -We are only providing here the most important changes in detail. For the full BC-Break list go to -the [full BC-Break list](#Full-BC-Break-list) - -## Detailed change list - -### Events - -* Removed `AggregateChanged` abstract class. Use `#[Event('eventName')]` instead. - -Before: - -```php -use Patchlevel\EventSourcing\Aggregate\AggregateChanged; - -final class ProfileCreated extends AggregateChanged -{ - public static function raise(string $id, string $name): static - { - return new static($id, ['profileId' => $id, 'name' => $name]); - } - - public function profileId(): string - { - return $this->aggregateId; - } - - public function name(): string - { - return $this->payload['name']; - } -} -``` - -After: - -```php -#[Event('profile.created')] -final class ProfileCreated -{ - public function __construct( - public readonly string $profileId, - public readonly string $name - ) - { - } -} -``` - -* Added `#[Normalize(new YourNormalizer())]` for more complicated properties like ValueObjects. -* Added `#[NormalizedName('foo')]`. - -```php -use YourApp\EmailNormalizer; -use Patchlevel\EventSourcing\Attribute\Normalize; - -#[Event('profile.created')] -final class ProfileCreated -{ - public function __construct( - public readonly string $profileId, - public readonly string $name, - #[Normalize(new EmailNormalizer())] - public readonly Email $email, - ) - { - } -} -``` - -### Aggregates - -* Aggregates now needs an attribute `#[Aggregate('name')]` with a unique name. -* Removed `AttributeApplyMethod` trait. Is default behaviour now. -* Removed `StrictApplyMethod` trait. Is default behaviour now. -* Removed `NonStrictApplyMethod` trait. Use `#[SuppressMissingApply]` instead. -* Rename method `record` to `recordThat`. - -### Schema - -* Changed database column from `aggregateId` to `aggregate_id`. -* Changed database column from `recordedOn` to `recorded_on`. -* Changed value of database column `event` from FQCN of the event to the name provided via the attribute. - -Update the two columns, for single table store: - -```SQL -ALTER TABLE eventstore RENAME COLUMN aggregateId TO aggregate_id; -ALTER TABLE eventstore RENAME COLUMN recordedOn TO recorded_on; -``` - -For the event name change we recommend using the upcasting feature like this: - -```php -use Patchlevel\EventSourcing\Metadata\Event\EventRegistry; -use Patchlevel\EventSourcing\Serializer\Upcast\Upcaster; -use Patchlevel\EventSourcing\Serializer\Upcast\Upcast; - -final class LegacyEventNameUpaster implements Upcaster -{ - public function __construct(private readonly EventRegistry $eventRegistry){} - - public function __invoke(Upcast $upcast): Upcast - { - return new Upcast($this->eventRegistry->eventName($upcast->eventName), $upcast->payload); - } -} -``` - -If you dont want to upcast everytime you could also use the pipeline to recreate the event-stream with the fixed event -name. See for that the documentation. - -### Store & Pipeline - -* Renamed and adjusted parameters for `save` at `Store` -* Removed `saveBatch` at `Store`. Use new `save` instead. -* Renamed and adjusted parameters for `save` at `PipelineStore` -* Removed `saveBatch` at `PipelineStore`. Use new `save` instead. -* Changed parameter for `Middleware::__invoke` from `EventBucket` to `Message`. -* Removed `EventBucket`. `Message` is kinda a replacement. -* Removed `ClassRenameMiddleware`. This is not needed anymore since the event name is saved instead. -* Removed `FromIndexEventMiddleware`. - -### Projection - -* Removed `create` method from `Projection` interface. Use `#[Create]` instead. -* Removed `drop` method from `Projection` interface. Use `#[Drop]` instead. -* Removed `handledEvents` method from `Projection` interface. Use `#[Handle]` instead. -* Rename `ProjectionRepository` to `ProjectionHandler`. -* Rename `DefaultProjectionRepistory` to `DefaultProjectionHandler`. - -### EventBus - -* Changed `DefaultEventBus::dispatch` to accept multiple `Message` objects instead of one `AggregateChanged`. - -### Snapshot - -* Removed `SnapshotableAggregateRoot` abstract class. Use `#[Snapshot]` instead. - -### Clock - -* Removed `Clock` singleton class. See `SystemClock`, `FrozenClock` as an implementation of the `Clock` interface - instead. - -## Full BC-Break list - -#### Added - -- [BC] Method save() was added to interface Patchlevel\EventSourcing\Store\PipelineStore -- [BC] Method save() was added to interface Patchlevel\EventSourcing\Store\Store - -#### Changed - -- [BC] The parameter $event of Patchlevel\EventSourcing\EventBus\EventBus#dispatch() changed from - Patchlevel\EventSourcing\Aggregate\AggregateChanged to a non-contravariant Patchlevel\EventSourcing\EventBus\Message -- [BC] The parameter $event of Patchlevel\EventSourcing\EventBus\EventBus#dispatch() changed from - Patchlevel\EventSourcing\Aggregate\AggregateChanged to Patchlevel\EventSourcing\EventBus\Message -- [BC] Parameter 0 of Patchlevel\EventSourcing\EventBus\EventBus#dispatch() changed name from event to messages -- [BC] The parameter $event of Patchlevel\EventSourcing\EventBus\Listener#__invoke() changed from - Patchlevel\EventSourcing\Aggregate\AggregateChanged to a non-contravariant Patchlevel\EventSourcing\EventBus\Message -- [BC] The parameter $event of Patchlevel\EventSourcing\EventBus\Listener#__invoke() changed from - Patchlevel\EventSourcing\Aggregate\AggregateChanged to Patchlevel\EventSourcing\EventBus\Message -- [BC] Parameter 0 of Patchlevel\EventSourcing\EventBus\Listener#__invoke() changed name from event to message -- [BC] The parameter $event of Patchlevel\EventSourcing\EventBus\SymfonyEventBus#dispatch() changed from - Patchlevel\EventSourcing\Aggregate\AggregateChanged to a non-contravariant Patchlevel\EventSourcing\EventBus\Message -- [BC] The parameter $event of Patchlevel\EventSourcing\EventBus\DefaultEventBus#dispatch() changed from - Patchlevel\EventSourcing\Aggregate\AggregateChanged to a non-contravariant Patchlevel\EventSourcing\EventBus\Message -- [BC] The parameter $event of Patchlevel\EventSourcing\WatchServer\WatchServerClient#send() changed from - Patchlevel\EventSourcing\Aggregate\AggregateChanged to a non-contravariant Patchlevel\EventSourcing\EventBus\Message -- [BC] The parameter $event of Patchlevel\EventSourcing\WatchServer\WatchServerClient#send() changed from - Patchlevel\EventSourcing\Aggregate\AggregateChanged to Patchlevel\EventSourcing\EventBus\Message -- [BC] Parameter 0 of Patchlevel\EventSourcing\WatchServer\WatchServerClient#send() changed name from event to message -- [BC] The parameter $event of Patchlevel\EventSourcing\WatchServer\WatchListener#__invoke() changed from - Patchlevel\EventSourcing\Aggregate\AggregateChanged to a non-contravariant Patchlevel\EventSourcing\EventBus\Message -- [BC] The parameter $snapshot of Patchlevel\EventSourcing\Snapshot\SnapshotStore#save() changed from - Patchlevel\EventSourcing\Snapshot\Snapshot to a non-contravariant Patchlevel\EventSourcing\Aggregate\AggregateRoot -- [BC] The parameter $snapshot of Patchlevel\EventSourcing\Snapshot\SnapshotStore#save() changed from - Patchlevel\EventSourcing\Snapshot\Snapshot to Patchlevel\EventSourcing\Aggregate\AggregateRoot -- [BC] Parameter 0 of Patchlevel\EventSourcing\Snapshot\SnapshotStore#save() changed name from snapshot to aggregateRoot -- [BC] The return type of Patchlevel\EventSourcing\Snapshot\SnapshotStore#load() changed from - Patchlevel\EventSourcing\Snapshot\Snapshot to the non-covariant Patchlevel\EventSourcing\Aggregate\AggregateRoot -- [BC] The return type of Patchlevel\EventSourcing\Snapshot\SnapshotStore#load() changed from - Patchlevel\EventSourcing\Snapshot\Snapshot to Patchlevel\EventSourcing\Aggregate\AggregateRoot -- [BC] Parameter 0 of Patchlevel\EventSourcing\Snapshot\SnapshotStore#load() changed name from aggregate to - aggregateClass -- [BC] Class Patchlevel\EventSourcing\Attribute\Apply became final -- [BC] The parameter $aggregateChangedClass of Patchlevel\EventSourcing\Attribute\Apply#__construct() changed from - string to string|null -- [BC] Parameter 0 of Patchlevel\EventSourcing\Attribute\Apply#__construct() changed name from aggregateChangedClass to - eventClass -- [BC] Class Patchlevel\EventSourcing\Attribute\SuppressMissingApply became final -- [BC] Class Patchlevel\EventSourcing\Attribute\Handle became final -- [BC] Parameter 0 of Patchlevel\EventSourcing\Attribute\Handle#__construct() changed name from aggregateChangedClass to - eventClass -- [BC] The parameter $bucket of Patchlevel\EventSourcing\Pipeline\Target\Target#save() changed from - Patchlevel\EventSourcing\Pipeline\EventBucket to a non-contravariant Patchlevel\EventSourcing\EventBus\Message -- [BC] The parameter $bucket of Patchlevel\EventSourcing\Pipeline\Target\Target#save() changed from - Patchlevel\EventSourcing\Pipeline\EventBucket to Patchlevel\EventSourcing\EventBus\Message -- [BC] Parameter 0 of Patchlevel\EventSourcing\Pipeline\Target\Target#save() changed name from bucket to message -- [BC] The parameter $bucket of Patchlevel\EventSourcing\Pipeline\Target\InMemoryTarget#save() changed from - Patchlevel\EventSourcing\Pipeline\EventBucket to a non-contravariant Patchlevel\EventSourcing\EventBus\Message -- [BC] The parameter $bucket of Patchlevel\EventSourcing\Pipeline\Target\StoreTarget#save() changed from - Patchlevel\EventSourcing\Pipeline\EventBucket to a non-contravariant Patchlevel\EventSourcing\EventBus\Message -- [BC] The parameter $bucket of Patchlevel\EventSourcing\Pipeline\Target\ProjectionTarget#save() changed from - Patchlevel\EventSourcing\Pipeline\EventBucket to a non-contravariant Patchlevel\EventSourcing\EventBus\Message -- [BC] The parameter $bucket of Patchlevel\EventSourcing\Pipeline\Middleware\UntilEventMiddleware#__invoke() changed - from Patchlevel\EventSourcing\Pipeline\EventBucket to a non-contravariant Patchlevel\EventSourcing\EventBus\Message -- [BC] The parameter $bucket of Patchlevel\EventSourcing\Pipeline\Middleware\ChainMiddleware#__invoke() changed from - Patchlevel\EventSourcing\Pipeline\EventBucket to a non-contravariant Patchlevel\EventSourcing\EventBus\Message -- [BC] The parameter $bucket of Patchlevel\EventSourcing\Pipeline\Middleware\ExcludeEventMiddleware#__invoke() changed - from Patchlevel\EventSourcing\Pipeline\EventBucket to a non-contravariant Patchlevel\EventSourcing\EventBus\Message -- [BC] The parameter $bucket of Patchlevel\EventSourcing\Pipeline\Middleware\RecalculatePlayheadMiddleware#__invoke() - changed from Patchlevel\EventSourcing\Pipeline\EventBucket to a non-contravariant - Patchlevel\EventSourcing\EventBus\Message -- [BC] The parameter $bucket of Patchlevel\EventSourcing\Pipeline\Middleware\Middleware#__invoke() changed from - Patchlevel\EventSourcing\Pipeline\EventBucket to a non-contravariant Patchlevel\EventSourcing\EventBus\Message -- [BC] The parameter $bucket of Patchlevel\EventSourcing\Pipeline\Middleware\Middleware#__invoke() changed from - Patchlevel\EventSourcing\Pipeline\EventBucket to Patchlevel\EventSourcing\EventBus\Message -- [BC] Parameter 0 of Patchlevel\EventSourcing\Pipeline\Middleware\Middleware#__invoke() changed name from bucket to - message -- [BC] The parameter $bucket of Patchlevel\EventSourcing\Pipeline\Middleware\IncludeEventMiddleware#__invoke() changed - from Patchlevel\EventSourcing\Pipeline\EventBucket to a non-contravariant Patchlevel\EventSourcing\EventBus\Message -- [BC] The parameter $bucket of Patchlevel\EventSourcing\Pipeline\Middleware\ReplaceEventMiddleware#__invoke() changed - from Patchlevel\EventSourcing\Pipeline\EventBucket to a non-contravariant Patchlevel\EventSourcing\EventBus\Message -- [BC] The parameter $bucket of Patchlevel\EventSourcing\Pipeline\Middleware\FilterEventMiddleware#__invoke() changed - from Patchlevel\EventSourcing\Pipeline\EventBucket to a non-contravariant Patchlevel\EventSourcing\EventBus\Message -- [BC] The parameter $aggregate of Patchlevel\EventSourcing\Aggregate\ApplyMethodNotFound#__construct() changed from - Patchlevel\EventSourcing\Aggregate\AggregateRoot to a non-contravariant string -- [BC] The parameter $event of Patchlevel\EventSourcing\Aggregate\ApplyMethodNotFound#__construct() changed from - Patchlevel\EventSourcing\Aggregate\AggregateChanged to a non-contravariant string -- [BC] The parameter $event of Patchlevel\EventSourcing\Aggregate\AggregateRoot#apply() changed from - Patchlevel\EventSourcing\Aggregate\AggregateChanged to object -- [BC] The number of required arguments for Patchlevel\EventSourcing\Store\DoctrineStore#__construct() increased from 1 - to 3 -- [BC] Parameter 0 of Patchlevel\EventSourcing\Store\DoctrineStore#__construct() changed name from eventConnection to - connection -- [BC] The parameter $aggregates of Patchlevel\EventSourcing\Store\SingleTableStore#__construct() changed from array to - a non-contravariant Patchlevel\EventSourcing\Serializer\EventSerializer -- [BC] The parameter $storeTableName of Patchlevel\EventSourcing\Store\SingleTableStore#__construct() changed from - string to a non-contravariant Patchlevel\EventSourcing\Metadata\AggregateRoot\AggregateRootRegistry -- [BC] The number of required arguments for Patchlevel\EventSourcing\Store\MultiTableStore#__construct() increased from - 2 to 3 -- [BC] The parameter $aggregates of Patchlevel\EventSourcing\Store\MultiTableStore#__construct() changed from array to a - non-contravariant Patchlevel\EventSourcing\Serializer\EventSerializer -- [BC] The parameter $metadataTableName of Patchlevel\EventSourcing\Store\MultiTableStore#__construct() changed from - string to a non-contravariant Patchlevel\EventSourcing\Metadata\AggregateRoot\AggregateRootRegistry -- [BC] The parameter $definition of Symfony\Component\Console\Command\Command#setDefinition() changed from no type to a - non-contravariant array|Symfony\Component\Console\Input\InputDefinition -- [BC] The parameter $default of Symfony\Component\Console\Command\Command#addArgument() changed from no type to a - non-contravariant mixed|null -- [BC] The parameter $shortcut of Symfony\Component\Console\Command\Command#addOption() changed from no type to a - non-contravariant string|array|null -- [BC] The parameter $default of Symfony\Component\Console\Command\Command#addOption() changed from no type to a - non-contravariant mixed|null -- [BC] The parameter $projectionRepository of Patchlevel\EventSourcing\Console\Command\ProjectionRebuildCommand#__ - construct() changed from Patchlevel\EventSourcing\Projection\ProjectionRepository to a non-contravariant - Patchlevel\EventSourcing\Projection\ProjectionHandler -- [BC] The parameter $definition of Symfony\Component\Console\Command\Command#setDefinition() changed from no type to a - non-contravariant array|Symfony\Component\Console\Input\InputDefinition -- [BC] The parameter $default of Symfony\Component\Console\Command\Command#addArgument() changed from no type to a - non-contravariant mixed|null -- [BC] The parameter $shortcut of Symfony\Component\Console\Command\Command#addOption() changed from no type to a - non-contravariant string|array|null -- [BC] The parameter $default of Symfony\Component\Console\Command\Command#addOption() changed from no type to a - non-contravariant mixed|null -- [BC] The parameter $definition of Symfony\Component\Console\Command\Command#setDefinition() changed from no type to a - non-contravariant array|Symfony\Component\Console\Input\InputDefinition -- [BC] The parameter $default of Symfony\Component\Console\Command\Command#addArgument() changed from no type to a - non-contravariant mixed|null -- [BC] The parameter $shortcut of Symfony\Component\Console\Command\Command#addOption() changed from no type to a - non-contravariant string|array|null -- [BC] The parameter $default of Symfony\Component\Console\Command\Command#addOption() changed from no type to a - non-contravariant mixed|null -- [BC] The parameter $definition of Symfony\Component\Console\Command\Command#setDefinition() changed from no type to a - non-contravariant array|Symfony\Component\Console\Input\InputDefinition -- [BC] The parameter $default of Symfony\Component\Console\Command\Command#addArgument() changed from no type to a - non-contravariant mixed|null -- [BC] The parameter $shortcut of Symfony\Component\Console\Command\Command#addOption() changed from no type to a - non-contravariant string|array|null -- [BC] The parameter $default of Symfony\Component\Console\Command\Command#addOption() changed from no type to a - non-contravariant mixed|null -- [BC] The number of required arguments for Patchlevel\EventSourcing\Console\Command\WatchCommand#__construct() - increased from 1 to 2 -- [BC] The parameter $definition of Symfony\Component\Console\Command\Command#setDefinition() changed from no type to a - non-contravariant array|Symfony\Component\Console\Input\InputDefinition -- [BC] The parameter $default of Symfony\Component\Console\Command\Command#addArgument() changed from no type to a - non-contravariant mixed|null -- [BC] The parameter $shortcut of Symfony\Component\Console\Command\Command#addOption() changed from no type to a - non-contravariant string|array|null -- [BC] The parameter $default of Symfony\Component\Console\Command\Command#addOption() changed from no type to a - non-contravariant mixed|null -- [BC] The parameter $definition of Symfony\Component\Console\Command\Command#setDefinition() changed from no type to a - non-contravariant array|Symfony\Component\Console\Input\InputDefinition -- [BC] The parameter $default of Symfony\Component\Console\Command\Command#addArgument() changed from no type to a - non-contravariant mixed|null -- [BC] The parameter $shortcut of Symfony\Component\Console\Command\Command#addOption() changed from no type to a - non-contravariant string|array|null -- [BC] The parameter $default of Symfony\Component\Console\Command\Command#addOption() changed from no type to a - non-contravariant mixed|null -- [BC] The parameter $definition of Symfony\Component\Console\Command\Command#setDefinition() changed from no type to a - non-contravariant array|Symfony\Component\Console\Input\InputDefinition -- [BC] The parameter $default of Symfony\Component\Console\Command\Command#addArgument() changed from no type to a - non-contravariant mixed|null -- [BC] The parameter $shortcut of Symfony\Component\Console\Command\Command#addOption() changed from no type to a - non-contravariant string|array|null -- [BC] The parameter $default of Symfony\Component\Console\Command\Command#addOption() changed from no type to a - non-contravariant mixed|null -- [BC] The parameter $projectionRepository of Patchlevel\EventSourcing\Console\Command\ProjectionCreateCommand#__ - construct() changed from Patchlevel\EventSourcing\Projection\ProjectionRepository to a non-contravariant - Patchlevel\EventSourcing\Projection\ProjectionHandler -- [BC] The parameter $definition of Symfony\Component\Console\Command\Command#setDefinition() changed from no type to a - non-contravariant array|Symfony\Component\Console\Input\InputDefinition -- [BC] The parameter $default of Symfony\Component\Console\Command\Command#addArgument() changed from no type to a - non-contravariant mixed|null -- [BC] The parameter $shortcut of Symfony\Component\Console\Command\Command#addOption() changed from no type to a - non-contravariant string|array|null -- [BC] The parameter $default of Symfony\Component\Console\Command\Command#addOption() changed from no type to a - non-contravariant mixed|null -- [BC] The number of required arguments for Patchlevel\EventSourcing\Console\Command\ShowCommand#__construct() increased - from 2 to 3 -- [BC] The parameter $aggregates of Patchlevel\EventSourcing\Console\Command\ShowCommand#__construct() changed from - array to a non-contravariant Patchlevel\EventSourcing\Serializer\EventSerializer -- [BC] The parameter $definition of Symfony\Component\Console\Command\Command#setDefinition() changed from no type to a - non-contravariant array|Symfony\Component\Console\Input\InputDefinition -- [BC] The parameter $default of Symfony\Component\Console\Command\Command#addArgument() changed from no type to a - non-contravariant mixed|null -- [BC] The parameter $shortcut of Symfony\Component\Console\Command\Command#addOption() changed from no type to a - non-contravariant string|array|null -- [BC] The parameter $default of Symfony\Component\Console\Command\Command#addOption() changed from no type to a - non-contravariant mixed|null -- [BC] The parameter $projectionRepository of Patchlevel\EventSourcing\Console\Command\ProjectionDropCommand#__ - construct() changed from Patchlevel\EventSourcing\Projection\ProjectionRepository to a non-contravariant - Patchlevel\EventSourcing\Projection\ProjectionHandler -- [BC] The parameter $definition of Symfony\Component\Console\Command\Command#setDefinition() changed from no type to a - non-contravariant array|Symfony\Component\Console\Input\InputDefinition -- [BC] The parameter $default of Symfony\Component\Console\Command\Command#addArgument() changed from no type to a - non-contravariant mixed|null -- [BC] The parameter $shortcut of Symfony\Component\Console\Command\Command#addOption() changed from no type to a - non-contravariant string|array|null -- [BC] The parameter $default of Symfony\Component\Console\Command\Command#addOption() changed from no type to a - non-contravariant mixed|null -- [BC] The parameter $repository of Patchlevel\EventSourcing\Projection\ProjectionListener#__construct() changed from - Patchlevel\EventSourcing\Projection\ProjectionRepository to a non-contravariant - Patchlevel\EventSourcing\Projection\ProjectionHandler -- [BC] The parameter $event of Patchlevel\EventSourcing\Projection\ProjectionListener#__invoke() changed from - Patchlevel\EventSourcing\Aggregate\AggregateChanged to a non-contravariant Patchlevel\EventSourcing\EventBus\Message - -#### Removed - -- [BC] Class Patchlevel\EventSourcing\Clock has been deleted -- [BC] Class Patchlevel\EventSourcing\WatchServer\DefaultWatchServerClient has been deleted -- [BC] Class Patchlevel\EventSourcing\WatchServer\DefaultWatchServer has been deleted -- [BC] Class Patchlevel\EventSourcing\Repository\SnapshotRepository has been deleted -- [BC] Class Patchlevel\EventSourcing\Snapshot\Psr6SnapshotStore has been deleted -- [BC] Class Patchlevel\EventSourcing\Snapshot\Psr16SnapshotStore has been deleted -- [BC] Class Patchlevel\EventSourcing\Snapshot\BatchSnapshotStore has been deleted -- [BC] Class Patchlevel\EventSourcing\Snapshot\InMemorySnapshotStore has been deleted -- [BC] Method Patchlevel\EventSourcing\Attribute\Apply#aggregateChangedClass() was removed -- [BC] Method Patchlevel\EventSourcing\Attribute\Handle#aggregateChangedClass() was removed -- [BC] Class Patchlevel\EventSourcing\Pipeline\Target\ProjectionRepositoryTarget has been deleted -- [BC] Method Patchlevel\EventSourcing\Pipeline\Target\InMemoryTarget#buckets() was removed -- [BC] Class Patchlevel\EventSourcing\Pipeline\EventBucket has been deleted -- [BC] Class Patchlevel\EventSourcing\Pipeline\Middleware\ClassRenameMiddleware has been deleted -- [BC] Method Patchlevel\EventSourcing\Pipeline\Middleware\RecalculatePlayheadMiddleware#__construct() was removed -- [BC] Class Patchlevel\EventSourcing\Pipeline\Middleware\FromIndexEventMiddleware has been deleted -- [BC] Class Patchlevel\EventSourcing\Aggregate\StrictApplyMethod has been deleted -- [BC] Class Patchlevel\EventSourcing\Aggregate\AttributeApplyMethod has been deleted -- [BC] Class Patchlevel\EventSourcing\Aggregate\AggregateChangeRecordedAlready has been deleted -- [BC] Class Patchlevel\EventSourcing\Aggregate\DuplicateApplyMethod has been deleted -- [BC] Class Patchlevel\EventSourcing\Aggregate\AggregateChanged has been deleted -- [BC] Class Patchlevel\EventSourcing\Aggregate\SnapshotableAggregateRoot has been deleted -- [BC] Class Patchlevel\EventSourcing\Aggregate\ClockRecordDate has been deleted -- [BC] Class Patchlevel\EventSourcing\Aggregate\NonStrictApplyMethod has been deleted -- [BC] Method Patchlevel\EventSourcing\Aggregate\AggregateRoot#record() was removed -- [BC] Method Patchlevel\EventSourcing\Aggregate\AggregateRoot::createFromEventStream() was removed -- [BC] Class Patchlevel\EventSourcing\Aggregate\AggregateChangeNotRecorded has been deleted -- [BC] Class Patchlevel\EventSourcing\Aggregate\PlayheadSequenceMismatch has been deleted -- [BC] Class Patchlevel\EventSourcing\Aggregate\ApplyAttributeNotFound has been deleted -- [BC] Method Patchlevel\EventSourcing\Store\PipelineStore#saveEventBucket() was removed -- [BC] Method Patchlevel\EventSourcing\Store\Store#saveBatch() was removed -- [BC] Method Patchlevel\EventSourcing\Store\DoctrineStore::normalizeResult() was removed -- [BC] Method Patchlevel\EventSourcing\Store\Store#saveBatch() was removed -- [BC] Class Patchlevel\EventSourcing\Store\AggregateIdMismatch has been deleted -- [BC] Method Patchlevel\EventSourcing\Store\Store#saveBatch() was removed -- [BC] Method Patchlevel\EventSourcing\Store\SingleTableStore#saveBatch() was removed -- [BC] Method Patchlevel\EventSourcing\Store\SingleTableStore#saveEventBucket() was removed -- [BC] Method Patchlevel\EventSourcing\Store\DoctrineStore::normalizeResult() was removed -- [BC] Method Patchlevel\EventSourcing\Store\MultiTableStore#saveBatch() was removed -- [BC] Method Patchlevel\EventSourcing\Store\MultiTableStore#saveEventBucket() was removed -- [BC] Method Patchlevel\EventSourcing\Store\DoctrineStore::normalizeResult() was removed -- [BC] Class Patchlevel\EventSourcing\Store\AggregateNotDefined has been deleted -- [BC] Class Patchlevel\EventSourcing\Console\EventPrinter has been deleted -- [BC] Method Patchlevel\EventSourcing\Projection\Projection#handledEvents() was removed -- [BC] Method Patchlevel\EventSourcing\Projection\Projection#create() was removed -- [BC] Method Patchlevel\EventSourcing\Projection\Projection#drop() was removed -- [BC] Class Patchlevel\EventSourcing\Projection\AttributeHandleMethod has been deleted -- [BC] Class Patchlevel\EventSourcing\Projection\MethodDoesNotExist has been deleted -- [BC] Class Patchlevel\EventSourcing\Projection\ProjectionRepository has been deleted -- [BC] Class Patchlevel\EventSourcing\Projection\DefaultProjectionRepository has been deleted -- [BC] Class Patchlevel\EventSourcing\Projection\DuplicateHandleMethod has been deleted -- [BC] Class Patchlevel\EventSourcing\Projection\ProjectionException has been deleted diff --git a/UPGRADE-3.0.md b/UPGRADE-3.0.md deleted file mode 100644 index 3793a144e..000000000 --- a/UPGRADE-3.0.md +++ /dev/null @@ -1,2 +0,0 @@ -The upgrade path is located in our docs. Please have a look at -[here](https://patchlevel.github.io/event-sourcing-docs/3.0/UPGRADE-3.0/). diff --git a/baseline.xml b/baseline.xml index e11f9c79d..d51023299 100644 --- a/baseline.xml +++ b/baseline.xml @@ -99,15 +99,9 @@ - - - - - - + + getClassName()]]> + diff --git a/deptrac-baseline.yaml b/deptrac-baseline.yaml index fe42e99fd..ed8398130 100644 --- a/deptrac-baseline.yaml +++ b/deptrac-baseline.yaml @@ -1,11 +1,5 @@ deptrac: skip_violations: - Patchlevel\EventSourcing\Aggregate\AggregateRootId: - - Patchlevel\EventSourcing\Serializer\Normalizer\IdNormalizer - Patchlevel\EventSourcing\Aggregate\CustomId: - - Patchlevel\EventSourcing\Serializer\Normalizer\IdNormalizer - Patchlevel\EventSourcing\Aggregate\Uuid: - - Patchlevel\EventSourcing\Serializer\Normalizer\IdNormalizer Patchlevel\EventSourcing\Attribute\Processor: - Patchlevel\EventSourcing\Subscription\RunMode Patchlevel\EventSourcing\Attribute\Projector: @@ -14,3 +8,9 @@ deptrac: - Patchlevel\EventSourcing\Aggregate\AggregateRoot Patchlevel\EventSourcing\Attribute\Subscriber: - Patchlevel\EventSourcing\Subscription\RunMode + Patchlevel\EventSourcing\Identifier\CustomId: + - Patchlevel\EventSourcing\Serializer\Normalizer\IdNormalizer + Patchlevel\EventSourcing\Identifier\Identifier: + - Patchlevel\EventSourcing\Serializer\Normalizer\IdNormalizer + Patchlevel\EventSourcing\Identifier\Uuid: + - Patchlevel\EventSourcing\Serializer\Normalizer\IdNormalizer diff --git a/deptrac.yaml b/deptrac.yaml index ded380b15..c785f07f3 100644 --- a/deptrac.yaml +++ b/deptrac.yaml @@ -33,6 +33,10 @@ deptrac: collectors: - type: directory value: src/EventBus/.* + - name: Identifier + collectors: + - type: directory + value: src/Identifier/.* - name: Message collectors: - type: directory @@ -104,12 +108,14 @@ deptrac: ruleset: Aggregate: - Attribute + - Identifier - MetadataAggregate Attribute: Clock: CommandBus: - Aggregate - Attribute + - Identifier - MetadataAggregate - Repository Console: @@ -159,6 +165,7 @@ deptrac: - Aggregate - Attribute - Clock + - Identifier - Message - MetadataEvent - MetadataSubscriber @@ -170,6 +177,7 @@ deptrac: Repository: - Aggregate - Clock + - Identifier - Message - MetadataAggregate - MetadataEvent @@ -178,12 +186,13 @@ deptrac: - Store Schema: Serializer: - - Aggregate - Cryptography + - Identifier - MetadataEvent Snapshot: - Aggregate - Cryptography + - Identifier - MetadataAggregate Store: - Aggregate diff --git a/docs/mkdocs.yml b/docs/mkdocs.yml index eb2dadbb1..342d3913a 100644 --- a/docs/mkdocs.yml +++ b/docs/mkdocs.yml @@ -101,7 +101,7 @@ nav: - Event Bus: event_bus.md - Query Bus: query_bus.md - Advanced: - - Aggregate ID: aggregate_id.md + - Identifier: identifier.md - Normalizer: normalizer.md - Snapshots: snapshots.md - Personal Data: personal_data.md diff --git a/docs/pages/UPGRADE-4.0.md b/docs/pages/UPGRADE-4.0.md index 52a4254fc..5b9abffff 100644 --- a/docs/pages/UPGRADE-4.0.md +++ b/docs/pages/UPGRADE-4.0.md @@ -2,12 +2,34 @@ ## Aggregates +### Aggregate Root + +Method `aggregateRootId` return typehint has been changed from `AggregateRootId` to `Identifier`. + +### Aggregate Root Id + +`AggregateRootId` was renamed to `Identifier` and moved to the `Patchlevel\EventSourcing\Identifier` namespace. + +Following classes have been moved to the `Patchlevel\EventSourcing\Identifier` namespace too: + +* `CustomId` +* `CustomIdBehaviour` +* `RamseyUuidV7Behaviour` +* `Uuid` + +Return typehint of `fromString` method has been changed from `self` to `static`. +All typehints of other classes `AggregateRootId` have been changed to `Identifier`. + ### Child Aggregate We removed our experimental feature of child aggregates. This was our first attempt to split aggregates into smaller parts, but we found a better way to do this with the `Micro Aggregate` feature. +## Aggregate Repository + +Typehints for the `AggregateRepository` have been changed, from `AggregateRootId` to `Identifier`. + ## Subscription The constructor of the `DefaultSubscriptionEngine` class has been changed. @@ -61,7 +83,6 @@ $subscriptionEngine = new DefaultSubscriptionEngine( RetryStrategyRepository::withDefault($retryStrategy), ); ``` - ## Store ### DoctrineDbalStore @@ -95,4 +116,4 @@ and replaced with the following headers: ### DoctrineSchemaSubscriber The `Patchlevel\EventSourcing\Schema\DoctrineSchemaSubscriber` has been removed. -use the `Patchlevel\EventSourcing\Schema\DoctrineSchemaListener` instead. \ No newline at end of file +use the `Patchlevel\EventSourcing\Schema\DoctrineSchemaListener` instead. diff --git a/docs/pages/aggregate.md b/docs/pages/aggregate.md index f9af65142..43132c272 100644 --- a/docs/pages/aggregate.md +++ b/docs/pages/aggregate.md @@ -24,9 +24,9 @@ To make it easy to register with a name, we also add the `Aggregate` attribute. ```php use Patchlevel\EventSourcing\Aggregate\BasicAggregateRoot; -use Patchlevel\EventSourcing\Aggregate\Uuid; use Patchlevel\EventSourcing\Attribute\Aggregate; use Patchlevel\EventSourcing\Attribute\Id; +use Patchlevel\EventSourcing\Identifier\Uuid; #[Aggregate('profile')] final class Profile extends BasicAggregateRoot @@ -50,7 +50,7 @@ final class Profile extends BasicAggregateRoot !!! tip - Find out more about aggregate IDs [here](./aggregate_id.md). + Find out more about aggregate IDs [here](./identifier.md). We use a so-called named constructor here to create an object of the AggregateRoot. The constructor itself is protected and cannot be called from outside. @@ -94,8 +94,8 @@ For our aggregate we create the Event `ProfileRegistered` with an ID and a name. We also give the event a unique name using the `Event` attribute. ```php -use Patchlevel\EventSourcing\Aggregate\Uuid; use Patchlevel\EventSourcing\Attribute\Event; +use Patchlevel\EventSourcing\Identifier\Uuid; #[Event('profile.registered')] final class ProfileRegistered @@ -115,10 +115,10 @@ After we have defined the event, we have to adapt the profile aggregate: ```php use Patchlevel\EventSourcing\Aggregate\BasicAggregateRoot; -use Patchlevel\EventSourcing\Aggregate\Uuid; use Patchlevel\EventSourcing\Attribute\Aggregate; use Patchlevel\EventSourcing\Attribute\Apply; use Patchlevel\EventSourcing\Attribute\Id; +use Patchlevel\EventSourcing\Identifier\Uuid; #[Aggregate('profile')] final class Profile extends BasicAggregateRoot @@ -190,10 +190,10 @@ This method then creates the event `NameChanged` and records it: ```php use Patchlevel\EventSourcing\Aggregate\BasicAggregateRoot; -use Patchlevel\EventSourcing\Aggregate\Uuid; use Patchlevel\EventSourcing\Attribute\Aggregate; use Patchlevel\EventSourcing\Attribute\Apply; use Patchlevel\EventSourcing\Attribute\Id; +use Patchlevel\EventSourcing\Identifier\Uuid; #[Aggregate('profile')] final class Profile extends BasicAggregateRoot @@ -466,10 +466,10 @@ We can now use the value object `Name` in our aggregate: ```php use Patchlevel\EventSourcing\Aggregate\BasicAggregateRoot; -use Patchlevel\EventSourcing\Aggregate\Uuid; use Patchlevel\EventSourcing\Attribute\Aggregate; use Patchlevel\EventSourcing\Attribute\Apply; use Patchlevel\EventSourcing\Attribute\Id; +use Patchlevel\EventSourcing\Identifier\Uuid; #[Aggregate('profile')] final class Profile extends BasicAggregateRoot @@ -587,9 +587,9 @@ But you can pass this information by yourself. ```php use Patchlevel\EventSourcing\Aggregate\BasicAggregateRoot; -use Patchlevel\EventSourcing\Aggregate\Uuid; use Patchlevel\EventSourcing\Attribute\Aggregate; use Patchlevel\EventSourcing\Attribute\Id; +use Patchlevel\EventSourcing\Identifier\Uuid; #[Aggregate('profile')] final class Profile extends BasicAggregateRoot @@ -614,9 +614,9 @@ But if you still want to make sure that the time is "now" and not in the past or ```php use Patchlevel\EventSourcing\Aggregate\BasicAggregateRoot; -use Patchlevel\EventSourcing\Aggregate\Uuid; use Patchlevel\EventSourcing\Attribute\Aggregate; use Patchlevel\EventSourcing\Attribute\Id; +use Patchlevel\EventSourcing\Identifier\Uuid; use Psr\Clock\ClockInterface; #[Aggregate('profile')] @@ -663,10 +663,10 @@ The order handle the order itself and the shipping handle the shipping of the or ```php use Patchlevel\EventSourcing\Aggregate\BasicAggregateRoot; -use Patchlevel\EventSourcing\Aggregate\Uuid; use Patchlevel\EventSourcing\Attribute\Aggregate; use Patchlevel\EventSourcing\Attribute\Apply; use Patchlevel\EventSourcing\Attribute\Id; +use Patchlevel\EventSourcing\Identifier\Uuid; #[Aggregate('order')] final class Order extends BasicAggregateRoot @@ -694,11 +694,11 @@ In this case, the `Shipping` aggregate listens to the `OrderCreated` event to in ```php use Patchlevel\EventSourcing\Aggregate\BasicAggregateRoot; -use Patchlevel\EventSourcing\Aggregate\Uuid; use Patchlevel\EventSourcing\Attribute\Aggregate; use Patchlevel\EventSourcing\Attribute\Apply; use Patchlevel\EventSourcing\Attribute\Id; use Patchlevel\EventSourcing\Attribute\Stream; +use Patchlevel\EventSourcing\Identifier\Uuid; #[Aggregate('shipping')] #[Stream(Order::class)] @@ -756,7 +756,7 @@ $aggregateRegistry = (new AttributeAggregateRootRegistryFactory())->create([/* p ``` ## Learn more -* [How to create own aggregate id](aggregate_id.md) +* [How to create own aggregate id](identifier.md) * [How to store and load aggregates](repository.md) * [How to snapshot aggregates](snapshots.md) * [How to create Projections](subscription.md) diff --git a/docs/pages/aggregate_id.md b/docs/pages/aggregate_id.md deleted file mode 100644 index c4c336be4..000000000 --- a/docs/pages/aggregate_id.md +++ /dev/null @@ -1,148 +0,0 @@ -# Aggregate ID - -The `aggregate id` is a unique identifier for an aggregate. -It is used to identify the aggregate in the event store. -The `aggregate` does not care how the id is generated, -since only an aggregate-wide unique string is expected in the store. - -This library provides you with a few options for generating the id. - -!!! warning - - Performance reasons, the default configuration of the store require an uuid string for `aggregate id`. - But technically, for the library, it can be any string. - If you want to use a custom id, you have to change the `aggregate_id_type` in the [store](store.md) configuration. - -## Uuid - -The easiest way is to use an `uuid` as an aggregate ID. -For this, we have the `Uuid` class, which is a simple wrapper for the [ramsey/uuid](https://github.com/ramsey/uuid) library. - -You can use it like this: - -```php -use Patchlevel\EventSourcing\Aggregate\BasicAggregateRoot; -use Patchlevel\EventSourcing\Aggregate\Uuid; -use Patchlevel\EventSourcing\Attribute\Aggregate; -use Patchlevel\EventSourcing\Attribute\Id; - -#[Aggregate('profile')] -final class Profile extends BasicAggregateRoot -{ - #[Id] - private Uuid $id; -} -``` -You have multiple options for generating an uuid: - -```php -use Patchlevel\EventSourcing\Aggregate\Uuid; - -$uuid = Uuid::generate(); -$uuid = Uuid::fromString('d6e8d7a0-4b0b-4e6a-8a9a-3a0b2d9d0e4e'); -``` -!!! Note - - We implemented the version 7 of the uuid, because it is most suitable for event sourcing. - More information about uuid versions can be found [here](https://uuid.ramsey.dev/en/stable/rfc4122.html). - -## Custom ID - -If you don't want to use an uuid, you can also use the custom ID implementation. -This is a value object that holds any string. - -```php -use Patchlevel\EventSourcing\Aggregate\BasicAggregateRoot; -use Patchlevel\EventSourcing\Aggregate\CustomId; -use Patchlevel\EventSourcing\Attribute\Aggregate; -use Patchlevel\EventSourcing\Attribute\Id; - -#[Aggregate('profile')] -final class Profile extends BasicAggregateRoot -{ - #[Id] - private CustomId $id; -} -``` -!!! warning - - If you want to use a custom id that is not an uuid, - you need to change the `aggregate_id_type` to `string` in the store configuration. - More information can be found [here](store.md). - -So you can use any string as an id: - -```php -use Patchlevel\EventSourcing\Aggregate\CustomId; - -$id = CustomId::fromString('my-id'); -``` -## Implement own ID - -Or even better, you create your own aggregate-specific ID class. -This allows you to ensure that the correct id is always used. -The whole thing looks like this: - -```php -use Patchlevel\EventSourcing\Aggregate\AggregateRootId; - -class ProfileId implements AggregateRootId -{ - private function __construct( - private readonly string $id, - ) { - } - - public function toString(): string - { - return $this->id; - } - - public static function fromString(string $id): self - { - return new self($id); - } -} -``` -So you can use it like this: - -```php -use Patchlevel\EventSourcing\Aggregate\BasicAggregateRoot; -use Patchlevel\EventSourcing\Attribute\Aggregate; -use Patchlevel\EventSourcing\Attribute\Id; - -#[Aggregate('profile')] -final class Profile extends BasicAggregateRoot -{ - #[Id] - private ProfileId $id; -} -``` -We also offer you some traits, so that you don't have to implement the `AggregateRootId` interface yourself. -Here for the uuid: - -```php -use Patchlevel\EventSourcing\Aggregate\AggregateRootId; -use Patchlevel\EventSourcing\Aggregate\RamseyUuidV7Behaviour; - -class ProfileId implements AggregateRootId -{ - use RamseyUuidV7Behaviour; -} -``` -Or for the custom id: - -```php -use Patchlevel\EventSourcing\Aggregate\AggregateRootId; -use Patchlevel\EventSourcing\Aggregate\CustomIdBehaviour; - -class ProfileId implements AggregateRootId -{ - use CustomIdBehaviour; -} -``` -### Learn more - -* [How to create an aggregate](aggregate.md) -* [How to create an event](events.md) -* [How to test an aggregate](testing.md) diff --git a/docs/pages/command_bus.md b/docs/pages/command_bus.md index 75d23da1c..33c2273f1 100644 --- a/docs/pages/command_bus.md +++ b/docs/pages/command_bus.md @@ -362,5 +362,5 @@ $provider = new ChainHandlerProvider([ * [How to use aggregates](aggregate.md) * [How to use events](events.md) * [How to use clock](clock.md) -* [How to use aggregate id](aggregate_id.md) +* [How to use aggregate id](identifier.md) * [How to use query bus](query_bus.md) diff --git a/docs/pages/events.md b/docs/pages/events.md index 4541319fb..c2af1761a 100644 --- a/docs/pages/events.md +++ b/docs/pages/events.md @@ -89,8 +89,8 @@ You can do that too. However, you must define a normalizer for this so that the library knows how to write this data to the database and load it again. ```php -use Patchlevel\EventSourcing\Aggregate\Uuid; use Patchlevel\EventSourcing\Attribute\Event; +use Patchlevel\EventSourcing\Identifier\Uuid; use Patchlevel\EventSourcing\Serializer\Normalizer\IdNormalizer; use Patchlevel\Hydrator\Normalizer\DateTimeImmutableNormalizer; diff --git a/docs/pages/getting_started.md b/docs/pages/getting_started.md index 317ebcfae..3df5c7ad2 100644 --- a/docs/pages/getting_started.md +++ b/docs/pages/getting_started.md @@ -10,8 +10,8 @@ First we define the events that happen in our system. A hotel can be created with a `name` and a `id`: ```php -use Patchlevel\EventSourcing\Aggregate\Uuid; use Patchlevel\EventSourcing\Attribute\Event; +use Patchlevel\EventSourcing\Identifier\Uuid; #[Event('hotel.created')] final class HotelCreated @@ -69,10 +69,10 @@ Last but not least, we need the associated apply methods to change the state. ```php use Patchlevel\EventSourcing\Aggregate\BasicAggregateRoot; -use Patchlevel\EventSourcing\Aggregate\Uuid; use Patchlevel\EventSourcing\Attribute\Aggregate; use Patchlevel\EventSourcing\Attribute\Apply; use Patchlevel\EventSourcing\Attribute\Id; +use Patchlevel\EventSourcing\Identifier\Uuid; #[Aggregate('hotel')] final class Hotel extends BasicAggregateRoot @@ -373,7 +373,7 @@ $engine->setup(skipBooting: true); We are now ready to use the Event Sourcing System. We can load, change and save aggregates. ```php -use Patchlevel\EventSourcing\Aggregate\Uuid; +use Patchlevel\EventSourcing\Identifier\Uuid; use Patchlevel\EventSourcing\Repository\Repository; $hotel1 = Hotel::create(Uuid::generate(), 'HOTEL'); @@ -393,7 +393,7 @@ $hotels = $hotelProjection->getHotels(); !!! note You can also use other forms of IDs such as uuid version 6 or a custom format. - You can find more about this [here](aggregate_id.md). + You can find more about this [here](identifier.md). ## Result diff --git a/docs/pages/identifier.md b/docs/pages/identifier.md new file mode 100644 index 000000000..cc101b2d7 --- /dev/null +++ b/docs/pages/identifier.md @@ -0,0 +1,123 @@ +# Identifier + +Identifiers are small, immutable value objects that represent IDs across the library in a type‑safe and consistent way. They are primarily used for aggregate root IDs, but can also be applied anywhere a stable string identifier is required (snapshots, repositories, your own domain objects, etc.). + +All identifiers must implement `Patchlevel\EventSourcing\Identifier\Identifier` and provide a stable string representation for storage and serialization. + +## Interface + +```php +interface Identifier +{ + public function toString(): string; + + public static function fromString(string $id): static; +} +``` +The string value returned by `toString()` is what gets persisted (e.g. in the event store) and serialized. `fromString()` reconstructs the value object from that string. + +## Built‑in identifiers + +We provide two ready‑to‑use implementations: + +### `Uuid` + +`Uuid` wraps [ramsey/uuid](https://github.com/ramsey/uuid) and uses UUID v7 by default, which is a good fit for event‑sourcing. + +```php +use Patchlevel\EventSourcing\Identifier\Uuid; + +$uuid = Uuid::generate(); +$uuid = Uuid::fromString('d6e8d7a0-4b0b-4e6a-8a9a-3a0b2d9d0e4e'); +``` +!!! note + + UUID v7 provides k‑sortable identifiers that work well with append‑only streams and database indexes. See the ramsey docs for details. + +### `CustomId` + +`CustomId` is a minimal string‑backed identifier. Use it if you want full control over the string format or if your IDs are provided by an external system. + +```php +use Patchlevel\EventSourcing\Identifier\CustomId; + +$id = CustomId::fromString('my-id'); +``` +## Domain‑specific identifiers + +For better domain modeling, define your own identifier types by implementing `Identifier` and encapsulating creation rules and validation. Two traits are available to make this easy: + +- `RamseyUuidV7Behaviour` for UUID v7 identifiers +- `CustomIdBehaviour` for string‑backed identifiers + +```php +use Patchlevel\EventSourcing\Identifier\Identifier; +use Patchlevel\EventSourcing\Identifier\RamseyUuidV7Behaviour; + +final class ProfileId implements Identifier +{ + use RamseyUuidV7Behaviour; +} +``` +or + +```php +use Patchlevel\EventSourcing\Identifier\CustomIdBehaviour; +use Patchlevel\EventSourcing\Identifier\Identifier; + +final class OrderNumber implements Identifier +{ + use CustomIdBehaviour; +} +``` +## Using identifiers with aggregates + +Aggregates expose and persist their IDs as `Identifier` instances. You can choose the concrete implementation that fits your domain. + +```php +use Patchlevel\EventSourcing\Aggregate\BasicAggregateRoot; +use Patchlevel\EventSourcing\Attribute\Aggregate; +use Patchlevel\EventSourcing\Attribute\Id; +use Patchlevel\EventSourcing\Identifier\Uuid; + +#[Aggregate('profile')] +final class Profile extends BasicAggregateRoot +{ + #[Id] + private Uuid $id; +} +``` +Or use your domain‑specific identifier: + +```php +use Patchlevel\EventSourcing\Aggregate\BasicAggregateRoot; +use Patchlevel\EventSourcing\Attribute\Aggregate; +use Patchlevel\EventSourcing\Attribute\Id; + +#[Aggregate('profile')] +final class Profile extends BasicAggregateRoot +{ + #[Id] + private ProfileId $id; +} +``` +## Serialization and normalization + +Identifiers integrate with the serializer via `IdNormalizer`. The `Identifier` interface is annotated so that instances are automatically normalized to strings and denormalized back to the correct class. + +This means you can safely use identifier types in command payloads, events, or snapshots without writing custom normalizers. + +## Testing + +For deterministic tests involving UUIDs, use `FakeRamseyUuidFactory` to generate predictable UUID v7 values. + +## Notes + +- Identifiers are stored as strings in the backing store, but you should always use concrete identifier types in your domain code for type‑safety and clarity. +- You can use identifiers beyond aggregates wherever an opaque, stable ID is needed. + +### Learn more + +* [How to create an aggregate](aggregate.md) +* [How to create an event](events.md) +* [How to test an aggregate](testing.md) diff --git a/docs/pages/normalizer.md b/docs/pages/normalizer.md index c798a0f22..c4fa7ed51 100644 --- a/docs/pages/normalizer.md +++ b/docs/pages/normalizer.md @@ -275,7 +275,7 @@ final class DTO If you have your own AggregateRootId, you can use the `IdNormalizer`. ```php -use Patchlevel\EventSourcing\Aggregate\Uuid; +use Patchlevel\EventSourcing\Identifier\Uuid; use Patchlevel\EventSourcing\Serializer\Normalizer\IdNormalizer; final class DTO @@ -291,7 +291,7 @@ final class DTO Optional you can also define the type of the id. ```php -use Patchlevel\EventSourcing\Aggregate\Uuid; +use Patchlevel\EventSourcing\Identifier\Uuid; use Patchlevel\EventSourcing\Serializer\Normalizer\IdNormalizer; final class DTO diff --git a/docs/pages/personal_data.md b/docs/pages/personal_data.md index e89afffe2..fdfb9703f 100644 --- a/docs/pages/personal_data.md +++ b/docs/pages/personal_data.md @@ -26,7 +26,7 @@ In order for the correct key to be used, a subject ID must be defined. Without Subject Id, no personal data can be encrypted or decrypted. ```php -use Patchlevel\EventSourcing\Aggregate\Uuid; +use Patchlevel\EventSourcing\Identifier\Uuid; use Patchlevel\Hydrator\Attribute\DataSubjectId; final class EmailChanged @@ -48,7 +48,7 @@ final class EmailChanged Next, you have to mark the properties that should be encrypted with the `#[PersonalData]` attribute. ```php -use Patchlevel\EventSourcing\Aggregate\Uuid; +use Patchlevel\EventSourcing\Identifier\Uuid; use Patchlevel\Hydrator\Attribute\DataSubjectId; use Patchlevel\Hydrator\Attribute\PersonalData; diff --git a/docs/pages/repository.md b/docs/pages/repository.md index cd0cd0a42..d66cb8302 100644 --- a/docs/pages/repository.md +++ b/docs/pages/repository.md @@ -154,7 +154,7 @@ All new events that have not yet been written to the database are fetched from t These events are then also append to the database. ```php -use Patchlevel\EventSourcing\Aggregate\Uuid; +use Patchlevel\EventSourcing\Identifier\Uuid; use Patchlevel\EventSourcing\Repository\Repository; $id = Uuid::generate(); @@ -187,7 +187,7 @@ An `aggregate` can be loaded using the `load` method. All events for the aggregate are loaded from the database and the current state is rebuilt. ```php -use Patchlevel\EventSourcing\Aggregate\Uuid; +use Patchlevel\EventSourcing\Identifier\Uuid; use Patchlevel\EventSourcing\Repository\Repository; $id = Uuid::fromString('229286ff-6f95-4df6-bc72-0a239fe7b284'); @@ -210,7 +210,7 @@ You can also check whether an `aggregate` with a certain id exists. It is checked whether any event with this id exists in the database. ```php -use Patchlevel\EventSourcing\Aggregate\Uuid; +use Patchlevel\EventSourcing\Identifier\Uuid; use Patchlevel\EventSourcing\Repository\Repository; $id = Uuid::fromString('229286ff-6f95-4df6-bc72-0a239fe7b284'); diff --git a/docs/pages/snapshots.md b/docs/pages/snapshots.md index 30b9c1842..aa1d28e80 100644 --- a/docs/pages/snapshots.md +++ b/docs/pages/snapshots.md @@ -82,10 +82,10 @@ You can define normalizers to bring the properties into the correct format. ```php use Patchlevel\EventSourcing\Aggregate\BasicAggregateRoot; -use Patchlevel\EventSourcing\Aggregate\Uuid; use Patchlevel\EventSourcing\Attribute\Aggregate; use Patchlevel\EventSourcing\Attribute\Id; use Patchlevel\EventSourcing\Attribute\Snapshot; +use Patchlevel\EventSourcing\Identifier\Uuid; #[Aggregate('profile')] #[Snapshot('default')] @@ -239,7 +239,7 @@ $snapshotStore->save($aggregate); You can also load an aggregate from the snapshot store: ```php -use Patchlevel\EventSourcing\Aggregate\Uuid; +use Patchlevel\EventSourcing\Identifier\Uuid; use Patchlevel\EventSourcing\Snapshot\SnapshotStore; $id = Uuid::fromString('229286ff-6f95-4df6-bc72-0a239fe7b284'); diff --git a/docs/pages/testing.md b/docs/pages/testing.md index d21f5d19a..aa8141aa5 100644 --- a/docs/pages/testing.md +++ b/docs/pages/testing.md @@ -198,7 +198,7 @@ Uuids are randomly generated and can be a problem in tests. If you want deterministic tests, you can use the `IncrementalRamseyUuidFactory` from the library. ```php -use Patchlevel\EventSourcing\Test\IncrementalRamseyUuidFactory; +use Patchlevel\EventSourcing\Identifier\FakeRamseyUuidFactory; use PHPUnit\Framework\TestCase; use Ramsey\Uuid\Uuid; @@ -206,7 +206,7 @@ final class ProfileTest extends TestCase { public function setUp(): void { - Uuid::setFactory(new IncrementalRamseyUuidFactory()); + Uuid::setFactory(new FakeRamseyUuidFactory()); } public function testCreateProfile(): void diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index 6d180b7c3..e656e2c60 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -48,6 +48,12 @@ parameters: count: 1 path: src/Repository/DefaultRepository.php + - + message: '#^Property Patchlevel\\EventSourcing\\Serializer\\Normalizer\\IdNormalizer\:\:\$identifierClass \(class\-string\\|null\) does not accept string\.$#' + identifier: assign.propertyType + count: 1 + path: src/Serializer/Normalizer/IdNormalizer.php + - message: '#^Parameter \#2 \$data of method Patchlevel\\Hydrator\\Hydrator\:\:hydrate\(\) expects array\, mixed given\.$#' identifier: argument.type @@ -138,12 +144,6 @@ parameters: count: 3 path: src/Subscription/ThrowableToErrorContextTransformer.php - - - message: '#^Parameter \#1 \$id of static method Patchlevel\\EventSourcing\\Tests\\Benchmark\\BasicImplementation\\Profile\:\:create\(\) expects Patchlevel\\EventSourcing\\Tests\\Benchmark\\BasicImplementation\\ProfileId, Patchlevel\\EventSourcing\\Aggregate\\AggregateRootId given\.$#' - identifier: argument.type - count: 1 - path: tests/Benchmark/SplitStreamBench.php - - message: '#^Call to static method PHPUnit\\Framework\\Assert\:\:assertInstanceOf\(\) with ''Patchlevel\\\\EventSourcing\\\\Tests\\\\Integration\\\\BankAccountSplitStream\\\\BankAccount'' and Patchlevel\\EventSourcing\\Tests\\Integration\\BankAccountSplitStream\\BankAccount will always evaluate to true\.$#' identifier: staticMethod.alreadyNarrowedType diff --git a/src/Aggregate/AggregateRoot.php b/src/Aggregate/AggregateRoot.php index 84c6eabcf..b9c7c1203 100644 --- a/src/Aggregate/AggregateRoot.php +++ b/src/Aggregate/AggregateRoot.php @@ -4,9 +4,11 @@ namespace Patchlevel\EventSourcing\Aggregate; +use Patchlevel\EventSourcing\Identifier\Identifier; + interface AggregateRoot { - public function aggregateRootId(): AggregateRootId; + public function aggregateRootId(): Identifier; /** @param iterable $events */ public function catchUp(iterable $events): void; diff --git a/src/Aggregate/AggregateRootAttributeBehaviour.php b/src/Aggregate/AggregateRootAttributeBehaviour.php index c8be85875..e66806d43 100644 --- a/src/Aggregate/AggregateRootAttributeBehaviour.php +++ b/src/Aggregate/AggregateRootAttributeBehaviour.php @@ -4,6 +4,7 @@ namespace Patchlevel\EventSourcing\Aggregate; +use Patchlevel\EventSourcing\Identifier\Identifier; use Patchlevel\Hydrator\Attribute\Ignore; use ReflectionProperty; @@ -15,7 +16,7 @@ trait AggregateRootAttributeBehaviour use AggregateRootMetadataAwareBehaviour; #[Ignore] - private AggregateRootId|null $cachedAggregateRootId = null; + private Identifier|null $cachedAggregateRootId = null; protected function apply(object $event): void { @@ -34,9 +35,9 @@ protected function apply(object $event): void $this->$method($event); } - public function aggregateRootId(): AggregateRootId + public function aggregateRootId(): Identifier { - if ($this->cachedAggregateRootId instanceof AggregateRootId) { + if ($this->cachedAggregateRootId instanceof Identifier) { return $this->cachedAggregateRootId; } @@ -47,7 +48,7 @@ public function aggregateRootId(): AggregateRootId /** @var mixed $aggregateRootId */ $aggregateRootId = $reflection->getValue($this); - if (!$aggregateRootId instanceof AggregateRootId) { + if (!$aggregateRootId instanceof Identifier) { throw new AggregateRootIdNotSupported($this::class, $aggregateRootId); } diff --git a/src/Aggregate/AggregateRootIdNotSupported.php b/src/Aggregate/AggregateRootIdNotSupported.php index a8fcd3509..525e9e102 100644 --- a/src/Aggregate/AggregateRootIdNotSupported.php +++ b/src/Aggregate/AggregateRootIdNotSupported.php @@ -4,6 +4,7 @@ namespace Patchlevel\EventSourcing\Aggregate; +use Patchlevel\EventSourcing\Identifier\Identifier; use RuntimeException; use function get_debug_type; @@ -18,7 +19,7 @@ public function __construct(string $aggregateRootClass, mixed $value) sprintf( 'aggregate root id in class "%s" must be instance of "%s", got "%s"', $aggregateRootClass, - AggregateRootId::class, + Identifier::class, get_debug_type($value), ), ); diff --git a/src/Aggregate/CustomId.php b/src/Aggregate/CustomId.php deleted file mode 100644 index 7335e2581..000000000 --- a/src/Aggregate/CustomId.php +++ /dev/null @@ -1,10 +0,0 @@ -save($aggregate); } - private function aggregateRootId(object $command): AggregateRootId + private function aggregateRootId(object $command): Identifier { $reflectionClass = new ReflectionClass($command); @@ -53,7 +53,7 @@ private function aggregateRootId(object $command): AggregateRootId $value = $property->getValue($command); - if (!$value instanceof AggregateRootId) { + if (!$value instanceof Identifier) { throw new InvalidArgumentException('Id property must be an instance of AggregateRootId'); } diff --git a/src/Identifier/CustomId.php b/src/Identifier/CustomId.php new file mode 100644 index 000000000..3ad9fd931 --- /dev/null +++ b/src/Identifier/CustomId.php @@ -0,0 +1,10 @@ + $aggregate */ - public function __construct(string $aggregate, AggregateRootId $id) + public function __construct(string $aggregate, Identifier $id) { parent::__construct( sprintf( diff --git a/src/Repository/AggregateDetached.php b/src/Repository/AggregateDetached.php index eb164cb9f..b0adf79f1 100644 --- a/src/Repository/AggregateDetached.php +++ b/src/Repository/AggregateDetached.php @@ -5,14 +5,14 @@ namespace Patchlevel\EventSourcing\Repository; use Patchlevel\EventSourcing\Aggregate\AggregateRoot; -use Patchlevel\EventSourcing\Aggregate\AggregateRootId; +use Patchlevel\EventSourcing\Identifier\Identifier; use function sprintf; final class AggregateDetached extends RepositoryException { /** @param class-string $aggregateRootClass */ - public function __construct(string $aggregateRootClass, AggregateRootId $aggregateRootId) + public function __construct(string $aggregateRootClass, Identifier $aggregateRootId) { parent::__construct( sprintf( diff --git a/src/Repository/AggregateNotFound.php b/src/Repository/AggregateNotFound.php index 33e864725..21341150d 100644 --- a/src/Repository/AggregateNotFound.php +++ b/src/Repository/AggregateNotFound.php @@ -4,13 +4,13 @@ namespace Patchlevel\EventSourcing\Repository; -use Patchlevel\EventSourcing\Aggregate\AggregateRootId; +use Patchlevel\EventSourcing\Identifier\Identifier; use function sprintf; final class AggregateNotFound extends RepositoryException { - public function __construct(string $aggregateRootClass, AggregateRootId $rootId) + public function __construct(string $aggregateRootClass, Identifier $rootId) { parent::__construct(sprintf('aggregate "%s::%s" not found', $aggregateRootClass, $rootId->toString())); } diff --git a/src/Repository/AggregateOutdated.php b/src/Repository/AggregateOutdated.php index d3d00b665..63e121643 100644 --- a/src/Repository/AggregateOutdated.php +++ b/src/Repository/AggregateOutdated.php @@ -5,14 +5,14 @@ namespace Patchlevel\EventSourcing\Repository; use Patchlevel\EventSourcing\Aggregate\AggregateRoot; -use Patchlevel\EventSourcing\Aggregate\AggregateRootId; +use Patchlevel\EventSourcing\Identifier\Identifier; use function sprintf; final class AggregateOutdated extends RepositoryException { /** @param class-string $aggregate */ - public function __construct(string $aggregate, AggregateRootId $id) + public function __construct(string $aggregate, Identifier $id) { parent::__construct( sprintf( diff --git a/src/Repository/AggregateUnknown.php b/src/Repository/AggregateUnknown.php index bbdad3f45..3024c2260 100644 --- a/src/Repository/AggregateUnknown.php +++ b/src/Repository/AggregateUnknown.php @@ -5,14 +5,14 @@ namespace Patchlevel\EventSourcing\Repository; use Patchlevel\EventSourcing\Aggregate\AggregateRoot; -use Patchlevel\EventSourcing\Aggregate\AggregateRootId; +use Patchlevel\EventSourcing\Identifier\Identifier; use function sprintf; final class AggregateUnknown extends RepositoryException { /** @param class-string $aggregateRootClass */ - public function __construct(string $aggregateRootClass, AggregateRootId $aggregateRootId) + public function __construct(string $aggregateRootClass, Identifier $aggregateRootId) { parent::__construct( sprintf( diff --git a/src/Repository/DefaultRepository.php b/src/Repository/DefaultRepository.php index ad89d6786..d392a99f0 100644 --- a/src/Repository/DefaultRepository.php +++ b/src/Repository/DefaultRepository.php @@ -5,9 +5,9 @@ namespace Patchlevel\EventSourcing\Repository; use Patchlevel\EventSourcing\Aggregate\AggregateRoot; -use Patchlevel\EventSourcing\Aggregate\AggregateRootId; use Patchlevel\EventSourcing\Clock\SystemClock; use Patchlevel\EventSourcing\EventBus\EventBus; +use Patchlevel\EventSourcing\Identifier\Identifier; use Patchlevel\EventSourcing\Message\Message; use Patchlevel\EventSourcing\Metadata\AggregateRoot\AggregateRootMetadata; use Patchlevel\EventSourcing\Repository\MessageDecorator\MessageDecorator; @@ -67,7 +67,7 @@ public function __construct( } /** @return T */ - public function load(AggregateRootId $id): AggregateRoot + public function load(Identifier $id): AggregateRoot { if ($this->snapshotStore && $this->metadata->snapshot) { try { @@ -162,7 +162,7 @@ public function load(AggregateRootId $id): AggregateRoot return $aggregate; } - public function has(AggregateRootId $id): bool + public function has(Identifier $id): bool { $criteria = new Criteria( new StreamCriterion($this->metadata->streamName($id->toString())), @@ -315,7 +315,7 @@ function () use ($messages, $streamName, $archiveTo): void { * * @return T */ - private function loadFromSnapshot(string $aggregateClass, AggregateRootId $id): AggregateRoot + private function loadFromSnapshot(string $aggregateClass, Identifier $id): AggregateRoot { assert($this->snapshotStore instanceof SnapshotStore); diff --git a/src/Repository/PlayheadMismatch.php b/src/Repository/PlayheadMismatch.php index d8199b9a8..48ee9ea8e 100644 --- a/src/Repository/PlayheadMismatch.php +++ b/src/Repository/PlayheadMismatch.php @@ -4,13 +4,13 @@ namespace Patchlevel\EventSourcing\Repository; -use Patchlevel\EventSourcing\Aggregate\AggregateRootId; +use Patchlevel\EventSourcing\Identifier\Identifier; use function sprintf; final class PlayheadMismatch extends RepositoryException { - public function __construct(string $aggregateRootClass, AggregateRootId $aggregateRootId, int $playhead, int $eventCount) + public function __construct(string $aggregateRootClass, Identifier $aggregateRootId, int $playhead, int $eventCount) { parent::__construct(sprintf( 'There is a mismatch between the playhead [%s] and the event count [%s] for the aggregate [%s] with the id [%s]', diff --git a/src/Repository/Repository.php b/src/Repository/Repository.php index 91483a7b8..92afa0931 100644 --- a/src/Repository/Repository.php +++ b/src/Repository/Repository.php @@ -5,7 +5,7 @@ namespace Patchlevel\EventSourcing\Repository; use Patchlevel\EventSourcing\Aggregate\AggregateRoot; -use Patchlevel\EventSourcing\Aggregate\AggregateRootId; +use Patchlevel\EventSourcing\Identifier\Identifier; /** @template T of AggregateRoot */ interface Repository @@ -15,9 +15,9 @@ interface Repository * * @throws AggregateNotFound */ - public function load(AggregateRootId $id): AggregateRoot; + public function load(Identifier $id): AggregateRoot; - public function has(AggregateRootId $id): bool; + public function has(Identifier $id): bool; /** * @param T $aggregate diff --git a/src/Repository/SnapshotRebuildFailed.php b/src/Repository/SnapshotRebuildFailed.php index a4d5aa74b..2921d5361 100644 --- a/src/Repository/SnapshotRebuildFailed.php +++ b/src/Repository/SnapshotRebuildFailed.php @@ -5,7 +5,7 @@ namespace Patchlevel\EventSourcing\Repository; use Patchlevel\EventSourcing\Aggregate\AggregateRoot; -use Patchlevel\EventSourcing\Aggregate\AggregateRootId; +use Patchlevel\EventSourcing\Identifier\Identifier; use Throwable; use function sprintf; @@ -15,7 +15,7 @@ final class SnapshotRebuildFailed extends RepositoryException /** @param class-string $aggregateRootClass */ public function __construct( private string $aggregateRootClass, - private AggregateRootId $aggregateRootId, + private Identifier $aggregateRootId, Throwable $previous, ) { parent::__construct( @@ -35,7 +35,7 @@ public function aggregateClass(): string return $this->aggregateRootClass; } - public function aggregateRootId(): AggregateRootId + public function aggregateRootId(): Identifier { return $this->aggregateRootId; } diff --git a/src/Serializer/Normalizer/IdNormalizer.php b/src/Serializer/Normalizer/IdNormalizer.php index f70be7650..d65d903b2 100644 --- a/src/Serializer/Normalizer/IdNormalizer.php +++ b/src/Serializer/Normalizer/IdNormalizer.php @@ -5,22 +5,23 @@ namespace Patchlevel\EventSourcing\Serializer\Normalizer; use Attribute; -use Patchlevel\EventSourcing\Aggregate\AggregateRootId; +use Patchlevel\EventSourcing\Identifier\Identifier; use Patchlevel\Hydrator\Normalizer\InvalidArgument; use Patchlevel\Hydrator\Normalizer\InvalidType; use Patchlevel\Hydrator\Normalizer\Normalizer; -use Patchlevel\Hydrator\Normalizer\ReflectionTypeAwareNormalizer; -use Patchlevel\Hydrator\Normalizer\ReflectionTypeUtil; -use ReflectionType; +use Patchlevel\Hydrator\Normalizer\TypeAwareNormalizer; +use Symfony\Component\TypeInfo\Type; +use Symfony\Component\TypeInfo\Type\NullableType; +use Symfony\Component\TypeInfo\Type\ObjectType; use function is_string; #[Attribute(Attribute::TARGET_PROPERTY | Attribute::TARGET_CLASS)] -final class IdNormalizer implements Normalizer, ReflectionTypeAwareNormalizer +final class IdNormalizer implements Normalizer, TypeAwareNormalizer { public function __construct( - /** @var class-string|null */ - private string|null $aggregateIdClass = null, + /** @var class-string|null */ + private string|null $identifierClass = null, ) { } @@ -30,16 +31,16 @@ public function normalize(mixed $value): string|null return null; } - $class = $this->aggregateIdClass(); + $class = $this->identifierClass(); - if (!$value instanceof AggregateRootId) { + if (!$value instanceof Identifier) { throw InvalidArgument::withWrongType($class, $value); } return $value->toString(); } - public function denormalize(mixed $value): AggregateRootId|null + public function denormalize(mixed $value): Identifier|null { if ($value === null) { return null; @@ -49,30 +50,35 @@ public function denormalize(mixed $value): AggregateRootId|null throw InvalidArgument::withWrongType('string', $value); } - $class = $this->aggregateIdClass(); + $class = $this->identifierClass(); return $class::fromString($value); } - public function handleReflectionType(ReflectionType|null $reflectionType): void + /** @return class-string */ + public function identifierClass(): string { - if ($this->aggregateIdClass !== null || $reflectionType === null) { - return; + if ($this->identifierClass === null) { + throw InvalidType::missingType(); } - $this->aggregateIdClass = ReflectionTypeUtil::classStringInstanceOf( - $reflectionType, - AggregateRootId::class, - ); + return $this->identifierClass; } - /** @return class-string */ - public function aggregateIdClass(): string + public function handleType(Type|null $type): void { - if ($this->aggregateIdClass === null) { - throw InvalidType::missingType(); + if ($this->identifierClass !== null || $type === null) { + return; + } + + if ($type instanceof NullableType) { + $type = $type->getWrappedType(); + } + + if (!$type instanceof ObjectType) { + return; } - return $this->aggregateIdClass; + $this->identifierClass = $type->getClassName(); } } diff --git a/src/Snapshot/DefaultSnapshotStore.php b/src/Snapshot/DefaultSnapshotStore.php index c52a60bef..5bab975f6 100644 --- a/src/Snapshot/DefaultSnapshotStore.php +++ b/src/Snapshot/DefaultSnapshotStore.php @@ -5,7 +5,7 @@ namespace Patchlevel\EventSourcing\Snapshot; use Patchlevel\EventSourcing\Aggregate\AggregateRoot; -use Patchlevel\EventSourcing\Aggregate\AggregateRootId; +use Patchlevel\EventSourcing\Identifier\Identifier; use Patchlevel\EventSourcing\Metadata\AggregateRoot\AggregateRootMetadataAwareMetadataFactory; use Patchlevel\EventSourcing\Metadata\AggregateRoot\AggregateRootMetadataFactory; use Patchlevel\EventSourcing\Snapshot\Adapter\SnapshotAdapter; @@ -66,7 +66,7 @@ public function save(AggregateRoot $aggregateRoot): void * * @template T of AggregateRoot */ - public function load(string $aggregateClass, AggregateRootId $id): AggregateRoot + public function load(string $aggregateClass, Identifier $id): AggregateRoot { $adapter = $this->adapter($aggregateClass); $key = $this->key($aggregateClass, $id); @@ -104,7 +104,7 @@ public function adapter(string $aggregateClass): SnapshotAdapter } /** @param class-string $aggregateClass */ - private function key(string $aggregateClass, AggregateRootId $aggregateId): string + private function key(string $aggregateClass, Identifier $aggregateId): string { $aggregateName = $this->metadataFactory->metadata($aggregateClass)->name; diff --git a/src/Snapshot/SnapshotNotFound.php b/src/Snapshot/SnapshotNotFound.php index e41f69234..0b4ef89f9 100644 --- a/src/Snapshot/SnapshotNotFound.php +++ b/src/Snapshot/SnapshotNotFound.php @@ -5,7 +5,7 @@ namespace Patchlevel\EventSourcing\Snapshot; use Patchlevel\EventSourcing\Aggregate\AggregateRoot; -use Patchlevel\EventSourcing\Aggregate\AggregateRootId; +use Patchlevel\EventSourcing\Identifier\Identifier; use Throwable; use function sprintf; @@ -13,7 +13,7 @@ final class SnapshotNotFound extends SnapshotException { /** @param class-string $aggregateRootClass */ - public function __construct(string $aggregateRootClass, AggregateRootId $rootId, Throwable|null $previous = null) + public function __construct(string $aggregateRootClass, Identifier $rootId, Throwable|null $previous = null) { parent::__construct( sprintf( diff --git a/src/Snapshot/SnapshotStore.php b/src/Snapshot/SnapshotStore.php index 89c53addb..d00300182 100644 --- a/src/Snapshot/SnapshotStore.php +++ b/src/Snapshot/SnapshotStore.php @@ -5,7 +5,7 @@ namespace Patchlevel\EventSourcing\Snapshot; use Patchlevel\EventSourcing\Aggregate\AggregateRoot; -use Patchlevel\EventSourcing\Aggregate\AggregateRootId; +use Patchlevel\EventSourcing\Identifier\Identifier; use Patchlevel\EventSourcing\Snapshot\Adapter\SnapshotNotFound; interface SnapshotStore @@ -28,5 +28,5 @@ public function save(AggregateRoot $aggregateRoot): void; * * @template T of AggregateRoot */ - public function load(string $aggregateClass, AggregateRootId $id): AggregateRoot; + public function load(string $aggregateClass, Identifier $id): AggregateRoot; } diff --git a/src/Subscription/Repository/RunSubscriptionEngineRepository.php b/src/Subscription/Repository/RunSubscriptionEngineRepository.php index 4da7c605f..2f1f39682 100644 --- a/src/Subscription/Repository/RunSubscriptionEngineRepository.php +++ b/src/Subscription/Repository/RunSubscriptionEngineRepository.php @@ -5,7 +5,7 @@ namespace Patchlevel\EventSourcing\Subscription\Repository; use Patchlevel\EventSourcing\Aggregate\AggregateRoot; -use Patchlevel\EventSourcing\Aggregate\AggregateRootId; +use Patchlevel\EventSourcing\Identifier\Identifier; use Patchlevel\EventSourcing\Repository\Repository; use Patchlevel\EventSourcing\Subscription\Engine\AlreadyProcessing; use Patchlevel\EventSourcing\Subscription\Engine\SubscriptionEngine; @@ -33,12 +33,12 @@ public function __construct( } /** @return T */ - public function load(AggregateRootId $id): AggregateRoot + public function load(Identifier $id): AggregateRoot { return $this->repository->load($id); } - public function has(AggregateRootId $id): bool + public function has(Identifier $id): bool { return $this->repository->has($id); } diff --git a/tests/Benchmark/BasicImplementation/ProfileId.php b/tests/Benchmark/BasicImplementation/ProfileId.php index 8a88d303d..ab0596d9f 100644 --- a/tests/Benchmark/BasicImplementation/ProfileId.php +++ b/tests/Benchmark/BasicImplementation/ProfileId.php @@ -4,10 +4,10 @@ namespace Patchlevel\EventSourcing\Tests\Benchmark\BasicImplementation; -use Patchlevel\EventSourcing\Aggregate\AggregateRootId; -use Patchlevel\EventSourcing\Aggregate\RamseyUuidV7Behaviour; +use Patchlevel\EventSourcing\Identifier\Identifier; +use Patchlevel\EventSourcing\Identifier\RamseyUuidV7Behaviour; -final class ProfileId implements AggregateRootId +final class ProfileId implements Identifier { use RamseyUuidV7Behaviour; } diff --git a/tests/Benchmark/PersonalDataBench.php b/tests/Benchmark/PersonalDataBench.php index 586a7bcce..0e7b93a92 100644 --- a/tests/Benchmark/PersonalDataBench.php +++ b/tests/Benchmark/PersonalDataBench.php @@ -4,8 +4,8 @@ namespace Patchlevel\EventSourcing\Tests\Benchmark; -use Patchlevel\EventSourcing\Aggregate\AggregateRootId; use Patchlevel\EventSourcing\Cryptography\DoctrineCipherKeyStore; +use Patchlevel\EventSourcing\Identifier\Identifier; use Patchlevel\EventSourcing\Repository\DefaultRepository; use Patchlevel\EventSourcing\Repository\Repository; use Patchlevel\EventSourcing\Schema\ChainDoctrineSchemaConfigurator; @@ -25,8 +25,8 @@ final class PersonalDataBench private Store $store; private Repository $repository; - private AggregateRootId $singleEventId; - private AggregateRootId $multipleEventsId; + private Identifier $singleEventId; + private Identifier $multipleEventsId; public function setUp(): void { diff --git a/tests/Benchmark/SimpleSetupStreamStoreBench.php b/tests/Benchmark/SimpleSetupStreamStoreBench.php index 55597f471..2b3397355 100644 --- a/tests/Benchmark/SimpleSetupStreamStoreBench.php +++ b/tests/Benchmark/SimpleSetupStreamStoreBench.php @@ -4,7 +4,7 @@ namespace Patchlevel\EventSourcing\Tests\Benchmark; -use Patchlevel\EventSourcing\Aggregate\AggregateRootId; +use Patchlevel\EventSourcing\Identifier\Identifier; use Patchlevel\EventSourcing\Repository\DefaultRepository; use Patchlevel\EventSourcing\Repository\Repository; use Patchlevel\EventSourcing\Schema\DoctrineSchemaDirector; @@ -22,8 +22,8 @@ final class SimpleSetupStreamStoreBench private Store $store; private Repository $repository; - private AggregateRootId $singleEventId; - private AggregateRootId $multipleEventsId; + private Identifier $singleEventId; + private Identifier $multipleEventsId; public function setUp(): void { diff --git a/tests/Benchmark/SnapshotsBench.php b/tests/Benchmark/SnapshotsBench.php index 4091bb966..43d8ec223 100644 --- a/tests/Benchmark/SnapshotsBench.php +++ b/tests/Benchmark/SnapshotsBench.php @@ -4,7 +4,7 @@ namespace Patchlevel\EventSourcing\Tests\Benchmark; -use Patchlevel\EventSourcing\Aggregate\AggregateRootId; +use Patchlevel\EventSourcing\Identifier\Identifier; use Patchlevel\EventSourcing\Repository\DefaultRepository; use Patchlevel\EventSourcing\Repository\Repository; use Patchlevel\EventSourcing\Schema\DoctrineSchemaDirector; @@ -28,7 +28,7 @@ final class SnapshotsBench private InMemorySnapshotAdapter $adapter; - private AggregateRootId $id; + private Identifier $id; public function setUp(): void { diff --git a/tests/Benchmark/SplitStreamBench.php b/tests/Benchmark/SplitStreamBench.php index b07804118..48ad920cf 100644 --- a/tests/Benchmark/SplitStreamBench.php +++ b/tests/Benchmark/SplitStreamBench.php @@ -4,7 +4,6 @@ namespace Patchlevel\EventSourcing\Tests\Benchmark; -use Patchlevel\EventSourcing\Aggregate\AggregateRootId; use Patchlevel\EventSourcing\Metadata\Event\AttributeEventMetadataFactory; use Patchlevel\EventSourcing\Repository\DefaultRepository; use Patchlevel\EventSourcing\Repository\MessageDecorator\SplitStreamDecorator; @@ -26,7 +25,7 @@ final class SplitStreamBench private Store $store; private Repository $repository; - private AggregateRootId $id; + private ProfileId $id; public function setUp(): void { diff --git a/tests/Benchmark/SubscriptionEngineBatchBench.php b/tests/Benchmark/SubscriptionEngineBatchBench.php index 0f314760f..f610ce9b2 100644 --- a/tests/Benchmark/SubscriptionEngineBatchBench.php +++ b/tests/Benchmark/SubscriptionEngineBatchBench.php @@ -4,7 +4,7 @@ namespace Patchlevel\EventSourcing\Tests\Benchmark; -use Patchlevel\EventSourcing\Aggregate\AggregateRootId; +use Patchlevel\EventSourcing\Identifier\Identifier; use Patchlevel\EventSourcing\Repository\DefaultRepository; use Patchlevel\EventSourcing\Repository\Repository; use Patchlevel\EventSourcing\Schema\ChainDoctrineSchemaConfigurator; @@ -32,7 +32,7 @@ final class SubscriptionEngineBatchBench private SubscriptionEngine $subscriptionEngine; - private AggregateRootId $id; + private Identifier $id; public function setUp(): void { diff --git a/tests/Benchmark/SubscriptionEngineBench.php b/tests/Benchmark/SubscriptionEngineBench.php index e5aeeb0de..70783e7e8 100644 --- a/tests/Benchmark/SubscriptionEngineBench.php +++ b/tests/Benchmark/SubscriptionEngineBench.php @@ -4,7 +4,7 @@ namespace Patchlevel\EventSourcing\Tests\Benchmark; -use Patchlevel\EventSourcing\Aggregate\AggregateRootId; +use Patchlevel\EventSourcing\Identifier\Identifier; use Patchlevel\EventSourcing\Metadata\Event\AttributeEventMetadataFactory; use Patchlevel\EventSourcing\Repository\DefaultRepository; use Patchlevel\EventSourcing\Repository\Repository; @@ -33,7 +33,7 @@ final class SubscriptionEngineBench private SubscriptionEngine $subscriptionEngine; - private AggregateRootId $id; + private Identifier $id; public function setUp(): void { diff --git a/tests/Integration/BankAccountSplitStream/AccountId.php b/tests/Integration/BankAccountSplitStream/AccountId.php index 3483bb241..bf632df12 100644 --- a/tests/Integration/BankAccountSplitStream/AccountId.php +++ b/tests/Integration/BankAccountSplitStream/AccountId.php @@ -4,10 +4,10 @@ namespace Patchlevel\EventSourcing\Tests\Integration\BankAccountSplitStream; -use Patchlevel\EventSourcing\Aggregate\AggregateRootId; -use Patchlevel\EventSourcing\Aggregate\RamseyUuidV7Behaviour; +use Patchlevel\EventSourcing\Identifier\Identifier; +use Patchlevel\EventSourcing\Identifier\RamseyUuidV7Behaviour; -final class AccountId implements AggregateRootId +final class AccountId implements Identifier { use RamseyUuidV7Behaviour; } diff --git a/tests/Integration/BasicImplementation/ProfileId.php b/tests/Integration/BasicImplementation/ProfileId.php index a92c7b40f..a185e7fb2 100644 --- a/tests/Integration/BasicImplementation/ProfileId.php +++ b/tests/Integration/BasicImplementation/ProfileId.php @@ -4,10 +4,10 @@ namespace Patchlevel\EventSourcing\Tests\Integration\BasicImplementation; -use Patchlevel\EventSourcing\Aggregate\AggregateRootId; -use Patchlevel\EventSourcing\Aggregate\RamseyUuidV7Behaviour; +use Patchlevel\EventSourcing\Identifier\Identifier; +use Patchlevel\EventSourcing\Identifier\RamseyUuidV7Behaviour; -final class ProfileId implements AggregateRootId +final class ProfileId implements Identifier { use RamseyUuidV7Behaviour; } diff --git a/tests/Integration/MicroAggregate/ProfileId.php b/tests/Integration/MicroAggregate/ProfileId.php index eb0ee0191..e56827e6b 100644 --- a/tests/Integration/MicroAggregate/ProfileId.php +++ b/tests/Integration/MicroAggregate/ProfileId.php @@ -4,10 +4,10 @@ namespace Patchlevel\EventSourcing\Tests\Integration\MicroAggregate; -use Patchlevel\EventSourcing\Aggregate\AggregateRootId; -use Patchlevel\EventSourcing\Aggregate\RamseyUuidV7Behaviour; +use Patchlevel\EventSourcing\Identifier\Identifier; +use Patchlevel\EventSourcing\Identifier\RamseyUuidV7Behaviour; -final class ProfileId implements AggregateRootId +final class ProfileId implements Identifier { use RamseyUuidV7Behaviour; } diff --git a/tests/Integration/PersonalData/ProfileId.php b/tests/Integration/PersonalData/ProfileId.php index 770fac011..7b475b851 100644 --- a/tests/Integration/PersonalData/ProfileId.php +++ b/tests/Integration/PersonalData/ProfileId.php @@ -4,10 +4,10 @@ namespace Patchlevel\EventSourcing\Tests\Integration\PersonalData; -use Patchlevel\EventSourcing\Aggregate\AggregateRootId; -use Patchlevel\EventSourcing\Aggregate\RamseyUuidV7Behaviour; +use Patchlevel\EventSourcing\Identifier\Identifier; +use Patchlevel\EventSourcing\Identifier\RamseyUuidV7Behaviour; -final class ProfileId implements AggregateRootId +final class ProfileId implements Identifier { use RamseyUuidV7Behaviour; } diff --git a/tests/Integration/Store/ProfileId.php b/tests/Integration/Store/ProfileId.php index ad102fa8c..936ab3fa1 100644 --- a/tests/Integration/Store/ProfileId.php +++ b/tests/Integration/Store/ProfileId.php @@ -4,10 +4,10 @@ namespace Patchlevel\EventSourcing\Tests\Integration\Store; -use Patchlevel\EventSourcing\Aggregate\AggregateRootId; -use Patchlevel\EventSourcing\Aggregate\RamseyUuidV7Behaviour; +use Patchlevel\EventSourcing\Identifier\Identifier; +use Patchlevel\EventSourcing\Identifier\RamseyUuidV7Behaviour; -final class ProfileId implements AggregateRootId +final class ProfileId implements Identifier { use RamseyUuidV7Behaviour; } diff --git a/tests/Integration/Subscription/ProfileId.php b/tests/Integration/Subscription/ProfileId.php index d51e463eb..e98eb2b9b 100644 --- a/tests/Integration/Subscription/ProfileId.php +++ b/tests/Integration/Subscription/ProfileId.php @@ -4,10 +4,10 @@ namespace Patchlevel\EventSourcing\Tests\Integration\Subscription; -use Patchlevel\EventSourcing\Aggregate\AggregateRootId; -use Patchlevel\EventSourcing\Aggregate\RamseyUuidV7Behaviour; +use Patchlevel\EventSourcing\Identifier\Identifier; +use Patchlevel\EventSourcing\Identifier\RamseyUuidV7Behaviour; -final class ProfileId implements AggregateRootId +final class ProfileId implements Identifier { use RamseyUuidV7Behaviour; } diff --git a/tests/Unit/Aggregate/AggregateRootIdNotSupportedTest.php b/tests/Unit/Aggregate/AggregateRootIdNotSupportedTest.php index 0b82e20eb..413dc6797 100644 --- a/tests/Unit/Aggregate/AggregateRootIdNotSupportedTest.php +++ b/tests/Unit/Aggregate/AggregateRootIdNotSupportedTest.php @@ -17,7 +17,7 @@ public function testCreate(): void $exception = new AggregateRootIdNotSupported(Profile::class, 1); self::assertSame( - 'aggregate root id in class "Patchlevel\EventSourcing\Tests\Unit\Fixture\Profile" must be instance of "Patchlevel\EventSourcing\Aggregate\AggregateRootId", got "int"', + 'aggregate root id in class "Patchlevel\EventSourcing\Tests\Unit\Fixture\Profile" must be instance of "Patchlevel\EventSourcing\Identifier\Identifier", got "int"', $exception->getMessage(), ); self::assertSame(0, $exception->getCode()); diff --git a/tests/Unit/Fixture/ProfileId.php b/tests/Unit/Fixture/ProfileId.php index 55fb67218..c77d931b0 100644 --- a/tests/Unit/Fixture/ProfileId.php +++ b/tests/Unit/Fixture/ProfileId.php @@ -4,16 +4,16 @@ namespace Patchlevel\EventSourcing\Tests\Unit\Fixture; -use Patchlevel\EventSourcing\Aggregate\AggregateRootId; +use Patchlevel\EventSourcing\Identifier\Identifier; -final class ProfileId implements AggregateRootId +final class ProfileId implements Identifier { private function __construct( private string $id, ) { } - public static function fromString(string $id): self + public static function fromString(string $id): static { return new self($id); } diff --git a/tests/Unit/Aggregate/CustomIdTest.php b/tests/Unit/Identifier/CustomIdTest.php similarity index 75% rename from tests/Unit/Aggregate/CustomIdTest.php rename to tests/Unit/Identifier/CustomIdTest.php index 8c0a1551d..845d52606 100644 --- a/tests/Unit/Aggregate/CustomIdTest.php +++ b/tests/Unit/Identifier/CustomIdTest.php @@ -2,9 +2,9 @@ declare(strict_types=1); -namespace Patchlevel\EventSourcing\Tests\Unit\Aggregate; +namespace Patchlevel\EventSourcing\Tests\Unit\Identifier; -use Patchlevel\EventSourcing\Aggregate\CustomId; +use Patchlevel\EventSourcing\Identifier\CustomId; use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\TestCase; diff --git a/tests/Unit/Test/IncrementalRamseyUuidFactoryTest.php b/tests/Unit/Identifier/FakeRamseyUuidFactoryTest.php similarity index 73% rename from tests/Unit/Test/IncrementalRamseyUuidFactoryTest.php rename to tests/Unit/Identifier/FakeRamseyUuidFactoryTest.php index 628f47d2f..e207d6444 100644 --- a/tests/Unit/Test/IncrementalRamseyUuidFactoryTest.php +++ b/tests/Unit/Identifier/FakeRamseyUuidFactoryTest.php @@ -2,20 +2,20 @@ declare(strict_types=1); -namespace Patchlevel\EventSourcing\Tests\Unit\Test; +namespace Patchlevel\EventSourcing\Tests\Unit\Identifier; -use Patchlevel\EventSourcing\Aggregate\Uuid; -use Patchlevel\EventSourcing\Test\IncrementalRamseyUuidFactory; +use Patchlevel\EventSourcing\Identifier\FakeRamseyUuidFactory; +use Patchlevel\EventSourcing\Identifier\Uuid; use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\TestCase; use Ramsey\Uuid\Uuid as RamseyUuid; -#[CoversClass(IncrementalRamseyUuidFactory::class)] -final class IncrementalRamseyUuidFactoryTest extends TestCase +#[CoversClass(FakeRamseyUuidFactory::class)] +final class FakeRamseyUuidFactoryTest extends TestCase { public function testGenerate(): void { - $factory = new IncrementalRamseyUuidFactory(); + $factory = new FakeRamseyUuidFactory(); self::assertSame('10000000-7000-0000-0000-000000000001', $factory->uuid7()->toString()); self::assertSame('10000000-7000-0000-0000-000000000002', $factory->uuid7()->toString()); @@ -31,7 +31,7 @@ public function testUuid(): void $previousFactory = RamseyUuid::getFactory(); try { - RamseyUuid::setFactory(new IncrementalRamseyUuidFactory()); + RamseyUuid::setFactory(new FakeRamseyUuidFactory()); self::assertSame('10000000-7000-0000-0000-000000000001', Uuid::generate()->toString()); self::assertSame('10000000-7000-0000-0000-000000000002', Uuid::generate()->toString()); diff --git a/tests/Unit/Aggregate/UuidTest.php b/tests/Unit/Identifier/UuidTest.php similarity index 91% rename from tests/Unit/Aggregate/UuidTest.php rename to tests/Unit/Identifier/UuidTest.php index 744ef4d07..f212f1793 100644 --- a/tests/Unit/Aggregate/UuidTest.php +++ b/tests/Unit/Identifier/UuidTest.php @@ -2,10 +2,10 @@ declare(strict_types=1); -namespace Patchlevel\EventSourcing\Tests\Unit\Aggregate; +namespace Patchlevel\EventSourcing\Tests\Unit\Identifier; use DateTimeInterface; -use Patchlevel\EventSourcing\Aggregate\Uuid; +use Patchlevel\EventSourcing\Identifier\Uuid; use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\TestCase; use Ramsey\Uuid\Uuid as RamseyUuid; diff --git a/tests/Unit/Serializer/Normalizer/IdNormalizerTest.php b/tests/Unit/Serializer/Normalizer/IdNormalizerTest.php index 9f0722cf7..720976f7e 100644 --- a/tests/Unit/Serializer/Normalizer/IdNormalizerTest.php +++ b/tests/Unit/Serializer/Normalizer/IdNormalizerTest.php @@ -5,19 +5,16 @@ namespace Patchlevel\EventSourcing\Tests\Unit\Serializer\Normalizer; use Attribute; -use Patchlevel\EventSourcing\Aggregate\CustomId; -use Patchlevel\EventSourcing\Aggregate\Uuid; +use Patchlevel\EventSourcing\Identifier\CustomId; +use Patchlevel\EventSourcing\Identifier\Uuid; use Patchlevel\EventSourcing\Serializer\Normalizer\IdNormalizer; -use Patchlevel\EventSourcing\Tests\Unit\Fixture\ProfileCreated; use Patchlevel\EventSourcing\Tests\Unit\Fixture\ProfileId; use Patchlevel\Hydrator\Normalizer\InvalidArgument; use Patchlevel\Hydrator\Normalizer\InvalidType; use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\TestCase; use Ramsey\Uuid\Exception\InvalidUuidStringException; -use ReflectionClass; -use ReflectionType; -use RuntimeException; +use Symfony\Component\TypeInfo\Type; #[CoversClass(IdNormalizer::class)] #[Attribute(Attribute::TARGET_PROPERTY)] @@ -38,7 +35,7 @@ public function testDenormalizeWithNull(): void public function testNormalizeWithInvalidArgument(): void { $this->expectException(InvalidArgument::class); - $this->expectExceptionMessage('type "Patchlevel\EventSourcing\Aggregate\CustomId" was expected but "string" was passed.'); + $this->expectExceptionMessage('type "Patchlevel\EventSourcing\Identifier\CustomId" was expected but "string" was passed.'); $normalizer = new IdNormalizer(CustomId::class); $normalizer->normalize('foo'); @@ -75,9 +72,9 @@ public function testDenormalizeWithWrongValue(): void public function testAutoDetect(): void { $normalizer = new IdNormalizer(); - $normalizer->handleReflectionType($this->reflectionType(ProfileCreated::class, 'profileId')); + $normalizer->handleType(Type::object(ProfileId::class)); - self::assertEquals(ProfileId::class, $normalizer->aggregateIdClass()); + self::assertEquals(ProfileId::class, $normalizer->identifierClass()); } public function testAutoDetectMissingType(): void @@ -85,7 +82,7 @@ public function testAutoDetectMissingType(): void $this->expectException(InvalidType::class); $normalizer = new IdNormalizer(); - $normalizer->aggregateIdClass(); + $normalizer->identifierClass(); } public function testAutoDetectMissingTypeBecauseNull(): void @@ -93,23 +90,8 @@ public function testAutoDetectMissingTypeBecauseNull(): void $this->expectException(InvalidType::class); $normalizer = new IdNormalizer(); - $normalizer->handleReflectionType(null); + $normalizer->handleType(null); - $normalizer->aggregateIdClass(); - } - - /** @param class-string $class */ - private function reflectionType(string $class, string $property): ReflectionType - { - $reflection = new ReflectionClass($class); - $property = $reflection->getProperty($property); - - $type = $property->getType(); - - if (!$type instanceof ReflectionType) { - throw new RuntimeException('no type'); - } - - return $type; + $normalizer->identifierClass(); } } diff --git a/tests/Unit/Snapshot/SnapshotNotFoundTest.php b/tests/Unit/Snapshot/SnapshotNotFoundTest.php index dab026d63..8aff32aea 100644 --- a/tests/Unit/Snapshot/SnapshotNotFoundTest.php +++ b/tests/Unit/Snapshot/SnapshotNotFoundTest.php @@ -4,8 +4,8 @@ namespace Patchlevel\EventSourcing\Tests\Unit\Snapshot; -use Patchlevel\EventSourcing\Aggregate\AggregateRootId; -use Patchlevel\EventSourcing\Aggregate\CustomIdBehaviour; +use Patchlevel\EventSourcing\Identifier\CustomIdBehaviour; +use Patchlevel\EventSourcing\Identifier\Identifier; use Patchlevel\EventSourcing\Snapshot\SnapshotNotFound; use Patchlevel\EventSourcing\Tests\Unit\Fixture\Profile; use PHPUnit\Framework\Attributes\CoversClass; @@ -16,7 +16,7 @@ final class SnapshotNotFoundTest extends TestCase { public function testCreate(): void { - $exception = new SnapshotNotFound(Profile::class, new class ('1') implements AggregateRootId { + $exception = new SnapshotNotFound(Profile::class, new class ('1') implements Identifier { use CustomIdBehaviour; }); diff --git a/tests/Unit/Subscription/ErrorContextTest.php b/tests/Unit/Subscription/ErrorContextTest.php index 132fb4bbf..ac2d244cd 100644 --- a/tests/Unit/Subscription/ErrorContextTest.php +++ b/tests/Unit/Subscription/ErrorContextTest.php @@ -4,7 +4,7 @@ namespace Patchlevel\EventSourcing\Tests\Unit\Subscription; -use Patchlevel\EventSourcing\Aggregate\CustomId; +use Patchlevel\EventSourcing\Identifier\CustomId; use Patchlevel\EventSourcing\Subscription\ThrowableToErrorContextTransformer; use PHPUnit\Framework\TestCase; use RuntimeException; @@ -54,7 +54,7 @@ public function testErrorContext(): void self::assertArrayHasKey('args', $firstTrace); self::assertSame([ ['string', 'test'], - ['object', 'Patchlevel\EventSourcing\Aggregate\CustomId'], + ['object', 'Patchlevel\EventSourcing\Identifier\CustomId'], ['resource', 'stream'], [ 'array',