From bf84fa9925354b370a47ec6472c7721680959da7 Mon Sep 17 00:00:00 2001 From: Bernhard Schmitt Date: Wed, 13 Mar 2024 07:27:53 +0100 Subject: [PATCH] 4708 - Add ExpectedVersion checks --- .../Feature/Common/ConstraintChecks.php | 12 ++++++++++++ .../Feature/ContentStreamCommandHandler.php | 19 ++++++++++++++++--- .../Feature/NodeCreation/NodeCreation.php | 3 ++- .../Feature/NodeDisabling/NodeDisabling.php | 6 ++++-- .../NodeDuplicationCommandHandler.php | 3 ++- .../NodeModification/NodeModification.php | 4 ++-- .../Classes/Feature/NodeMove/NodeMove.php | 3 ++- .../NodeReferencing/NodeReferencing.php | 3 ++- .../Feature/NodeRemoval/NodeRemoval.php | 3 ++- .../Feature/NodeRenaming/NodeRenaming.php | 3 ++- .../Feature/NodeTypeChange/NodeTypeChange.php | 3 ++- .../Feature/NodeVariation/NodeVariation.php | 3 ++- .../RootNodeCreation/RootNodeHandling.php | 6 ++++-- 13 files changed, 54 insertions(+), 17 deletions(-) diff --git a/Neos.ContentRepository.Core/Classes/Feature/Common/ConstraintChecks.php b/Neos.ContentRepository.Core/Classes/Feature/Common/ConstraintChecks.php index 4c632e8d06b..c876ca652f5 100644 --- a/Neos.ContentRepository.Core/Classes/Feature/Common/ConstraintChecks.php +++ b/Neos.ContentRepository.Core/Classes/Feature/Common/ConstraintChecks.php @@ -58,6 +58,7 @@ use Neos\ContentRepository\Core\NodeType\NodeTypeName; use Neos\ContentRepository\Core\SharedModel\Workspace\ContentStreamId; use Neos\ContentRepository\Core\SharedModel\Workspace\WorkspaceName; +use Neos\EventStore\Model\EventStream\ExpectedVersion; /** * @internal implementation details of command handlers @@ -676,4 +677,15 @@ protected function validateReferenceProperties( } } } + + protected function getExpectedVersionOfContentStream( + ContentStreamId $contentStreamId, + ContentRepository $contentRepository + ): ExpectedVersion { + return ExpectedVersion::fromVersion( + $contentRepository->getContentStreamFinder() + ->findVersionForContentStream($contentStreamId) + ->unwrap() + ); + } } diff --git a/Neos.ContentRepository.Core/Classes/Feature/ContentStreamCommandHandler.php b/Neos.ContentRepository.Core/Classes/Feature/ContentStreamCommandHandler.php index 7e82f2407ce..50a6e69e7a9 100644 --- a/Neos.ContentRepository.Core/Classes/Feature/ContentStreamCommandHandler.php +++ b/Neos.ContentRepository.Core/Classes/Feature/ContentStreamCommandHandler.php @@ -19,6 +19,7 @@ use Neos\ContentRepository\Core\ContentRepository; use Neos\ContentRepository\Core\EventStore\Events; use Neos\ContentRepository\Core\EventStore\EventsToPublish; +use Neos\ContentRepository\Core\Feature\Common\ConstraintChecks; use Neos\ContentRepository\Core\Feature\ContentStreamCreation\Command\CreateContentStream; use Neos\ContentRepository\Core\Feature\ContentStreamCreation\Event\ContentStreamWasCreated; use Neos\ContentRepository\Core\Feature\ContentStreamForking\Command\CloseContentStream; @@ -84,7 +85,7 @@ private function handleCloseContentStream( ContentRepository $contentRepository ): EventsToPublish { $this->requireContentStreamToExist($command->contentStreamId, $contentRepository); - + $expectedVersion = $this->getExpectedVersionOfContentStream($command->contentStreamId, $contentRepository); $streamName = ContentStreamEventStreamName::fromContentStreamId($command->contentStreamId)->getEventStreamName(); return new EventsToPublish( @@ -94,7 +95,7 @@ private function handleCloseContentStream( $command->contentStreamId, ), ), - ExpectedVersion::ANY() + $expectedVersion ); } @@ -135,6 +136,7 @@ private function handleRemoveContentStream( ContentRepository $contentRepository ): EventsToPublish { $this->requireContentStreamToExist($command->contentStreamId, $contentRepository); + $expectedVersion = $this->getExpectedVersionOfContentStream($command->contentStreamId, $contentRepository); $streamName = ContentStreamEventStreamName::fromContentStreamId( $command->contentStreamId @@ -147,7 +149,7 @@ private function handleRemoveContentStream( $command->contentStreamId, ), ), - ExpectedVersion::ANY() + $expectedVersion ); } @@ -194,4 +196,15 @@ protected function requireContentStreamToNotBeClosed( ); } } + + protected function getExpectedVersionOfContentStream( + ContentStreamId $contentStreamId, + ContentRepository $contentRepository + ): ExpectedVersion { + return ExpectedVersion::fromVersion( + $contentRepository->getContentStreamFinder() + ->findVersionForContentStream($contentStreamId) + ->unwrap() + ); + } } diff --git a/Neos.ContentRepository.Core/Classes/Feature/NodeCreation/NodeCreation.php b/Neos.ContentRepository.Core/Classes/Feature/NodeCreation/NodeCreation.php index 61d46423f6f..84afd869e5c 100644 --- a/Neos.ContentRepository.Core/Classes/Feature/NodeCreation/NodeCreation.php +++ b/Neos.ContentRepository.Core/Classes/Feature/NodeCreation/NodeCreation.php @@ -130,6 +130,7 @@ private function handleCreateNodeAggregateWithNodeAndSerializedProperties( ContentRepository $contentRepository ): EventsToPublish { $contentStreamId = $this->requireContentStream($command->workspaceName, $contentRepository); + $expectedVersion = $this->getExpectedVersionOfContentStream($contentStreamId, $contentRepository); $this->requireDimensionSpacePointToExist($command->originDimensionSpacePoint->toDimensionSpacePoint()); $nodeType = $this->requireNodeType($command->nodeTypeName); $this->requireNodeTypeToNotBeAbstract($nodeType); @@ -227,7 +228,7 @@ private function handleCreateNodeAggregateWithNodeAndSerializedProperties( ContentStreamEventStreamName::fromContentStreamId($contentStreamId) ->getEventStreamName(), NodeAggregateEventPublisher::enrichWithCommand($command, Events::fromArray($events)), - ExpectedVersion::ANY() + $expectedVersion ); } diff --git a/Neos.ContentRepository.Core/Classes/Feature/NodeDisabling/NodeDisabling.php b/Neos.ContentRepository.Core/Classes/Feature/NodeDisabling/NodeDisabling.php index 05e92f0d1f6..84bcfccd4ea 100644 --- a/Neos.ContentRepository.Core/Classes/Feature/NodeDisabling/NodeDisabling.php +++ b/Neos.ContentRepository.Core/Classes/Feature/NodeDisabling/NodeDisabling.php @@ -49,6 +49,7 @@ private function handleDisableNodeAggregate( ContentRepository $contentRepository ): EventsToPublish { $contentStreamId = $this->requireContentStream($command->workspaceName, $contentRepository); + $expectedVersion = $this->getExpectedVersionOfContentStream($contentStreamId, $contentRepository); $this->requireDimensionSpacePointToExist($command->coveredDimensionSpacePoint); $nodeAggregate = $this->requireProjectedNodeAggregate( $contentStreamId, @@ -87,7 +88,7 @@ private function handleDisableNodeAggregate( $command, $events ), - ExpectedVersion::ANY() + $expectedVersion ); } @@ -103,6 +104,7 @@ public function handleEnableNodeAggregate( ContentRepository $contentRepository ): EventsToPublish { $contentStreamId = $this->requireContentStream($command->workspaceName, $contentRepository); + $expectedVersion = $this->getExpectedVersionOfContentStream($contentStreamId, $contentRepository); $this->requireDimensionSpacePointToExist($command->coveredDimensionSpacePoint); $nodeAggregate = $this->requireProjectedNodeAggregate( $contentStreamId, @@ -137,7 +139,7 @@ public function handleEnableNodeAggregate( return new EventsToPublish( ContentStreamEventStreamName::fromContentStreamId($contentStreamId)->getEventStreamName(), NodeAggregateEventPublisher::enrichWithCommand($command, $events), - ExpectedVersion::ANY() + $expectedVersion ); } } diff --git a/Neos.ContentRepository.Core/Classes/Feature/NodeDuplication/NodeDuplicationCommandHandler.php b/Neos.ContentRepository.Core/Classes/Feature/NodeDuplication/NodeDuplicationCommandHandler.php index a3cabe78633..8c3d2fb2498 100644 --- a/Neos.ContentRepository.Core/Classes/Feature/NodeDuplication/NodeDuplicationCommandHandler.php +++ b/Neos.ContentRepository.Core/Classes/Feature/NodeDuplication/NodeDuplicationCommandHandler.php @@ -83,6 +83,7 @@ private function handleCopyNodesRecursively( ): EventsToPublish { // Basic constraints (Content Stream / Dimension Space Point / Node Type of to-be-inserted root node) $contentStreamId = $this->requireContentStream($command->workspaceName, $contentRepository); + $expectedVersion = $this->getExpectedVersionOfContentStream($contentStreamId, $contentRepository); $this->requireDimensionSpacePointToExist( $command->targetDimensionSpacePoint->toDimensionSpacePoint() ); @@ -168,7 +169,7 @@ private function handleCopyNodesRecursively( $command, Events::fromArray($events) ), - ExpectedVersion::ANY() + $expectedVersion ); } diff --git a/Neos.ContentRepository.Core/Classes/Feature/NodeModification/NodeModification.php b/Neos.ContentRepository.Core/Classes/Feature/NodeModification/NodeModification.php index efe0299926f..91511f5e62c 100644 --- a/Neos.ContentRepository.Core/Classes/Feature/NodeModification/NodeModification.php +++ b/Neos.ContentRepository.Core/Classes/Feature/NodeModification/NodeModification.php @@ -80,7 +80,7 @@ private function handleSetSerializedNodeProperties( ContentRepository $contentRepository ): EventsToPublish { $contentStreamId = $this->requireContentStream($command->workspaceName, $contentRepository); - $contentStreamVersion = $contentRepository->getContentStreamFinder()->findVersionForContentStream($contentStreamId); + $expectedVersion = $this->getExpectedVersionOfContentStream($contentStreamId, $contentRepository); // Check if node exists $nodeAggregate = $this->requireProjectedNodeAggregate( $contentStreamId, @@ -137,7 +137,7 @@ private function handleSetSerializedNodeProperties( $command, Events::fromArray($events) ), - ExpectedVersion::fromVersion($contentStreamVersion->unwrap()) + $expectedVersion ); } diff --git a/Neos.ContentRepository.Core/Classes/Feature/NodeMove/NodeMove.php b/Neos.ContentRepository.Core/Classes/Feature/NodeMove/NodeMove.php index 8068541a4b7..7dd6afde4cd 100644 --- a/Neos.ContentRepository.Core/Classes/Feature/NodeMove/NodeMove.php +++ b/Neos.ContentRepository.Core/Classes/Feature/NodeMove/NodeMove.php @@ -76,6 +76,7 @@ private function handleMoveNodeAggregate( ContentRepository $contentRepository ): EventsToPublish { $contentStreamId = $this->requireContentStream($command->workspaceName, $contentRepository); + $expectedVersion = $this->getExpectedVersionOfContentStream($contentStreamId, $contentRepository); $this->requireDimensionSpacePointToExist($command->dimensionSpacePoint); $nodeAggregate = $this->requireProjectedNodeAggregate( $contentStreamId, @@ -179,7 +180,7 @@ private function handleMoveNodeAggregate( $command, $events ), - ExpectedVersion::ANY() + $expectedVersion ); } diff --git a/Neos.ContentRepository.Core/Classes/Feature/NodeReferencing/NodeReferencing.php b/Neos.ContentRepository.Core/Classes/Feature/NodeReferencing/NodeReferencing.php index 06dd9d61770..064f7fa3c9b 100644 --- a/Neos.ContentRepository.Core/Classes/Feature/NodeReferencing/NodeReferencing.php +++ b/Neos.ContentRepository.Core/Classes/Feature/NodeReferencing/NodeReferencing.php @@ -101,6 +101,7 @@ private function handleSetSerializedNodeReferences( ContentRepository $contentRepository ): EventsToPublish { $contentStreamId = $this->requireContentStream($command->workspaceName, $contentRepository); + $expectedVersion = $this->getExpectedVersionOfContentStream($contentStreamId, $contentRepository); $this->requireDimensionSpacePointToExist( $command->sourceOriginDimensionSpacePoint->toDimensionSpacePoint() ); @@ -162,7 +163,7 @@ private function handleSetSerializedNodeReferences( $command, $events ), - ExpectedVersion::ANY() + $expectedVersion ); } } diff --git a/Neos.ContentRepository.Core/Classes/Feature/NodeRemoval/NodeRemoval.php b/Neos.ContentRepository.Core/Classes/Feature/NodeRemoval/NodeRemoval.php index 4dd31e09d71..30a1f9a5650 100644 --- a/Neos.ContentRepository.Core/Classes/Feature/NodeRemoval/NodeRemoval.php +++ b/Neos.ContentRepository.Core/Classes/Feature/NodeRemoval/NodeRemoval.php @@ -51,6 +51,7 @@ private function handleRemoveNodeAggregate( ContentRepository $contentRepository ): EventsToPublish { $contentStreamId = $this->requireContentStream($command->workspaceName, $contentRepository); + $expectedVersion = $this->getExpectedVersionOfContentStream($contentStreamId, $contentRepository); $nodeAggregate = $this->requireProjectedNodeAggregate( $contentStreamId, $command->nodeAggregateId, @@ -95,7 +96,7 @@ private function handleRemoveNodeAggregate( $command, $events ), - ExpectedVersion::ANY() + $expectedVersion ); } diff --git a/Neos.ContentRepository.Core/Classes/Feature/NodeRenaming/NodeRenaming.php b/Neos.ContentRepository.Core/Classes/Feature/NodeRenaming/NodeRenaming.php index 827f4626bf0..ac2f8787e5f 100644 --- a/Neos.ContentRepository.Core/Classes/Feature/NodeRenaming/NodeRenaming.php +++ b/Neos.ContentRepository.Core/Classes/Feature/NodeRenaming/NodeRenaming.php @@ -34,6 +34,7 @@ trait NodeRenaming private function handleChangeNodeAggregateName(ChangeNodeAggregateName $command, ContentRepository $contentRepository): EventsToPublish { $contentStreamId = $this->requireContentStream($command->workspaceName, $contentRepository); + $expectedVersion = $this->getExpectedVersionOfContentStream($contentStreamId, $contentRepository); $nodeAggregate = $this->requireProjectedNodeAggregate( $contentStreamId, $command->nodeAggregateId, @@ -68,7 +69,7 @@ private function handleChangeNodeAggregateName(ChangeNodeAggregateName $command, $command, $events ), - ExpectedVersion::ANY() + $expectedVersion ); } } diff --git a/Neos.ContentRepository.Core/Classes/Feature/NodeTypeChange/NodeTypeChange.php b/Neos.ContentRepository.Core/Classes/Feature/NodeTypeChange/NodeTypeChange.php index 3d8da216fbf..cffac2fce5e 100644 --- a/Neos.ContentRepository.Core/Classes/Feature/NodeTypeChange/NodeTypeChange.php +++ b/Neos.ContentRepository.Core/Classes/Feature/NodeTypeChange/NodeTypeChange.php @@ -113,6 +113,7 @@ private function handleChangeNodeAggregateType( **************/ // existence of content stream, node type and node aggregate $contentStreamId = $this->requireContentStream($command->workspaceName, $contentRepository); + $expectedVersion = $this->getExpectedVersionOfContentStream($contentStreamId, $contentRepository); $newNodeType = $this->requireNodeType($command->newNodeTypeName); $nodeAggregate = $this->requireProjectedNodeAggregate( $contentStreamId, @@ -223,7 +224,7 @@ private function handleChangeNodeAggregateType( $command, Events::fromArray($events), ), - ExpectedVersion::ANY() + $expectedVersion ); } diff --git a/Neos.ContentRepository.Core/Classes/Feature/NodeVariation/NodeVariation.php b/Neos.ContentRepository.Core/Classes/Feature/NodeVariation/NodeVariation.php index 1991c25173f..6ae6688e7e3 100644 --- a/Neos.ContentRepository.Core/Classes/Feature/NodeVariation/NodeVariation.php +++ b/Neos.ContentRepository.Core/Classes/Feature/NodeVariation/NodeVariation.php @@ -52,6 +52,7 @@ private function handleCreateNodeVariant( ContentRepository $contentRepository ): EventsToPublish { $contentStreamId = $this->requireContentStream($command->workspaceName, $contentRepository); + $expectedVersion = $this->getExpectedVersionOfContentStream($contentStreamId, $contentRepository); $nodeAggregate = $this->requireProjectedNodeAggregate( $contentStreamId, $command->nodeAggregateId, @@ -90,7 +91,7 @@ private function handleCreateNodeVariant( $command, $events ), - ExpectedVersion::ANY() + $expectedVersion ); } } diff --git a/Neos.ContentRepository.Core/Classes/Feature/RootNodeCreation/RootNodeHandling.php b/Neos.ContentRepository.Core/Classes/Feature/RootNodeCreation/RootNodeHandling.php index a84fe0aad52..0772c5c7731 100644 --- a/Neos.ContentRepository.Core/Classes/Feature/RootNodeCreation/RootNodeHandling.php +++ b/Neos.ContentRepository.Core/Classes/Feature/RootNodeCreation/RootNodeHandling.php @@ -71,6 +71,7 @@ private function handleCreateRootNodeAggregateWithNode( ContentRepository $contentRepository ): EventsToPublish { $contentStreamId = $this->requireContentStream($command->workspaceName, $contentRepository); + $expectedVersion = $this->getExpectedVersionOfContentStream($contentStreamId, $contentRepository); $this->requireProjectedNodeAggregateToNotExist( $contentStreamId, $command->nodeAggregateId, @@ -121,7 +122,7 @@ private function handleCreateRootNodeAggregateWithNode( $command, Events::fromArray($events) ), - ExpectedVersion::ANY() + $expectedVersion ); } @@ -148,6 +149,7 @@ private function handleUpdateRootNodeAggregateDimensions( ContentRepository $contentRepository ): EventsToPublish { $contentStreamId = $this->requireContentStream($command->workspaceName, $contentRepository); + $expectedVersion = $this->getExpectedVersionOfContentStream($contentStreamId, $contentRepository); $nodeAggregate = $this->requireProjectedNodeAggregate( $contentStreamId, $command->nodeAggregateId, @@ -174,7 +176,7 @@ private function handleUpdateRootNodeAggregateDimensions( $command, $events ), - ExpectedVersion::ANY() + $expectedVersion ); }