Skip to content

Commit

Permalink
TASK: Fix find operation
Browse files Browse the repository at this point in the history
Absolute pathes are handled separately as the fizzle parser cannot handle the syntax
  • Loading branch information
mficzel committed Nov 10, 2023
1 parent 5f288c6 commit e7de457
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 48 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<int,mixed> $filterResults */
$filterResults = iterator_to_array($filterQuery);
}
/** @var array<int,mixed> $filterResults */
$filterResults = $filterQuery->getContext();
$result = array_merge($result, $filterResults);
}
$result = array_merge($result, $filterResults);
}

$uniqueResult = [];
Expand Down
9 changes: 2 additions & 7 deletions Neos.Neos/Tests/Behavior/Features/Fusion/FlowQuery.feature
Original file line number Diff line number Diff line change
Expand Up @@ -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()}
Expand All @@ -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
Expand Down

0 comments on commit e7de457

Please sign in to comment.