diff --git a/Neos.ContentGraph.DoctrineDbalAdapter/src/DoctrineDbalContentGraphProjection.php b/Neos.ContentGraph.DoctrineDbalAdapter/src/DoctrineDbalContentGraphProjection.php index d2b530d7333..b0ec1b842b0 100644 --- a/Neos.ContentGraph.DoctrineDbalAdapter/src/DoctrineDbalContentGraphProjection.php +++ b/Neos.ContentGraph.DoctrineDbalAdapter/src/DoctrineDbalContentGraphProjection.php @@ -486,7 +486,7 @@ private function whenNodeReferencesWereSet(NodeReferencesWereSet $event, EventEn foreach ($event->affectedSourceOriginDimensionSpacePoints as $originDimensionSpacePoint) { $nodeAnchorPoint = $this->projectionContentGraph ->getAnchorPointForNodeAndOriginDimensionSpacePointAndContentStream( - $event->sourceNodeAggregateId, + $event->nodeAggregateId, $originDimensionSpacePoint, $event->contentStreamId ); @@ -514,7 +514,7 @@ function (NodeRecord $node) use ($eventEnvelope) { $nodeAnchorPoint = $this->projectionContentGraph ->getAnchorPointForNodeAndOriginDimensionSpacePointAndContentStream( - $event->sourceNodeAggregateId, + $event->nodeAggregateId, $originDimensionSpacePoint, $event->contentStreamId ); diff --git a/Neos.ContentGraph.PostgreSQLAdapter/src/Domain/Projection/Feature/NodeReferencing.php b/Neos.ContentGraph.PostgreSQLAdapter/src/Domain/Projection/Feature/NodeReferencing.php index 0f18c42294f..9eaaddb790b 100644 --- a/Neos.ContentGraph.PostgreSQLAdapter/src/Domain/Projection/Feature/NodeReferencing.php +++ b/Neos.ContentGraph.PostgreSQLAdapter/src/Domain/Projection/Feature/NodeReferencing.php @@ -39,7 +39,7 @@ private function whenNodeReferencesWereSet(NodeReferencesWereSet $event): void $nodeRecord = $this->getProjectionHypergraph()->findNodeRecordByOrigin( $event->contentStreamId, $originDimensionSpacePoint, - $event->sourceNodeAggregateId + $event->nodeAggregateId ); if ($nodeRecord) { diff --git a/Neos.ContentRepository.Core/Classes/Feature/NodeReferencing/Event/NodeReferencesWereSet.php b/Neos.ContentRepository.Core/Classes/Feature/NodeReferencing/Event/NodeReferencesWereSet.php index 27f3bd49c11..6db631b6430 100644 --- a/Neos.ContentRepository.Core/Classes/Feature/NodeReferencing/Event/NodeReferencesWereSet.php +++ b/Neos.ContentRepository.Core/Classes/Feature/NodeReferencing/Event/NodeReferencesWereSet.php @@ -29,7 +29,7 @@ public function __construct( public WorkspaceName $workspaceName, public ContentStreamId $contentStreamId, - public NodeAggregateId $sourceNodeAggregateId, + public NodeAggregateId $nodeAggregateId, /** * While only one origin dimension space point is selected when initializing the command, * a whole set of origin dimension space points might be affected depending on the @@ -47,15 +47,9 @@ public function getContentStreamId(): ContentStreamId return $this->contentStreamId; } - /** - * this method is implemented for fulfilling the {@see EmbedsContentStreamAndNodeAggregateId} interface, - * needed for proper content cache flushing in Neos. - * - * @return NodeAggregateId - */ public function getNodeAggregateId(): NodeAggregateId { - return $this->sourceNodeAggregateId; + return $this->nodeAggregateId; } public function withWorkspaceNameAndContentStreamId(WorkspaceName $targetWorkspaceName, ContentStreamId $contentStreamId): self @@ -63,7 +57,7 @@ public function withWorkspaceNameAndContentStreamId(WorkspaceName $targetWorkspa return new self( $targetWorkspaceName, $contentStreamId, - $this->sourceNodeAggregateId, + $this->nodeAggregateId, $this->affectedSourceOriginDimensionSpacePoints, $this->referenceName, $this->references, @@ -75,7 +69,9 @@ public static function fromArray(array $values): self return new self( WorkspaceName::fromString($values['workspaceName']), ContentStreamId::fromString($values['contentStreamId']), - NodeAggregateId::fromString($values['sourceNodeAggregateId']), + array_key_exists('sourceNodeAggregateId', $values) + ? NodeAggregateId::fromString($values['sourceNodeAggregateId']) + : NodeAggregateId::fromString($values['nodeAggregateId']), OriginDimensionSpacePointSet::fromArray($values['affectedSourceOriginDimensionSpacePoints']), ReferenceName::fromString($values['referenceName']), SerializedNodeReferences::fromArray($values['references']), diff --git a/Neos.ContentRepository.Core/Tests/Unit/Feature/NodeCreation/Event/NodeAggregateWithNodeWasCreatedTest.php b/Neos.ContentRepository.Core/Tests/Unit/Feature/NodeCreation/Event/NodeAggregateWithNodeWasCreatedTest.php new file mode 100644 index 00000000000..677ed3fb971 --- /dev/null +++ b/Neos.ContentRepository.Core/Tests/Unit/Feature/NodeCreation/Event/NodeAggregateWithNodeWasCreatedTest.php @@ -0,0 +1,135 @@ + $payload + * @dataProvider eventPayloadProviderWithLegacySucceedingNodeAggregateIdFormat + */ + public function testFromArray(array $payload, NodeAggregateWithNodeWasCreated $expectedEvent): void + { + self::assertEquals($expectedEvent, NodeAggregateWithNodeWasCreated::fromArray($payload)); + } + + /** + * The coveredDimensionSpacePoints and succeedingNodeAggregateId were replaced with `InterdimensionalSiblings`. + * A runtime migration was added to {@see NodeAggregateWithNodeWasCreated::fromArray()} to handle the legacy format. + * + * Via #4961: https://github.com/neos/neos-development-collection/pull/4961 + * + * Included in April 2024 + * + * @return iterable + */ + public static function eventPayloadProviderWithLegacySucceedingNodeAggregateIdFormat(): iterable + { + yield 'legacy coveredDimensionSpacePoints succeedingNodeAggregateId fields are transformed' => [ + [ + 'contentStreamId' => 'd1afafaf-e078-4b44-a9a2-077094e8e45b', + 'nodeAggregateId' => '872344d1-7da5-4b17-a1f0-0138987431a9', + 'nodeTypeName' => 'Vendor.Site:Document.Page', + 'originDimensionSpacePoint' => + [ + 'language' => 'pl', + ], + 'coveredDimensionSpacePoints' => + [ + [ + 'language' => 'pl', + ], + ], + 'parentNodeAggregateId' => '6b6e1251-4346-494f-ac56-526a30a5741d', + 'nodeName' => null, + 'initialPropertyValues' => [], + 'nodeAggregateClassification' => 'regular', + 'succeedingNodeAggregateId' => '30ef3082-e37f-4346-83cf-45ed0249381f', + 'workspaceName' => 'user-soee', + ], + new NodeAggregateWithNodeWasCreated( + WorkspaceName::fromString('user-soee'), + ContentStreamId::fromString('d1afafaf-e078-4b44-a9a2-077094e8e45b'), + NodeAggregateId::fromString('872344d1-7da5-4b17-a1f0-0138987431a9'), + NodeTypeName::fromString('Vendor.Site:Document.Page'), + OriginDimensionSpacePoint::fromArray(['language' => 'pl']), + new InterdimensionalSiblings( + new InterdimensionalSibling( + DimensionSpacePoint::fromArray(['language' => 'pl']), + NodeAggregateId::fromString('30ef3082-e37f-4346-83cf-45ed0249381f') + ) + ), + NodeAggregateId::fromString('6b6e1251-4346-494f-ac56-526a30a5741d'), + null, + SerializedPropertyValues::createEmpty(), + NodeAggregateClassification::CLASSIFICATION_REGULAR + ) + ]; + + yield 'legacy succeedingNodeAggregateId field is null' => [ + [ + 'contentStreamId' => 'd1afafaf-e078-4b44-a9a2-077094e8e45b', + 'nodeAggregateId' => '872344d1-7da5-4b17-a1f0-0138987431a9', + 'nodeTypeName' => 'Vendor.Site:Document.Page', + 'originDimensionSpacePoint' => + [ + 'language' => 'pl', + ], + 'coveredDimensionSpacePoints' => + [ + [ + 'language' => 'pl', + ], + ], + 'parentNodeAggregateId' => '6b6e1251-4346-494f-ac56-526a30a5741d', + 'nodeName' => null, + 'initialPropertyValues' => [], + 'nodeAggregateClassification' => 'regular', + 'succeedingNodeAggregateId' => null, + 'workspaceName' => 'user-soee', + ], + new NodeAggregateWithNodeWasCreated( + WorkspaceName::fromString('user-soee'), + ContentStreamId::fromString('d1afafaf-e078-4b44-a9a2-077094e8e45b'), + NodeAggregateId::fromString('872344d1-7da5-4b17-a1f0-0138987431a9'), + NodeTypeName::fromString('Vendor.Site:Document.Page'), + OriginDimensionSpacePoint::fromArray(['language' => 'pl']), + new InterdimensionalSiblings( + new InterdimensionalSibling( + DimensionSpacePoint::fromArray(['language' => 'pl']), + null + ) + ), + NodeAggregateId::fromString('6b6e1251-4346-494f-ac56-526a30a5741d'), + null, + SerializedPropertyValues::createEmpty(), + NodeAggregateClassification::CLASSIFICATION_REGULAR + ) + ]; + } +} diff --git a/Neos.ContentRepository.Core/Tests/Unit/Feature/NodeMove/Event/NodeAggregateWasMovedTest.php b/Neos.ContentRepository.Core/Tests/Unit/Feature/NodeMove/Event/NodeAggregateWasMovedTest.php index 1b7936e4f0a..1fc8cdb0be6 100644 --- a/Neos.ContentRepository.Core/Tests/Unit/Feature/NodeMove/Event/NodeAggregateWasMovedTest.php +++ b/Neos.ContentRepository.Core/Tests/Unit/Feature/NodeMove/Event/NodeAggregateWasMovedTest.php @@ -28,7 +28,7 @@ class NodeAggregateWasMovedTest extends TestCase { /** * @param array $payload - * @dataProvider eventPayloadProvider + * @dataProvider eventPayloadProviderWithLegacyNodeMoveMappingsFormat */ public function testFromArray(array $payload, NodeAggregateWasMoved $expectedEvent): void { @@ -36,9 +36,16 @@ public function testFromArray(array $payload, NodeAggregateWasMoved $expectedEve } /** - * @return \Traversable> + * The `MoveNodeMappings` were replaced with `InterdimensionalSiblings`. + * A runtime migration was added to {@see NodeAggregateWasMoved::fromArray()} to handle the legacy format. + * + * Via #4993: https://github.com/neos/neos-development-collection/pull/4993 + * + * Included in April 2024 + * + * @return iterable */ - public static function eventPayloadProvider(): \Traversable + public static function eventPayloadProviderWithLegacyNodeMoveMappingsFormat(): iterable { yield 'singleNodeMoveMappingWithSibling' => [ 'payload' => [ diff --git a/Neos.ContentRepository.Core/Tests/Unit/Feature/NodeReferencing/Event/NodeReferencesWereSetTest.php b/Neos.ContentRepository.Core/Tests/Unit/Feature/NodeReferencing/Event/NodeReferencesWereSetTest.php new file mode 100644 index 00000000000..8567d7b088a --- /dev/null +++ b/Neos.ContentRepository.Core/Tests/Unit/Feature/NodeReferencing/Event/NodeReferencesWereSetTest.php @@ -0,0 +1,77 @@ + $payload + * @dataProvider eventPayloadProviderWithLegacySourceNodeAggregateIdFormat + */ + public function testFromArray(array $payload, NodeReferencesWereSet $expectedEvent): void + { + self::assertEquals($expectedEvent, NodeReferencesWereSet::fromArray($payload)); + } + + /** + * The property sourceNodeAggregateId was renamed to nodeAggregateId. + * A runtime migration was added to {@see NodeReferencesWereSet::fromArray()} to handle the legacy format. + * + * Via #5153: https://github.com/neos/neos-development-collection/pull/5153 + * + * Included in Juni 2024 + * + * @return iterable + */ + public static function eventPayloadProviderWithLegacySourceNodeAggregateIdFormat(): iterable + { + yield 'legacy coveredDimensionSpacePoints succeedingNodeAggregateId fields are transformed' => [ + [ + 'contentStreamId' => 'e542b7d2-a7c1-4bd8-b02a-3e8450829965', + 'sourceNodeAggregateId' => '3b4ecdc0-8115-41ed-805d-fb98ced2276a', + 'affectedSourceOriginDimensionSpacePoints' => + [ + [ + 'language' => 'en_US', + ], + ], + 'referenceName' => 'blogs', + 'references' => [], + 'workspaceName' => 'user-admin', + ], + new NodeReferencesWereSet( + WorkspaceName::fromString('user-admin'), + ContentStreamId::fromString('e542b7d2-a7c1-4bd8-b02a-3e8450829965'), + NodeAggregateId::fromString('3b4ecdc0-8115-41ed-805d-fb98ced2276a'), + OriginDimensionSpacePointSet::fromArray([ + [ + 'language' => 'en_US', + ], + ]), + ReferenceName::fromString('blogs'), + SerializedNodeReferences::fromArray([]) + ) + ]; + } +} diff --git a/Neos.ContentRepository.LegacyNodeMigration/Tests/Behavior/Features/References.feature b/Neos.ContentRepository.LegacyNodeMigration/Tests/Behavior/Features/References.feature index 8cd77523574..43b37d74ac4 100644 --- a/Neos.ContentRepository.LegacyNodeMigration/Tests/Behavior/Features/References.feature +++ b/Neos.ContentRepository.LegacyNodeMigration/Tests/Behavior/Features/References.feature @@ -36,14 +36,14 @@ Feature: Migrations that contain nodes with "reference" or "references propertie | c | /sites/site/c | Some.Package:SomeNodeType | {"text": "This is c", "refs": ["a", "b"]} | And I run the event migration Then I expect the following events to be exported - | Type | Payload | - | RootNodeAggregateWithNodeWasCreated | {"nodeAggregateId": "sites"} | - | NodeAggregateWithNodeWasCreated | {"nodeAggregateId": "site"} | - | NodeAggregateWithNodeWasCreated | {"nodeAggregateId": "a"} | - | NodeAggregateWithNodeWasCreated | {"nodeAggregateId": "b"} | - | NodeAggregateWithNodeWasCreated | {"nodeAggregateId": "c"} | - | NodeReferencesWereSet | {"sourceNodeAggregateId":"a","affectedSourceOriginDimensionSpacePoints":[[]],"referenceName":"ref","references":{"b":{"targetNodeAggregateId":"b","properties":null}}} | - | NodeReferencesWereSet | {"sourceNodeAggregateId":"c","affectedSourceOriginDimensionSpacePoints":[[]],"referenceName":"refs","references":{"a":{"targetNodeAggregateId":"a","properties":null},"b":{"targetNodeAggregateId":"b","properties":null}}} | + | Type | Payload | + | RootNodeAggregateWithNodeWasCreated | {"nodeAggregateId": "sites"} | + | NodeAggregateWithNodeWasCreated | {"nodeAggregateId": "site"} | + | NodeAggregateWithNodeWasCreated | {"nodeAggregateId": "a"} | + | NodeAggregateWithNodeWasCreated | {"nodeAggregateId": "b"} | + | NodeAggregateWithNodeWasCreated | {"nodeAggregateId": "c"} | + | NodeReferencesWereSet | {"nodeAggregateId":"a","affectedSourceOriginDimensionSpacePoints":[[]],"referenceName":"ref","references":{"b":{"targetNodeAggregateId":"b","properties":null}}} | + | NodeReferencesWereSet | {"nodeAggregateId":"c","affectedSourceOriginDimensionSpacePoints":[[]],"referenceName":"refs","references":{"a":{"targetNodeAggregateId":"a","properties":null},"b":{"targetNodeAggregateId":"b","properties":null}}} | Scenario: Node with references in one dimension @@ -60,16 +60,16 @@ Feature: Migrations that contain nodes with "reference" or "references propertie | c | /sites/site/c | Some.Package:SomeNodeType | {"language": ["ch"]} | {"text": "This is c", "refs": ["a", "b"]} | And I run the event migration Then I expect the following events to be exported - | Type | Payload | - | RootNodeAggregateWithNodeWasCreated | {"nodeAggregateId": "sites"} | - | NodeAggregateWithNodeWasCreated | {"nodeAggregateId": "site"} | - | NodePeerVariantWasCreated | {} | - | NodeAggregateWithNodeWasCreated | {"nodeAggregateId": "a"} | - | NodeAggregateWithNodeWasCreated | {"nodeAggregateId": "b"} | - | NodeAggregateWithNodeWasCreated | {"nodeAggregateId": "c"} | - | NodeReferencesWereSet | {"sourceNodeAggregateId":"a","affectedSourceOriginDimensionSpacePoints":[{"language": "en"}],"referenceName":"ref","references":{"b":{"targetNodeAggregateId":"b","properties":null}}} | - | NodeReferencesWereSet | {"sourceNodeAggregateId":"b","affectedSourceOriginDimensionSpacePoints":[{"language": "de"}],"referenceName":"ref","references":{"a":{"targetNodeAggregateId":"a","properties":null}}} | - | NodeReferencesWereSet | {"sourceNodeAggregateId":"c","affectedSourceOriginDimensionSpacePoints":[{"language": "ch"}],"referenceName":"refs","references":{"a":{"targetNodeAggregateId":"a","properties":null},"b":{"targetNodeAggregateId":"b","properties":null}}} | + | Type | Payload | + | RootNodeAggregateWithNodeWasCreated | {"nodeAggregateId": "sites"} | + | NodeAggregateWithNodeWasCreated | {"nodeAggregateId": "site"} | + | NodePeerVariantWasCreated | {} | + | NodeAggregateWithNodeWasCreated | {"nodeAggregateId": "a"} | + | NodeAggregateWithNodeWasCreated | {"nodeAggregateId": "b"} | + | NodeAggregateWithNodeWasCreated | {"nodeAggregateId": "c"} | + | NodeReferencesWereSet | {"nodeAggregateId":"a","affectedSourceOriginDimensionSpacePoints":[{"language": "en"}],"referenceName":"ref","references":{"b":{"targetNodeAggregateId":"b","properties":null}}} | + | NodeReferencesWereSet | {"nodeAggregateId":"b","affectedSourceOriginDimensionSpacePoints":[{"language": "de"}],"referenceName":"ref","references":{"a":{"targetNodeAggregateId":"a","properties":null}}} | + | NodeReferencesWereSet | {"nodeAggregateId":"c","affectedSourceOriginDimensionSpacePoints":[{"language": "ch"}],"referenceName":"refs","references":{"a":{"targetNodeAggregateId":"a","properties":null},"b":{"targetNodeAggregateId":"b","properties":null}}} | Scenario: Nodes with properties that are not part of the node type schema (see https://github.com/neos/neos-development-collection/issues/4804) When I have the following node data rows: diff --git a/Neos.Neos/Classes/PendingChangesProjection/ChangeProjection.php b/Neos.Neos/Classes/PendingChangesProjection/ChangeProjection.php index 4788ef66df1..79a588d66c7 100644 --- a/Neos.Neos/Classes/PendingChangesProjection/ChangeProjection.php +++ b/Neos.Neos/Classes/PendingChangesProjection/ChangeProjection.php @@ -263,7 +263,7 @@ private function whenNodeReferencesWereSet(NodeReferencesWereSet $event): void foreach ($event->affectedSourceOriginDimensionSpacePoints as $dimensionSpacePoint) { $this->markAsChanged( $event->contentStreamId, - $event->sourceNodeAggregateId, + $event->nodeAggregateId, $dimensionSpacePoint ); }