From 56ee87fd70732f71cb7e7b7c2fe4498026fd23eb Mon Sep 17 00:00:00 2001 From: mhsdesign <85400359+mhsdesign@users.noreply.github.com> Date: Thu, 16 Nov 2023 13:33:56 +0100 Subject: [PATCH 1/8] !!! TASK: Rename `findChildNodeConnectedThroughEdgeName` to `findChildNodeByNodeName` --- .../src/Domain/Repository/ContentSubgraph.php | 6 +++--- .../src/Domain/Repository/ContentSubhypergraph.php | 8 ++++---- .../Command/CreateNodeAggregateWithNode.php | 2 +- .../Classes/Feature/NodeTypeChange/NodeTypeChange.php | 2 +- .../Command/CreateRootNodeAggregateWithNode.php | 2 +- .../ContentSubgraphWithRuntimeCaches.php | 10 +++++----- .../ContentGraph/ContentSubgraphInterface.php | 4 ++-- .../Classes/Projection/ContentGraph/Node.php | 2 +- .../Classes/FlowQueryOperations/ChildrenOperation.php | 2 +- .../src/Adjustment/TetheredNodeAdjustments.php | 2 +- .../Features/Bootstrap/CRTestSuiteRuntimeVariables.php | 2 +- .../Behavior/Features/Bootstrap/NodeTraversalTrait.php | 2 +- .../Behavior/Features/Bootstrap/ProjectedNodeTrait.php | 2 +- Neos.Neos/Classes/Domain/Service/SiteNodeUtility.php | 2 +- 14 files changed, 24 insertions(+), 24 deletions(-) diff --git a/Neos.ContentGraph.DoctrineDbalAdapter/src/Domain/Repository/ContentSubgraph.php b/Neos.ContentGraph.DoctrineDbalAdapter/src/Domain/Repository/ContentSubgraph.php index 4100d614945..55b0a9d36b1 100644 --- a/Neos.ContentGraph.DoctrineDbalAdapter/src/Domain/Repository/ContentSubgraph.php +++ b/Neos.ContentGraph.DoctrineDbalAdapter/src/Domain/Repository/ContentSubgraph.php @@ -229,7 +229,7 @@ public function findNodeByAbsolutePath(AbsoluteNodePath $path): ?Node : null; } - public function findChildNodeConnectedThroughEdgeName(NodeAggregateId $parentNodeAggregateId, NodeName $edgeName): ?Node + public function findChildNodeByNodeName(NodeAggregateId $parentNodeAggregateId, NodeName $nodeName): ?Node { $queryBuilder = $this->createQueryBuilder() ->select('cn.*, h.name, h.contentstreamid') @@ -239,7 +239,7 @@ public function findChildNodeConnectedThroughEdgeName(NodeAggregateId $parentNod ->where('pn.nodeaggregateid = :parentNodeAggregateId')->setParameter('parentNodeAggregateId', $parentNodeAggregateId->value) ->andWhere('h.contentstreamid = :contentStreamId')->setParameter('contentStreamId', $this->contentStreamId->value) ->andWhere('h.dimensionspacepointhash = :dimensionSpacePointHash')->setParameter('dimensionSpacePointHash', $this->dimensionSpacePoint->hash) - ->andWhere('h.name = :edgeName')->setParameter('edgeName', $edgeName->value); + ->andWhere('h.name = :edgeName')->setParameter('edgeName', $nodeName->value); $this->addRestrictionRelationConstraints($queryBuilder, 'cn'); return $this->fetchNode($queryBuilder); } @@ -473,7 +473,7 @@ private function findNodeByPathFromStartingNode(NodePath $path, Node $startingNo foreach ($path->getParts() as $edgeName) { // id exists here :) - $currentNode = $this->findChildNodeConnectedThroughEdgeName($currentNode->nodeAggregateId, $edgeName); + $currentNode = $this->findChildNodeByNodeName($currentNode->nodeAggregateId, $edgeName); if ($currentNode === null) { return null; } diff --git a/Neos.ContentGraph.PostgreSQLAdapter/src/Domain/Repository/ContentSubhypergraph.php b/Neos.ContentGraph.PostgreSQLAdapter/src/Domain/Repository/ContentSubhypergraph.php index 32705839a97..65a11f84fd3 100644 --- a/Neos.ContentGraph.PostgreSQLAdapter/src/Domain/Repository/ContentSubhypergraph.php +++ b/Neos.ContentGraph.PostgreSQLAdapter/src/Domain/Repository/ContentSubhypergraph.php @@ -287,9 +287,9 @@ public function findNodeByAbsolutePath(AbsoluteNodePath $path): ?Node : null; } - public function findChildNodeConnectedThroughEdgeName( + public function findChildNodeByNodeName( NodeAggregateId $parentNodeAggregateId, - NodeName $edgeName + NodeName $nodeName ): ?Node { $query = HypergraphChildQuery::create( $this->contentStreamId, @@ -298,7 +298,7 @@ public function findChildNodeConnectedThroughEdgeName( ); $query = $query->withDimensionSpacePoint($this->dimensionSpacePoint) ->withRestriction($this->visibilityConstraints) - ->withChildNodeName($edgeName); + ->withChildNodeName($nodeName); $nodeRow = $query->execute($this->getDatabaseConnection())->fetchAssociative(); @@ -519,7 +519,7 @@ private function findNodeByPathFromStartingNode(NodePath $path, Node $startingNo $currentNode = $startingNode; foreach ($path->getParts() as $edgeName) { // id exists here :) - $currentNode = $this->findChildNodeConnectedThroughEdgeName($currentNode->nodeAggregateId, $edgeName); + $currentNode = $this->findChildNodeByNodeName($currentNode->nodeAggregateId, $edgeName); if ($currentNode === null) { return null; } diff --git a/Neos.ContentRepository.Core/Classes/Feature/NodeCreation/Command/CreateNodeAggregateWithNode.php b/Neos.ContentRepository.Core/Classes/Feature/NodeCreation/Command/CreateNodeAggregateWithNode.php index 8f67052dd59..e6c9d382056 100644 --- a/Neos.ContentRepository.Core/Classes/Feature/NodeCreation/Command/CreateNodeAggregateWithNode.php +++ b/Neos.ContentRepository.Core/Classes/Feature/NodeCreation/Command/CreateNodeAggregateWithNode.php @@ -97,7 +97,7 @@ public function withInitialPropertyValues(PropertyValuesToWrite $newInitialPrope * a tethered node aggregate id, you need to generate the child node aggregate ids in advance. * * _Alternatively you would need to fetch the created tethered node first from the subgraph. - * {@see ContentSubgraphInterface::findChildNodeConnectedThroughEdgeName()}_ + * {@see ContentSubgraphInterface::findChildNodeByNodeName()}_ * * The helper method {@see NodeAggregateIdsByNodePaths::createForNodeType()} will generate recursively * node aggregate ids for every tethered child node: diff --git a/Neos.ContentRepository.Core/Classes/Feature/NodeTypeChange/NodeTypeChange.php b/Neos.ContentRepository.Core/Classes/Feature/NodeTypeChange/NodeTypeChange.php index 0f68cba7042..1bd6a00b316 100644 --- a/Neos.ContentRepository.Core/Classes/Feature/NodeTypeChange/NodeTypeChange.php +++ b/Neos.ContentRepository.Core/Classes/Feature/NodeTypeChange/NodeTypeChange.php @@ -197,7 +197,7 @@ private function handleChangeNodeAggregateType( $node->originDimensionSpacePoint->toDimensionSpacePoint(), VisibilityConstraints::withoutRestrictions() ); - $tetheredNode = $subgraph->findChildNodeConnectedThroughEdgeName( + $tetheredNode = $subgraph->findChildNodeByNodeName( $node->nodeAggregateId, $tetheredNodeName ); diff --git a/Neos.ContentRepository.Core/Classes/Feature/RootNodeCreation/Command/CreateRootNodeAggregateWithNode.php b/Neos.ContentRepository.Core/Classes/Feature/RootNodeCreation/Command/CreateRootNodeAggregateWithNode.php index 0e2ceab99de..54fda72a946 100644 --- a/Neos.ContentRepository.Core/Classes/Feature/RootNodeCreation/Command/CreateRootNodeAggregateWithNode.php +++ b/Neos.ContentRepository.Core/Classes/Feature/RootNodeCreation/Command/CreateRootNodeAggregateWithNode.php @@ -70,7 +70,7 @@ public static function create(ContentStreamId $contentStreamId, NodeAggregateId * a tethered node aggregate id, you need to generate the child node aggregate ids in advance. * * _Alternatively you would need to fetch the created tethered node first from the subgraph. - * {@see ContentSubgraphInterface::findChildNodeConnectedThroughEdgeName()}_ + * {@see ContentSubgraphInterface::findChildNodeByNodeName()}_ * * The helper method {@see NodeAggregateIdsByNodePaths::createForNodeType()} will generate recursively * node aggregate ids for every tethered child node: diff --git a/Neos.ContentRepository.Core/Classes/Projection/ContentGraph/ContentGraphWithRuntimeCaches/ContentSubgraphWithRuntimeCaches.php b/Neos.ContentRepository.Core/Classes/Projection/ContentGraph/ContentGraphWithRuntimeCaches/ContentSubgraphWithRuntimeCaches.php index 7660d7c154d..7d572302090 100644 --- a/Neos.ContentRepository.Core/Classes/Projection/ContentGraph/ContentGraphWithRuntimeCaches/ContentSubgraphWithRuntimeCaches.php +++ b/Neos.ContentRepository.Core/Classes/Projection/ContentGraph/ContentGraphWithRuntimeCaches/ContentSubgraphWithRuntimeCaches.php @@ -175,17 +175,17 @@ public function findNodeByAbsolutePath(AbsoluteNodePath $path): ?Node return $this->wrappedContentSubgraph->findNodeByAbsolutePath($path); } - public function findChildNodeConnectedThroughEdgeName(NodeAggregateId $parentNodeAggregateId, NodeName $edgeName): ?Node + public function findChildNodeByNodeName(NodeAggregateId $parentNodeAggregateId, NodeName $nodeName): ?Node { $namedChildNodeCache = $this->inMemoryCache->getNamedChildNodeByNodeIdCache(); - if ($namedChildNodeCache->contains($parentNodeAggregateId, $edgeName)) { - return $namedChildNodeCache->get($parentNodeAggregateId, $edgeName); + if ($namedChildNodeCache->contains($parentNodeAggregateId, $nodeName)) { + return $namedChildNodeCache->get($parentNodeAggregateId, $nodeName); } - $node = $this->wrappedContentSubgraph->findChildNodeConnectedThroughEdgeName($parentNodeAggregateId, $edgeName); + $node = $this->wrappedContentSubgraph->findChildNodeByNodeName($parentNodeAggregateId, $nodeName); if ($node === null) { return null; } - $namedChildNodeCache->add($parentNodeAggregateId, $edgeName, $node); + $namedChildNodeCache->add($parentNodeAggregateId, $nodeName, $node); $this->inMemoryCache->getNodeByNodeAggregateIdCache()->add($node->nodeAggregateId, $node); return $node; } diff --git a/Neos.ContentRepository.Core/Classes/Projection/ContentGraph/ContentSubgraphInterface.php b/Neos.ContentRepository.Core/Classes/Projection/ContentGraph/ContentSubgraphInterface.php index 5f65fb6a0f1..84422e63831 100644 --- a/Neos.ContentRepository.Core/Classes/Projection/ContentGraph/ContentSubgraphInterface.php +++ b/Neos.ContentRepository.Core/Classes/Projection/ContentGraph/ContentSubgraphInterface.php @@ -103,9 +103,9 @@ public function findPrecedingSiblingNodes(NodeAggregateId $siblingNodeAggregateI /** * Find a single child node by its name * - * @return Node|null the node that is connected to its parent with the specified $edgeName, or NULL if no matching node exists or the parent node is not accessible + * @return Node|null the node that is connected to its parent with the specified $nodeName, or NULL if no matching node exists or the parent node is not accessible */ - public function findChildNodeConnectedThroughEdgeName(NodeAggregateId $parentNodeAggregateId, NodeName $edgeName): ?Node; + public function findChildNodeByNodeName(NodeAggregateId $parentNodeAggregateId, NodeName $nodeName): ?Node; /** * Recursively find all nodes above the $entryNodeAggregateId that match the specified $filter and return them as a flat list diff --git a/Neos.ContentRepository.Core/Classes/Projection/ContentGraph/Node.php b/Neos.ContentRepository.Core/Classes/Projection/ContentGraph/Node.php index d29f4191ec9..bc227090293 100644 --- a/Neos.ContentRepository.Core/Classes/Projection/ContentGraph/Node.php +++ b/Neos.ContentRepository.Core/Classes/Projection/ContentGraph/Node.php @@ -44,7 +44,7 @@ * @param NodeTypeName $nodeTypeName The node's node type name; always set, even if unknown to the NodeTypeManager * @param NodeType|null $nodeType The node's node type, null if unknown to the NodeTypeManager - @deprecated Don't rely on this too much, as the capabilities of the NodeType here will probably change a lot; Ask the {@see NodeTypeManager} instead * @param PropertyCollection $properties All properties of this node. References are NOT part of this API; To access references, {@see ContentSubgraphInterface::findReferences()} can be used; To read the serialized properties, call properties->serialized(). - * @param NodeName|null $nodeName The optional name of this node {@see ContentSubgraphInterface::findChildNodeConnectedThroughEdgeName()} + * @param NodeName|null $nodeName The optional name of this node {@see ContentSubgraphInterface::findChildNodeByNodeName()} * @param Timestamps $timestamps Creation and modification timestamps of this node */ private function __construct( diff --git a/Neos.ContentRepository.NodeAccess/Classes/FlowQueryOperations/ChildrenOperation.php b/Neos.ContentRepository.NodeAccess/Classes/FlowQueryOperations/ChildrenOperation.php index c9bfd37be60..d2263ed2aa7 100644 --- a/Neos.ContentRepository.NodeAccess/Classes/FlowQueryOperations/ChildrenOperation.php +++ b/Neos.ContentRepository.NodeAccess/Classes/FlowQueryOperations/ChildrenOperation.php @@ -143,7 +143,7 @@ protected function earlyOptimizationOfFilters(FlowQuery $flowQuery, array $parse $resolvedNode = $contextNode; while (($nodePathSegment = array_shift($currentPathSegments)) && !is_null($resolvedNode)) { $resolvedNode = $this->contentRepositoryRegistry->subgraphForNode($resolvedNode) - ->findChildNodeConnectedThroughEdgeName( + ->findChildNodeByNodeName( $resolvedNode->nodeAggregateId, NodeName::fromString($nodePathSegment) ); diff --git a/Neos.ContentRepository.StructureAdjustment/src/Adjustment/TetheredNodeAdjustments.php b/Neos.ContentRepository.StructureAdjustment/src/Adjustment/TetheredNodeAdjustments.php index 2883857ff9b..6bfe6cd82aa 100644 --- a/Neos.ContentRepository.StructureAdjustment/src/Adjustment/TetheredNodeAdjustments.php +++ b/Neos.ContentRepository.StructureAdjustment/src/Adjustment/TetheredNodeAdjustments.php @@ -73,7 +73,7 @@ public function findAdjustmentsForNodeType(NodeTypeName $nodeTypeName): \Generat $originDimensionSpacePoint->toDimensionSpacePoint(), VisibilityConstraints::withoutRestrictions() ); - $tetheredNode = $subgraph->findChildNodeConnectedThroughEdgeName( + $tetheredNode = $subgraph->findChildNodeByNodeName( $nodeAggregate->nodeAggregateId, $tetheredNodeName ); diff --git a/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/CRTestSuiteRuntimeVariables.php b/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/CRTestSuiteRuntimeVariables.php index 6013ed435f0..ec0c5d2b864 100644 --- a/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/CRTestSuiteRuntimeVariables.php +++ b/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/CRTestSuiteRuntimeVariables.php @@ -161,7 +161,7 @@ public function getCurrentSubgraph(): ContentSubgraphInterface */ public function iRememberNodeAggregateIdOfNodesChildAs(string $parentNodeAggregateId, string $childNodeName, string $indexName): void { - $this->rememberedNodeAggregateIds[$indexName] = $this->getCurrentSubgraph()->findChildNodeConnectedThroughEdgeName( + $this->rememberedNodeAggregateIds[$indexName] = $this->getCurrentSubgraph()->findChildNodeByNodeName( NodeAggregateId::fromString($parentNodeAggregateId), NodeName::fromString($childNodeName) )->nodeAggregateId; diff --git a/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/NodeTraversalTrait.php b/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/NodeTraversalTrait.php index 1e0323c69d2..2f1465e03ba 100644 --- a/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/NodeTraversalTrait.php +++ b/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/NodeTraversalTrait.php @@ -166,7 +166,7 @@ public function iExecuteTheFindChildNodeConnectedThroughEdgeNameQueryIExpectTheF $edgeName = NodeName::fromString($edgeNameSerialized); $expectedNodeAggregateId = $expectedNodeIdSerialized !== null ? NodeAggregateId::fromString($expectedNodeIdSerialized) : null; - $actualNode = $this->getCurrentSubgraph()->findChildNodeConnectedThroughEdgeName($parentNodeAggregateId, $edgeName); + $actualNode = $this->getCurrentSubgraph()->findChildNodeByNodeName($parentNodeAggregateId, $edgeName); Assert::assertSame($actualNode?->nodeAggregateId->value, $expectedNodeAggregateId?->value); } diff --git a/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/ProjectedNodeTrait.php b/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/ProjectedNodeTrait.php index e0abd0e1d3c..f7552da7c89 100644 --- a/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/ProjectedNodeTrait.php +++ b/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/ProjectedNodeTrait.php @@ -456,7 +456,7 @@ public function iExpectThisNodeToBeTheChildOfNode(string $serializedParentNodeDi Assert::assertTrue($expectedParentDiscriminator->equals($actualParentDiscriminator), 'Parent discriminator does not match. Expected was ' . json_encode($expectedParentDiscriminator) . ', given was ' . json_encode($actualParentDiscriminator)); $expectedChildDiscriminator = NodeDiscriminator::fromNode($currentNode); - $child = $subgraph->findChildNodeConnectedThroughEdgeName($parent->nodeAggregateId, $currentNode->nodeName); + $child = $subgraph->findChildNodeByNodeName($parent->nodeAggregateId, $currentNode->nodeName); $actualChildDiscriminator = NodeDiscriminator::fromNode($child); Assert::assertTrue($expectedChildDiscriminator->equals($actualChildDiscriminator), 'Child discriminator does not match. Expected was ' . json_encode($expectedChildDiscriminator) . ', given was ' . json_encode($actualChildDiscriminator)); }); diff --git a/Neos.Neos/Classes/Domain/Service/SiteNodeUtility.php b/Neos.Neos/Classes/Domain/Service/SiteNodeUtility.php index a93df26f963..e58e686b1c1 100644 --- a/Neos.Neos/Classes/Domain/Service/SiteNodeUtility.php +++ b/Neos.Neos/Classes/Domain/Service/SiteNodeUtility.php @@ -75,7 +75,7 @@ public function findSiteNodeBySite( ); $rootNode = $rootNodeAggregate->getNodeByCoveredDimensionSpacePoint($dimensionSpacePoint); - $siteNode = $subgraph->findChildNodeConnectedThroughEdgeName( + $siteNode = $subgraph->findChildNodeByNodeName( $rootNode->nodeAggregateId, $site->getNodeName()->toNodeName() ); From 68f086278c3565183a3dda1ff2138f8978d1c578 Mon Sep 17 00:00:00 2001 From: mhsdesign <85400359+mhsdesign@users.noreply.github.com> Date: Thu, 16 Nov 2023 13:39:52 +0100 Subject: [PATCH 2/8] TASK: String replace `findChildNodeConnectedThroughEdgeName` to `findChildNodeByNodeName` in tests --- ...dChildNodeConnectedThroughEdgeName.feature | 20 +++++++++---------- .../Features/Bootstrap/NodeTraversalTrait.php | 6 +++--- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/NodeTraversal/FindChildNodeConnectedThroughEdgeName.feature b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/NodeTraversal/FindChildNodeConnectedThroughEdgeName.feature index 67898ef2130..92e68a70c05 100644 --- a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/NodeTraversal/FindChildNodeConnectedThroughEdgeName.feature +++ b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/NodeTraversal/FindChildNodeConnectedThroughEdgeName.feature @@ -1,5 +1,5 @@ @contentrepository @adapters=DoctrineDBAL,Postgres -Feature: Find nodes using the findChildNodeConnectedThroughEdgeName query +Feature: Find nodes using the findChildNodeByNodeName query Background: Given using the following content dimensions: @@ -88,15 +88,15 @@ Feature: Find nodes using the findChildNodeConnectedThroughEdgeName query And the graph projection is fully up to date Scenario: - # findChildNodeConnectedThroughEdgeName queries without results - When I execute the findChildNodeConnectedThroughEdgeName query for parent node aggregate id "non-existing" and edge name "non-existing" I expect no node to be returned - When I execute the findChildNodeConnectedThroughEdgeName query for parent node aggregate id "home" and edge name "non-existing" I expect no node to be returned - When I execute the findChildNodeConnectedThroughEdgeName query for parent node aggregate id "non-existing" and edge name "home" I expect no node to be returned + # findChildNodeByNodeName queries without results + When I execute the findChildNodeByNodeName query for parent node aggregate id "non-existing" and edge name "non-existing" I expect no node to be returned + When I execute the findChildNodeByNodeName query for parent node aggregate id "home" and edge name "non-existing" I expect no node to be returned + When I execute the findChildNodeByNodeName query for parent node aggregate id "non-existing" and edge name "home" I expect no node to be returned # node "a2a2" is disabled and should not be returned - When I execute the findChildNodeConnectedThroughEdgeName query for parent node aggregate id "a2a" and edge name "a2a2" I expect no node to be returned + When I execute the findChildNodeByNodeName query for parent node aggregate id "a2a" and edge name "a2a2" I expect no node to be returned # node "a2a2" is disabled and should not lead to results if specified as parent node id - When I execute the findChildNodeConnectedThroughEdgeName query for parent node aggregate id "a2a2" and edge name "a2a2a" I expect no node to be returned + When I execute the findChildNodeByNodeName query for parent node aggregate id "a2a2" and edge name "a2a2a" I expect no node to be returned - # findChildNodeConnectedThroughEdgeName queries with results - When I execute the findChildNodeConnectedThroughEdgeName query for parent node aggregate id "home" and edge name "contact" I expect the node "contact" to be returned - When I execute the findChildNodeConnectedThroughEdgeName query for parent node aggregate id "a2a" and edge name "a2a1" I expect the node "a2a1" to be returned + # findChildNodeByNodeName queries with results + When I execute the findChildNodeByNodeName query for parent node aggregate id "home" and edge name "contact" I expect the node "contact" to be returned + When I execute the findChildNodeByNodeName query for parent node aggregate id "a2a" and edge name "a2a1" I expect the node "a2a1" to be returned diff --git a/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/NodeTraversalTrait.php b/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/NodeTraversalTrait.php index 2f1465e03ba..493b40ebea7 100644 --- a/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/NodeTraversalTrait.php +++ b/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/NodeTraversalTrait.php @@ -157,10 +157,10 @@ public function iExecuteTheFindNodeByAbsolutePathQueryIExpectTheFollowingNodes(s } /** - * @When I execute the findChildNodeConnectedThroughEdgeName query for parent node aggregate id :parentNodeIdSerialized and edge name :edgeNameSerialized I expect no node to be returned - * @When I execute the findChildNodeConnectedThroughEdgeName query for parent node aggregate id :parentNodeIdSerialized and edge name :edgeNameSerialized I expect the node :expectedNodeIdSerialized to be returned + * @When I execute the findChildNodeByNodeName query for parent node aggregate id :parentNodeIdSerialized and edge name :edgeNameSerialized I expect no node to be returned + * @When I execute the findChildNodeByNodeName query for parent node aggregate id :parentNodeIdSerialized and edge name :edgeNameSerialized I expect the node :expectedNodeIdSerialized to be returned */ - public function iExecuteTheFindChildNodeConnectedThroughEdgeNameQueryIExpectTheFollowingNodes(string $parentNodeIdSerialized, string $edgeNameSerialized, string $expectedNodeIdSerialized = null): void + public function iExecuteTheFindChildNodeByNodeNameQueryIExpectTheFollowingNodes(string $parentNodeIdSerialized, string $edgeNameSerialized, string $expectedNodeIdSerialized = null): void { $parentNodeAggregateId = NodeAggregateId::fromString($parentNodeIdSerialized); $edgeName = NodeName::fromString($edgeNameSerialized); From 139c60743aa3c73684d420e0e7313038016bb127 Mon Sep 17 00:00:00 2001 From: mhsdesign <85400359+mhsdesign@users.noreply.github.com> Date: Fri, 17 Nov 2023 23:57:57 +0100 Subject: [PATCH 3/8] TASK: Replace `findChildNodeConnectedThroughEdgeName` with `findNodeByPath` --- .../src/Domain/Repository/ContentSubgraph.php | 5 ++--- .../src/Domain/Repository/ContentSubhypergraph.php | 2 +- .../Feature/NodeTypeChange/NodeTypeChange.php | 6 +++--- .../FlowQueryOperations/ChildrenOperation.php | 14 +++++--------- .../src/Adjustment/TetheredNodeAdjustments.php | 5 +++-- .../Bootstrap/CRTestSuiteRuntimeVariables.php | 5 +++-- .../Features/Bootstrap/NodeTraversalTrait.php | 2 +- .../Features/Bootstrap/ProjectedNodeTrait.php | 2 +- .../Classes/Domain/Service/SiteNodeUtility.php | 7 ++++--- 9 files changed, 23 insertions(+), 25 deletions(-) diff --git a/Neos.ContentGraph.DoctrineDbalAdapter/src/Domain/Repository/ContentSubgraph.php b/Neos.ContentGraph.DoctrineDbalAdapter/src/Domain/Repository/ContentSubgraph.php index 55b0a9d36b1..747a627c08d 100644 --- a/Neos.ContentGraph.DoctrineDbalAdapter/src/Domain/Repository/ContentSubgraph.php +++ b/Neos.ContentGraph.DoctrineDbalAdapter/src/Domain/Repository/ContentSubgraph.php @@ -229,7 +229,7 @@ public function findNodeByAbsolutePath(AbsoluteNodePath $path): ?Node : null; } - public function findChildNodeByNodeName(NodeAggregateId $parentNodeAggregateId, NodeName $nodeName): ?Node + private function findChildNodeConnectedThroughEdgeName(NodeAggregateId $parentNodeAggregateId, NodeName $nodeName): ?Node { $queryBuilder = $this->createQueryBuilder() ->select('cn.*, h.name, h.contentstreamid') @@ -472,8 +472,7 @@ private function findNodeByPathFromStartingNode(NodePath $path, Node $startingNo $currentNode = $startingNode; foreach ($path->getParts() as $edgeName) { - // id exists here :) - $currentNode = $this->findChildNodeByNodeName($currentNode->nodeAggregateId, $edgeName); + $currentNode = $this->findChildNodeConnectedThroughEdgeName($currentNode->nodeAggregateId, $edgeName); if ($currentNode === null) { return null; } diff --git a/Neos.ContentGraph.PostgreSQLAdapter/src/Domain/Repository/ContentSubhypergraph.php b/Neos.ContentGraph.PostgreSQLAdapter/src/Domain/Repository/ContentSubhypergraph.php index 65a11f84fd3..22e11906c46 100644 --- a/Neos.ContentGraph.PostgreSQLAdapter/src/Domain/Repository/ContentSubhypergraph.php +++ b/Neos.ContentGraph.PostgreSQLAdapter/src/Domain/Repository/ContentSubhypergraph.php @@ -287,7 +287,7 @@ public function findNodeByAbsolutePath(AbsoluteNodePath $path): ?Node : null; } - public function findChildNodeByNodeName( + private function findChildNodeConnectedThroughEdgeName( NodeAggregateId $parentNodeAggregateId, NodeName $nodeName ): ?Node { diff --git a/Neos.ContentRepository.Core/Classes/Feature/NodeTypeChange/NodeTypeChange.php b/Neos.ContentRepository.Core/Classes/Feature/NodeTypeChange/NodeTypeChange.php index 1bd6a00b316..5a89e670ca6 100644 --- a/Neos.ContentRepository.Core/Classes/Feature/NodeTypeChange/NodeTypeChange.php +++ b/Neos.ContentRepository.Core/Classes/Feature/NodeTypeChange/NodeTypeChange.php @@ -197,9 +197,9 @@ private function handleChangeNodeAggregateType( $node->originDimensionSpacePoint->toDimensionSpacePoint(), VisibilityConstraints::withoutRestrictions() ); - $tetheredNode = $subgraph->findChildNodeByNodeName( - $node->nodeAggregateId, - $tetheredNodeName + $tetheredNode = $subgraph->findNodeByPath( + NodePath::fromNodeNames($tetheredNodeName), + $node->nodeAggregateId ); if ($tetheredNode === null) { $tetheredNodeAggregateId = $command->tetheredDescendantNodeAggregateIds diff --git a/Neos.ContentRepository.NodeAccess/Classes/FlowQueryOperations/ChildrenOperation.php b/Neos.ContentRepository.NodeAccess/Classes/FlowQueryOperations/ChildrenOperation.php index d2263ed2aa7..cce0d558a0a 100644 --- a/Neos.ContentRepository.NodeAccess/Classes/FlowQueryOperations/ChildrenOperation.php +++ b/Neos.ContentRepository.NodeAccess/Classes/FlowQueryOperations/ChildrenOperation.php @@ -12,6 +12,7 @@ */ use Neos\ContentRepository\Core\Projection\ContentGraph\Filter\FindChildNodesFilter; +use Neos\ContentRepository\Core\Projection\ContentGraph\NodePath; use Neos\ContentRepository\Core\SharedModel\Node\NodeName; use Neos\ContentRepository\Core\Projection\ContentGraph\Filter\NodeType\NodeTypeCriteria; use Neos\ContentRepository\Core\NodeType\NodeTypeNames; @@ -136,18 +137,13 @@ protected function earlyOptimizationOfFilters(FlowQuery $flowQuery, array $parse // Optimize property name filter if present if (isset($filter['PropertyNameFilter']) || isset($filter['PathFilter'])) { $nodePath = $filter['PropertyNameFilter'] ?? $filter['PathFilter']; - $nodePathSegments = explode('/', $nodePath); /** @var Node $contextNode */ foreach ($flowQuery->getContext() as $contextNode) { - $currentPathSegments = $nodePathSegments; - $resolvedNode = $contextNode; - while (($nodePathSegment = array_shift($currentPathSegments)) && !is_null($resolvedNode)) { - $resolvedNode = $this->contentRepositoryRegistry->subgraphForNode($resolvedNode) - ->findChildNodeByNodeName( - $resolvedNode->nodeAggregateId, - NodeName::fromString($nodePathSegment) + $resolvedNode = $this->contentRepositoryRegistry->subgraphForNode($contextNode) + ->findNodeByPath( + NodePath::fromString($nodePath), + $contextNode->nodeAggregateId, ); - } if (!is_null($resolvedNode) && !isset($filteredOutputNodeIdentifiers[ $resolvedNode->nodeAggregateId->value diff --git a/Neos.ContentRepository.StructureAdjustment/src/Adjustment/TetheredNodeAdjustments.php b/Neos.ContentRepository.StructureAdjustment/src/Adjustment/TetheredNodeAdjustments.php index 6bfe6cd82aa..fda50ee2891 100644 --- a/Neos.ContentRepository.StructureAdjustment/src/Adjustment/TetheredNodeAdjustments.php +++ b/Neos.ContentRepository.StructureAdjustment/src/Adjustment/TetheredNodeAdjustments.php @@ -11,6 +11,7 @@ use Neos\ContentRepository\Core\Feature\NodeMove\Dto\CoverageNodeMoveMappings; use Neos\ContentRepository\Core\Projection\ContentGraph\Filter\FindChildNodesFilter; use Neos\ContentRepository\Core\Projection\ContentGraph\NodeAggregate; +use Neos\ContentRepository\Core\Projection\ContentGraph\NodePath; use Neos\ContentRepository\Core\SharedModel\Node\NodeAggregateId; use Neos\ContentRepository\Core\SharedModel\Workspace\ContentStreamId; use Neos\ContentRepository\Core\Feature\NodeMove\Event\NodeAggregateWasMoved; @@ -73,9 +74,9 @@ public function findAdjustmentsForNodeType(NodeTypeName $nodeTypeName): \Generat $originDimensionSpacePoint->toDimensionSpacePoint(), VisibilityConstraints::withoutRestrictions() ); - $tetheredNode = $subgraph->findChildNodeByNodeName( + $tetheredNode = $subgraph->findNodeByPath( + NodePath::fromNodeNames($tetheredNodeName), $nodeAggregate->nodeAggregateId, - $tetheredNodeName ); if ($tetheredNode === null) { $foundMissingOrDisallowedTetheredNodes = true; diff --git a/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/CRTestSuiteRuntimeVariables.php b/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/CRTestSuiteRuntimeVariables.php index ec0c5d2b864..b4e6246665b 100644 --- a/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/CRTestSuiteRuntimeVariables.php +++ b/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/CRTestSuiteRuntimeVariables.php @@ -21,6 +21,7 @@ use Neos\ContentRepository\Core\Projection\ContentGraph\ContentSubgraphInterface; use Neos\ContentRepository\Core\Projection\ContentGraph\Node; use Neos\ContentRepository\Core\Projection\ContentGraph\NodeAggregate; +use Neos\ContentRepository\Core\Projection\ContentGraph\NodePath; use Neos\ContentRepository\Core\Projection\ContentGraph\VisibilityConstraints; use Neos\ContentRepository\Core\SharedModel\Node\NodeName; use Neos\ContentRepository\Core\SharedModel\User\UserId; @@ -161,9 +162,9 @@ public function getCurrentSubgraph(): ContentSubgraphInterface */ public function iRememberNodeAggregateIdOfNodesChildAs(string $parentNodeAggregateId, string $childNodeName, string $indexName): void { - $this->rememberedNodeAggregateIds[$indexName] = $this->getCurrentSubgraph()->findChildNodeByNodeName( + $this->rememberedNodeAggregateIds[$indexName] = $this->getCurrentSubgraph()->findNodeByPath( + NodePath::fromString($childNodeName), NodeAggregateId::fromString($parentNodeAggregateId), - NodeName::fromString($childNodeName) )->nodeAggregateId; } diff --git a/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/NodeTraversalTrait.php b/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/NodeTraversalTrait.php index 493b40ebea7..96b94004e02 100644 --- a/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/NodeTraversalTrait.php +++ b/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/NodeTraversalTrait.php @@ -166,7 +166,7 @@ public function iExecuteTheFindChildNodeByNodeNameQueryIExpectTheFollowingNodes( $edgeName = NodeName::fromString($edgeNameSerialized); $expectedNodeAggregateId = $expectedNodeIdSerialized !== null ? NodeAggregateId::fromString($expectedNodeIdSerialized) : null; - $actualNode = $this->getCurrentSubgraph()->findChildNodeByNodeName($parentNodeAggregateId, $edgeName); + $actualNode = $this->getCurrentSubgraph()->findNodeByPath(NodePath::fromNodeNames($edgeName), $parentNodeAggregateId); Assert::assertSame($actualNode?->nodeAggregateId->value, $expectedNodeAggregateId?->value); } diff --git a/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/ProjectedNodeTrait.php b/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/ProjectedNodeTrait.php index f7552da7c89..27bbb983e95 100644 --- a/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/ProjectedNodeTrait.php +++ b/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/ProjectedNodeTrait.php @@ -456,7 +456,7 @@ public function iExpectThisNodeToBeTheChildOfNode(string $serializedParentNodeDi Assert::assertTrue($expectedParentDiscriminator->equals($actualParentDiscriminator), 'Parent discriminator does not match. Expected was ' . json_encode($expectedParentDiscriminator) . ', given was ' . json_encode($actualParentDiscriminator)); $expectedChildDiscriminator = NodeDiscriminator::fromNode($currentNode); - $child = $subgraph->findChildNodeByNodeName($parent->nodeAggregateId, $currentNode->nodeName); + $child = $subgraph->findNodeByPath(NodePath::fromNodeNames($currentNode->nodeName), $parent->nodeAggregateId); $actualChildDiscriminator = NodeDiscriminator::fromNode($child); Assert::assertTrue($expectedChildDiscriminator->equals($actualChildDiscriminator), 'Child discriminator does not match. Expected was ' . json_encode($expectedChildDiscriminator) . ', given was ' . json_encode($actualChildDiscriminator)); }); diff --git a/Neos.Neos/Classes/Domain/Service/SiteNodeUtility.php b/Neos.Neos/Classes/Domain/Service/SiteNodeUtility.php index e58e686b1c1..076d6d93043 100644 --- a/Neos.Neos/Classes/Domain/Service/SiteNodeUtility.php +++ b/Neos.Neos/Classes/Domain/Service/SiteNodeUtility.php @@ -17,6 +17,7 @@ use Neos\ContentRepository\Core\DimensionSpace\DimensionSpacePoint; use Neos\ContentRepository\Core\Projection\ContentGraph\Node; +use Neos\ContentRepository\Core\Projection\ContentGraph\NodePath; use Neos\ContentRepository\Core\Projection\ContentGraph\VisibilityConstraints; use Neos\ContentRepository\Core\SharedModel\Workspace\ContentStreamId; use Neos\ContentRepositoryRegistry\ContentRepositoryRegistry; @@ -75,9 +76,9 @@ public function findSiteNodeBySite( ); $rootNode = $rootNodeAggregate->getNodeByCoveredDimensionSpacePoint($dimensionSpacePoint); - $siteNode = $subgraph->findChildNodeByNodeName( - $rootNode->nodeAggregateId, - $site->getNodeName()->toNodeName() + $siteNode = $subgraph->findNodeByPath( + NodePath::fromNodeNames($site->getNodeName()->toNodeName()), + $rootNode->nodeAggregateId ); if (!$siteNode) { From 53bc7d32cdc5a8cfaefb19163aa957bf86626312 Mon Sep 17 00:00:00 2001 From: mhsdesign <85400359+mhsdesign@users.noreply.github.com> Date: Sat, 18 Nov 2023 12:43:38 +0100 Subject: [PATCH 4/8] TASK: Remove `findChildNodeConnectedThroughEdgeName` correctly and add runtime cache for `findNodeByPath` --- .../src/Domain/Repository/ContentSubgraph.php | 5 +++ .../Repository/ContentSubhypergraph.php | 2 +- .../ContentSubgraphWithRuntimeCaches.php | 35 +++++++++++++++---- .../ContentGraph/ContentSubgraphInterface.php | 7 ---- 4 files changed, 35 insertions(+), 14 deletions(-) diff --git a/Neos.ContentGraph.DoctrineDbalAdapter/src/Domain/Repository/ContentSubgraph.php b/Neos.ContentGraph.DoctrineDbalAdapter/src/Domain/Repository/ContentSubgraph.php index 747a627c08d..295895505ab 100644 --- a/Neos.ContentGraph.DoctrineDbalAdapter/src/Domain/Repository/ContentSubgraph.php +++ b/Neos.ContentGraph.DoctrineDbalAdapter/src/Domain/Repository/ContentSubgraph.php @@ -229,6 +229,11 @@ public function findNodeByAbsolutePath(AbsoluteNodePath $path): ?Node : null; } + /** + * Find a single child node by its name + * + * @return Node|null the node that is connected to its parent with the specified $nodeName, or NULL if no matching node exists or the parent node is not accessible + */ private function findChildNodeConnectedThroughEdgeName(NodeAggregateId $parentNodeAggregateId, NodeName $nodeName): ?Node { $queryBuilder = $this->createQueryBuilder() diff --git a/Neos.ContentGraph.PostgreSQLAdapter/src/Domain/Repository/ContentSubhypergraph.php b/Neos.ContentGraph.PostgreSQLAdapter/src/Domain/Repository/ContentSubhypergraph.php index 22e11906c46..57ce5ccf93c 100644 --- a/Neos.ContentGraph.PostgreSQLAdapter/src/Domain/Repository/ContentSubhypergraph.php +++ b/Neos.ContentGraph.PostgreSQLAdapter/src/Domain/Repository/ContentSubhypergraph.php @@ -519,7 +519,7 @@ private function findNodeByPathFromStartingNode(NodePath $path, Node $startingNo $currentNode = $startingNode; foreach ($path->getParts() as $edgeName) { // id exists here :) - $currentNode = $this->findChildNodeByNodeName($currentNode->nodeAggregateId, $edgeName); + $currentNode = $this->findChildNodeConnectedThroughEdgeName($currentNode->nodeAggregateId, $edgeName); if ($currentNode === null) { return null; } diff --git a/Neos.ContentRepository.Core/Classes/Projection/ContentGraph/ContentGraphWithRuntimeCaches/ContentSubgraphWithRuntimeCaches.php b/Neos.ContentRepository.Core/Classes/Projection/ContentGraph/ContentGraphWithRuntimeCaches/ContentSubgraphWithRuntimeCaches.php index 7d572302090..c3c82e5e609 100644 --- a/Neos.ContentRepository.Core/Classes/Projection/ContentGraph/ContentGraphWithRuntimeCaches/ContentSubgraphWithRuntimeCaches.php +++ b/Neos.ContentRepository.Core/Classes/Projection/ContentGraph/ContentGraphWithRuntimeCaches/ContentSubgraphWithRuntimeCaches.php @@ -165,23 +165,46 @@ public function findParentNode(NodeAggregateId $childNodeAggregateId): ?Node public function findNodeByPath(NodePath $path, NodeAggregateId $startingNodeAggregateId): ?Node { - // TODO implement runtime caches - return $this->wrappedContentSubgraph->findNodeByPath($path, $startingNodeAggregateId); + // this implementation is copied from the DoctrineAdapter to make it cache-able + $startingNode = $this->findNodeById($startingNodeAggregateId); + + return $startingNode + ? $this->findNodeByPathFromStartingNode($path, $startingNode) + : null; } public function findNodeByAbsolutePath(AbsoluteNodePath $path): ?Node { - // TODO implement runtime caches - return $this->wrappedContentSubgraph->findNodeByAbsolutePath($path); + // this implementation is copied from the DoctrineAdapter to make it cache-able + $startingNode = $this->findRootNodeByType($path->rootNodeTypeName); + + return $startingNode + ? $this->findNodeByPathFromStartingNode($path->path, $startingNode) + : null; + } + + private function findNodeByPathFromStartingNode(NodePath $path, Node $startingNode): ?Node + { + $currentNode = $startingNode; + + foreach ($path->getParts() as $edgeName) { + $currentNode = $this->findChildNodeConnectedThroughEdgeName($currentNode->nodeAggregateId, $edgeName); + if ($currentNode === null) { + return null; + } + } + return $currentNode; } - public function findChildNodeByNodeName(NodeAggregateId $parentNodeAggregateId, NodeName $nodeName): ?Node + private function findChildNodeConnectedThroughEdgeName(NodeAggregateId $parentNodeAggregateId, NodeName $nodeName): ?Node { $namedChildNodeCache = $this->inMemoryCache->getNamedChildNodeByNodeIdCache(); if ($namedChildNodeCache->contains($parentNodeAggregateId, $nodeName)) { return $namedChildNodeCache->get($parentNodeAggregateId, $nodeName); } - $node = $this->wrappedContentSubgraph->findChildNodeByNodeName($parentNodeAggregateId, $nodeName); + // naturally we would want to call $wrappedContentSubgraph->findChildNodeConnectedThroughEdgeName here, + // but this is not part of the interface and private. Calling find by path with a single segment does the same + $node = $this->wrappedContentSubgraph->findNodeByPath(NodePath::fromNodeNames($nodeName), $parentNodeAggregateId); if ($node === null) { return null; } diff --git a/Neos.ContentRepository.Core/Classes/Projection/ContentGraph/ContentSubgraphInterface.php b/Neos.ContentRepository.Core/Classes/Projection/ContentGraph/ContentSubgraphInterface.php index 84422e63831..df6259c3858 100644 --- a/Neos.ContentRepository.Core/Classes/Projection/ContentGraph/ContentSubgraphInterface.php +++ b/Neos.ContentRepository.Core/Classes/Projection/ContentGraph/ContentSubgraphInterface.php @@ -100,13 +100,6 @@ public function findSucceedingSiblingNodes(NodeAggregateId $siblingNodeAggregate */ public function findPrecedingSiblingNodes(NodeAggregateId $siblingNodeAggregateId, Filter\FindPrecedingSiblingNodesFilter $filter): Nodes; - /** - * Find a single child node by its name - * - * @return Node|null the node that is connected to its parent with the specified $nodeName, or NULL if no matching node exists or the parent node is not accessible - */ - public function findChildNodeByNodeName(NodeAggregateId $parentNodeAggregateId, NodeName $nodeName): ?Node; - /** * Recursively find all nodes above the $entryNodeAggregateId that match the specified $filter and return them as a flat list */ From ae0679b3cebea878ddd2f7e236b75decf2a8547b Mon Sep 17 00:00:00 2001 From: mhsdesign <85400359+mhsdesign@users.noreply.github.com> Date: Sat, 18 Nov 2023 13:05:48 +0100 Subject: [PATCH 5/8] TASK: Improve documentation about NodeName & co --- .../Command/CreateNodeAggregateWithNode.php | 2 +- .../Command/CreateRootNodeAggregateWithNode.php | 2 +- .../Projection/ContentGraph/AbsoluteNodePath.php | 10 ++++++++-- .../ContentGraph/ContentSubgraphInterface.php | 2 +- .../Classes/Projection/ContentGraph/Node.php | 2 +- .../Classes/Projection/ContentGraph/NodePath.php | 14 ++++++++++++-- .../Classes/SharedModel/Node/NodeName.php | 5 ++++- 7 files changed, 28 insertions(+), 9 deletions(-) diff --git a/Neos.ContentRepository.Core/Classes/Feature/NodeCreation/Command/CreateNodeAggregateWithNode.php b/Neos.ContentRepository.Core/Classes/Feature/NodeCreation/Command/CreateNodeAggregateWithNode.php index e6c9d382056..9a026208dae 100644 --- a/Neos.ContentRepository.Core/Classes/Feature/NodeCreation/Command/CreateNodeAggregateWithNode.php +++ b/Neos.ContentRepository.Core/Classes/Feature/NodeCreation/Command/CreateNodeAggregateWithNode.php @@ -97,7 +97,7 @@ public function withInitialPropertyValues(PropertyValuesToWrite $newInitialPrope * a tethered node aggregate id, you need to generate the child node aggregate ids in advance. * * _Alternatively you would need to fetch the created tethered node first from the subgraph. - * {@see ContentSubgraphInterface::findChildNodeByNodeName()}_ + * {@see ContentSubgraphInterface::findNodeByPath()}_ * * The helper method {@see NodeAggregateIdsByNodePaths::createForNodeType()} will generate recursively * node aggregate ids for every tethered child node: diff --git a/Neos.ContentRepository.Core/Classes/Feature/RootNodeCreation/Command/CreateRootNodeAggregateWithNode.php b/Neos.ContentRepository.Core/Classes/Feature/RootNodeCreation/Command/CreateRootNodeAggregateWithNode.php index 54fda72a946..ec9b7f83096 100644 --- a/Neos.ContentRepository.Core/Classes/Feature/RootNodeCreation/Command/CreateRootNodeAggregateWithNode.php +++ b/Neos.ContentRepository.Core/Classes/Feature/RootNodeCreation/Command/CreateRootNodeAggregateWithNode.php @@ -70,7 +70,7 @@ public static function create(ContentStreamId $contentStreamId, NodeAggregateId * a tethered node aggregate id, you need to generate the child node aggregate ids in advance. * * _Alternatively you would need to fetch the created tethered node first from the subgraph. - * {@see ContentSubgraphInterface::findChildNodeByNodeName()}_ + * {@see ContentSubgraphInterface::findNodeByPath()}_ * * The helper method {@see NodeAggregateIdsByNodePaths::createForNodeType()} will generate recursively * node aggregate ids for every tethered child node: diff --git a/Neos.ContentRepository.Core/Classes/Projection/ContentGraph/AbsoluteNodePath.php b/Neos.ContentRepository.Core/Classes/Projection/ContentGraph/AbsoluteNodePath.php index d6ea986467b..8c8682a0d71 100644 --- a/Neos.ContentRepository.Core/Classes/Projection/ContentGraph/AbsoluteNodePath.php +++ b/Neos.ContentRepository.Core/Classes/Projection/ContentGraph/AbsoluteNodePath.php @@ -49,8 +49,14 @@ public static function fromRootNodeTypeNameAndRelativePath( } /** - * The ancestors must be ordered with the root node first, so if you call this using - * {@see ContentSubgraphInterface::findAncestorNodes()}, you need to call ${@see Nodes::reverse()} first + * The ancestors must be ordered with the root node first. + * + * If you want to retrieve the path of a node using {@see ContentSubgraphInterface::findAncestorNodes()}, you need to reverse the order first {@see Nodes::reverse()} + * + * ```php + * $ancestors = $this->findAncestorNodes($leafNode->nodeAggregateId, FindAncestorNodesFilter::create())->reverse(); + * $absoluteNodePath = AbsoluteNodePath::fromLeafNodeAndAncestors($leafNode, $ancestors); + * ``` */ public static function fromLeafNodeAndAncestors(Node $leafNode, Nodes $ancestors): self { diff --git a/Neos.ContentRepository.Core/Classes/Projection/ContentGraph/ContentSubgraphInterface.php b/Neos.ContentRepository.Core/Classes/Projection/ContentGraph/ContentSubgraphInterface.php index df6259c3858..2548e84d879 100644 --- a/Neos.ContentRepository.Core/Classes/Projection/ContentGraph/ContentSubgraphInterface.php +++ b/Neos.ContentRepository.Core/Classes/Projection/ContentGraph/ContentSubgraphInterface.php @@ -190,7 +190,7 @@ public function findNodeByAbsolutePath(AbsoluteNodePath $path): ?Node; /** * Determine the absolute path of a node * - * @deprecated use ${@see self::findAncestorNodes()} instead + * @deprecated use {@see self::findAncestorNodes()} in combination with {@see AbsoluteNodePath::fromLeafNodeAndAncestors()} instead * @throws \InvalidArgumentException if the node path could not be retrieved because it is inaccessible or contains no valid path. The latter can happen if any node in the hierarchy has no name */ public function retrieveNodePath(NodeAggregateId $nodeAggregateId): AbsoluteNodePath; diff --git a/Neos.ContentRepository.Core/Classes/Projection/ContentGraph/Node.php b/Neos.ContentRepository.Core/Classes/Projection/ContentGraph/Node.php index bc227090293..66f65a2e080 100644 --- a/Neos.ContentRepository.Core/Classes/Projection/ContentGraph/Node.php +++ b/Neos.ContentRepository.Core/Classes/Projection/ContentGraph/Node.php @@ -44,7 +44,7 @@ * @param NodeTypeName $nodeTypeName The node's node type name; always set, even if unknown to the NodeTypeManager * @param NodeType|null $nodeType The node's node type, null if unknown to the NodeTypeManager - @deprecated Don't rely on this too much, as the capabilities of the NodeType here will probably change a lot; Ask the {@see NodeTypeManager} instead * @param PropertyCollection $properties All properties of this node. References are NOT part of this API; To access references, {@see ContentSubgraphInterface::findReferences()} can be used; To read the serialized properties, call properties->serialized(). - * @param NodeName|null $nodeName The optional name of this node {@see ContentSubgraphInterface::findChildNodeByNodeName()} + * @param NodeName|null $nodeName The optionally named hierarchy relation to the node's parent. * @param Timestamps $timestamps Creation and modification timestamps of this node */ private function __construct( diff --git a/Neos.ContentRepository.Core/Classes/Projection/ContentGraph/NodePath.php b/Neos.ContentRepository.Core/Classes/Projection/ContentGraph/NodePath.php index 147f434598e..340142b48e9 100644 --- a/Neos.ContentRepository.Core/Classes/Projection/ContentGraph/NodePath.php +++ b/Neos.ContentRepository.Core/Classes/Projection/ContentGraph/NodePath.php @@ -17,13 +17,23 @@ use Neos\ContentRepository\Core\SharedModel\Node\NodeName; /** - * The relative node path is a collection of NodeNames. If it contains no elements, it is considered root. + * The relative node path is a collection of node names {@see NodeName}. If it contains no elements, it is considered root. * * Example: * root path: '' is resolved to [] - * non-root path: 'my/site' is resolved to ~ ['my', 'site'] + * non-root path: 'my-site/main' is resolved to ~ ['my-site', 'main'] * * It describes the hierarchy path of a node to an ancestor node in a subgraph. + * + * To fetch a node on a path use the subgraph: {@see ContentSubgraphInterface::findNodeByPath()} + * + * ```php + * $subgraph->findNodeByPath( + * NodePath::fromNodeNames(NodeName::fromString("main")), + * $parentNodeAggregateId + * ) + * ``` + * * @api */ final class NodePath implements \JsonSerializable diff --git a/Neos.ContentRepository.Core/Classes/SharedModel/Node/NodeName.php b/Neos.ContentRepository.Core/Classes/SharedModel/Node/NodeName.php index 017ab717eba..e90166425c3 100644 --- a/Neos.ContentRepository.Core/Classes/SharedModel/Node/NodeName.php +++ b/Neos.ContentRepository.Core/Classes/SharedModel/Node/NodeName.php @@ -15,13 +15,16 @@ namespace Neos\ContentRepository\Core\SharedModel\Node; use Behat\Transliterator\Transliterator; +use Neos\ContentRepository\Core\Projection\ContentGraph\NodePath; /** - * The Node name is the "path part" of the node; i.e. when accessing the node "/foo" via path, + * The Node name is the "path part" of the node; i.e. when accessing the node "/foo" via path {@see NodePath}, * the node name is "foo". * * Semantically it describes the hierarchical relation of a node to its parent, e.g. "main" denotes the main child node. * + * Multiple node names describe a node path {@see NodePath} + * * @api */ final class NodeName implements \JsonSerializable From aff2eff5daaae945d25e86ab1c8281d89eea9c52 Mon Sep 17 00:00:00 2001 From: mhsdesign <85400359+mhsdesign@users.noreply.github.com> Date: Sun, 19 Nov 2023 17:51:14 +0100 Subject: [PATCH 6/8] TASK: Allow `NodeName` in findNodeByPath() --- .../src/Domain/Repository/ContentSubgraph.php | 4 +++- .../src/Domain/Repository/ContentSubhypergraph.php | 4 +++- .../Feature/NodeTypeChange/NodeTypeChange.php | 2 +- .../Projection/ContentGraph/AbsoluteNodePath.php | 13 +++++++++++-- .../ContentSubgraphWithRuntimeCaches.php | 8 +++++--- .../ContentGraph/ContentSubgraphInterface.php | 4 +++- .../Classes/Projection/ContentGraph/NodePath.php | 6 +++--- .../Classes/SharedModel/Node/NodeName.php | 9 +++++++++ .../src/Adjustment/TetheredNodeAdjustments.php | 2 +- .../Features/Bootstrap/NodeTraversalTrait.php | 2 +- .../Features/Bootstrap/ProjectedNodeTrait.php | 2 +- .../Classes/Domain/Service/SiteNodeUtility.php | 2 +- 12 files changed, 42 insertions(+), 16 deletions(-) diff --git a/Neos.ContentGraph.DoctrineDbalAdapter/src/Domain/Repository/ContentSubgraph.php b/Neos.ContentGraph.DoctrineDbalAdapter/src/Domain/Repository/ContentSubgraph.php index 295895505ab..775cb944eeb 100644 --- a/Neos.ContentGraph.DoctrineDbalAdapter/src/Domain/Repository/ContentSubgraph.php +++ b/Neos.ContentGraph.DoctrineDbalAdapter/src/Domain/Repository/ContentSubgraph.php @@ -211,8 +211,10 @@ public function findParentNode(NodeAggregateId $childNodeAggregateId): ?Node return $this->fetchNode($queryBuilder); } - public function findNodeByPath(NodePath $path, NodeAggregateId $startingNodeAggregateId): ?Node + public function findNodeByPath(NodePath|NodeName $path, NodeAggregateId $startingNodeAggregateId): ?Node { + $path = $path instanceof NodeName ? NodePath::fromNodeNames($path) : $path; + $startingNode = $this->findNodeById($startingNodeAggregateId); return $startingNode diff --git a/Neos.ContentGraph.PostgreSQLAdapter/src/Domain/Repository/ContentSubhypergraph.php b/Neos.ContentGraph.PostgreSQLAdapter/src/Domain/Repository/ContentSubhypergraph.php index 57ce5ccf93c..cf3aafd476d 100644 --- a/Neos.ContentGraph.PostgreSQLAdapter/src/Domain/Repository/ContentSubhypergraph.php +++ b/Neos.ContentGraph.PostgreSQLAdapter/src/Domain/Repository/ContentSubhypergraph.php @@ -269,8 +269,10 @@ public function findParentNode(NodeAggregateId $childNodeAggregateId): ?Node ) : null; } - public function findNodeByPath(NodePath $path, NodeAggregateId $startingNodeAggregateId): ?Node + public function findNodeByPath(NodePath|NodeName $path, NodeAggregateId $startingNodeAggregateId): ?Node { + $path = $path instanceof NodeName ? NodePath::fromNodeNames($path) : $path; + $startingNode = $this->findNodeById($startingNodeAggregateId); return $startingNode diff --git a/Neos.ContentRepository.Core/Classes/Feature/NodeTypeChange/NodeTypeChange.php b/Neos.ContentRepository.Core/Classes/Feature/NodeTypeChange/NodeTypeChange.php index 5a89e670ca6..09f97b8a12c 100644 --- a/Neos.ContentRepository.Core/Classes/Feature/NodeTypeChange/NodeTypeChange.php +++ b/Neos.ContentRepository.Core/Classes/Feature/NodeTypeChange/NodeTypeChange.php @@ -198,7 +198,7 @@ private function handleChangeNodeAggregateType( VisibilityConstraints::withoutRestrictions() ); $tetheredNode = $subgraph->findNodeByPath( - NodePath::fromNodeNames($tetheredNodeName), + $tetheredNodeName, $node->nodeAggregateId ); if ($tetheredNode === null) { diff --git a/Neos.ContentRepository.Core/Classes/Projection/ContentGraph/AbsoluteNodePath.php b/Neos.ContentRepository.Core/Classes/Projection/ContentGraph/AbsoluteNodePath.php index 8c8682a0d71..1d36fa18c2d 100644 --- a/Neos.ContentRepository.Core/Classes/Projection/ContentGraph/AbsoluteNodePath.php +++ b/Neos.ContentRepository.Core/Classes/Projection/ContentGraph/AbsoluteNodePath.php @@ -24,10 +24,19 @@ * Example: * root path: '/' results in * ~ {"rootNodeTypeName": "Neos.ContentRepository:Root", "path": []} - * non-root path: '//my/site' results in - * ~ {"rootNodeTypeName": "Neos.ContentRepository:Root", "path": ["my","site"]} + * non-root path: '//my-site/main' results in + * ~ {"rootNodeTypeName": "Neos.ContentRepository:Root", "path": ["my-site", "main"]} * * It describes the hierarchy path of a node to and including its root node in a subgraph. + * + * To fetch a node via an absolute path use the subgraph: {@see ContentSubgraphInterface::findNodeByAbsolutePath()} + * + * ```php + * $subgraph->findNodeByAbsolutePath( + * AbsoluteNodePath::fromString("//my-site/main") + * ) + * ``` + * * @api */ final class AbsoluteNodePath implements \JsonSerializable diff --git a/Neos.ContentRepository.Core/Classes/Projection/ContentGraph/ContentGraphWithRuntimeCaches/ContentSubgraphWithRuntimeCaches.php b/Neos.ContentRepository.Core/Classes/Projection/ContentGraph/ContentGraphWithRuntimeCaches/ContentSubgraphWithRuntimeCaches.php index c3c82e5e609..0d6608b2777 100644 --- a/Neos.ContentRepository.Core/Classes/Projection/ContentGraph/ContentGraphWithRuntimeCaches/ContentSubgraphWithRuntimeCaches.php +++ b/Neos.ContentRepository.Core/Classes/Projection/ContentGraph/ContentGraphWithRuntimeCaches/ContentSubgraphWithRuntimeCaches.php @@ -163,8 +163,10 @@ public function findParentNode(NodeAggregateId $childNodeAggregateId): ?Node return $parentNode; } - public function findNodeByPath(NodePath $path, NodeAggregateId $startingNodeAggregateId): ?Node + public function findNodeByPath(NodePath|NodeName $path, NodeAggregateId $startingNodeAggregateId): ?Node { + $path = $path instanceof NodeName ? NodePath::fromNodeNames($path) : $path; + // this implementation is copied from the DoctrineAdapter to make it cache-able $startingNode = $this->findNodeById($startingNodeAggregateId); @@ -203,8 +205,8 @@ private function findChildNodeConnectedThroughEdgeName(NodeAggregateId $parentNo return $namedChildNodeCache->get($parentNodeAggregateId, $nodeName); } // naturally we would want to call $wrappedContentSubgraph->findChildNodeConnectedThroughEdgeName here, - // but this is not part of the interface and private. Calling find by path with a single segment does the same - $node = $this->wrappedContentSubgraph->findNodeByPath(NodePath::fromNodeNames($nodeName), $parentNodeAggregateId); + // but this is not part of the interface and private. Calling find with a single segment does the same + $node = $this->wrappedContentSubgraph->findNodeByPath($nodeName, $parentNodeAggregateId); if ($node === null) { return null; } diff --git a/Neos.ContentRepository.Core/Classes/Projection/ContentGraph/ContentSubgraphInterface.php b/Neos.ContentRepository.Core/Classes/Projection/ContentGraph/ContentSubgraphInterface.php index 2548e84d879..e3f5fe29b85 100644 --- a/Neos.ContentRepository.Core/Classes/Projection/ContentGraph/ContentSubgraphInterface.php +++ b/Neos.ContentRepository.Core/Classes/Projection/ContentGraph/ContentSubgraphInterface.php @@ -174,10 +174,12 @@ public function countBackReferences(NodeAggregateId $nodeAggregateId, Filter\Cou /** * Find a single node underneath $startingNodeAggregateId that matches the specified $path * + * If a node name as $path is given it will be treated as path with a single segment. + * * NOTE: This operation is most likely to be deprecated since the concept of node paths is not really used in the core, and it has some logical issues * @return Node|null the node that matches the given $path, or NULL if no node on that path is accessible */ - public function findNodeByPath(NodePath $path, NodeAggregateId $startingNodeAggregateId): ?Node; + public function findNodeByPath(NodePath|NodeName $path, NodeAggregateId $startingNodeAggregateId): ?Node; /** * Find a single node underneath that matches the specified absolute $path diff --git a/Neos.ContentRepository.Core/Classes/Projection/ContentGraph/NodePath.php b/Neos.ContentRepository.Core/Classes/Projection/ContentGraph/NodePath.php index 340142b48e9..a6c755f109a 100644 --- a/Neos.ContentRepository.Core/Classes/Projection/ContentGraph/NodePath.php +++ b/Neos.ContentRepository.Core/Classes/Projection/ContentGraph/NodePath.php @@ -21,7 +21,7 @@ * * Example: * root path: '' is resolved to [] - * non-root path: 'my-site/main' is resolved to ~ ['my-site', 'main'] + * non-root path: 'my-document/main' is resolved to ~ ['my-document', 'main'] * * It describes the hierarchy path of a node to an ancestor node in a subgraph. * @@ -29,8 +29,8 @@ * * ```php * $subgraph->findNodeByPath( - * NodePath::fromNodeNames(NodeName::fromString("main")), - * $parentNodeAggregateId + * NodePath::fromString("my-document/main"), + * $siteNodeAggregateId * ) * ``` * diff --git a/Neos.ContentRepository.Core/Classes/SharedModel/Node/NodeName.php b/Neos.ContentRepository.Core/Classes/SharedModel/Node/NodeName.php index e90166425c3..5d64588e5ec 100644 --- a/Neos.ContentRepository.Core/Classes/SharedModel/Node/NodeName.php +++ b/Neos.ContentRepository.Core/Classes/SharedModel/Node/NodeName.php @@ -25,6 +25,15 @@ * * Multiple node names describe a node path {@see NodePath} * + * To fetch the child node that is connected with the parent via the name "main" use the subgraph's: {@see ContentSubgraphInterface::findNodeByPath()} + * + * ```php + * $subgraph->findNodeByPath( + * NodeName::fromString("main"), + * $parentNodeAggregateId + * ) + * ``` + * * @api */ final class NodeName implements \JsonSerializable diff --git a/Neos.ContentRepository.StructureAdjustment/src/Adjustment/TetheredNodeAdjustments.php b/Neos.ContentRepository.StructureAdjustment/src/Adjustment/TetheredNodeAdjustments.php index fda50ee2891..c4dc2eebf33 100644 --- a/Neos.ContentRepository.StructureAdjustment/src/Adjustment/TetheredNodeAdjustments.php +++ b/Neos.ContentRepository.StructureAdjustment/src/Adjustment/TetheredNodeAdjustments.php @@ -75,7 +75,7 @@ public function findAdjustmentsForNodeType(NodeTypeName $nodeTypeName): \Generat VisibilityConstraints::withoutRestrictions() ); $tetheredNode = $subgraph->findNodeByPath( - NodePath::fromNodeNames($tetheredNodeName), + $tetheredNodeName, $nodeAggregate->nodeAggregateId, ); if ($tetheredNode === null) { diff --git a/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/NodeTraversalTrait.php b/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/NodeTraversalTrait.php index 96b94004e02..2ecc12f0f7a 100644 --- a/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/NodeTraversalTrait.php +++ b/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/NodeTraversalTrait.php @@ -166,7 +166,7 @@ public function iExecuteTheFindChildNodeByNodeNameQueryIExpectTheFollowingNodes( $edgeName = NodeName::fromString($edgeNameSerialized); $expectedNodeAggregateId = $expectedNodeIdSerialized !== null ? NodeAggregateId::fromString($expectedNodeIdSerialized) : null; - $actualNode = $this->getCurrentSubgraph()->findNodeByPath(NodePath::fromNodeNames($edgeName), $parentNodeAggregateId); + $actualNode = $this->getCurrentSubgraph()->findNodeByPath($edgeName, $parentNodeAggregateId); Assert::assertSame($actualNode?->nodeAggregateId->value, $expectedNodeAggregateId?->value); } diff --git a/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/ProjectedNodeTrait.php b/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/ProjectedNodeTrait.php index 27bbb983e95..5ba244abcd9 100644 --- a/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/ProjectedNodeTrait.php +++ b/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/ProjectedNodeTrait.php @@ -456,7 +456,7 @@ public function iExpectThisNodeToBeTheChildOfNode(string $serializedParentNodeDi Assert::assertTrue($expectedParentDiscriminator->equals($actualParentDiscriminator), 'Parent discriminator does not match. Expected was ' . json_encode($expectedParentDiscriminator) . ', given was ' . json_encode($actualParentDiscriminator)); $expectedChildDiscriminator = NodeDiscriminator::fromNode($currentNode); - $child = $subgraph->findNodeByPath(NodePath::fromNodeNames($currentNode->nodeName), $parent->nodeAggregateId); + $child = $subgraph->findNodeByPath($currentNode->nodeName, $parent->nodeAggregateId); $actualChildDiscriminator = NodeDiscriminator::fromNode($child); Assert::assertTrue($expectedChildDiscriminator->equals($actualChildDiscriminator), 'Child discriminator does not match. Expected was ' . json_encode($expectedChildDiscriminator) . ', given was ' . json_encode($actualChildDiscriminator)); }); diff --git a/Neos.Neos/Classes/Domain/Service/SiteNodeUtility.php b/Neos.Neos/Classes/Domain/Service/SiteNodeUtility.php index 076d6d93043..548c392160b 100644 --- a/Neos.Neos/Classes/Domain/Service/SiteNodeUtility.php +++ b/Neos.Neos/Classes/Domain/Service/SiteNodeUtility.php @@ -77,7 +77,7 @@ public function findSiteNodeBySite( $rootNode = $rootNodeAggregate->getNodeByCoveredDimensionSpacePoint($dimensionSpacePoint); $siteNode = $subgraph->findNodeByPath( - NodePath::fromNodeNames($site->getNodeName()->toNodeName()), + $site->getNodeName()->toNodeName(), $rootNode->nodeAggregateId ); From e2560cc25360cca192b6f0362a14286f1a170b1b Mon Sep 17 00:00:00 2001 From: mhsdesign <85400359+mhsdesign@users.noreply.github.com> Date: Sun, 19 Nov 2023 18:00:32 +0100 Subject: [PATCH 7/8] TASK: Rebrand `findChildNodeConnectedThroughEdgeName` tests as findNodeByPath as NodeName --- ...ature => FindNodeByPathAsNodeName.feature} | 20 +++++++++---------- .../Features/Bootstrap/NodeTraversalTrait.php | 4 ++-- 2 files changed, 12 insertions(+), 12 deletions(-) rename Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/NodeTraversal/{FindChildNodeConnectedThroughEdgeName.feature => FindNodeByPathAsNodeName.feature} (80%) diff --git a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/NodeTraversal/FindChildNodeConnectedThroughEdgeName.feature b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/NodeTraversal/FindNodeByPathAsNodeName.feature similarity index 80% rename from Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/NodeTraversal/FindChildNodeConnectedThroughEdgeName.feature rename to Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/NodeTraversal/FindNodeByPathAsNodeName.feature index 92e68a70c05..9125fd17850 100644 --- a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/NodeTraversal/FindChildNodeConnectedThroughEdgeName.feature +++ b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/NodeTraversal/FindNodeByPathAsNodeName.feature @@ -1,5 +1,5 @@ @contentrepository @adapters=DoctrineDBAL,Postgres -Feature: Find nodes using the findChildNodeByNodeName query +Feature: Find nodes using the findNodeByPath query with node name as path argument Background: Given using the following content dimensions: @@ -88,15 +88,15 @@ Feature: Find nodes using the findChildNodeByNodeName query And the graph projection is fully up to date Scenario: - # findChildNodeByNodeName queries without results - When I execute the findChildNodeByNodeName query for parent node aggregate id "non-existing" and edge name "non-existing" I expect no node to be returned - When I execute the findChildNodeByNodeName query for parent node aggregate id "home" and edge name "non-existing" I expect no node to be returned - When I execute the findChildNodeByNodeName query for parent node aggregate id "non-existing" and edge name "home" I expect no node to be returned + # findNodeByPath queries without results + When I execute the findNodeByPath query for parent node aggregate id "non-existing" and node name "non-existing" as path I expect no node to be returned + When I execute the findNodeByPath query for parent node aggregate id "home" and node name "non-existing" as path I expect no node to be returned + When I execute the findNodeByPath query for parent node aggregate id "non-existing" and node name "home" as path I expect no node to be returned # node "a2a2" is disabled and should not be returned - When I execute the findChildNodeByNodeName query for parent node aggregate id "a2a" and edge name "a2a2" I expect no node to be returned + When I execute the findNodeByPath query for parent node aggregate id "a2a" and node name "a2a2" as path I expect no node to be returned # node "a2a2" is disabled and should not lead to results if specified as parent node id - When I execute the findChildNodeByNodeName query for parent node aggregate id "a2a2" and edge name "a2a2a" I expect no node to be returned + When I execute the findNodeByPath query for parent node aggregate id "a2a2" and node name "a2a2a" as path I expect no node to be returned - # findChildNodeByNodeName queries with results - When I execute the findChildNodeByNodeName query for parent node aggregate id "home" and edge name "contact" I expect the node "contact" to be returned - When I execute the findChildNodeByNodeName query for parent node aggregate id "a2a" and edge name "a2a1" I expect the node "a2a1" to be returned + # findNodeByPath queries with results + When I execute the findNodeByPath query for parent node aggregate id "home" and node name "contact" as path I expect the node "contact" to be returned + When I execute the findNodeByPath query for parent node aggregate id "a2a" and node name "a2a1" as path I expect the node "a2a1" to be returned diff --git a/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/NodeTraversalTrait.php b/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/NodeTraversalTrait.php index 2ecc12f0f7a..61089e1bd16 100644 --- a/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/NodeTraversalTrait.php +++ b/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/NodeTraversalTrait.php @@ -157,8 +157,8 @@ public function iExecuteTheFindNodeByAbsolutePathQueryIExpectTheFollowingNodes(s } /** - * @When I execute the findChildNodeByNodeName query for parent node aggregate id :parentNodeIdSerialized and edge name :edgeNameSerialized I expect no node to be returned - * @When I execute the findChildNodeByNodeName query for parent node aggregate id :parentNodeIdSerialized and edge name :edgeNameSerialized I expect the node :expectedNodeIdSerialized to be returned + * @When I execute the findNodeByPath query for parent node aggregate id :parentNodeIdSerialized and node name :edgeNameSerialized as path I expect no node to be returned + * @When I execute the findNodeByPath query for parent node aggregate id :parentNodeIdSerialized and node name :edgeNameSerialized as path I expect the node :expectedNodeIdSerialized to be returned */ public function iExecuteTheFindChildNodeByNodeNameQueryIExpectTheFollowingNodes(string $parentNodeIdSerialized, string $edgeNameSerialized, string $expectedNodeIdSerialized = null): void { From ec744067096f170b224b92f269d3b6140818adec Mon Sep 17 00:00:00 2001 From: mhsdesign <85400359+mhsdesign@users.noreply.github.com> Date: Sun, 19 Nov 2023 18:02:08 +0100 Subject: [PATCH 8/8] TASK: ContentSubgraphWithRuntimeCaches revert implementation detail lacking approach --- .../ContentSubgraphWithRuntimeCaches.php | 48 ++----------------- 1 file changed, 4 insertions(+), 44 deletions(-) diff --git a/Neos.ContentRepository.Core/Classes/Projection/ContentGraph/ContentGraphWithRuntimeCaches/ContentSubgraphWithRuntimeCaches.php b/Neos.ContentRepository.Core/Classes/Projection/ContentGraph/ContentGraphWithRuntimeCaches/ContentSubgraphWithRuntimeCaches.php index 0d6608b2777..496e55db2b6 100644 --- a/Neos.ContentRepository.Core/Classes/Projection/ContentGraph/ContentGraphWithRuntimeCaches/ContentSubgraphWithRuntimeCaches.php +++ b/Neos.ContentRepository.Core/Classes/Projection/ContentGraph/ContentGraphWithRuntimeCaches/ContentSubgraphWithRuntimeCaches.php @@ -165,54 +165,14 @@ public function findParentNode(NodeAggregateId $childNodeAggregateId): ?Node public function findNodeByPath(NodePath|NodeName $path, NodeAggregateId $startingNodeAggregateId): ?Node { - $path = $path instanceof NodeName ? NodePath::fromNodeNames($path) : $path; - - // this implementation is copied from the DoctrineAdapter to make it cache-able - $startingNode = $this->findNodeById($startingNodeAggregateId); - - return $startingNode - ? $this->findNodeByPathFromStartingNode($path, $startingNode) - : null; + // TODO: implement runtime caches + return $this->wrappedContentSubgraph->findNodeByPath($path, $startingNodeAggregateId); } public function findNodeByAbsolutePath(AbsoluteNodePath $path): ?Node { - // this implementation is copied from the DoctrineAdapter to make it cache-able - $startingNode = $this->findRootNodeByType($path->rootNodeTypeName); - - return $startingNode - ? $this->findNodeByPathFromStartingNode($path->path, $startingNode) - : null; - } - - private function findNodeByPathFromStartingNode(NodePath $path, Node $startingNode): ?Node - { - $currentNode = $startingNode; - - foreach ($path->getParts() as $edgeName) { - $currentNode = $this->findChildNodeConnectedThroughEdgeName($currentNode->nodeAggregateId, $edgeName); - if ($currentNode === null) { - return null; - } - } - return $currentNode; - } - - private function findChildNodeConnectedThroughEdgeName(NodeAggregateId $parentNodeAggregateId, NodeName $nodeName): ?Node - { - $namedChildNodeCache = $this->inMemoryCache->getNamedChildNodeByNodeIdCache(); - if ($namedChildNodeCache->contains($parentNodeAggregateId, $nodeName)) { - return $namedChildNodeCache->get($parentNodeAggregateId, $nodeName); - } - // naturally we would want to call $wrappedContentSubgraph->findChildNodeConnectedThroughEdgeName here, - // but this is not part of the interface and private. Calling find with a single segment does the same - $node = $this->wrappedContentSubgraph->findNodeByPath($nodeName, $parentNodeAggregateId); - if ($node === null) { - return null; - } - $namedChildNodeCache->add($parentNodeAggregateId, $nodeName, $node); - $this->inMemoryCache->getNodeByNodeAggregateIdCache()->add($node->nodeAggregateId, $node); - return $node; + // TODO: implement runtime caches + return $this->wrappedContentSubgraph->findNodeByAbsolutePath($path); } public function findSucceedingSiblingNodes(NodeAggregateId $siblingNodeAggregateId, FindSucceedingSiblingNodesFilter $filter): Nodes