protected function addCondition($condition, array $params, array &$conditions, array &$conditionsParameters)
{
if (is_array($condition) && !empty($params[0]) && is_array($params[0])) {
return $this->addConditionComposition($condition, $params[0], $conditions, $conditionsParameters);
}
$hash = $this->getConditionHash($condition, $params);
if (isset($this->conditions[$hash])) {
return FALSE;
}
$this->conditions[$hash] = $condition;
$placeholderCount = substr_count($condition, '?');
if ($placeholderCount > 1 && count($params) === 1 && is_array($params[0])) {
$params = $params[0];
}
$condition = trim($condition);
if ($placeholderCount === 0 && count($params) === 1) {
$condition .= ' ?';
} elseif ($placeholderCount !== count($params)) {
throw new Nette\InvalidArgumentException('Argument count does not match placeholder count.');
}
$replace = NULL;
$placeholderNum = 0;
foreach ($params as $arg) {
preg_match('#(?:.*?\\?.*?){' . $placeholderNum . '}(((?:&|\\||^|~|\\+|-|\\*|/|%|\\(|,|<|>|=|(?<=\\W|^)(?:REGEXP|ALL|AND|ANY|BETWEEN|EXISTS|IN|[IR]?LIKE|OR|NOT|SOME|INTERVAL))\\s*)?(?:\\(\\?\\)|\\?))#s', $condition, $match, PREG_OFFSET_CAPTURE);
$hasOperator = $match[1][0] === '?' && $match[1][1] === 0 ? TRUE : !empty($match[2][0]);
if ($arg === NULL) {
$replace = 'IS NULL';
if ($hasOperator) {
if (trim($match[2][0]) === 'NOT') {
$replace = 'IS NOT NULL';
} else {
throw new Nette\InvalidArgumentException('Column operator does not accept NULL argument.');
}
}
} elseif (is_array($arg) || $arg instanceof Selection) {
if ($hasOperator) {
if (trim($match[2][0]) === 'NOT') {
$match[2][0] = rtrim($match[2][0]) . ' IN ';
} elseif (trim($match[2][0]) !== 'IN') {
throw new Nette\InvalidArgumentException('Column operator does not accept array argument.');
}
} else {
$match[2][0] = 'IN ';
}
if ($arg instanceof Selection) {
$clone = clone $arg;
if (!$clone->getSqlBuilder()->select) {
try {
$clone->select($clone->getPrimary());
} catch (\LogicException $e) {
throw new Nette\InvalidArgumentException('Selection argument must have defined a select column.', 0, $e);
}
}
if ($this->driver->isSupported(ISupplementalDriver::SUPPORT_SUBSELECT)) {
$arg = NULL;
$replace = $match[2][0] . '(' . $clone->getSql() . ')';
$conditionsParameters = array_merge($conditionsParameters, $clone->getSqlBuilder()->getParameters());
} else {
$arg = [];
foreach ($clone as $row) {
$arg[] = array_values(iterator_to_array($row));
}
}
}
if ($arg !== NULL) {
if (!$arg) {
$hasBrackets = strpos($condition, '(') !== FALSE;
$hasOperators = preg_match('#AND|OR#', $condition);
$hasNot = strpos($condition, 'NOT') !== FALSE;
$hasPrefixNot = strpos($match[2][0], 'NOT') !== FALSE;
if (!$hasBrackets && ($hasOperators || $hasNot && !$hasPrefixNot)) {
throw new Nette\InvalidArgumentException('Possible SQL query corruption. Add parentheses around operators.');
}
if ($hasPrefixNot) {
$replace = 'IS NULL OR TRUE';
} else {
$replace = 'IS NULL AND FALSE';
}
$arg = NULL;
} else {
$replace = $match[2][0] . '(?)';
$conditionsParameters[] = $arg;
}
}
} elseif ($arg instanceof SqlLiteral) {
$conditionsParameters[] = $arg;
} else {
if (!$hasOperator) {
$replace = '= ?';
}
$conditionsParameters[] = $arg;
}
if ($replace) {
$condition = substr_replace($condition, $replace, $match[1][1], strlen($match[1][0]));
$replace = NULL;
}
if ($arg !== NULL) {
$placeholderNum++;
}
}
$conditions[] = $condition;
return TRUE;
}