diff --git a/Neos.ContentRepository.Core/Classes/Feature/NodeMove/Event/NodeAggregateWasMoved.php b/Neos.ContentRepository.Core/Classes/Feature/NodeMove/Event/NodeAggregateWasMoved.php index c9c50fa03f2..f94f7b8b257 100644 --- a/Neos.ContentRepository.Core/Classes/Feature/NodeMove/Event/NodeAggregateWasMoved.php +++ b/Neos.ContentRepository.Core/Classes/Feature/NodeMove/Event/NodeAggregateWasMoved.php @@ -63,6 +63,10 @@ public function __construct( public ContentStreamId $contentStreamId, public NodeAggregateId $nodeAggregateId, public ?NodeAggregateId $newParentNodeAggregateId, + /** + * @var DimensionSpacePoint $dimensionSpacePoint This is one of the *covered* dimension space points of the node aggregate and not necessarily one of the occupied ones. This allows us to move virtual specializations only when using the scatter strategy + */ + public DimensionSpacePoint $dimensionSpacePoint, public InterdimensionalSiblings $succeedingSiblingsForCoverage, ) { } @@ -89,6 +93,7 @@ public function withWorkspaceNameAndContentStreamId(WorkspaceName $targetWorkspa $contentStreamId, $this->nodeAggregateId, $this->newParentNodeAggregateId, + $this->dimensionSpacePoint, $this->succeedingSiblingsForCoverage, ); } @@ -132,6 +137,7 @@ public static function fromArray(array $values): self ContentStreamId::fromString($values['contentStreamId']), NodeAggregateId::fromString($values['nodeAggregateId']), $newParentNodeAggregateId, + DimensionSpacePoint::fromArray($values['dimensionSpacePoint']), $succeedingSiblingsForCoverage, ); } diff --git a/Neos.ContentRepository.Core/Classes/Feature/NodeMove/NodeMove.php b/Neos.ContentRepository.Core/Classes/Feature/NodeMove/NodeMove.php index 5dfae05275c..9ab73f3a5a6 100644 --- a/Neos.ContentRepository.Core/Classes/Feature/NodeMove/NodeMove.php +++ b/Neos.ContentRepository.Core/Classes/Feature/NodeMove/NodeMove.php @@ -187,6 +187,7 @@ private function handleMoveNodeAggregate( $contentStreamId, $command->nodeAggregateId, $command->newParentNodeAggregateId, + $command->dimensionSpacePoint, $this->resolveInterdimensionalSiblingsForMove( $contentGraph, $command->dimensionSpacePoint, diff --git a/Neos.ContentRepository.LegacyNodeMigration/Classes/Processors/EventExportProcessor.php b/Neos.ContentRepository.LegacyNodeMigration/Classes/Processors/EventExportProcessor.php index 6d547c385bc..1ec7ed32a60 100644 --- a/Neos.ContentRepository.LegacyNodeMigration/Classes/Processors/EventExportProcessor.php +++ b/Neos.ContentRepository.LegacyNodeMigration/Classes/Processors/EventExportProcessor.php @@ -443,6 +443,7 @@ private function createNodeVariant(NodeAggregateId $nodeAggregateId, OriginDimen $this->contentStreamId, $nodeAggregateId, $parentNodeAggregate->nodeAggregateId, + $originDimensionSpacePoint->toDimensionSpacePoint(), new InterdimensionalSiblings( new InterdimensionalSibling( $originDimensionSpacePoint->toDimensionSpacePoint(), diff --git a/Neos.ContentRepository.StructureAdjustment/src/Adjustment/TetheredNodeAdjustments.php b/Neos.ContentRepository.StructureAdjustment/src/Adjustment/TetheredNodeAdjustments.php index 9d985cc2399..e7023a845ad 100644 --- a/Neos.ContentRepository.StructureAdjustment/src/Adjustment/TetheredNodeAdjustments.php +++ b/Neos.ContentRepository.StructureAdjustment/src/Adjustment/TetheredNodeAdjustments.php @@ -235,18 +235,21 @@ private function reorderNodes( $succeedingNode = $actualTetheredChildNodes[$succeedingSiblingNodeName]; $succeedingSiblingsForCoverage = []; + $arbitraryCoveredDimensionSpacePoint = null; foreach ($coverageByOrigin as $coveredDimensionSpacePoint) { $succeedingSiblingsForCoverage[] = new InterdimensionalSibling( $coveredDimensionSpacePoint, $succeedingNode->aggregateId ); + $arbitraryCoveredDimensionSpacePoint = $coveredDimensionSpacePoint; } - + assert($arbitraryCoveredDimensionSpacePoint !== null); $events[] = new NodeAggregateWasMoved( $workspaceName, $contentStreamId, $nodeToMove->aggregateId, null, + $arbitraryCoveredDimensionSpacePoint, new InterdimensionalSiblings(...$succeedingSiblingsForCoverage), ); diff --git a/Neos.Neos/Classes/PendingChangesProjection/ChangeProjection.php b/Neos.Neos/Classes/PendingChangesProjection/ChangeProjection.php index 4f91f39cea2..41a5a693556 100644 --- a/Neos.Neos/Classes/PendingChangesProjection/ChangeProjection.php +++ b/Neos.Neos/Classes/PendingChangesProjection/ChangeProjection.php @@ -214,21 +214,16 @@ private function whenNodeAggregateWasMoved(NodeAggregateWasMoved $event): void return; } - $affectedDimensionSpacePoints = iterator_to_array($event->succeedingSiblingsForCoverage->toDimensionSpacePointSet()); - $arbitraryDimensionSpacePoint = reset($affectedDimensionSpacePoints); - if ($arbitraryDimensionSpacePoint instanceof DimensionSpacePoint) { - // always the case due to constraint enforcement (at least one DSP is selected and must have a succeeding sibling or null) - - // WORKAROUND: we simply use the event's first DSP here as the origin dimension space point. - // But this DSP is not necessarily occupied. - // @todo properly handle this by storing the necessary information in the projection - - $this->markAsMoved( - $event->getContentStreamId(), - $event->getNodeAggregateId(), - OriginDimensionSpacePoint::fromDimensionSpacePoint($arbitraryDimensionSpacePoint) - ); - } + // WORKAROUND: we simply use the event's DSP here as the origin dimension space point. + // But this DSP is not necessarily occupied. + // @todo properly handle this by storing the necessary information in the projection + // todo so we need to create a change if there is none???? + + $this->markAsMoved( + $event->getContentStreamId(), + $event->getNodeAggregateId(), + OriginDimensionSpacePoint::fromDimensionSpacePoint($event->dimensionSpacePoint) + ); } private function whenNodePropertiesWereSet(NodePropertiesWereSet $event): void