From 7af08e48d3ee66231b139fd1cc93555d2e2ce65f Mon Sep 17 00:00:00 2001 From: mhsdesign <85400359+mhsdesign@users.noreply.github.com> Date: Wed, 1 Nov 2023 10:15:39 +0100 Subject: [PATCH] TASK: Fix unstructured node handling in legacy migration --- .../Classes/NodeDataToAssetsProcessor.php | 14 +++++++------- .../Classes/NodeDataToEventsProcessor.php | 14 +++++++++++--- .../Behavior/Bootstrap/FeatureContext.php | 2 +- .../Tests/Behavior/Features/Errors.feature | 4 ++-- .../Tests/Behavior/Features/Variants.feature | 19 ++++++++++--------- 5 files changed, 31 insertions(+), 22 deletions(-) diff --git a/Neos.ContentRepository.LegacyNodeMigration/Classes/NodeDataToAssetsProcessor.php b/Neos.ContentRepository.LegacyNodeMigration/Classes/NodeDataToAssetsProcessor.php index 0d60b591cee..f96db3b58cc 100644 --- a/Neos.ContentRepository.LegacyNodeMigration/Classes/NodeDataToAssetsProcessor.php +++ b/Neos.ContentRepository.LegacyNodeMigration/Classes/NodeDataToAssetsProcessor.php @@ -44,16 +44,16 @@ public function run(): ProcessorResult { $numberOfErrors = 0; foreach ($this->nodeDataRows as $nodeDataRow) { + if ($nodeDataRow['path'] === '/sites') { + // the sites node has no properties and is unstructured + continue; + } $nodeTypeName = NodeTypeName::fromString($nodeDataRow['nodetype']); - try { - $nodeType = $this->nodeTypeManager->getNodeType($nodeTypeName); - } catch (NodeTypeNotFoundException $exception) { - $numberOfErrors ++; - $this->dispatch(Severity::ERROR, '%s. Node: "%s"', $exception->getMessage(), $nodeDataRow['identifier']); + if (!$this->nodeTypeManager->hasNodeType($nodeTypeName)) { + $this->dispatch(Severity::ERROR, 'The node type "%s" is not available. Node: "%s"', $nodeTypeName->value, $nodeDataRow['identifier']); continue; } - // HACK the following line is required in order to fully initialize the node type - $nodeType->getFullConfiguration(); + $nodeType = $this->nodeTypeManager->getNodeType($nodeTypeName); try { $properties = json_decode($nodeDataRow['properties'], true, 512, JSON_THROW_ON_ERROR); } catch (\JsonException $exception) { diff --git a/Neos.ContentRepository.LegacyNodeMigration/Classes/NodeDataToEventsProcessor.php b/Neos.ContentRepository.LegacyNodeMigration/Classes/NodeDataToEventsProcessor.php index 4f8bb63a3e9..cc3ad13609b 100644 --- a/Neos.ContentRepository.LegacyNodeMigration/Classes/NodeDataToEventsProcessor.php +++ b/Neos.ContentRepository.LegacyNodeMigration/Classes/NodeDataToEventsProcessor.php @@ -256,16 +256,24 @@ public function processNodeDataWithoutFallbackToEmptyDimension(NodeAggregateId $ $nodeName = end($pathParts); assert($nodeName !== false); $nodeTypeName = NodeTypeName::fromString($nodeDataRow['nodetype']); - $nodeType = $this->nodeTypeManager->getNodeType($nodeTypeName); - $serializedPropertyValuesAndReferences = $this->extractPropertyValuesAndReferences($nodeDataRow, $nodeType); + + $nodeType = $this->nodeTypeManager->hasNodeType($nodeTypeName) ? $this->nodeTypeManager->getNodeType($nodeTypeName) : null; $isSiteNode = $nodeDataRow['parentpath'] === '/sites'; - if ($isSiteNode && !$nodeType->isOfType(NodeTypeNameFactory::NAME_SITE)) { + if ($isSiteNode && !$nodeType?->isOfType(NodeTypeNameFactory::NAME_SITE)) { throw new MigrationException(sprintf( 'The site node "%s" (type: "%s") must be of type "%s"', $nodeDataRow['identifier'], $nodeTypeName->value, NodeTypeNameFactory::NAME_SITE ), 1695801620); } + if (!$nodeType) { + $this->dispatch(Severity::ERROR, 'The node type "%s" is not available. Node: "%s"', $nodeTypeName->value, $nodeDataRow['identifier']); + return; + } + + $nodeType = $this->nodeTypeManager->getNodeType($nodeTypeName); + $serializedPropertyValuesAndReferences = $this->extractPropertyValuesAndReferences($nodeDataRow, $nodeType); + if ($this->isAutoCreatedChildNode($parentNodeAggregate->nodeTypeName, $nodeName) && !$this->visitedNodes->containsNodeAggregate($nodeAggregateId)) { // Create tethered node if the node was not found before. // If the node was already visited, we want to create a node variant (and keep the tethering status) diff --git a/Neos.ContentRepository.LegacyNodeMigration/Tests/Behavior/Bootstrap/FeatureContext.php b/Neos.ContentRepository.LegacyNodeMigration/Tests/Behavior/Bootstrap/FeatureContext.php index 53b87836684..32b714bbbb3 100644 --- a/Neos.ContentRepository.LegacyNodeMigration/Tests/Behavior/Bootstrap/FeatureContext.php +++ b/Neos.ContentRepository.LegacyNodeMigration/Tests/Behavior/Bootstrap/FeatureContext.php @@ -193,7 +193,7 @@ public function iExpectTheFollowingEventsToBeExported(TableNode $table): void */ public function iExpectTheFollwingErrorsToBeLogged(TableNode $table): void { - Assert::assertSame($this->loggedErrors, $table->getColumn(0), 'Expected logged errors do not match'); + Assert::assertSame($table->getColumn(0), $this->loggedErrors, 'Expected logged errors do not match'); $this->loggedErrors = []; } diff --git a/Neos.ContentRepository.LegacyNodeMigration/Tests/Behavior/Features/Errors.feature b/Neos.ContentRepository.LegacyNodeMigration/Tests/Behavior/Features/Errors.feature index 33af167cd03..5058e8674d6 100644 --- a/Neos.ContentRepository.LegacyNodeMigration/Tests/Behavior/Features/Errors.feature +++ b/Neos.ContentRepository.LegacyNodeMigration/Tests/Behavior/Features/Errors.feature @@ -100,11 +100,11 @@ Feature: Exceptional cases during migrations When I have the following node data rows: | Identifier | Path | Properties | Node Type | | sites | /sites | | | - | a | /sites/a | not json | Some.Package:SomeNodeType | + | a | /sites/a | not json | Some.Package:Homepage | And I run the event migration Then I expect a MigrationError with the message """ - Failed to decode properties "not json" of node "a" (type: "Some.Package:SomeNodeType"): Could not convert database value "not json" to Doctrine Type flow_json_array + Failed to decode properties "not json" of node "a" (type: "Some.Package:Homepage"): Could not convert database value "not json" to Doctrine Type flow_json_array """ Scenario: Node variants with the same dimension diff --git a/Neos.ContentRepository.LegacyNodeMigration/Tests/Behavior/Features/Variants.feature b/Neos.ContentRepository.LegacyNodeMigration/Tests/Behavior/Features/Variants.feature index a0e35e8fc92..40ff8fca40a 100644 --- a/Neos.ContentRepository.LegacyNodeMigration/Tests/Behavior/Features/Variants.feature +++ b/Neos.ContentRepository.LegacyNodeMigration/Tests/Behavior/Features/Variants.feature @@ -11,6 +11,7 @@ Feature: Migrating nodes with content dimensions 'Some.Package:Homepage': superTypes: 'Neos.Neos:Site': true + 'Some.Package:Thing': {} """ And using identifier "default", I define a content repository And I am in content repository "default" @@ -66,10 +67,10 @@ Feature: Migrating nodes with content dimensions | Identifier | Path | Node Type | Dimension Values | | sites | /sites | unstructured | | | site | /sites/site | Some.Package:Homepage | {"language": ["de"]} | - | a | /sites/site/a | unstructured | {"language": ["de"]} | - | a1 | /sites/site/a/a1 | unstructured | {"language": ["de"]} | - | b | /sites/site/b | unstructured | {"language": ["de"]} | - | a1 | /sites/site/b/a1 | unstructured | {"language": ["ch"]} | + | a | /sites/site/a | Some.Package:Thing | {"language": ["de"]} | + | a1 | /sites/site/a/a1 | Some.Package:Thing | {"language": ["de"]} | + | b | /sites/site/b | Some.Package:Thing | {"language": ["de"]} | + | a1 | /sites/site/b/a1 | Some.Package:Thing | {"language": ["ch"]} | And I run the event migration Then I expect the following events to be exported | Type | Payload | @@ -87,11 +88,11 @@ Feature: Migrating nodes with content dimensions | Identifier | Path | Node Type | Dimension Values | | sites | /sites | unstructured | | | site | /sites/site | Some.Package:Homepage | {"language": ["de"]} | - | a | /sites/site/a | unstructured | {"language": ["de"]} | - | a1 | /sites/site/a/a1 | unstructured | {"language": ["de"]} | - | b | /sites/site/b | unstructured | {"language": ["de"]} | - | a | /sites/site/b/a | unstructured | {"language": ["ch"]} | - | a1 | /sites/site/b/a/a1 | unstructured | {"language": ["ch"]} | + | a | /sites/site/a | Some.Package:Thing | {"language": ["de"]} | + | a1 | /sites/site/a/a1 | Some.Package:Thing | {"language": ["de"]} | + | b | /sites/site/b | Some.Package:Thing | {"language": ["de"]} | + | a | /sites/site/b/a | Some.Package:Thing | {"language": ["ch"]} | + | a1 | /sites/site/b/a/a1 | Some.Package:Thing | {"language": ["ch"]} | And I run the event migration Then I expect the following events to be exported | Type | Payload |