diff --git a/Neos.ContentRepository.NodeAccess/Classes/FlowQueryOperations/ChildrenOperation.php b/Neos.ContentRepository.NodeAccess/Classes/FlowQueryOperations/ChildrenOperation.php index c9bfd37be60..46b4e7cbe33 100644 --- a/Neos.ContentRepository.NodeAccess/Classes/FlowQueryOperations/ChildrenOperation.php +++ b/Neos.ContentRepository.NodeAccess/Classes/FlowQueryOperations/ChildrenOperation.php @@ -195,7 +195,7 @@ protected function earlyOptimizationOfFilters(FlowQuery $flowQuery, array $parse }); $filteredFlowQuery = new FlowQuery($filteredOutput); $filteredFlowQuery->pushOperation('filter', [$attributeFilters]); - $filteredOutput = $filteredFlowQuery->getContext(); + $filteredOutput = iterator_to_array($filteredFlowQuery); } // Add filtered nodes to output diff --git a/Neos.ContentRepository.NodeAccess/Classes/FlowQueryOperations/FindOperation.php b/Neos.ContentRepository.NodeAccess/Classes/FlowQueryOperations/FindOperation.php index c2543d47b7d..988b05cd669 100644 --- a/Neos.ContentRepository.NodeAccess/Classes/FlowQueryOperations/FindOperation.php +++ b/Neos.ContentRepository.NodeAccess/Classes/FlowQueryOperations/FindOperation.php @@ -125,53 +125,56 @@ public function evaluate(FlowQuery $flowQuery, array $arguments): void $entryPoints = $this->getEntryPoints($contextNodes); - // handle absolute node pathes and return early as fizzle cannot parse this syntax - if (preg_match('/^\\/<[A-Za-z0-9\\.]+\\:[A-Za-z0-9\\.]+>(\\/[a-z0-9\\-]+)*$/', $selectorAndFilter)) { - $nodePath = AbsoluteNodePath::tryFromString($selectorAndFilter); - $nodes = $this->addNodesByPath($nodePath, $entryPoints, []); - $flowQuery->setContext($nodes); - return; - } - /** @var Node[] $result */ $result = []; - $parsedFilter = FizzleParser::parseFilterGroup($selectorAndFilter); - $entryPoints = $this->getEntryPoints($contextNodes); - foreach ($parsedFilter['Filters'] as $filter) { - $filterResults = []; - $generatedNodes = false; - if (isset($filter['IdentifierFilter'])) { - $nodeAggregateId = NodeAggregateId::fromString($filter['IdentifierFilter']); - $filterResults = $this->addNodesById($nodeAggregateId, $entryPoints, $filterResults); - $generatedNodes = true; - } elseif (isset($filter['PropertyNameFilter']) || isset($filter['PathFilter'])) { - $nodePath = AbsoluteNodePath::tryFromString($filter['PropertyNameFilter'] ?? $filter['PathFilter']) - ?: NodePath::fromString($filter['PropertyNameFilter'] ?? $filter['PathFilter']); - $filterResults = $this->addNodesByPath($nodePath, $entryPoints, $filterResults); - $generatedNodes = true; + $selectorAndFilterParts = explode(',', $selectorAndFilter); + foreach ($selectorAndFilterParts as $selectorAndFilterPart) { + // handle absolute node pathes separetely as fizzle cannot parse this syntax + if (preg_match('/^\\/<[A-Za-z0-9\\.]+\\:[A-Za-z0-9\\.]+>(\\/[a-z0-9\\-]+)*$/', $selectorAndFilterPart)) { + $nodePath = AbsoluteNodePath::tryFromString($selectorAndFilterPart); + $nodes = $this->addNodesByPath($nodePath, $entryPoints, []); + $result = array_merge($result, $nodes); + continue; } - if (isset($filter['AttributeFilters']) && $filter['AttributeFilters'][0]['Operator'] === 'instanceof') { - $nodeTypeName = NodeTypeName::fromString($filter['AttributeFilters'][0]['Operand']); - $filterResults = $this->addNodesByType($nodeTypeName, $entryPoints, $filterResults); - unset($filter['AttributeFilters'][0]); - $generatedNodes = true; - } - if (isset($filter['AttributeFilters']) && count($filter['AttributeFilters']) > 0) { - if (!$generatedNodes) { - throw new FlowQueryException( - 'find() needs an identifier, path or instanceof filter for the first filter part', - 1436884196 - ); + $parsedFilter = FizzleParser::parseFilterGroup($selectorAndFilterPart); + $entryPoints = $this->getEntryPoints($contextNodes); + foreach ($parsedFilter['Filters'] as $filter) { + $filterResults = []; + $generatedNodes = false; + if (isset($filter['IdentifierFilter'])) { + $nodeAggregateId = NodeAggregateId::fromString($filter['IdentifierFilter']); + $filterResults = $this->addNodesById($nodeAggregateId, $entryPoints, $filterResults); + $generatedNodes = true; + } elseif (isset($filter['PropertyNameFilter']) || isset($filter['PathFilter'])) { + $nodePath = AbsoluteNodePath::tryFromString($filter['PropertyNameFilter'] ?? $filter['PathFilter']) + ?: NodePath::fromString($filter['PropertyNameFilter'] ?? $filter['PathFilter']); + $filterResults = $this->addNodesByPath($nodePath, $entryPoints, $filterResults); + $generatedNodes = true; + } + + if (isset($filter['AttributeFilters']) && $filter['AttributeFilters'][0]['Operator'] === 'instanceof') { + $nodeTypeName = NodeTypeName::fromString($filter['AttributeFilters'][0]['Operand']); + $filterResults = $this->addNodesByType($nodeTypeName, $entryPoints, $filterResults); + unset($filter['AttributeFilters'][0]); + $generatedNodes = true; } - $filterQuery = new FlowQuery($filterResults); - foreach ($filter['AttributeFilters'] as $attributeFilter) { - $filterQuery->pushOperation('filter', [$attributeFilter['text']]); + if (isset($filter['AttributeFilters']) && count($filter['AttributeFilters']) > 0) { + if (!$generatedNodes) { + throw new FlowQueryException( + 'find() needs an identifier, path or instanceof filter for the first filter part', + 1436884196 + ); + } + $filterQuery = new FlowQuery($filterResults); + foreach ($filter['AttributeFilters'] as $attributeFilter) { + $filterQuery->pushOperation('filter', [$attributeFilter['text']]); + } + /** @var array $filterResults */ + $filterResults = iterator_to_array($filterQuery); } - /** @var array $filterResults */ - $filterResults = $filterQuery->getContext(); + $result = array_merge($result, $filterResults); } - $result = array_merge($result, $filterResults); } $uniqueResult = []; diff --git a/Neos.Neos/Tests/Behavior/Features/Fusion/FlowQuery.feature b/Neos.Neos/Tests/Behavior/Features/Fusion/FlowQuery.feature index 9289758f8bd..07835b41d8a 100644 --- a/Neos.Neos/Tests/Behavior/Features/Fusion/FlowQuery.feature +++ b/Neos.Neos/Tests/Behavior/Features/Fusion/FlowQuery.feature @@ -351,14 +351,8 @@ Feature: Tests for the "Neos.ContentRepository" Flow Query methods. When I execute the following Fusion code: """fusion test = Neos.Fusion:DataStructure { - # @todo Decide wether the changed order of the results compared to Neos 8.3 is ok - # Result in Neos 8.3: "typeFilter: a1a,a1b1a,a1a2,a1b2,a1a3,a1a4,a1a5,a1a6" - # Result in Neos 9.0: "typeFilter: a1a,a1a2,a1b2,a1a3,a1a4,a1a5,a1a6,a1b1a" typeFilter = ${q(node).find('[instanceof Neos.Neos:Test.DocumentType2]').get()} - # @todo Fix and re enable `combinedFilter` case - # Result in Neos 8.3: "combinedFilter: a1b1a" - # Result in Neos 9.0: "combinedFilter: a1a,a1a2,a1b2,a1a3,a1a4,a1a5,a1a6,a1b1a" - # combinedFilter = ${q(node).find('[instanceof Neos.Neos:Test.DocumentType2][uriPathSegment*="b1"]').get()} + combinedFilter = ${q(node).find('[instanceof Neos.Neos:Test.DocumentType2][uriPathSegment*="b1"]').get()} identifier = ${q(node).find('#a1b1a').get()} name = ${q(node).find('a1b').get()} relativePath = ${q(node).find('a1b/a1b1').get()} @@ -369,6 +363,7 @@ Feature: Tests for the "Neos.ContentRepository" Flow Query methods. Then I expect the following Fusion rendering result: """ typeFilter: a1a,a1a2,a1b2,a1a3,a1a4,a1a5,a1a6,a1b1a + combinedFilter: a1b1a identifier: a1b1a name: a1b relativePath: a1b1