useHashEq && $this->isPathPrefixOperator($operator)) { $this->useHashEq = false; } parent::inspectOperator($operator); } public function processOperator(ISearchOperator &$operator) { if (!$this->useHashEq && $operator instanceof ISearchComparison && !$operator->getExtra() && $operator->getField() === 'path' && $operator->getType() === ISearchComparison::COMPARE_EQUAL) { $operator->setQueryHint(ISearchComparison::HINT_PATH_EQ_HASH, false); } parent::processOperator($operator); } private function isPathPrefixOperator(ISearchOperator $operator): bool { if ($operator instanceof ISearchBinaryOperator && $operator->getType() === ISearchBinaryOperator::OPERATOR_OR && count($operator->getArguments()) == 2) { $a = $operator->getArguments()[0]; $b = $operator->getArguments()[1]; if ($this->operatorPairIsPathPrefix($a, $b) || $this->operatorPairIsPathPrefix($b, $a)) { return true; } } return false; } private function operatorPairIsPathPrefix(ISearchOperator $like, ISearchOperator $equal): bool { return ( $like instanceof ISearchComparison && $equal instanceof ISearchComparison && !$like->getExtra() && !$equal->getExtra() && $like->getField() === 'path' && $equal->getField() === 'path' && $like->getType() === ISearchComparison::COMPARE_LIKE_CASE_SENSITIVE && $equal->getType() === ISearchComparison::COMPARE_EQUAL && $like->getValue() === SearchComparison::escapeLikeParameter($equal->getValue()) . '/%' ); } }