diff --git a/Neos.ContentGraph.DoctrineDbalAdapter/src/Domain/Repository/ContentSubgraph.php b/Neos.ContentGraph.DoctrineDbalAdapter/src/Domain/Repository/ContentSubgraph.php index 4100d614945..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 @@ -229,7 +231,12 @@ public function findNodeByAbsolutePath(AbsoluteNodePath $path): ?Node : null; } - public function findChildNodeConnectedThroughEdgeName(NodeAggregateId $parentNodeAggregateId, NodeName $edgeName): ?Node + /** + * 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() ->select('cn.*, h.name, h.contentstreamid') @@ -239,7 +246,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); } @@ -472,7 +479,6 @@ private function findNodeByPathFromStartingNode(NodePath $path, Node $startingNo $currentNode = $startingNode; foreach ($path->getParts() as $edgeName) { - // id exists here :) $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 32705839a97..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 @@ -287,9 +289,9 @@ public function findNodeByAbsolutePath(AbsoluteNodePath $path): ?Node : null; } - public function findChildNodeConnectedThroughEdgeName( + private function findChildNodeConnectedThroughEdgeName( NodeAggregateId $parentNodeAggregateId, - NodeName $edgeName + NodeName $nodeName ): ?Node { $query = HypergraphChildQuery::create( $this->contentStreamId, @@ -298,7 +300,7 @@ public function findChildNodeConnectedThroughEdgeName( ); $query = $query->withDimensionSpacePoint($this->dimensionSpacePoint) ->withRestriction($this->visibilityConstraints) - ->withChildNodeName($edgeName); + ->withChildNodeName($nodeName); $nodeRow = $query->execute($this->getDatabaseConnection())->fetchAssociative(); diff --git a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/NodeTraversal/FindChildNodeConnectedThroughEdgeName.feature b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/NodeTraversal/FindNodeByPathAsNodeName.feature similarity index 79% rename from Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/NodeTraversal/FindChildNodeConnectedThroughEdgeName.feature rename to Neos.ContentRepository.BehavioralTests/Tests/Behavior/Features/NodeTraversal/FindNodeByPathAsNodeName.feature index 67898ef2130..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 findChildNodeConnectedThroughEdgeName 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 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 + # 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 findChildNodeConnectedThroughEdgeName 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 findChildNodeConnectedThroughEdgeName 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 - # 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 + # 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.Core/Classes/Feature/NodeCreation/Command/CreateNodeAggregateWithNode.php b/Neos.ContentRepository.Core/Classes/Feature/NodeCreation/Command/CreateNodeAggregateWithNode.php index 266c5fc3c08..fe125c03c8d 100644 --- a/Neos.ContentRepository.Core/Classes/Feature/NodeCreation/Command/CreateNodeAggregateWithNode.php +++ b/Neos.ContentRepository.Core/Classes/Feature/NodeCreation/Command/CreateNodeAggregateWithNode.php @@ -95,7 +95,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::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/NodeTypeChange/NodeTypeChange.php b/Neos.ContentRepository.Core/Classes/Feature/NodeTypeChange/NodeTypeChange.php index 0f68cba7042..09f97b8a12c 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->findChildNodeConnectedThroughEdgeName( - $node->nodeAggregateId, - $tetheredNodeName + $tetheredNode = $subgraph->findNodeByPath( + $tetheredNodeName, + $node->nodeAggregateId ); if ($tetheredNode === null) { $tetheredNodeAggregateId = $command->tetheredDescendantNodeAggregateIds diff --git a/Neos.ContentRepository.Core/Classes/Feature/RootNodeCreation/Command/CreateRootNodeAggregateWithNode.php b/Neos.ContentRepository.Core/Classes/Feature/RootNodeCreation/Command/CreateRootNodeAggregateWithNode.php index 0e2ceab99de..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::findChildNodeConnectedThroughEdgeName()}_ + * {@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..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 @@ -49,8 +58,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/ContentGraphWithRuntimeCaches/ContentSubgraphWithRuntimeCaches.php b/Neos.ContentRepository.Core/Classes/Projection/ContentGraph/ContentGraphWithRuntimeCaches/ContentSubgraphWithRuntimeCaches.php index 7660d7c154d..496e55db2b6 100644 --- a/Neos.ContentRepository.Core/Classes/Projection/ContentGraph/ContentGraphWithRuntimeCaches/ContentSubgraphWithRuntimeCaches.php +++ b/Neos.ContentRepository.Core/Classes/Projection/ContentGraph/ContentGraphWithRuntimeCaches/ContentSubgraphWithRuntimeCaches.php @@ -163,33 +163,18 @@ 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 { - // TODO implement runtime caches + // TODO: implement runtime caches return $this->wrappedContentSubgraph->findNodeByPath($path, $startingNodeAggregateId); } public function findNodeByAbsolutePath(AbsoluteNodePath $path): ?Node { - // TODO implement runtime caches + // TODO: implement runtime caches return $this->wrappedContentSubgraph->findNodeByAbsolutePath($path); } - public function findChildNodeConnectedThroughEdgeName(NodeAggregateId $parentNodeAggregateId, NodeName $edgeName): ?Node - { - $namedChildNodeCache = $this->inMemoryCache->getNamedChildNodeByNodeIdCache(); - if ($namedChildNodeCache->contains($parentNodeAggregateId, $edgeName)) { - return $namedChildNodeCache->get($parentNodeAggregateId, $edgeName); - } - $node = $this->wrappedContentSubgraph->findChildNodeConnectedThroughEdgeName($parentNodeAggregateId, $edgeName); - if ($node === null) { - return null; - } - $namedChildNodeCache->add($parentNodeAggregateId, $edgeName, $node); - $this->inMemoryCache->getNodeByNodeAggregateIdCache()->add($node->nodeAggregateId, $node); - return $node; - } - public function findSucceedingSiblingNodes(NodeAggregateId $siblingNodeAggregateId, FindSucceedingSiblingNodesFilter $filter): Nodes { // TODO implement runtime caches diff --git a/Neos.ContentRepository.Core/Classes/Projection/ContentGraph/ContentSubgraphInterface.php b/Neos.ContentRepository.Core/Classes/Projection/ContentGraph/ContentSubgraphInterface.php index 5f65fb6a0f1..e3f5fe29b85 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 $edgeName, or NULL if no matching node exists or the parent node is not accessible - */ - public function findChildNodeConnectedThroughEdgeName(NodeAggregateId $parentNodeAggregateId, NodeName $edgeName): ?Node; - /** * Recursively find all nodes above the $entryNodeAggregateId that match the specified $filter and return them as a flat list */ @@ -181,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 @@ -197,7 +192,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 446ecc996de..55f6e39a563 100644 --- a/Neos.ContentRepository.Core/Classes/Projection/ContentGraph/Node.php +++ b/Neos.ContentRepository.Core/Classes/Projection/ContentGraph/Node.php @@ -46,7 +46,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 use {@see PropertyCollection::serialized()}. - * @param NodeName|null $nodeName The optional name of this node {@see ContentSubgraphInterface::findChildNodeConnectedThroughEdgeName()} + * @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..a6c755f109a 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-document/main' is resolved to ~ ['my-document', '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::fromString("my-document/main"), + * $siteNodeAggregateId + * ) + * ``` + * * @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..5d64588e5ec 100644 --- a/Neos.ContentRepository.Core/Classes/SharedModel/Node/NodeName.php +++ b/Neos.ContentRepository.Core/Classes/SharedModel/Node/NodeName.php @@ -15,13 +15,25 @@ 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} + * + * 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.NodeAccess/Classes/FlowQueryOperations/ChildrenOperation.php b/Neos.ContentRepository.NodeAccess/Classes/FlowQueryOperations/ChildrenOperation.php index c9bfd37be60..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) - ->findChildNodeConnectedThroughEdgeName( - $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 2883857ff9b..c4dc2eebf33 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->findChildNodeConnectedThroughEdgeName( + $tetheredNode = $subgraph->findNodeByPath( + $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 6013ed435f0..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()->findChildNodeConnectedThroughEdgeName( + $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 d0b9d016695..168a6f7a055 100644 --- a/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/NodeTraversalTrait.php +++ b/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/NodeTraversalTrait.php @@ -157,16 +157,16 @@ 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 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 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); $expectedNodeAggregateId = $expectedNodeIdSerialized !== null ? NodeAggregateId::fromString($expectedNodeIdSerialized) : null; - $actualNode = $this->getCurrentSubgraph()->findChildNodeConnectedThroughEdgeName($parentNodeAggregateId, $edgeName); + $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 e0abd0e1d3c..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->findChildNodeConnectedThroughEdgeName($parent->nodeAggregateId, $currentNode->nodeName); + $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 a93df26f963..548c392160b 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->findChildNodeConnectedThroughEdgeName( - $rootNode->nodeAggregateId, - $site->getNodeName()->toNodeName() + $siteNode = $subgraph->findNodeByPath( + $site->getNodeName()->toNodeName(), + $rootNode->nodeAggregateId ); if (!$siteNode) {