/** * Parse condition; * * @param $str * @return array * @throws SyntaxErrorException */ private static function parseCondition($str) : array { $parts = []; // REMOVE TRAILING SPACES $str = trim($str); // LOOP THROUGH ALL CHARACTERS $iMax = strlen($str); /** @noinspection ForeachInvariantsInspection */ for ($i = 0; $i < $iMax; $i++) { // IF CHARACTER IS LEFT BRACKET, FIND PAIR BRACKET AND RECURSIVELY FIND CONDITIONS WITHIN THESE BRACKETS if ($str[$i] === '(') { $pairBracketIndex = self::findPairBracketIndex($str, $i + 1); if ($pairBracketIndex > 0) { $part = new WherePart(); $part->type = WherePartType::SUBCONDITION; $subCondition = substr($str, $i + 1, $pairBracketIndex - $i - 1); $part->baseExpr = trim($subCondition); $part->subTree = self::parseCondition($subCondition); $parts[] = $part; $i = $pairBracketIndex; continue; } else { throw new SyntaxErrorException('Missing pair bracket'); } } else { if ($str[$i] === ' ') { if (trim(substr($str, $i, 4)) === Operator::AND) { $part = new WherePart(); $part->type = WherePartType::OPERATOR; $part->value = Operator::AND; $parts[] = $part; $i += 3; } else { if (trim(substr($str, $i, 3)) === Operator::OR) { $part = new WherePart(); $part->type = WherePartType::OPERATOR; $part->value = Operator::OR; $parts[] = $part; $i += 2; } } } else { $match = []; $wasFound = preg_match(self::$regKeyOpValue, substr($str, $i), $match); if ($wasFound) { $part = new WherePart(); $part->type = WherePartType::CONDITION; $part->key = Column::parse($match['key']); $value = $match['value']; if (StringUtils::startsWith($value, '"') && StringUtils::endsWith($value, '"')) { $value = StringUtils::substring($value, 1, StringUtils::length($value) - 1); } $part->value = $value; $part->operator = $match['operator']; $parts[] = $part; $i = $i + strlen($match[0]) - 1; } else { $part = new WherePart(); $part->type = 'UNKNOWN'; $part->value = $str[$i]; $parts[] = $part; $context = self::getErrorContext($str, $i); throw new SyntaxErrorException("Unrecognized char sequence at '{$context['subString']}' starting from index {$context['errorAt']}"); } } } } return $parts; }