Neos\ContentRepository\Eel\FlowQueryOperations\ChildrenOperation::earlyOptimizationOfFilters PHP Method

earlyOptimizationOfFilters() protected method

Optimize for typical use cases, filter by node name and filter by NodeType (instanceof). These cases are now optimized and will only load the nodes that match the filters.
protected earlyOptimizationOfFilters ( FlowQuery $flowQuery, array $parsedFilter ) : boolean
$flowQuery Neos\Eel\FlowQuery\FlowQuery
$parsedFilter array
return boolean
    protected function earlyOptimizationOfFilters(FlowQuery $flowQuery, array $parsedFilter)
    {
        $optimized = false;
        $output = array();
        $outputNodePaths = array();
        foreach ($parsedFilter['Filters'] as $filter) {
            $instanceOfFilters = array();
            $attributeFilters = array();
            if (isset($filter['AttributeFilters'])) {
                foreach ($filter['AttributeFilters'] as $attributeFilter) {
                    if ($attributeFilter['Operator'] === 'instanceof' && $attributeFilter['Identifier'] === null) {
                        $instanceOfFilters[] = $attributeFilter;
                    } else {
                        $attributeFilters[] = $attributeFilter;
                    }
                }
            }
            // Only apply optimization if there's a property name filter or a instanceof filter or another filter already did optimization
            if (isset($filter['PropertyNameFilter']) || isset($filter['PathFilter']) || count($instanceOfFilters) > 0 || $optimized === true) {
                $optimized = true;
                $filteredOutput = array();
                $filteredOutputNodePaths = array();
                // Optimize property name filter if present
                if (isset($filter['PropertyNameFilter']) || isset($filter['PathFilter'])) {
                    $nodePath = isset($filter['PropertyNameFilter']) ? $filter['PropertyNameFilter'] : $filter['PathFilter'];
                    /** @var NodeInterface $contextNode */
                    foreach ($flowQuery->getContext() as $contextNode) {
                        $childNode = $contextNode->getNode($nodePath);
                        if ($childNode !== null && !isset($filteredOutputNodePaths[$childNode->getPath()])) {
                            $filteredOutput[] = $childNode;
                            $filteredOutputNodePaths[$childNode->getPath()] = true;
                        }
                    }
                } elseif (count($instanceOfFilters) > 0) {
                    // Optimize node type filter if present
                    $allowedNodeTypes = array_map(function ($instanceOfFilter) {
                        return $instanceOfFilter['Operand'];
                    }, $instanceOfFilters);
                    /** @var NodeInterface $contextNode */
                    foreach ($flowQuery->getContext() as $contextNode) {
                        /** @var NodeInterface $childNode */
                        foreach ($contextNode->getChildNodes(implode($allowedNodeTypes, ',')) as $childNode) {
                            if (!isset($filteredOutputNodePaths[$childNode->getPath()])) {
                                $filteredOutput[] = $childNode;
                                $filteredOutputNodePaths[$childNode->getPath()] = true;
                            }
                        }
                    }
                }
                // Apply attribute filters if present
                if (isset($filter['AttributeFilters'])) {
                    $attributeFilters = array_reduce($filter['AttributeFilters'], function ($filters, $attributeFilter) {
                        return $filters . $attributeFilter['text'];
                    });
                    $filteredFlowQuery = new FlowQuery($filteredOutput);
                    $filteredFlowQuery->pushOperation('filter', array($attributeFilters));
                    $filteredOutput = $filteredFlowQuery->get();
                }
                // Add filtered nodes to output
                foreach ($filteredOutput as $filteredNode) {
                    if (!isset($outputNodePaths[$filteredNode->getPath()])) {
                        $output[] = $filteredNode;
                    }
                }
            }
        }
        if ($optimized === true) {
            $flowQuery->setContext($output);
        }
        return $optimized;
    }