From ab41496c4532e4baab65f74a03f04fc629a95bec Mon Sep 17 00:00:00 2001 From: mhsdesign <85400359+mhsdesign@users.noreply.github.com> Date: Tue, 14 May 2024 21:07:07 +0200 Subject: [PATCH] TASK: Remove `NodeTypeManager::getTetheredNodesConfigurationForNodeType()` Previously known as `NodeType::getAutoCreatedChildNodes` --- .../Feature/Common/ConstraintChecks.php | 12 +++---- .../Feature/Common/TetheredNodeInternals.php | 28 ++++++++-------- .../Dto/NodeAggregateIdsByNodePaths.php | 11 +++++-- .../Feature/NodeCreation/NodeCreation.php | 23 +++++++------ .../Feature/NodeTypeChange/NodeTypeChange.php | 29 +++++++--------- .../RootNodeCreation/RootNodeHandling.php | 18 +++++----- .../Classes/NodeType/NodeTypeManager.php | 32 ------------------ .../NodeType/TetheredNodeTypeDefinitions.php | 2 +- .../Unit/NodeType/NodeTypeManagerTest.php | 5 ++- .../Adjustment/TetheredNodeAdjustments.php | 33 ++++++++----------- .../Classes/Service/NodeTypeSchemaBuilder.php | 8 ++--- 11 files changed, 83 insertions(+), 118 deletions(-) diff --git a/Neos.ContentRepository.Core/Classes/Feature/Common/ConstraintChecks.php b/Neos.ContentRepository.Core/Classes/Feature/Common/ConstraintChecks.php index a57d8688b01..6514d818b4a 100644 --- a/Neos.ContentRepository.Core/Classes/Feature/Common/ConstraintChecks.php +++ b/Neos.ContentRepository.Core/Classes/Feature/Common/ConstraintChecks.php @@ -172,14 +172,13 @@ protected function requireRootNodeTypeToBeUnoccupied( /** * @param NodeType $nodeType - * @throws NodeTypeNotFoundException the configured child nodeType doesnt exist + * @throws NodeTypeNotFound the configured child nodeType doesnt exist */ protected function requireTetheredDescendantNodeTypesToExist(NodeType $nodeType): void { - // this getter throws if any of the child nodeTypes doesnt exist! - $tetheredNodeTypes = $this->getNodeTypeManager()->getTetheredNodesConfigurationForNodeType($nodeType->name); - foreach ($tetheredNodeTypes as $tetheredNodeType) { - $this->requireTetheredDescendantNodeTypesToExist($tetheredNodeType); + foreach ($nodeType->tetheredNodeTypeDefinitions as $tetheredNodeTypeDefinition) { + $nodeType = $this->requireNodeType($tetheredNodeTypeDefinition->nodeTypeName); + $this->requireTetheredDescendantNodeTypesToExist($nodeType); } } @@ -189,7 +188,8 @@ protected function requireTetheredDescendantNodeTypesToExist(NodeType $nodeType) */ protected function requireTetheredDescendantNodeTypesToNotBeOfTypeRoot(NodeType $nodeType): void { - foreach ($this->getNodeTypeManager()->getTetheredNodesConfigurationForNodeType($nodeType->name) as $tetheredChildNodeType) { + foreach ($nodeType->tetheredNodeTypeDefinitions as $tetheredNodeTypeDefinition) { + $tetheredChildNodeType = $this->requireNodeType($tetheredNodeTypeDefinition->nodeTypeName); if ($tetheredChildNodeType->isOfType(NodeTypeName::ROOT_NODE_TYPE_NAME)) { throw new NodeTypeIsOfTypeRoot( 'Node type "' . $nodeType->name->value . '" for tethered descendant is of type root.', diff --git a/Neos.ContentRepository.Core/Classes/Feature/Common/TetheredNodeInternals.php b/Neos.ContentRepository.Core/Classes/Feature/Common/TetheredNodeInternals.php index c99412cd353..36f27b2e80a 100644 --- a/Neos.ContentRepository.Core/Classes/Feature/Common/TetheredNodeInternals.php +++ b/Neos.ContentRepository.Core/Classes/Feature/Common/TetheredNodeInternals.php @@ -20,15 +20,13 @@ use Neos\ContentRepository\Core\Feature\NodeModification\Dto\SerializedPropertyValues; use Neos\ContentRepository\Core\Feature\NodeVariation\Event\NodePeerVariantWasCreated; use Neos\ContentRepository\Core\Infrastructure\Property\PropertyConverter; -use Neos\ContentRepository\Core\NodeType\NodeType; use Neos\ContentRepository\Core\NodeType\NodeTypeName; +use Neos\ContentRepository\Core\NodeType\TetheredNodeTypeDefinition; use Neos\ContentRepository\Core\Projection\ContentGraph\ContentGraphInterface; use Neos\ContentRepository\Core\Projection\ContentGraph\Node; use Neos\ContentRepository\Core\Projection\ContentGraph\NodeAggregate; use Neos\ContentRepository\Core\SharedModel\Node\NodeAggregateClassification; use Neos\ContentRepository\Core\SharedModel\Node\NodeAggregateId; -use Neos\ContentRepository\Core\SharedModel\Node\NodeName; -use Neos\ContentRepository\Core\SharedModel\Workspace\ContentStreamId; /** * @internal implementation details of command handlers @@ -58,15 +56,19 @@ protected function createEventsForMissingTetheredNode( ContentGraphInterface $contentGraph, NodeAggregate $parentNodeAggregate, OriginDimensionSpacePoint $originDimensionSpacePoint, - NodeName $tetheredNodeName, - ?NodeAggregateId $tetheredNodeAggregateId, - NodeType $expectedTetheredNodeType + TetheredNodeTypeDefinition $tetheredNodeTypeDefinition, + ?NodeAggregateId $tetheredNodeAggregateId ): Events { $childNodeAggregate = $contentGraph->findChildNodeAggregateByName( $parentNodeAggregate->nodeAggregateId, - $tetheredNodeName + $tetheredNodeTypeDefinition->name ); + $expectedTetheredNodeType = $this->nodeTypeManager->getNodeType($tetheredNodeTypeDefinition->nodeTypeName); + $defaultProperties = $expectedTetheredNodeType + ? SerializedPropertyValues::defaultFromNodeType($expectedTetheredNodeType, $this->getPropertyConverter()) + : SerializedPropertyValues::createEmpty(); + if ($childNodeAggregate === null) { // there is no tethered child node aggregate already; let's create it! $nodeType = $this->nodeTypeManager->getNodeType($parentNodeAggregate->nodeTypeName); @@ -91,14 +93,14 @@ protected function createEventsForMissingTetheredNode( $events[] = new NodeAggregateWithNodeWasCreated( $parentNodeAggregate->contentStreamId, $tetheredNodeAggregateId, - $expectedTetheredNodeType->name, + $tetheredNodeTypeDefinition->nodeTypeName, $rootGeneralizationOrigin, InterdimensionalSiblings::fromDimensionSpacePointSetWithoutSucceedingSiblings( $this->getInterDimensionalVariationGraph()->getSpecializationSet($rootGeneralization) ), $parentNodeAggregate->nodeAggregateId, - $tetheredNodeName, - SerializedPropertyValues::defaultFromNodeType($expectedTetheredNodeType, $this->getPropertyConverter()), + $tetheredNodeTypeDefinition->name, + $defaultProperties, NodeAggregateClassification::CLASSIFICATION_TETHERED, ); $creationOriginDimensionSpacePoint = $rootGeneralizationOrigin; @@ -110,14 +112,14 @@ protected function createEventsForMissingTetheredNode( new NodeAggregateWithNodeWasCreated( $parentNodeAggregate->contentStreamId, $tetheredNodeAggregateId ?: NodeAggregateId::create(), - $expectedTetheredNodeType->name, + $tetheredNodeTypeDefinition->nodeTypeName, $originDimensionSpacePoint, InterdimensionalSiblings::fromDimensionSpacePointSetWithoutSucceedingSiblings( $parentNodeAggregate->getCoverageByOccupant($originDimensionSpacePoint) ), $parentNodeAggregate->nodeAggregateId, - $tetheredNodeName, - SerializedPropertyValues::defaultFromNodeType($expectedTetheredNodeType, $this->getPropertyConverter()), + $tetheredNodeTypeDefinition->name, + $defaultProperties, NodeAggregateClassification::CLASSIFICATION_TETHERED, ) ); diff --git a/Neos.ContentRepository.Core/Classes/Feature/NodeCreation/Dto/NodeAggregateIdsByNodePaths.php b/Neos.ContentRepository.Core/Classes/Feature/NodeCreation/Dto/NodeAggregateIdsByNodePaths.php index d5eda29f1d9..083a4cfb607 100644 --- a/Neos.ContentRepository.Core/Classes/Feature/NodeCreation/Dto/NodeAggregateIdsByNodePaths.php +++ b/Neos.ContentRepository.Core/Classes/Feature/NodeCreation/Dto/NodeAggregateIdsByNodePaths.php @@ -18,6 +18,7 @@ use Neos\ContentRepository\Core\NodeType\NodeTypeManager; use Neos\ContentRepository\Core\NodeType\NodeTypeName; use Neos\ContentRepository\Core\Projection\ContentGraph\NodePath; +use Neos\ContentRepository\Core\SharedModel\Exception\NodeTypeNotFound; use Neos\ContentRepository\Core\SharedModel\Node\NodeAggregateId; /** @@ -128,12 +129,16 @@ private static function createNodeAggregateIdsForNodeType( ?string $pathPrefix = null ): array { $nodeAggregateIds = []; - foreach ($nodeTypeManager->getTetheredNodesConfigurationForNodeType($nodeTypeName) as $nodeName => $childNodeType) { - $path = $pathPrefix ? $pathPrefix . '/' . $nodeName : $nodeName; + $nodeType = $nodeTypeManager->getNodeType($nodeTypeName); + if (!$nodeType) { + throw new NodeTypeNotFound(sprintf('Cannot build NodeAggregateIdsByNodePaths because NodeType %s does not exist.', $nodeTypeName->value), 1715711379); + } + foreach ($nodeType->tetheredNodeTypeDefinitions as $tetheredNodeTypeDefinition) { + $path = $pathPrefix ? $pathPrefix . '/' . $tetheredNodeTypeDefinition->name->value : $tetheredNodeTypeDefinition->name->value; $nodeAggregateIds[$path] = NodeAggregateId::create(); $nodeAggregateIds = array_merge( $nodeAggregateIds, - self::createNodeAggregateIdsForNodeType($childNodeType->name, $nodeTypeManager, $path) + self::createNodeAggregateIdsForNodeType($tetheredNodeTypeDefinition->nodeTypeName, $nodeTypeManager, $path) ); } diff --git a/Neos.ContentRepository.Core/Classes/Feature/NodeCreation/NodeCreation.php b/Neos.ContentRepository.Core/Classes/Feature/NodeCreation/NodeCreation.php index 6e8666fa09e..38fb29ef5a3 100644 --- a/Neos.ContentRepository.Core/Classes/Feature/NodeCreation/NodeCreation.php +++ b/Neos.ContentRepository.Core/Classes/Feature/NodeCreation/NodeCreation.php @@ -209,7 +209,7 @@ private function handleCreateNodeAggregateWithNodeAndSerializedProperties( array_push($events, ...iterator_to_array($this->handleTetheredChildNodes( $command, $contentGraph, - $command->nodeTypeName, + $nodeType, $coveredDimensionSpacePoints, $command->nodeAggregateId, $descendantNodeAggregateIds, @@ -257,30 +257,33 @@ private function createRegularWithNode( private function handleTetheredChildNodes( CreateNodeAggregateWithNodeAndSerializedProperties $command, ContentGraphInterface $contentGraph, - NodeTypeName $nodeTypeName, + NodeType $nodeType, DimensionSpacePointSet $coveredDimensionSpacePoints, NodeAggregateId $parentNodeAggregateId, NodeAggregateIdsByNodePaths $nodeAggregateIds, ?NodePath $nodePath ): Events { $events = []; - foreach ($this->getNodeTypeManager()->getTetheredNodesConfigurationForNodeType($nodeTypeName) as $nodeNameString => $childNodeType) { - $nodeName = NodeName::fromString($nodeNameString); + foreach ($nodeType->tetheredNodeTypeDefinitions as $tetheredNodeTypeDefinition) { + $childNodeType = $this->requireNodeType($tetheredNodeTypeDefinition->nodeTypeName); $childNodePath = $nodePath - ? $nodePath->appendPathSegment($nodeName) - : NodePath::fromString($nodeName->value); + ? $nodePath->appendPathSegment($tetheredNodeTypeDefinition->name) + : NodePath::fromString($tetheredNodeTypeDefinition->name->value); $childNodeAggregateId = $nodeAggregateIds->getNodeAggregateId($childNodePath) ?? NodeAggregateId::create(); - $initialPropertyValues = SerializedPropertyValues::defaultFromNodeType($childNodeType, $this->getPropertyConverter()); + $initialPropertyValues = SerializedPropertyValues::defaultFromNodeType( + $childNodeType, + $this->getPropertyConverter() + ); $events[] = new NodeAggregateWithNodeWasCreated( $contentGraph->getContentStreamId(), $childNodeAggregateId, - $childNodeType->name, + $tetheredNodeTypeDefinition->nodeTypeName, $command->originDimensionSpacePoint, InterdimensionalSiblings::fromDimensionSpacePointSetWithoutSucceedingSiblings($coveredDimensionSpacePoints), $parentNodeAggregateId, - $nodeName, + $tetheredNodeTypeDefinition->name, $initialPropertyValues, NodeAggregateClassification::CLASSIFICATION_TETHERED, ); @@ -288,7 +291,7 @@ private function handleTetheredChildNodes( array_push($events, ...iterator_to_array($this->handleTetheredChildNodes( $command, $contentGraph, - $childNodeType->name, + $childNodeType, $coveredDimensionSpacePoints, $childNodeAggregateId, $nodeAggregateIds, diff --git a/Neos.ContentRepository.Core/Classes/Feature/NodeTypeChange/NodeTypeChange.php b/Neos.ContentRepository.Core/Classes/Feature/NodeTypeChange/NodeTypeChange.php index 16219eb7160..72c20f0d7fc 100644 --- a/Neos.ContentRepository.Core/Classes/Feature/NodeTypeChange/NodeTypeChange.php +++ b/Neos.ContentRepository.Core/Classes/Feature/NodeTypeChange/NodeTypeChange.php @@ -28,8 +28,8 @@ use Neos\ContentRepository\Core\Feature\NodeTypeChange\Event\NodeAggregateTypeWasChanged; use Neos\ContentRepository\Core\NodeType\NodeType; use Neos\ContentRepository\Core\NodeType\NodeTypeManager; +use Neos\ContentRepository\Core\NodeType\TetheredNodeTypeDefinition; use Neos\ContentRepository\Core\Projection\ContentGraph\ContentGraphInterface; -use Neos\ContentRepository\Core\NodeType\NodeTypeName; use Neos\ContentRepository\Core\Projection\ContentGraph\Node; use Neos\ContentRepository\Core\Projection\ContentGraph\NodeAggregate; use Neos\ContentRepository\Core\Projection\ContentGraph\NodePath; @@ -90,9 +90,8 @@ abstract protected function createEventsForMissingTetheredNode( ContentGraphInterface $contentGraph, NodeAggregate $parentNodeAggregate, OriginDimensionSpacePoint $originDimensionSpacePoint, - NodeName $tetheredNodeName, - NodeAggregateId $tetheredNodeAggregateId, - NodeType $expectedTetheredNodeType + TetheredNodeTypeDefinition $tetheredNodeTypeDefinition, + NodeAggregateId $tetheredNodeAggregateId ): Events; /** @@ -177,36 +176,32 @@ private function handleChangeNodeAggregateType( array_push($events, ...iterator_to_array($this->deleteObsoleteTetheredNodesWhenChangingNodeType( $contentGraph, $nodeAggregate, - $command->newNodeTypeName + $newNodeType ))); } // new tethered child nodes - $expectedTetheredNodes = $this->getNodeTypeManager()->getTetheredNodesConfigurationForNodeType($command->newNodeTypeName); foreach ($nodeAggregate->getNodes() as $node) { assert($node instanceof Node); - foreach ($expectedTetheredNodes as $serializedTetheredNodeName => $expectedTetheredNodeType) { - $tetheredNodeName = NodeName::fromString($serializedTetheredNodeName); - + foreach ($newNodeType->tetheredNodeTypeDefinitions as $tetheredNodeTypeDefinition) { $tetheredNode = $contentGraph->getSubgraph( $node->originDimensionSpacePoint->toDimensionSpacePoint(), VisibilityConstraints::withoutRestrictions() )->findNodeByPath( - $tetheredNodeName, + $tetheredNodeTypeDefinition->name, $node->nodeAggregateId, ); if ($tetheredNode === null) { $tetheredNodeAggregateId = $command->tetheredDescendantNodeAggregateIds - ->getNodeAggregateId(NodePath::fromString($tetheredNodeName->value)) + ->getNodeAggregateId(NodePath::fromNodeNames($tetheredNodeTypeDefinition->name)) ?: NodeAggregateId::create(); array_push($events, ...iterator_to_array($this->createEventsForMissingTetheredNode( $contentGraph, $nodeAggregate, $node->originDimensionSpacePoint, - $tetheredNodeName, - $tetheredNodeAggregateId, - $expectedTetheredNodeType + $tetheredNodeTypeDefinition, + $tetheredNodeAggregateId ))); } } @@ -348,17 +343,15 @@ private function deleteDisallowedNodesWhenChangingNodeType( private function deleteObsoleteTetheredNodesWhenChangingNodeType( ContentGraphInterface $contentGraph, NodeAggregate $nodeAggregate, - NodeTypeName $newNodeTypeName + NodeType $newNodeType ): Events { - $expectedTetheredNodes = $this->getNodeTypeManager()->getTetheredNodesConfigurationForNodeType($newNodeTypeName); - $events = []; // find disallowed tethered nodes $tetheredNodeAggregates = $contentGraph->findTetheredChildNodeAggregates($nodeAggregate->nodeAggregateId); foreach ($tetheredNodeAggregates as $tetheredNodeAggregate) { /* @var $tetheredNodeAggregate NodeAggregate */ - if ($tetheredNodeAggregate->nodeName !== null && !isset($expectedTetheredNodes[$tetheredNodeAggregate->nodeName->value])) { + if ($tetheredNodeAggregate->nodeName !== null && !$newNodeType->tetheredNodeTypeDefinitions->contain($tetheredNodeAggregate->nodeName)) { // this aggregate (or parts thereof) are DISALLOWED according to constraints. // We now need to find out which edges we need to remove, $dimensionSpacePointsToBeRemoved = $this->findDimensionSpacePointsConnectingParentAndChildAggregate( diff --git a/Neos.ContentRepository.Core/Classes/Feature/RootNodeCreation/RootNodeHandling.php b/Neos.ContentRepository.Core/Classes/Feature/RootNodeCreation/RootNodeHandling.php index ab6f0a1b9a5..da442c82b68 100644 --- a/Neos.ContentRepository.Core/Classes/Feature/RootNodeCreation/RootNodeHandling.php +++ b/Neos.ContentRepository.Core/Classes/Feature/RootNodeCreation/RootNodeHandling.php @@ -105,7 +105,7 @@ private function handleCreateRootNodeAggregateWithNode( foreach ($this->getInterDimensionalVariationGraph()->getRootGeneralizations() as $rootGeneralization) { array_push($events, ...iterator_to_array($this->handleTetheredRootChildNodes( $contentGraph->getContentStreamId(), - $command->nodeTypeName, + $nodeType, OriginDimensionSpacePoint::fromDimensionSpacePoint($rootGeneralization), $this->getInterDimensionalVariationGraph()->getSpecializationSet($rootGeneralization, true), $command->nodeAggregateId, @@ -184,7 +184,7 @@ private function handleUpdateRootNodeAggregateDimensions( */ private function handleTetheredRootChildNodes( ContentStreamId $contentStreamId, - NodeTypeName $nodeTypeName, + NodeType $nodeType, OriginDimensionSpacePoint $originDimensionSpacePoint, DimensionSpacePointSet $coveredDimensionSpacePoints, NodeAggregateId $parentNodeAggregateId, @@ -192,11 +192,11 @@ private function handleTetheredRootChildNodes( ?NodePath $nodePath ): Events { $events = []; - foreach ($this->getNodeTypeManager()->getTetheredNodesConfigurationForNodeType($nodeTypeName) as $nodeNameString => $childNodeType) { - $nodeName = NodeName::fromString($nodeNameString); + foreach ($nodeType->tetheredNodeTypeDefinitions as $tetheredNodeTypeDefinition) { + $childNodeType = $this->requireNodeType($tetheredNodeTypeDefinition->nodeTypeName); $childNodePath = $nodePath - ? $nodePath->appendPathSegment($nodeName) - : NodePath::fromString($nodeName->value); + ? $nodePath->appendPathSegment($tetheredNodeTypeDefinition->name) + : NodePath::fromNodeNames($tetheredNodeTypeDefinition->name); $childNodeAggregateId = $nodeAggregateIdsByNodePath->getNodeAggregateId($childNodePath) ?? NodeAggregateId::create(); $initialPropertyValues = SerializedPropertyValues::defaultFromNodeType($childNodeType, $this->getPropertyConverter()); @@ -204,17 +204,17 @@ private function handleTetheredRootChildNodes( $events[] = $this->createTetheredWithNodeForRoot( $contentStreamId, $childNodeAggregateId, - $childNodeType->name, + $tetheredNodeTypeDefinition->nodeTypeName, $originDimensionSpacePoint, $coveredDimensionSpacePoints, $parentNodeAggregateId, - $nodeName, + $tetheredNodeTypeDefinition->name, $initialPropertyValues ); array_push($events, ...iterator_to_array($this->handleTetheredRootChildNodes( $contentStreamId, - $childNodeType->name, + $childNodeType, $originDimensionSpacePoint, $coveredDimensionSpacePoints, $childNodeAggregateId, diff --git a/Neos.ContentRepository.Core/Classes/NodeType/NodeTypeManager.php b/Neos.ContentRepository.Core/Classes/NodeType/NodeTypeManager.php index a099ba73665..855a9433cab 100644 --- a/Neos.ContentRepository.Core/Classes/NodeType/NodeTypeManager.php +++ b/Neos.ContentRepository.Core/Classes/NodeType/NodeTypeManager.php @@ -189,24 +189,6 @@ public function overrideNodeTypes(array $completeNodeTypeConfiguration): void } } - /** - * Return an array with child nodes which should be automatically created - * Return an array with child nodes which should be automatically created - * - * @return array the key of this array is the name of the child, and the value its NodeType. - */ - public function getTetheredNodesConfigurationForNodeType(NodeTypeName $nodeTypeName): array - { - $childNodeConfiguration = $this->requireNodeType($nodeTypeName)->getConfiguration('childNodes'); - $autoCreatedChildNodes = []; - foreach ($childNodeConfiguration ?? [] as $childNodeName => $configurationForChildNode) { - if (isset($configurationForChildNode['type'])) { - $autoCreatedChildNodes[NodeName::transliterateFromString($childNodeName)->value] = $this->requireNodeType($configurationForChildNode['type']); - } - } - return $autoCreatedChildNodes; - } - /** * Checks if the given $nodeTypeNameToCheck is allowed as a childNode of the given $tetheredNodeName. * @@ -369,18 +351,4 @@ private function evaluateSuperTypeConfiguration( return $superType; } - - /** - * Helper to throw if the NodeType doesn't exit - */ - private function requireNodeType(string|NodeTypeName $nodeTypeName): NodeType - { - return $this->getNodeType($nodeTypeName) ?? throw new NodeTypeNotFoundException( - sprintf( - 'The node type "%s" is not available', - $nodeTypeName instanceof NodeTypeName ? $nodeTypeName->value : $nodeTypeName - ), - 1316598370 - ); - } } diff --git a/Neos.ContentRepository.Core/Classes/NodeType/TetheredNodeTypeDefinitions.php b/Neos.ContentRepository.Core/Classes/NodeType/TetheredNodeTypeDefinitions.php index 5f8f8a1e682..17ba4edfc28 100644 --- a/Neos.ContentRepository.Core/Classes/NodeType/TetheredNodeTypeDefinitions.php +++ b/Neos.ContentRepository.Core/Classes/NodeType/TetheredNodeTypeDefinitions.php @@ -65,7 +65,7 @@ public function get(NodeName|string $nodeName): ?TetheredNodeTypeDefinition public function getIterator(): \Traversable { - return yield from $this->tetheredNodeTypeDefinitions; + yield from $this->tetheredNodeTypeDefinitions; } /** diff --git a/Neos.ContentRepository.Core/Tests/Unit/NodeType/NodeTypeManagerTest.php b/Neos.ContentRepository.Core/Tests/Unit/NodeType/NodeTypeManagerTest.php index 017274ad619..6eb8fb13a23 100644 --- a/Neos.ContentRepository.Core/Tests/Unit/NodeType/NodeTypeManagerTest.php +++ b/Neos.ContentRepository.Core/Tests/Unit/NodeType/NodeTypeManagerTest.php @@ -433,10 +433,9 @@ public function anInheritedNodeTypePropertyCanBeOverruledWithEmptyArray(): void */ public function getAutoCreatedChildNodesReturnsLowercaseNames() { - $parentNodeTypeName = NodeTypeName::fromString('Neos.ContentRepository.Testing:Page2'); - $autoCreatedChildNodes = $this->nodeTypeManager->getTetheredNodesConfigurationForNodeType($parentNodeTypeName); + $parentNodeType = $this->nodeTypeManager->getNodeType(NodeTypeName::fromString('Neos.ContentRepository.Testing:Page2')); // This is configured as "nodeName" above, but should be normalized to "nodename" - self::assertArrayHasKey('nodename', $autoCreatedChildNodes); + self::assertNotNull($parentNodeType->tetheredNodeTypeDefinitions->contain('nodename')); } /** diff --git a/Neos.ContentRepository.StructureAdjustment/src/Adjustment/TetheredNodeAdjustments.php b/Neos.ContentRepository.StructureAdjustment/src/Adjustment/TetheredNodeAdjustments.php index f58e4bb02f2..c3ce45a2aae 100644 --- a/Neos.ContentRepository.StructureAdjustment/src/Adjustment/TetheredNodeAdjustments.php +++ b/Neos.ContentRepository.StructureAdjustment/src/Adjustment/TetheredNodeAdjustments.php @@ -51,8 +51,6 @@ public function findAdjustmentsForNodeType(NodeTypeName $nodeTypeName): \Generat // In case we cannot find the expected tethered nodes, this fix cannot do anything. return; } - $expectedTetheredNodes = $this->nodeTypeManager->getTetheredNodesConfigurationForNodeType($nodeTypeName); - foreach ($this->projectedNodeIterator->nodeAggregatesOfType($nodeTypeName) as $nodeAggregate) { // find missing tethered nodes $foundMissingOrDisallowedTetheredNodes = false; @@ -63,14 +61,12 @@ public function findAdjustmentsForNodeType(NodeTypeName $nodeTypeName): \Generat : $nodeAggregate->occupiedDimensionSpacePoints; foreach ($originDimensionSpacePoints as $originDimensionSpacePoint) { - foreach ($expectedTetheredNodes as $tetheredNodeName => $expectedTetheredNodeType) { - $tetheredNodeName = NodeName::fromString($tetheredNodeName); - + foreach ($nodeType->tetheredNodeTypeDefinitions as $tetheredNodeTypeDefinition) { $tetheredNode = $this->projectedNodeIterator->contentGraph->getSubgraph( $originDimensionSpacePoint->toDimensionSpacePoint(), VisibilityConstraints::withoutRestrictions() )->findNodeByPath( - $tetheredNodeName, + $tetheredNodeTypeDefinition->name, $nodeAggregate->nodeAggregateId ); if ($tetheredNode === null) { @@ -82,15 +78,14 @@ public function findAdjustmentsForNodeType(NodeTypeName $nodeTypeName): \Generat $originDimensionSpacePoint, $nodeAggregate->nodeAggregateId, StructureAdjustment::TETHERED_NODE_MISSING, - 'The tethered child node "' . $tetheredNodeName->value . '" is missing.', - function () use ($nodeAggregate, $originDimensionSpacePoint, $tetheredNodeName, $expectedTetheredNodeType) { + 'The tethered child node "' . $tetheredNodeTypeDefinition->name->value . '" is missing.', + function () use ($nodeAggregate, $originDimensionSpacePoint, $tetheredNodeTypeDefinition) { $events = $this->createEventsForMissingTetheredNode( $this->projectedNodeIterator->contentGraph, $nodeAggregate, $originDimensionSpacePoint, - $tetheredNodeName, - null, - $expectedTetheredNodeType + $tetheredNodeTypeDefinition, + null ); $streamName = ContentStreamEventStreamName::fromContentStreamId($nodeAggregate->contentStreamId); @@ -103,7 +98,7 @@ function () use ($nodeAggregate, $originDimensionSpacePoint, $tetheredNodeName, ); } else { yield from $this->ensureNodeIsTethered($tetheredNode); - yield from $this->ensureNodeIsOfType($tetheredNode, $expectedTetheredNodeType); + yield from $this->ensureNodeIsOfType($tetheredNode, $tetheredNodeTypeDefinition->nodeTypeName); } } } @@ -114,7 +109,7 @@ function () use ($nodeAggregate, $originDimensionSpacePoint, $tetheredNodeName, ); foreach ($tetheredNodeAggregates as $tetheredNodeAggregate) { assert($tetheredNodeAggregate->nodeName !== null); // it's tethered! - if (!isset($expectedTetheredNodes[$tetheredNodeAggregate->nodeName->value])) { + if (!$nodeType->tetheredNodeTypeDefinitions->contain($tetheredNodeAggregate->nodeName)) { $foundMissingOrDisallowedTetheredNodes = true; yield StructureAdjustment::createForNodeAggregate( $tetheredNodeAggregate, @@ -142,7 +137,7 @@ function () use ($tetheredNodeAggregate) { } } - if (array_keys($actualTetheredChildNodes) !== array_keys($expectedTetheredNodes)) { + if (array_keys($actualTetheredChildNodes) !== array_keys($nodeType->tetheredNodeTypeDefinitions->toArray())) { // we need to re-order: We go from the last to the first yield StructureAdjustment::createForNodeIdentity( $nodeAggregate->contentStreamId, @@ -150,14 +145,14 @@ function () use ($tetheredNodeAggregate) { $nodeAggregate->nodeAggregateId, StructureAdjustment::TETHERED_NODE_WRONGLY_ORDERED, 'Tethered nodes wrongly ordered, expected: ' - . implode(', ', array_keys($expectedTetheredNodes)) + . implode(', ', array_keys($nodeType->tetheredNodeTypeDefinitions->toArray())) . ' - actual: ' . implode(', ', array_keys($actualTetheredChildNodes)), fn () => $this->reorderNodes( $nodeAggregate->contentStreamId, $nodeAggregate->getCoverageByOccupant($originDimensionSpacePoint), $actualTetheredChildNodes, - array_keys($expectedTetheredNodes) + array_keys($nodeType->tetheredNodeTypeDefinitions->toArray()) ) ); } @@ -183,13 +178,13 @@ private function ensureNodeIsTethered(Node $node): \Generator /** * @return \Generator */ - private function ensureNodeIsOfType(Node $node, NodeType $expectedNodeType): \Generator + private function ensureNodeIsOfType(Node $node, NodeTypeName $expectedNodeTypeName): \Generator { - if ($node->nodeTypeName->value !== $expectedNodeType->name->value) { + if ($node->nodeTypeName->value !== $expectedNodeTypeName->value) { yield StructureAdjustment::createForNode( $node, StructureAdjustment::TETHERED_NODE_TYPE_WRONG, - 'should be of type "' . $expectedNodeType->name->value . '", but was "' . $node->nodeTypeName->value . '".' + 'should be of type "' . $expectedNodeTypeName->value . '", but was "' . $node->nodeTypeName->value . '".' ); } } diff --git a/Neos.Neos/Classes/Service/NodeTypeSchemaBuilder.php b/Neos.Neos/Classes/Service/NodeTypeSchemaBuilder.php index 4f6d755a356..a2834140522 100644 --- a/Neos.Neos/Classes/Service/NodeTypeSchemaBuilder.php +++ b/Neos.Neos/Classes/Service/NodeTypeSchemaBuilder.php @@ -109,10 +109,10 @@ protected function generateConstraints() } } - foreach ($this->nodeTypeManager->getTetheredNodesConfigurationForNodeType($nodeType->name) as $key => $_x) { - foreach ($nodeTypes as $innerNodeTypeName => $_y) { - if ($this->nodeTypeManager->isNodeTypeAllowedAsChildToTetheredNode($nodeType->name, NodeName::fromString($key), NodeTypeName::fromString($innerNodeTypeName))) { - $constraints[$nodeTypeName]['childNodes'][$key]['nodeTypes'][$innerNodeTypeName] = true; + foreach ($nodeType->tetheredNodeTypeDefinitions as $tetheredNodeTypeDefinition) { + foreach ($nodeTypes as $innerNodeTypeName => $_x) { + if ($this->nodeTypeManager->isNodeTypeAllowedAsChildToTetheredNode($nodeType->name, $tetheredNodeTypeDefinition->name, NodeTypeName::fromString($innerNodeTypeName))) { + $constraints[$nodeTypeName]['childNodes'][$tetheredNodeTypeDefinition->name->value]['nodeTypes'][$innerNodeTypeName] = true; } } }