diff --git a/Neos.ContentRepository.BehavioralTests/Configuration/Testing/Settings.yaml b/Neos.ContentRepository.BehavioralTests/Configuration/Testing/Settings.yaml index 24d25b2706..e108882120 100644 --- a/Neos.ContentRepository.BehavioralTests/Configuration/Testing/Settings.yaml +++ b/Neos.ContentRepository.BehavioralTests/Configuration/Testing/Settings.yaml @@ -43,6 +43,27 @@ Neos: options: instanceId: debug + t_extensibility: + eventStore: + factoryObjectName: Neos\ContentRepositoryRegistry\Factory\EventStore\DoctrineEventStoreFactory + nodeTypeManager: + factoryObjectName: Neos\ContentRepository\TestSuite\Fakes\FakeNodeTypeManagerFactory + contentDimensionSource: + factoryObjectName: Neos\ContentRepository\TestSuite\Fakes\FakeContentDimensionSourceFactory + authProvider: + factoryObjectName: Neos\ContentRepository\TestSuite\Fakes\FakeAuthProviderFactory + clock: + factoryObjectName: Neos\ContentRepositoryRegistry\Factory\Clock\SystemClockFactory + subscriptionStore: + factoryObjectName: Neos\ContentRepositoryRegistry\Factory\SubscriptionStore\SubscriptionStoreFactory + propertyConverters: {} + contentGraphProjection: + factoryObjectName: Neos\ContentGraph\DoctrineDbalAdapter\DoctrineDbalContentGraphProjectionFactory + catchUpHooks: {} + commandHooks: + 'Neos.Testing:FakeCommandHook': + factoryObjectName: Neos\ContentRepository\TestSuite\Fakes\FakeCommandHookFactory + t_subscription: eventStore: factoryObjectName: Neos\ContentRepositoryRegistry\Factory\EventStore\DoctrineEventStoreFactory diff --git a/Neos.ContentRepository.BehavioralTests/Tests/Functional/Extensibility/AbstractExtensibilityTestCase.php b/Neos.ContentRepository.BehavioralTests/Tests/Functional/Extensibility/AbstractExtensibilityTestCase.php new file mode 100644 index 0000000000..7be79e2fc4 --- /dev/null +++ b/Neos.ContentRepository.BehavioralTests/Tests/Functional/Extensibility/AbstractExtensibilityTestCase.php @@ -0,0 +1,83 @@ +getObject(Connection::class)->getDatabasePlatform() instanceof PostgreSQLPlatform) { + $this->markTestSkipped('TODO: The content graph is not available in postgres currently: https://github.com/neos/neos-development-collection/issues/3855'); + } + + $this->fakeCommandHook = $this->getMockBuilder(CommandHookInterface::class)->disableAutoReturnValueGeneration()->getMock(); + + FakeCommandHookFactory::setCommandHook( + $this->fakeCommandHook + ); + + FakeNodeTypeManagerFactory::setConfiguration([ + 'Neos.ContentRepository:Root' => [], + 'Neos.ContentRepository.Testing:Document' => [ + 'properties' => [ + 'title' => [ + 'type' => 'string' + ] + ] + ] + ]); + FakeContentDimensionSourceFactory::setWithoutDimensions(); + + $this->getObject(ContentRepositoryRegistry::class)->resetFactoryInstance(static::$contentRepositoryId); + + /** @var ContentRepositoryMaintainer $contentRepositoryMaintainer */ + $contentRepositoryMaintainer = $this->getObject(ContentRepositoryRegistry::class)->buildService(static::$contentRepositoryId, new ContentRepositoryMaintainerFactory()); + $contentRepositoryMaintainer->setUp(); + // reset events and projections + $contentRepositoryMaintainer->prune(); + + $this->contentRepository = $this->getObject(ContentRepositoryRegistry::class)->get(static::$contentRepositoryId); + } + + /** + * @template T of object + * @param class-string $className + * + * @return T + */ + final protected function getObject(string $className): object + { + return Bootstrap::$staticObjectManager->get($className); + } +} diff --git a/Neos.ContentRepository.BehavioralTests/Tests/Functional/Extensibility/CommandHookTest.php b/Neos.ContentRepository.BehavioralTests/Tests/Functional/Extensibility/CommandHookTest.php new file mode 100644 index 0000000000..8cf590debf --- /dev/null +++ b/Neos.ContentRepository.BehavioralTests/Tests/Functional/Extensibility/CommandHookTest.php @@ -0,0 +1,218 @@ +fakeCommandHook->expects(self::once())->method('onBeforeHandle')->with($command)->willReturn($command); + $this->fakeCommandHook->expects(self::once())->method('onAfterHandle')->with($command, $expectedEvents)->willReturn(Commands::createEmpty()); + + $this->contentRepository->handle($command); + } + + /** + * onBeforeHandle and onAfterHandle are invoked in various cases, for control flow aware commands and also simple ones + */ + public function testCommandHookWithMultipleCommands(): void + { + $testCases = [ + [ + 'command' => CreateRootWorkspace::create(WorkspaceName::forLive(), ContentStreamId::fromString('cs-live')), + 'eventClassNames' => [ContentStreamWasCreated::class, RootWorkspaceWasCreated::class] + ], + [ + 'command' => CreateWorkspace::create(WorkspaceName::fromString('user'), WorkspaceName::forLive(), ContentStreamId::fromString('cs-user')), + 'eventClassNames' => [ContentStreamWasForked::class, WorkspaceWasCreated::class] + ], + [ + 'command' => CreateRootNodeAggregateWithNode::create(WorkspaceName::fromString('user'), NodeAggregateId::fromString('node'), NodeTypeName::fromString(NodeTypeName::ROOT_NODE_TYPE_NAME)), + 'eventClassNames' => [RootNodeAggregateWithNodeWasCreated::class] + ], + [ + 'command' => PublishWorkspace::create(WorkspaceName::fromString('user')), + 'eventClassNames' => [ContentStreamWasClosed::class, RootNodeAggregateWithNodeWasCreated::class, ContentStreamWasForked::class, WorkspaceWasPublished::class, ContentStreamWasRemoved::class] + ], + ]; + + $this->fakeCommandHook->expects($i = self::exactly(count($testCases)))->method('onBeforeHandle')->willReturnCallback(function (CommandInterface $command) use ($i, $testCases) { + $caseIndex = $i->getInvocationCount() - 1; + + $testCase = $testCases[$caseIndex]; + self::assertEquals($testCase['command'], $command, sprintf('The command at step %s doesnt match as expected', $caseIndex)); + return $testCase['command']; + }); + $this->fakeCommandHook->expects($i = self::exactly(count($testCases)))->method('onAfterHandle')->willReturnCallback(function (CommandInterface $command, Events $events) use ($i, $testCases) { + $caseIndex = $i->getInvocationCount() - 1; + + $testCase = $testCases[$caseIndex]; + self::assertEquals($testCase['command'], $command, sprintf('The command at step %s doesnt match as expected', $caseIndex)); + self::assertEquals($testCase['eventClassNames'], $events->map(fn ($event) => $event::class), sprintf('The events at step %s doesnt match as expected', $caseIndex)); + return Commands::createEmpty(); + }); + + foreach ($testCases as $testCase) { + $this->contentRepository->handle($testCase['command']); + } + } + + /** + * onBeforeHandle can exchange the command that was passed by returning something else + */ + public function testCommandHookReplacesCommand(): void + { + $command = CreateRootWorkspace::create(WorkspaceName::forLive(), ContentStreamId::fromString('cs-live')); + + $replacedCommand = CreateRootWorkspace::create(WorkspaceName::fromString('replaced'), ContentStreamId::fromString('cs-replaced')); + $expectedEvents = Events::fromArray([ + new ContentStreamWasCreated(ContentStreamId::fromString('cs-replaced')), + new RootWorkspaceWasCreated(WorkspaceName::fromString('replaced'), ContentStreamId::fromString('cs-replaced')) + ]); + + $this->fakeCommandHook->expects(self::once())->method('onBeforeHandle')->with($command)->willReturn($replacedCommand); + $this->fakeCommandHook->expects(self::once())->method('onAfterHandle')->with($replacedCommand, $expectedEvents)->willReturn(Commands::createEmpty()); + + $this->contentRepository->handle($command); + + self::assertNull($this->contentRepository->findWorkspaceByName(WorkspaceName::forLive())); + self::assertNotNull($this->contentRepository->findWorkspaceByName(WorkspaceName::fromString('replaced'))); + } + + /** + * Test for simple command handling with a followup, like issue a command on live a node was directly created on live - not published + */ + public function testIssueFollowupCommandsSimpleCase(): void + { + $this->fakeCommandHook->expects(self::exactly(4))->method('onBeforeHandle')->willReturnArgument(0); + $this->fakeCommandHook->expects($i = self::exactly(4))->method('onAfterHandle')->willReturnCallback(function (CommandInterface $command, Events $events) use ($i) { + if ($i->getInvocationCount() === 3) { + self::assertInstanceOf(CreateNodeAggregateWithNode::class, $command); + self::assertEquals([NodeAggregateWithNodeWasCreated::class], $events->map(fn ($event) => $event::class)); + + $subgraph = $this->contentRepository->getContentGraph(WorkspaceName::forLive())->getSubgraph(DimensionSpacePoint::createWithoutDimensions(), VisibilityConstraints::withoutRestrictions()); + $node = $subgraph->findNodeById(NodeAggregateId::fromString('document-node')); + self::assertNotNull($node, 'The node must exist onAfterHandle'); + self::assertNull($node->getProperty('title')); + + return Commands::create(SetNodeProperties::create( + WorkspaceName::forLive(), + NodeAggregateId::fromString('document-node'), + OriginDimensionSpacePoint::createWithoutDimensions(), + PropertyValuesToWrite::fromArray([ + 'title' => 'set by hook' + ]) + )); + } elseif ($i->getInvocationCount() === 4) { + // recursion passes the via the previous onAfterHandle hook back here: + self::assertInstanceOf(SetNodeProperties::class, $command); + + return Commands::createEmpty(); + } else { + return Commands::createEmpty(); + } + }); + + $this->contentRepository->handle(CreateRootWorkspace::create(WorkspaceName::forLive(), ContentStreamId::fromString('cs-live'))); + $this->contentRepository->handle(CreateRootNodeAggregateWithNode::create(WorkspaceName::forLive(), NodeAggregateId::fromString('root'), NodeTypeName::fromString(NodeTypeName::ROOT_NODE_TYPE_NAME))); + $this->contentRepository->handle(CreateNodeAggregateWithNode::create( + WorkspaceName::forLive(), + NodeAggregateId::fromString('document-node'), + NodeTypeName::fromString('Neos.ContentRepository.Testing:Document'), + OriginDimensionSpacePoint::createWithoutDimensions(), + parentNodeAggregateId: NodeAggregateId::fromString('root') + )); + + $subgraph = $this->contentRepository->getContentGraph(WorkspaceName::forLive())->getSubgraph(DimensionSpacePoint::createWithoutDimensions(), VisibilityConstraints::withoutRestrictions()); + $node = $subgraph->findNodeById(NodeAggregateId::fromString('document-node')); + self::assertNotNull($node); + self::assertEquals('set by hook', $node->getProperty('title')); + } + + /** + * Test for control-flow aware command handling with a followup, like issue a command on live if PublishWorkspace contains a certain creation of a node + */ + public function testIssueFollowupCommandOnPublish(): void + { + $this->fakeCommandHook->expects(self::exactly(6))->method('onBeforeHandle')->willReturnArgument(0); + $this->fakeCommandHook->expects($i = self::exactly(6))->method('onAfterHandle')->willReturnCallback(function (CommandInterface $command, Events $events) use ($i) { + if ($i->getInvocationCount() === 5) { + self::assertInstanceOf(PublishWorkspace::class, $command); + self::assertContains(NodeAggregateWithNodeWasCreated::class, $events->map(fn ($event) => $event::class)); + + $subgraph = $this->contentRepository->getContentGraph(WorkspaceName::forLive())->getSubgraph(DimensionSpacePoint::createWithoutDimensions(), VisibilityConstraints::withoutRestrictions()); + $node = $subgraph->findNodeById(NodeAggregateId::fromString('document-node')); + self::assertNotNull($node, 'The node must exist onAfterHandle'); + self::assertNull($node->getProperty('title')); + + return Commands::create(SetNodeProperties::create( + WorkspaceName::forLive(), + NodeAggregateId::fromString('document-node'), + OriginDimensionSpacePoint::createWithoutDimensions(), + PropertyValuesToWrite::fromArray([ + 'title' => 'set by hook' + ]) + )); + } elseif ($i->getInvocationCount() === 6) { + // recursion passes the via the previous onAfterHandle hook back here: + self::assertInstanceOf(SetNodeProperties::class, $command); + + return Commands::createEmpty(); + } else { + return Commands::createEmpty(); + } + }); + + $this->contentRepository->handle(CreateRootWorkspace::create(WorkspaceName::forLive(), ContentStreamId::fromString('cs-live'))); + $this->contentRepository->handle(CreateRootNodeAggregateWithNode::create(WorkspaceName::forLive(), NodeAggregateId::fromString('root'), NodeTypeName::fromString(NodeTypeName::ROOT_NODE_TYPE_NAME))); + $this->contentRepository->handle(CreateWorkspace::create(WorkspaceName::fromString('user'), WorkspaceName::forLive(), ContentStreamId::fromString('cs-user'))); + $this->contentRepository->handle(CreateNodeAggregateWithNode::create( + WorkspaceName::fromString('user'), + NodeAggregateId::fromString('document-node'), + NodeTypeName::fromString('Neos.ContentRepository.Testing:Document'), + OriginDimensionSpacePoint::createWithoutDimensions(), + parentNodeAggregateId: NodeAggregateId::fromString('root') + )); + $this->contentRepository->handle(PublishWorkspace::create(WorkspaceName::fromString('user'))); + + $subgraph = $this->contentRepository->getContentGraph(WorkspaceName::forLive())->getSubgraph(DimensionSpacePoint::createWithoutDimensions(), VisibilityConstraints::withoutRestrictions()); + $node = $subgraph->findNodeById(NodeAggregateId::fromString('document-node')); + self::assertNotNull($node); + self::assertEquals('set by hook', $node->getProperty('title')); + } +} diff --git a/Neos.ContentRepository.Core/Classes/CommandHandler/CommandHookInterface.php b/Neos.ContentRepository.Core/Classes/CommandHandler/CommandHookInterface.php index 2afb7b2ea3..f73ebe28e4 100644 --- a/Neos.ContentRepository.Core/Classes/CommandHandler/CommandHookInterface.php +++ b/Neos.ContentRepository.Core/Classes/CommandHandler/CommandHookInterface.php @@ -5,6 +5,7 @@ namespace Neos\ContentRepository\Core\CommandHandler; use Neos\ContentRepository\Core\ContentRepository; +use Neos\ContentRepository\Core\EventStore\Events; /** * Contract for a hook that is invoked just before any command is processed via {@see ContentRepository::handle()} @@ -22,4 +23,11 @@ interface CommandHookInterface * @return CommandInterface This hook must return a command instance. It can be the unaltered incoming $command or a new instance */ public function onBeforeHandle(CommandInterface $command): CommandInterface; + + /** + * @param CommandInterface $command The command that was just handled + * @param Events $events The events that resulted from the handled command + * @return Commands This hook must return Commands that will be handled after the incoming $command. The Commands can be empty. + */ + public function onAfterHandle(CommandInterface $command, Events $events): Commands; } diff --git a/Neos.ContentRepository.Core/Classes/CommandHandler/CommandHooks.php b/Neos.ContentRepository.Core/Classes/CommandHandler/CommandHooks.php index 0f96412fc3..840629c522 100644 --- a/Neos.ContentRepository.Core/Classes/CommandHandler/CommandHooks.php +++ b/Neos.ContentRepository.Core/Classes/CommandHandler/CommandHooks.php @@ -4,6 +4,8 @@ namespace Neos\ContentRepository\Core\CommandHandler; +use Neos\ContentRepository\Core\EventStore\Events; + /** * Collection of {@see CommandHookInterface} instances, functioning as a delegating command hook implementation * @@ -53,4 +55,13 @@ public function onBeforeHandle(CommandInterface $command): CommandInterface } return $command; } + + public function onAfterHandle(CommandInterface $command, Events $events): Commands + { + $commands = Commands::createEmpty(); + foreach ($this->commandHooks as $commandHook) { + $commands = $commands->merge($commandHook->onAfterHandle($command, $events)); + } + return $commands; + } } diff --git a/Neos.ContentRepository.Core/Classes/ContentRepository.php b/Neos.ContentRepository.Core/Classes/ContentRepository.php index 1d2ece621e..e941231fea 100644 --- a/Neos.ContentRepository.Core/Classes/ContentRepository.php +++ b/Neos.ContentRepository.Core/Classes/ContentRepository.php @@ -23,6 +23,7 @@ use Neos\ContentRepository\Core\EventStore\DecoratedEvent; use Neos\ContentRepository\Core\EventStore\EventInterface; use Neos\ContentRepository\Core\EventStore\EventNormalizer; +use Neos\ContentRepository\Core\EventStore\DecoratedEvents; use Neos\ContentRepository\Core\EventStore\Events as DomainEvents; use Neos\ContentRepository\Core\EventStore\EventsToPublish; use Neos\ContentRepository\Core\EventStore\InitiatingEventMetadata; @@ -37,8 +38,6 @@ use Neos\ContentRepository\Core\Projection\ProjectionStates; use Neos\ContentRepository\Core\SharedModel\ContentRepository\ContentRepositoryId; use Neos\ContentRepository\Core\SharedModel\Exception\WorkspaceDoesNotExist; -use Neos\ContentRepository\Core\SharedModel\Id\UuidFactory; -use Neos\ContentRepository\Core\SharedModel\Workspace\ContentStreams; use Neos\ContentRepository\Core\SharedModel\Workspace\Workspace; use Neos\ContentRepository\Core\SharedModel\Workspace\WorkspaceName; use Neos\ContentRepository\Core\SharedModel\Workspace\Workspaces; @@ -106,14 +105,20 @@ public function handle(CommandInterface $command): void if ($fullCatchUpResult->hadErrors()) { throw CatchUpHadErrors::createFromErrors($fullCatchUpResult->errors); } + $additionalCommands = $this->commandHook->onAfterHandle($command, $toPublish->events->toInnerEvents()); + foreach ($additionalCommands as $additionalCommand) { + $this->handle($additionalCommand); + } return; } // control-flow aware command handling via generator + $emittedEvents = DomainEvents::createEmpty(); try { foreach ($toPublish as $eventsToPublish) { try { $this->eventStore->commit($eventsToPublish->streamName, $this->enrichAndNormalizeEvents($eventsToPublish->events, $correlationId), $eventsToPublish->expectedVersion); + $emittedEvents = $emittedEvents->withAppendedEvents($eventsToPublish->events->toInnerEvents()); } catch (ConcurrencyException $concurrencyException) { // we pass the exception into the generator (->throw), so it could be try-caught and reacted upon: // @@ -138,6 +143,10 @@ public function handle(CommandInterface $command): void throw CatchUpHadErrors::createFromErrors($fullCatchUpResult->errors); } } + $additionalCommands = $this->commandHook->onAfterHandle($command, $emittedEvents); + foreach ($additionalCommands as $additionalCommand) { + $this->handle($additionalCommand); + } } @@ -210,7 +219,7 @@ public function getContentDimensionSource(): ContentDimensionSourceInterface return $this->contentDimensionSource; } - private function enrichAndNormalizeEvents(DomainEvents $events, CorrelationId $correlationId): Events + private function enrichAndNormalizeEvents(DecoratedEvents $events, CorrelationId $correlationId): Events { $initiatingUserId = $this->authProvider->getAuthenticatedUserId() ?? UserId::forSystemUser(); $initiatingTimestamp = $this->clock->now(); diff --git a/Neos.ContentRepository.Core/Classes/EventStore/DecoratedEvents.php b/Neos.ContentRepository.Core/Classes/EventStore/DecoratedEvents.php new file mode 100644 index 0000000000..f4dbe0544b --- /dev/null +++ b/Neos.ContentRepository.Core/Classes/EventStore/DecoratedEvents.php @@ -0,0 +1,79 @@ + Writable events must contain at least one event + * + * We do not skip the case for 0 events to ensure each command always maps to a mutation. + * Forgiving noop behaviour is not intended for this low level code. + * + * @implements \IteratorAggregate + * @internal only used during event publishing (from within command handlers) - and their implementation is not API + */ +final readonly class DecoratedEvents implements \IteratorAggregate, \Countable +{ + /** + * @var non-empty-array + */ + public array $items; + + private function __construct(EventInterface|DecoratedEvent ...$events) + { + /** @var non-empty-array $events */ + $this->items = $events; + } + + public static function with(EventInterface|DecoratedEvent $event): self + { + return new self($event); + } + + public function withAppendedEvents(DecoratedEvents $events): self + { + return new self(...$this->items, ...$events->items); + } + + /** + * @param non-empty-array $events + * @return static + */ + public static function fromArray(array $events): self + { + return new self(...$events); + } + + public function getIterator(): \Traversable + { + yield from $this->items; + } + + /** + * @template T + * @param \Closure(EventInterface|DecoratedEvent $event): T $callback + * @return non-empty-list + */ + public function map(\Closure $callback): array + { + return array_map($callback, $this->items); + } + + public function toInnerEvents(): Events + { + return Events::fromArray($this->map(fn (EventInterface|DecoratedEvent $event) => $event instanceof DecoratedEvent ? $event->innerEvent : $event)); + } + + public function count(): int + { + return count($this->items); + } +} diff --git a/Neos.ContentRepository.Core/Classes/EventStore/Events.php b/Neos.ContentRepository.Core/Classes/EventStore/Events.php index 622f625cac..f302eea5de 100644 --- a/Neos.ContentRepository.Core/Classes/EventStore/Events.php +++ b/Neos.ContentRepository.Core/Classes/EventStore/Events.php @@ -4,52 +4,43 @@ namespace Neos\ContentRepository\Core\EventStore; -use Neos\EventStore\EventStoreInterface; /** - * A set of Content Repository "domain events", part of {@see EventsToPublish} + * A set of Content Repository "domain events" * - * For better type checking we ensure that this collection is never empty. - * That is because {@see EventStoreInterface::commit()} will throw an exception if there are 0 events passed: - * - * > Writable events must contain at least one event - * - * We do not skip the case for 0 events to ensure each command always maps to a mutation. - * Forgiving noop behaviour is not intended for this low level code. - * - * @implements \IteratorAggregate - * @internal only used during event publishing (from within command handlers) - and their implementation is not API + * @implements \IteratorAggregate + * @api */ final readonly class Events implements \IteratorAggregate, \Countable { /** - * @var non-empty-array + * @var non-empty-array */ public array $items; - private function __construct(EventInterface|DecoratedEvent ...$events) + private function __construct(EventInterface ...$events) { - /** @var non-empty-array $events */ + /** @var non-empty-array $events */ $this->items = $events; } - public static function with(EventInterface|DecoratedEvent $event): self + /** + * @param non-empty-array $events + * @return static + */ + public static function fromArray(array $events): self { - return new self($event); + return new self(...$events); } - public function withAppendedEvents(Events $events): self + public static function createEmpty(): self { - return new self(...$this->items, ...$events->items); + return new self(); } - /** - * @param non-empty-array $events - * @return static - */ - public static function fromArray(array $events): self + public function withAppendedEvents(Events $events): self { - return new self(...$events); + return new self(...$this->items, ...$events->items); } public function getIterator(): \Traversable @@ -59,7 +50,7 @@ public function getIterator(): \Traversable /** * @template T - * @param \Closure(EventInterface|DecoratedEvent $event): T $callback + * @param \Closure(EventInterface $event): T $callback * @return non-empty-list */ public function map(\Closure $callback): array diff --git a/Neos.ContentRepository.Core/Classes/EventStore/EventsToPublish.php b/Neos.ContentRepository.Core/Classes/EventStore/EventsToPublish.php index ee9e22ef10..e34352ff72 100644 --- a/Neos.ContentRepository.Core/Classes/EventStore/EventsToPublish.php +++ b/Neos.ContentRepository.Core/Classes/EventStore/EventsToPublish.php @@ -20,12 +20,12 @@ { public function __construct( public StreamName $streamName, - public Events $events, + public DecoratedEvents $events, public ExpectedVersion $expectedVersion, ) { } - public function withAppendedEvents(Events $events): self + public function withAppendedEvents(DecoratedEvents $events): self { return new self( $this->streamName, diff --git a/Neos.ContentRepository.Core/Classes/EventStore/InitiatingEventMetadata.php b/Neos.ContentRepository.Core/Classes/EventStore/InitiatingEventMetadata.php index 260226553e..567286d181 100644 --- a/Neos.ContentRepository.Core/Classes/EventStore/InitiatingEventMetadata.php +++ b/Neos.ContentRepository.Core/Classes/EventStore/InitiatingEventMetadata.php @@ -30,13 +30,13 @@ private function __construct() * the "initiatingTimestamp" will be kept and is never overridden again. */ public static function enrichEventsWithInitiatingMetadata( - Events $events, + DecoratedEvents $events, UserId $initiatingUserId, \DateTimeImmutable $initiatingTimestamp, - ): Events { + ): DecoratedEvents { $initiatingTimestampFormatted = $initiatingTimestamp->format(\DateTimeInterface::ATOM); - return Events::fromArray( + return DecoratedEvents::fromArray( $events->map(function (EventInterface|DecoratedEvent $event) use ( $initiatingUserId, $initiatingTimestampFormatted diff --git a/Neos.ContentRepository.Core/Classes/Feature/Common/NodeVariationInternals.php b/Neos.ContentRepository.Core/Classes/Feature/Common/NodeVariationInternals.php index 349de0d4ce..3749ff0006 100644 --- a/Neos.ContentRepository.Core/Classes/Feature/Common/NodeVariationInternals.php +++ b/Neos.ContentRepository.Core/Classes/Feature/Common/NodeVariationInternals.php @@ -18,7 +18,7 @@ use Neos\ContentRepository\Core\DimensionSpace\DimensionSpacePointSet; use Neos\ContentRepository\Core\DimensionSpace\OriginDimensionSpacePoint; use Neos\ContentRepository\Core\EventStore\EventInterface; -use Neos\ContentRepository\Core\EventStore\Events; +use Neos\ContentRepository\Core\EventStore\DecoratedEvents; use Neos\ContentRepository\Core\Feature\NodeVariation\Event\NodeGeneralizationVariantWasCreated; use Neos\ContentRepository\Core\Feature\NodeVariation\Event\NodePeerVariantWasCreated; use Neos\ContentRepository\Core\Feature\NodeVariation\Event\NodeSpecializationVariantWasCreated; @@ -40,7 +40,7 @@ protected function createEventsForVariations( OriginDimensionSpacePoint $sourceOrigin, OriginDimensionSpacePoint $targetOrigin, NodeAggregate $nodeAggregate - ): Events { + ): DecoratedEvents { return match ( $this->getInterDimensionalVariationGraph()->getVariantType( $targetOrigin->toDimensionSpacePoint(), @@ -73,7 +73,7 @@ protected function handleCreateNodeSpecializationVariant( OriginDimensionSpacePoint $sourceOrigin, OriginDimensionSpacePoint $targetOrigin, NodeAggregate $nodeAggregate - ): Events { + ): DecoratedEvents { $specializationVisibility = $this->calculateEffectiveVisibility($targetOrigin, $nodeAggregate); $events = $this->collectNodeSpecializationVariantsThatWillHaveBeenCreated( $contentGraph, @@ -84,7 +84,7 @@ protected function handleCreateNodeSpecializationVariant( [] ); - return Events::fromArray($events); + return DecoratedEvents::fromArray($events); } /** @@ -136,7 +136,7 @@ protected function handleCreateNodeGeneralizationVariant( OriginDimensionSpacePoint $sourceOrigin, OriginDimensionSpacePoint $targetOrigin, NodeAggregate $nodeAggregate - ): Events { + ): DecoratedEvents { $generalizationVisibility = $this->calculateEffectiveVisibility($targetOrigin, $nodeAggregate); $events = $this->collectNodeGeneralizationVariantsThatWillHaveBeenCreated( $contentGraph, @@ -147,7 +147,7 @@ protected function handleCreateNodeGeneralizationVariant( [] ); - return Events::fromArray($events); + return DecoratedEvents::fromArray($events); } /** @@ -199,7 +199,7 @@ protected function handleCreateNodePeerVariant( OriginDimensionSpacePoint $sourceOrigin, OriginDimensionSpacePoint $targetOrigin, NodeAggregate $nodeAggregate - ): Events { + ): DecoratedEvents { $peerVisibility = $this->calculateEffectiveVisibility($targetOrigin, $nodeAggregate); $events = $this->collectNodePeerVariantsThatWillHaveBeenCreated( $contentGraph, @@ -210,7 +210,7 @@ protected function handleCreateNodePeerVariant( [] ); - return Events::fromArray($events); + return DecoratedEvents::fromArray($events); } /** diff --git a/Neos.ContentRepository.Core/Classes/Feature/Common/TetheredNodeInternals.php b/Neos.ContentRepository.Core/Classes/Feature/Common/TetheredNodeInternals.php index c53ca1f431..3bff45ffc9 100644 --- a/Neos.ContentRepository.Core/Classes/Feature/Common/TetheredNodeInternals.php +++ b/Neos.ContentRepository.Core/Classes/Feature/Common/TetheredNodeInternals.php @@ -18,7 +18,7 @@ use Neos\ContentRepository\Core\DimensionSpace\OriginDimensionSpacePointSet; use Neos\ContentRepository\Core\DimensionSpace\VariantType; use Neos\ContentRepository\Core\EventStore\EventInterface; -use Neos\ContentRepository\Core\EventStore\Events; +use Neos\ContentRepository\Core\EventStore\DecoratedEvents; use Neos\ContentRepository\Core\Feature\NodeCreation\Dto\NodeAggregateIdsByNodePaths; use Neos\ContentRepository\Core\Feature\NodeCreation\Event\NodeAggregateWithNodeWasCreated; use Neos\ContentRepository\Core\Feature\NodeModification\Dto\SerializedPropertyValues; @@ -56,7 +56,7 @@ abstract protected function createEventsForVariations( OriginDimensionSpacePoint $sourceOrigin, OriginDimensionSpacePoint $targetOrigin, NodeAggregate $nodeAggregate - ): Events; + ): DecoratedEvents; /** * This is the remediation action for non-existing tethered nodes. @@ -72,7 +72,7 @@ protected function createEventsForMissingTetheredNode( OriginDimensionSpacePoint $originDimensionSpacePoint, TetheredNodeTypeDefinition $tetheredNodeTypeDefinition, ?NodeAggregateId $tetheredNodeAggregateId - ): Events { + ): DecoratedEvents { $childNodeAggregate = $contentGraph->findChildNodeAggregateByName( $parentNodeAggregate->nodeAggregateId, $tetheredNodeTypeDefinition->name @@ -123,9 +123,9 @@ protected function createEventsForMissingTetheredNode( $creationOriginDimensionSpacePoint = $rootGeneralizationOrigin; } } - return Events::fromArray($events); + return DecoratedEvents::fromArray($events); } - return Events::with( + return DecoratedEvents::with( new NodeAggregateWithNodeWasCreated( $contentGraph->getWorkspaceName(), $contentGraph->getContentStreamId(), @@ -271,7 +271,7 @@ protected function createEventsForWronglyTypedNodeAggregate( NodePath $currentNodePath, NodeAggregateTypeChangeChildConstraintConflictResolutionStrategy $conflictResolutionStrategy, NodeAggregateIds $alreadyRemovedNodeAggregateIds, - ): Events { + ): DecoratedEvents { $events = []; $tetheredNodeType = $this->requireNodeType($newNodeTypeName); @@ -362,6 +362,6 @@ protected function createEventsForWronglyTypedNodeAggregate( } } - return Events::fromArray($events); + return DecoratedEvents::fromArray($events); } } diff --git a/Neos.ContentRepository.Core/Classes/Feature/ContentStreamHandling.php b/Neos.ContentRepository.Core/Classes/Feature/ContentStreamHandling.php index 9f4ccdfa71..5706241984 100644 --- a/Neos.ContentRepository.Core/Classes/Feature/ContentStreamHandling.php +++ b/Neos.ContentRepository.Core/Classes/Feature/ContentStreamHandling.php @@ -6,7 +6,7 @@ use Neos\ContentRepository\Core\CommandHandler\CommandHandlingDependencies; use Neos\ContentRepository\Core\EventStore\DecoratedEvent; -use Neos\ContentRepository\Core\EventStore\Events; +use Neos\ContentRepository\Core\EventStore\DecoratedEvents; use Neos\ContentRepository\Core\EventStore\EventsToPublish; use Neos\ContentRepository\Core\Feature\ContentStreamClosing\Event\ContentStreamWasClosed; use Neos\ContentRepository\Core\Feature\ContentStreamClosing\Event\ContentStreamWasReopened; @@ -36,7 +36,7 @@ private function closeContentStream( return new EventsToPublish( $streamName, - Events::with( + DecoratedEvents::with( new ContentStreamWasClosed( $contentStreamId, ), @@ -55,7 +55,7 @@ private function reopenContentStreamWithoutConstraintChecks( ): EventsToPublish { return new EventsToPublish( ContentStreamEventStreamName::fromContentStreamId($contentStreamId)->getEventStreamName(), - Events::with( + DecoratedEvents::with( DecoratedEvent::create( new ContentStreamWasReopened( $contentStreamId @@ -84,7 +84,7 @@ private function forkContentStream( ): EventsToPublish { return new EventsToPublish( ContentStreamEventStreamName::fromContentStreamId($newContentStreamId)->getEventStreamName(), - Events::with( + DecoratedEvents::with( DecoratedEvent::create( event: new ContentStreamWasForked( $newContentStreamId, @@ -108,7 +108,7 @@ private function removeContentStreamWithoutConstraintChecks( ): EventsToPublish { return new EventsToPublish( ContentStreamEventStreamName::fromContentStreamId($contentStreamId)->getEventStreamName(), - Events::with( + DecoratedEvents::with( new ContentStreamWasRemoved( $contentStreamId, ), diff --git a/Neos.ContentRepository.Core/Classes/Feature/DimensionSpaceAdjustment/DimensionSpaceCommandHandler.php b/Neos.ContentRepository.Core/Classes/Feature/DimensionSpaceAdjustment/DimensionSpaceCommandHandler.php index 72695af98c..e504b8d3af 100644 --- a/Neos.ContentRepository.Core/Classes/Feature/DimensionSpaceAdjustment/DimensionSpaceCommandHandler.php +++ b/Neos.ContentRepository.Core/Classes/Feature/DimensionSpaceAdjustment/DimensionSpaceCommandHandler.php @@ -24,7 +24,7 @@ use Neos\ContentRepository\Core\DimensionSpace\Exception\DimensionSpacePointNotFound; use Neos\ContentRepository\Core\DimensionSpace\InterDimensionalVariationGraph; use Neos\ContentRepository\Core\DimensionSpace\VariantType; -use Neos\ContentRepository\Core\EventStore\Events; +use Neos\ContentRepository\Core\EventStore\DecoratedEvents; use Neos\ContentRepository\Core\EventStore\EventsToPublish; use Neos\ContentRepository\Core\Feature\Common\RebasableToOtherWorkspaceInterface; use Neos\ContentRepository\Core\Feature\ContentStreamEventStreamName; @@ -81,7 +81,7 @@ private function handleMoveDimensionSpacePoint( $streamName, RebaseableCommand::enrichWithCommand( $command, - Events::with( + DecoratedEvents::with( new DimensionSpacePointWasMoved( $contentGraph->getWorkspaceName(), $contentGraph->getContentStreamId(), @@ -114,7 +114,7 @@ private function handleAddDimensionShineThrough( $streamName, RebaseableCommand::enrichWithCommand( $command, - Events::with( + DecoratedEvents::with( new DimensionShineThroughWasAdded( $contentGraph->getWorkspaceName(), $contentGraph->getContentStreamId(), diff --git a/Neos.ContentRepository.Core/Classes/Feature/NodeCreation/NodeCreation.php b/Neos.ContentRepository.Core/Classes/Feature/NodeCreation/NodeCreation.php index df4415e6df..9145e55ae2 100644 --- a/Neos.ContentRepository.Core/Classes/Feature/NodeCreation/NodeCreation.php +++ b/Neos.ContentRepository.Core/Classes/Feature/NodeCreation/NodeCreation.php @@ -18,7 +18,7 @@ use Neos\ContentRepository\Core\DimensionSpace; use Neos\ContentRepository\Core\DimensionSpace\DimensionSpacePointSet; use Neos\ContentRepository\Core\EventStore\EventInterface; -use Neos\ContentRepository\Core\EventStore\Events; +use Neos\ContentRepository\Core\EventStore\DecoratedEvents; use Neos\ContentRepository\Core\EventStore\EventsToPublish; use Neos\ContentRepository\Core\Feature\Common\InterdimensionalSiblings; use Neos\ContentRepository\Core\Feature\RebaseableCommand; @@ -226,7 +226,7 @@ private function handleCreateNodeAggregateWithNodeAndSerializedProperties( return new EventsToPublish( ContentStreamEventStreamName::fromContentStreamId($contentGraph->getContentStreamId()) ->getEventStreamName(), - RebaseableCommand::enrichWithCommand($command, Events::fromArray($events)), + RebaseableCommand::enrichWithCommand($command, DecoratedEvents::fromArray($events)), $expectedVersion ); } diff --git a/Neos.ContentRepository.Core/Classes/Feature/NodeDisabling/NodeDisabling.php b/Neos.ContentRepository.Core/Classes/Feature/NodeDisabling/NodeDisabling.php index 2cb0cde47f..f0f721c472 100644 --- a/Neos.ContentRepository.Core/Classes/Feature/NodeDisabling/NodeDisabling.php +++ b/Neos.ContentRepository.Core/Classes/Feature/NodeDisabling/NodeDisabling.php @@ -17,7 +17,7 @@ use Neos\ContentRepository\Core\CommandHandler\CommandHandlingDependencies; use Neos\ContentRepository\Core\DimensionSpace; use Neos\ContentRepository\Core\DimensionSpace\Exception\DimensionSpacePointNotFound; -use Neos\ContentRepository\Core\EventStore\Events; +use Neos\ContentRepository\Core\EventStore\DecoratedEvents; use Neos\ContentRepository\Core\EventStore\EventsToPublish; use Neos\ContentRepository\Core\Feature\NodeDisabling\Exception\NodeAggregateIsAlreadyDisabled; use Neos\ContentRepository\Core\Feature\NodeDisabling\Exception\NodeAggregateIsAlreadyEnabled; @@ -70,7 +70,7 @@ private function handleDisableNodeAggregate( $this->getInterDimensionalVariationGraph() ); - $events = Events::with( + $events = DecoratedEvents::with( new SubtreeWasTagged( $contentGraph->getWorkspaceName(), $contentGraph->getContentStreamId(), @@ -125,7 +125,7 @@ public function handleEnableNodeAggregate( $this->getInterDimensionalVariationGraph() ); - $events = Events::with( + $events = DecoratedEvents::with( new SubtreeWasUntagged( $contentGraph->getWorkspaceName(), $contentGraph->getContentStreamId(), diff --git a/Neos.ContentRepository.Core/Classes/Feature/NodeDuplication/NodeDuplicationCommandHandler.php b/Neos.ContentRepository.Core/Classes/Feature/NodeDuplication/NodeDuplicationCommandHandler.php index d102d58e26..458b746dec 100644 --- a/Neos.ContentRepository.Core/Classes/Feature/NodeDuplication/NodeDuplicationCommandHandler.php +++ b/Neos.ContentRepository.Core/Classes/Feature/NodeDuplication/NodeDuplicationCommandHandler.php @@ -22,7 +22,7 @@ use Neos\ContentRepository\Core\DimensionSpace\DimensionSpacePointSet; use Neos\ContentRepository\Core\DimensionSpace\InterDimensionalVariationGraph; use Neos\ContentRepository\Core\DimensionSpace\OriginDimensionSpacePoint; -use Neos\ContentRepository\Core\EventStore\Events; +use Neos\ContentRepository\Core\EventStore\DecoratedEvents; use Neos\ContentRepository\Core\EventStore\EventsToPublish; use Neos\ContentRepository\Core\Feature\Common\ConstraintChecks; use Neos\ContentRepository\Core\Feature\Common\InterdimensionalSiblings; @@ -162,7 +162,7 @@ private function handleCopyNodesRecursively( )->getEventStreamName(), RebaseableCommand::enrichWithCommand( $command, - Events::fromArray($events) + DecoratedEvents::fromArray($events) ), $expectedVersion ); diff --git a/Neos.ContentRepository.Core/Classes/Feature/NodeModification/NodeModification.php b/Neos.ContentRepository.Core/Classes/Feature/NodeModification/NodeModification.php index 334491930e..3e62437841 100644 --- a/Neos.ContentRepository.Core/Classes/Feature/NodeModification/NodeModification.php +++ b/Neos.ContentRepository.Core/Classes/Feature/NodeModification/NodeModification.php @@ -15,7 +15,7 @@ namespace Neos\ContentRepository\Core\Feature\NodeModification; use Neos\ContentRepository\Core\CommandHandler\CommandHandlingDependencies; -use Neos\ContentRepository\Core\EventStore\Events; +use Neos\ContentRepository\Core\EventStore\DecoratedEvents; use Neos\ContentRepository\Core\EventStore\EventsToPublish; use Neos\ContentRepository\Core\Feature\RebaseableCommand; use Neos\ContentRepository\Core\Feature\ContentStreamEventStreamName; @@ -139,7 +139,7 @@ private function handleSetSerializedNodeProperties( ->getEventStreamName(), RebaseableCommand::enrichWithCommand( $command, - Events::fromArray($events) + DecoratedEvents::fromArray($events) ), $expectedVersion ); diff --git a/Neos.ContentRepository.Core/Classes/Feature/NodeMove/NodeMove.php b/Neos.ContentRepository.Core/Classes/Feature/NodeMove/NodeMove.php index 5dfae05275..199ec34a78 100644 --- a/Neos.ContentRepository.Core/Classes/Feature/NodeMove/NodeMove.php +++ b/Neos.ContentRepository.Core/Classes/Feature/NodeMove/NodeMove.php @@ -19,7 +19,7 @@ use Neos\ContentRepository\Core\DimensionSpace\DimensionSpacePoint; use Neos\ContentRepository\Core\DimensionSpace\DimensionSpacePointSet; use Neos\ContentRepository\Core\DimensionSpace\Exception\DimensionSpacePointNotFound; -use Neos\ContentRepository\Core\EventStore\Events; +use Neos\ContentRepository\Core\EventStore\DecoratedEvents; use Neos\ContentRepository\Core\EventStore\EventsToPublish; use Neos\ContentRepository\Core\Feature\Common\InterdimensionalSibling; use Neos\ContentRepository\Core\Feature\Common\InterdimensionalSiblings; @@ -181,7 +181,7 @@ private function handleMoveNodeAggregate( } } - $events = Events::with( + $events = DecoratedEvents::with( new NodeAggregateWasMoved( $command->workspaceName, $contentStreamId, diff --git a/Neos.ContentRepository.Core/Classes/Feature/NodeReferencing/NodeReferencing.php b/Neos.ContentRepository.Core/Classes/Feature/NodeReferencing/NodeReferencing.php index 5bee070100..a25f822baa 100644 --- a/Neos.ContentRepository.Core/Classes/Feature/NodeReferencing/NodeReferencing.php +++ b/Neos.ContentRepository.Core/Classes/Feature/NodeReferencing/NodeReferencing.php @@ -15,7 +15,7 @@ namespace Neos\ContentRepository\Core\Feature\NodeReferencing; use Neos\ContentRepository\Core\CommandHandler\CommandHandlingDependencies; -use Neos\ContentRepository\Core\EventStore\Events; +use Neos\ContentRepository\Core\EventStore\DecoratedEvents; use Neos\ContentRepository\Core\EventStore\EventsToPublish; use Neos\ContentRepository\Core\Feature\Common\ConstraintChecks; use Neos\ContentRepository\Core\Feature\Common\NodeReferencingInternals; @@ -153,7 +153,7 @@ private function handleSetSerializedNodeReferences( throw new \RuntimeException('Cannot handle "SetSerializedNodeReferences" with no references to modify', 1736797975); } - $events = Events::fromArray($events); + $events = DecoratedEvents::fromArray($events); return new EventsToPublish( ContentStreamEventStreamName::fromContentStreamId($contentGraph->getContentStreamId()) diff --git a/Neos.ContentRepository.Core/Classes/Feature/NodeRemoval/NodeRemoval.php b/Neos.ContentRepository.Core/Classes/Feature/NodeRemoval/NodeRemoval.php index 92dee4b597..2f370d34ea 100644 --- a/Neos.ContentRepository.Core/Classes/Feature/NodeRemoval/NodeRemoval.php +++ b/Neos.ContentRepository.Core/Classes/Feature/NodeRemoval/NodeRemoval.php @@ -17,7 +17,7 @@ use Neos\ContentRepository\Core\CommandHandler\CommandHandlingDependencies; use Neos\ContentRepository\Core\DimensionSpace; use Neos\ContentRepository\Core\DimensionSpace\Exception\DimensionSpacePointNotFound; -use Neos\ContentRepository\Core\EventStore\Events; +use Neos\ContentRepository\Core\EventStore\DecoratedEvents; use Neos\ContentRepository\Core\EventStore\EventsToPublish; use Neos\ContentRepository\Core\Feature\RebaseableCommand; use Neos\ContentRepository\Core\Feature\ContentStreamEventStreamName; @@ -69,7 +69,7 @@ private function handleRemoveNodeAggregate( ); } - $events = Events::with( + $events = DecoratedEvents::with( new NodeAggregateWasRemoved( $contentGraph->getWorkspaceName(), $contentGraph->getContentStreamId(), diff --git a/Neos.ContentRepository.Core/Classes/Feature/NodeRenaming/NodeRenaming.php b/Neos.ContentRepository.Core/Classes/Feature/NodeRenaming/NodeRenaming.php index f353134034..21f3bcbb2c 100644 --- a/Neos.ContentRepository.Core/Classes/Feature/NodeRenaming/NodeRenaming.php +++ b/Neos.ContentRepository.Core/Classes/Feature/NodeRenaming/NodeRenaming.php @@ -15,7 +15,7 @@ namespace Neos\ContentRepository\Core\Feature\NodeRenaming; use Neos\ContentRepository\Core\CommandHandler\CommandHandlingDependencies; -use Neos\ContentRepository\Core\EventStore\Events; +use Neos\ContentRepository\Core\EventStore\DecoratedEvents; use Neos\ContentRepository\Core\EventStore\EventsToPublish; use Neos\ContentRepository\Core\Feature\Common\ConstraintChecks; use Neos\ContentRepository\Core\Feature\RebaseableCommand; @@ -50,7 +50,7 @@ private function handleChangeNodeAggregateName(ChangeNodeAggregateName $command, $this->requireNodeTypeNotToDeclareTetheredChildNodeName($parentNodeAggregate->nodeTypeName, $command->newNodeName); } - $events = Events::with( + $events = DecoratedEvents::with( new NodeAggregateNameWasChanged( $contentGraph->getWorkspaceName(), $contentGraph->getContentStreamId(), diff --git a/Neos.ContentRepository.Core/Classes/Feature/NodeTypeChange/NodeTypeChange.php b/Neos.ContentRepository.Core/Classes/Feature/NodeTypeChange/NodeTypeChange.php index acb6e5a4c9..12dfb73624 100644 --- a/Neos.ContentRepository.Core/Classes/Feature/NodeTypeChange/NodeTypeChange.php +++ b/Neos.ContentRepository.Core/Classes/Feature/NodeTypeChange/NodeTypeChange.php @@ -18,7 +18,7 @@ use Neos\ContentRepository\Core\DimensionSpace\OriginDimensionSpacePoint; use Neos\ContentRepository\Core\DimensionSpace\OriginDimensionSpacePointSet; use Neos\ContentRepository\Core\EventStore\EventInterface; -use Neos\ContentRepository\Core\EventStore\Events; +use Neos\ContentRepository\Core\EventStore\DecoratedEvents; use Neos\ContentRepository\Core\EventStore\EventsToPublish; use Neos\ContentRepository\Core\Feature\RebaseableCommand; use Neos\ContentRepository\Core\Feature\Common\NodeTypeChangeInternals; @@ -113,7 +113,7 @@ abstract protected function createEventsForWronglyTypedNodeAggregate( NodePath $currentNodePath, NodeAggregateTypeChangeChildConstraintConflictResolutionStrategy $conflictResolutionStrategy, NodeAggregateIds $alreadyRemovedNodeAggregates, - ): Events; + ): DecoratedEvents; abstract protected function createEventsForMissingTetheredNode( ContentGraphInterface $contentGraph, @@ -121,7 +121,7 @@ abstract protected function createEventsForMissingTetheredNode( OriginDimensionSpacePoint $originDimensionSpacePoint, TetheredNodeTypeDefinition $tetheredNodeTypeDefinition, NodeAggregateId $tetheredNodeAggregateId - ): Events; + ): DecoratedEvents; /** * @throws NodeTypeNotFound @@ -285,7 +285,7 @@ private function handleChangeNodeAggregateType( ContentStreamEventStreamName::fromContentStreamId($contentGraph->getContentStreamId())->getEventStreamName(), RebaseableCommand::enrichWithCommand( $command, - Events::fromArray($events), + DecoratedEvents::fromArray($events), ), $expectedVersion ); diff --git a/Neos.ContentRepository.Core/Classes/Feature/RebaseableCommand.php b/Neos.ContentRepository.Core/Classes/Feature/RebaseableCommand.php index 2ea502274f..9748a19ec0 100644 --- a/Neos.ContentRepository.Core/Classes/Feature/RebaseableCommand.php +++ b/Neos.ContentRepository.Core/Classes/Feature/RebaseableCommand.php @@ -5,7 +5,7 @@ namespace Neos\ContentRepository\Core\Feature; use Neos\ContentRepository\Core\EventStore\DecoratedEvent; -use Neos\ContentRepository\Core\EventStore\Events; +use Neos\ContentRepository\Core\EventStore\DecoratedEvents; use Neos\ContentRepository\Core\EventStore\InitiatingEventMetadata; use Neos\ContentRepository\Core\Feature\Common\PublishableToWorkspaceInterface; use Neos\ContentRepository\Core\Feature\Common\RebasableToOtherWorkspaceInterface; @@ -61,8 +61,8 @@ public static function extractFromEventEnvelope(EventEnvelope $eventEnvelope): s */ public static function enrichWithCommand( RebasableToOtherWorkspaceInterface $command, - Events $events, - ): Events { + DecoratedEvents $events, + ): DecoratedEvents { $processedEvents = []; $causationId = null; $i = 0; @@ -112,6 +112,6 @@ public static function enrichWithCommand( $i++; } - return Events::fromArray($processedEvents); + return DecoratedEvents::fromArray($processedEvents); } } diff --git a/Neos.ContentRepository.Core/Classes/Feature/RootNodeCreation/RootNodeHandling.php b/Neos.ContentRepository.Core/Classes/Feature/RootNodeCreation/RootNodeHandling.php index 8c131e00a0..7446e9d499 100644 --- a/Neos.ContentRepository.Core/Classes/Feature/RootNodeCreation/RootNodeHandling.php +++ b/Neos.ContentRepository.Core/Classes/Feature/RootNodeCreation/RootNodeHandling.php @@ -18,7 +18,7 @@ use Neos\ContentRepository\Core\DimensionSpace\DimensionSpacePointSet; use Neos\ContentRepository\Core\DimensionSpace\OriginDimensionSpacePoint; use Neos\ContentRepository\Core\EventStore\EventInterface; -use Neos\ContentRepository\Core\EventStore\Events; +use Neos\ContentRepository\Core\EventStore\DecoratedEvents; use Neos\ContentRepository\Core\EventStore\EventsToPublish; use Neos\ContentRepository\Core\Feature\Common\InterdimensionalSiblings; use Neos\ContentRepository\Core\Feature\RebaseableCommand; @@ -122,7 +122,7 @@ private function handleCreateRootNodeAggregateWithNode( $contentStreamEventStream->getEventStreamName(), RebaseableCommand::enrichWithCommand( $command, - Events::fromArray($events) + DecoratedEvents::fromArray($events) ), $expectedVersion ); @@ -161,7 +161,7 @@ private function handleUpdateRootNodeAggregateDimensions( throw new NodeAggregateIsNotRoot('The node aggregate ' . $nodeAggregate->nodeAggregateId->value . ' is not classified as root, but should be for command UpdateRootNodeAggregateDimensions.', 1678647355); } - $events = Events::with( + $events = DecoratedEvents::with( new RootNodeAggregateDimensionsWereUpdated( $contentGraph->getWorkspaceName(), $contentGraph->getContentStreamId(), diff --git a/Neos.ContentRepository.Core/Classes/Feature/SubtreeTagging/SubtreeTagging.php b/Neos.ContentRepository.Core/Classes/Feature/SubtreeTagging/SubtreeTagging.php index 5fd8271c82..7db2a14aa1 100644 --- a/Neos.ContentRepository.Core/Classes/Feature/SubtreeTagging/SubtreeTagging.php +++ b/Neos.ContentRepository.Core/Classes/Feature/SubtreeTagging/SubtreeTagging.php @@ -16,7 +16,7 @@ use Neos\ContentRepository\Core\CommandHandler\CommandHandlingDependencies; use Neos\ContentRepository\Core\DimensionSpace; -use Neos\ContentRepository\Core\EventStore\Events; +use Neos\ContentRepository\Core\EventStore\DecoratedEvents; use Neos\ContentRepository\Core\EventStore\EventsToPublish; use Neos\ContentRepository\Core\Feature\Common\ConstraintChecks; use Neos\ContentRepository\Core\Feature\RebaseableCommand; @@ -59,7 +59,7 @@ private function handleTagSubtree(TagSubtree $command, CommandHandlingDependenci $this->getInterDimensionalVariationGraph() ); - $events = Events::with( + $events = DecoratedEvents::with( new SubtreeWasTagged( $contentGraph->getWorkspaceName(), $contentGraph->getContentStreamId(), @@ -104,7 +104,7 @@ public function handleUntagSubtree(UntagSubtree $command, CommandHandlingDepende $this->getInterDimensionalVariationGraph() ); - $events = Events::with( + $events = DecoratedEvents::with( new SubtreeWasUntagged( $contentGraph->getWorkspaceName(), $contentGraph->getContentStreamId(), diff --git a/Neos.ContentRepository.Core/Classes/Feature/WorkspaceCommandHandler.php b/Neos.ContentRepository.Core/Classes/Feature/WorkspaceCommandHandler.php index f06de074a3..a252170ba0 100644 --- a/Neos.ContentRepository.Core/Classes/Feature/WorkspaceCommandHandler.php +++ b/Neos.ContentRepository.Core/Classes/Feature/WorkspaceCommandHandler.php @@ -21,7 +21,7 @@ use Neos\ContentRepository\Core\ContentRepository; use Neos\ContentRepository\Core\EventStore\DecoratedEvent; use Neos\ContentRepository\Core\EventStore\EventNormalizer; -use Neos\ContentRepository\Core\EventStore\Events; +use Neos\ContentRepository\Core\EventStore\DecoratedEvents; use Neos\ContentRepository\Core\EventStore\EventsToPublish; use Neos\ContentRepository\Core\Feature\Common\PublishableToWorkspaceInterface; use Neos\ContentRepository\Core\Feature\Common\RebasableToOtherWorkspaceInterface; @@ -141,7 +141,7 @@ private function handleCreateWorkspace( yield new EventsToPublish( WorkspaceEventStreamName::fromWorkspaceName($command->workspaceName)->getEventStreamName(), - Events::with( + DecoratedEvents::with( new WorkspaceWasCreated( $command->workspaceName, $command->baseWorkspaceName, @@ -166,7 +166,7 @@ private function handleCreateRootWorkspace( yield new EventsToPublish( ContentStreamEventStreamName::fromContentStreamId($command->newContentStreamId)->getEventStreamName(), - Events::with( + DecoratedEvents::with( new ContentStreamWasCreated( $command->newContentStreamId, ) @@ -176,7 +176,7 @@ private function handleCreateRootWorkspace( yield new EventsToPublish( WorkspaceEventStreamName::fromWorkspaceName($command->workspaceName)->getEventStreamName(), - Events::with( + DecoratedEvents::with( new RootWorkspaceWasCreated( $command->workspaceName, $command->newContentStreamId @@ -261,7 +261,7 @@ static function ($handle) use ($rebaseableCommands): void { yield new EventsToPublish( WorkspaceEventStreamName::fromWorkspaceName($workspace->workspaceName)->getEventStreamName(), - Events::with( + DecoratedEvents::with( new WorkspaceWasPublished( $workspace->workspaceName, $baseWorkspace->workspaceName, @@ -291,7 +291,7 @@ private function rebaseWorkspaceWithoutChanges( yield new EventsToPublish( WorkspaceEventStreamName::fromWorkspaceName($workspace->workspaceName)->getEventStreamName(), - Events::with( + DecoratedEvents::with( new WorkspaceWasRebased( $workspace->workspaceName, $newContentStreamId, @@ -312,7 +312,7 @@ private function getCopiedEventsOfEventStream( WorkspaceName $targetWorkspaceName, ContentStreamId $targetContentStreamId, EventStreamInterface $eventStream - ): Events|null { + ): DecoratedEvents|null { $events = []; foreach ($eventStream as $eventEnvelope) { $event = $this->eventNormalizer->denormalize($eventEnvelope->event); @@ -326,7 +326,7 @@ private function getCopiedEventsOfEventStream( } // this could technically empty, but we handle it as a no-op - return $events !== [] ? Events::fromArray($events) : null; + return $events !== [] ? DecoratedEvents::fromArray($events) : null; } /** @@ -410,7 +410,7 @@ static function ($handle) use ($rebaseableCommands): void { $baseWorkspaceContentStreamVersion, new EventsToPublish( WorkspaceEventStreamName::fromWorkspaceName($command->workspaceName)->getEventStreamName(), - Events::with( + DecoratedEvents::with( new WorkspaceWasRebased( $command->workspaceName, $command->rebasedContentStreamId, @@ -529,7 +529,7 @@ static function ($handle) use ($commandSimulator, $matchingCommands, $remainingC Version::fromInteger($baseWorkspaceContentStreamVersion->value + ($selectedEventsOfWorkspaceToPublish?->count() ?? 0)), new EventsToPublish( WorkspaceEventStreamName::fromWorkspaceName($command->workspaceName)->getEventStreamName(), - Events::fromArray([ + DecoratedEvents::fromArray([ new WorkspaceWasPublished( $command->workspaceName, $baseWorkspace->workspaceName, @@ -637,7 +637,7 @@ static function ($handle) use ($commandsToKeep): void { $baseWorkspaceContentStreamVersion, new EventsToPublish( WorkspaceEventStreamName::fromWorkspaceName($command->workspaceName)->getEventStreamName(), - Events::with( + DecoratedEvents::with( new WorkspaceWasDiscarded( $command->workspaceName, $command->newContentStreamId, @@ -703,7 +703,7 @@ private function discardWorkspace( yield new EventsToPublish( WorkspaceEventStreamName::fromWorkspaceName($workspace->workspaceName)->getEventStreamName(), - Events::with( + DecoratedEvents::with( new WorkspaceWasDiscarded( $workspace->workspaceName, $newContentStream, @@ -753,7 +753,7 @@ private function handleChangeBaseWorkspace( yield new EventsToPublish( WorkspaceEventStreamName::fromWorkspaceName($command->workspaceName)->getEventStreamName(), - Events::with( + DecoratedEvents::with( new WorkspaceBaseWorkspaceWasChanged( $command->workspaceName, $command->baseWorkspaceName, @@ -776,7 +776,7 @@ private function handleDeleteWorkspace( yield new EventsToPublish( ContentStreamEventStreamName::fromContentStreamId($workspace->currentContentStreamId)->getEventStreamName(), - Events::with( + DecoratedEvents::with( new ContentStreamWasRemoved( $workspace->currentContentStreamId, ), @@ -786,7 +786,7 @@ private function handleDeleteWorkspace( yield new EventsToPublish( WorkspaceEventStreamName::fromWorkspaceName($command->workspaceName)->getEventStreamName(), - Events::with( + DecoratedEvents::with( new WorkspaceWasRemoved( $command->workspaceName, ) @@ -800,7 +800,7 @@ private function forkNewContentStreamAndApplyEvents( ContentStreamId $sourceContentStreamId, Version $sourceContentStreamVersion, EventsToPublish $pointWorkspaceToNewContentStream, - Events|null $eventsToApplyOnNewContentStream, + DecoratedEvents|null $eventsToApplyOnNewContentStream, string $debugReasonForFork ): \Generator { yield $this->forkContentStream( @@ -808,7 +808,7 @@ private function forkNewContentStreamAndApplyEvents( $sourceContentStreamId, $sourceContentStreamVersion, $debugReasonForFork . sprintf('; Apply %d events on new (temporary closed) content stream', $eventsToApplyOnNewContentStream?->count() ?? 0) - )->withAppendedEvents(Events::with( + )->withAppendedEvents(DecoratedEvents::with( new ContentStreamWasClosed( $newContentStreamId ) @@ -819,7 +819,7 @@ private function forkNewContentStreamAndApplyEvents( yield new EventsToPublish( ContentStreamEventStreamName::fromContentStreamId($newContentStreamId) ->getEventStreamName(), - Events::fromArray([ + DecoratedEvents::fromArray([ ...($eventsToApplyOnNewContentStream ?? []), new ContentStreamWasReopened( $newContentStreamId diff --git a/Neos.ContentRepository.StructureAdjustment/src/Adjustment/DisallowedChildNodeAdjustment.php b/Neos.ContentRepository.StructureAdjustment/src/Adjustment/DisallowedChildNodeAdjustment.php index 82a57da378..f344ec0814 100644 --- a/Neos.ContentRepository.StructureAdjustment/src/Adjustment/DisallowedChildNodeAdjustment.php +++ b/Neos.ContentRepository.StructureAdjustment/src/Adjustment/DisallowedChildNodeAdjustment.php @@ -9,7 +9,7 @@ use Neos\ContentRepository\Core\DimensionSpace\DimensionSpacePointSet; use Neos\ContentRepository\Core\DimensionSpace\OriginDimensionSpacePoint; use Neos\ContentRepository\Core\DimensionSpace\OriginDimensionSpacePointSet; -use Neos\ContentRepository\Core\EventStore\Events; +use Neos\ContentRepository\Core\EventStore\DecoratedEvents; use Neos\ContentRepository\Core\EventStore\EventsToPublish; use Neos\ContentRepository\Core\Feature\ContentStreamEventStreamName; use Neos\ContentRepository\Core\Feature\NodeRemoval\Event\NodeAggregateWasRemoved; @@ -126,7 +126,7 @@ private function removeNodeInSingleDimensionSpacePoint( DimensionSpacePoint $dimensionSpacePoint ): EventsToPublish { $referenceOrigin = OriginDimensionSpacePoint::fromDimensionSpacePoint($dimensionSpacePoint); - $events = Events::with( + $events = DecoratedEvents::with( new NodeAggregateWasRemoved( $this->contentGraph->getWorkspaceName(), $this->contentGraph->getContentStreamId(), diff --git a/Neos.ContentRepository.StructureAdjustment/src/Adjustment/PropertyAdjustment.php b/Neos.ContentRepository.StructureAdjustment/src/Adjustment/PropertyAdjustment.php index 67c309e691..a0e859309b 100644 --- a/Neos.ContentRepository.StructureAdjustment/src/Adjustment/PropertyAdjustment.php +++ b/Neos.ContentRepository.StructureAdjustment/src/Adjustment/PropertyAdjustment.php @@ -4,7 +4,7 @@ namespace Neos\ContentRepository\StructureAdjustment\Adjustment; -use Neos\ContentRepository\Core\EventStore\Events; +use Neos\ContentRepository\Core\EventStore\DecoratedEvents; use Neos\ContentRepository\Core\EventStore\EventsToPublish; use Neos\ContentRepository\Core\Feature\ContentStreamEventStreamName; use Neos\ContentRepository\Core\Feature\NodeModification\Dto\SerializedPropertyValue; @@ -114,7 +114,7 @@ private function publishNodePropertiesWereSet( SerializedPropertyValues $serializedPropertyValues, PropertyNames $propertyNames ): EventsToPublish { - $events = Events::with( + $events = DecoratedEvents::with( new NodePropertiesWereSet( $this->contentGraph->getWorkspaceName(), $this->contentGraph->getContentStreamId(), diff --git a/Neos.ContentRepository.StructureAdjustment/src/Adjustment/RemoveNodeAggregateTrait.php b/Neos.ContentRepository.StructureAdjustment/src/Adjustment/RemoveNodeAggregateTrait.php index 50d39f7e91..80354a03c4 100644 --- a/Neos.ContentRepository.StructureAdjustment/src/Adjustment/RemoveNodeAggregateTrait.php +++ b/Neos.ContentRepository.StructureAdjustment/src/Adjustment/RemoveNodeAggregateTrait.php @@ -4,7 +4,7 @@ namespace Neos\ContentRepository\StructureAdjustment\Adjustment; -use Neos\ContentRepository\Core\EventStore\Events; +use Neos\ContentRepository\Core\EventStore\DecoratedEvents; use Neos\ContentRepository\Core\EventStore\EventsToPublish; use Neos\ContentRepository\Core\Feature\ContentStreamEventStreamName; use Neos\ContentRepository\Core\Feature\NodeRemoval\Event\NodeAggregateWasRemoved; @@ -16,7 +16,7 @@ trait RemoveNodeAggregateTrait { private function removeNodeAggregate(ContentGraphInterface $contentGraph, NodeAggregate $tetheredNodeAggregate): EventsToPublish { - $events = Events::with( + $events = DecoratedEvents::with( new NodeAggregateWasRemoved( $contentGraph->getWorkspaceName(), $contentGraph->getContentStreamId(), diff --git a/Neos.ContentRepository.StructureAdjustment/src/Adjustment/TetheredNodeAdjustments.php b/Neos.ContentRepository.StructureAdjustment/src/Adjustment/TetheredNodeAdjustments.php index 896cfcdd34..901feb146a 100644 --- a/Neos.ContentRepository.StructureAdjustment/src/Adjustment/TetheredNodeAdjustments.php +++ b/Neos.ContentRepository.StructureAdjustment/src/Adjustment/TetheredNodeAdjustments.php @@ -6,7 +6,7 @@ use Neos\ContentRepository\Core\DimensionSpace; use Neos\ContentRepository\Core\DimensionSpace\DimensionSpacePointSet; -use Neos\ContentRepository\Core\EventStore\Events; +use Neos\ContentRepository\Core\EventStore\DecoratedEvents; use Neos\ContentRepository\Core\EventStore\EventsToPublish; use Neos\ContentRepository\Core\Feature\Common\InterdimensionalSibling; use Neos\ContentRepository\Core\Feature\Common\InterdimensionalSiblings; @@ -261,7 +261,7 @@ private function reorderNodes( $streamName = ContentStreamEventStreamName::fromContentStreamId($contentStreamId); return new EventsToPublish( $streamName->getEventStreamName(), - Events::fromArray($events), + DecoratedEvents::fromArray($events), ExpectedVersion::ANY() ); } diff --git a/Neos.ContentRepository.TestSuite/Classes/Fakes/FakeCommandHookFactory.php b/Neos.ContentRepository.TestSuite/Classes/Fakes/FakeCommandHookFactory.php new file mode 100644 index 0000000000..3d1f240f11 --- /dev/null +++ b/Neos.ContentRepository.TestSuite/Classes/Fakes/FakeCommandHookFactory.php @@ -0,0 +1,24 @@ +