class DatabaseCondition implements QueryConditionInterface, Countable {
protected
$conditions =
array();
protected
$arguments =
array();
protected $updated = TRUE;
public function __construct($conjunction) {
$this->conditions['#conjunction'] = $conjunction;
}
/**
* Return the size of this conditional. This is part of the Countable interface.
*
* The size of the conditional is the size of its conditional array minus
* one, because one element is the the conjunction.
*/
public function count() {
return count($this->
conditions) -
1;
}
public function condition($field, $value = NULL, $operator = '=') {
$this->
conditions[] =
array(
'field' => $field,
'value' => $value,
'operator' => $operator,
);
$this->updated = TRUE;
return $this;
}
public function where
($snippet,
$args =
array()) {
$this->
conditions[] =
array(
'field' => $field,
'value' => $args,
'operator' => NULL,
);
$this->updated = TRUE;
return $this;
}
public function conditions() {
// If there's only one entry, it's just the default #type, which means
// we don't really have any conditions to speak of.
return (count($this->
conditions) >
1) ?
$this->
conditions :
array();
}
public function arguments() {
return $this->arguments;
}
public function compile(DatabaseConnection $connection) {
// This value is static, so it will increment across the entire request
// rather than just this query. That is OK, because we only need definitive
// placeholder names if we're going to use them for _alter hooks, which we
// are not. The alter hook would intervene before compilation.
$condition_fragments =
array();
$conditions = $this->conditions;
$conjunction = $conditions['#conjunction'];
unset($conditions['#conjunction']);
foreach ($conditions as $condition) {
if (!
empty($condition['operator'])) {
// It's a structured condition, so parse it out accordingly.
if ($condition['field'] instanceof QueryConditionInterface) {
// Compile the sub-condition recursively and add it to the list.
$return = $condition['field']->compile($connection);
$condition_fragments[] = $return['fragment'];
$arguments += $return['arguments'];
}
else {
// For simplicity, we treat all operators as the same data structure.
// In the typical degenerate case, this won't get changed.
$operator_defaults =
array(
'prefix' => '',
'postfix' => '',
'delimiter' => '',
'operator' => $condition['operator'],
);
$operator = $connection->mapConditionOperator($condition['operator']);
$operator = $this->mapConditionOperator($condition['operator']);
}
$operator += $operator_defaults;
if ($condition['value'] instanceof SelectQuery) {
$placeholders[] = (string)$condition['value'];
$arguments += $condition['value']->arguments();
}
// We assume that if there is a delimiter, then the value is an
// array. If not, it is a scalar. For simplicity, we first convert
// up to an array so that we can build the placeholders in the same way.
elseif (!$operator['delimiter']) {
$condition['value'] =
array($condition['value']);
}
foreach ($condition['value'] as $value) {
$placeholder = ':db_condition_placeholder_'. $next_placeholder++;
$arguments[$placeholder] = $value;
$placeholders[] = $placeholder;
}
$condition_fragments[] =
'(' .
$condition['field'] .
$operator['operator'] .
$operator['prefix'] .
implode($condition['delimiter'],
$placeholders) .
$operator['postfix'] .
')';
}
}
else {
// This condition is a literal string, so let it through as is.
$condition_fragments[] = '(' . $condition['field'] . ')';
$arguments += $condition['value'];
}
}
$this->updated = FALSE;
//$this->stringVersion = implode($conjunction, $condition_fragments);
//$this->arguments = $arguments;
'fragment' =>
implode($conjunction,
$condition_fragments),
'arguments' => $arguments,
);
}
/**
* Gets any special processing requirements for the condition operator.
*
* Some condition types require special processing, such as IN, because
* the value data they pass in is not a simple value. This is a simple
* overridable lookup function.
*
* @param $operator
* The condition operator, such as "IN", "BETWEEN", etc. Case-sensitive.
* @return
* The extra handling directives for the specified operator, or NULL.
*/
protected function mapConditionOperator($operator) {
'BETWEEN' =>
array('delimiter' =>
' AND '),
'IN' =>
array('delimiter' =>
', ',
'prefix' =>
' (',
'postfix' =>
')'),
'NOT IN' =>
array('delimiter' =>
', ',
'prefix' =>
' (',
'postfix' =>
')'),
'LIKE' =>
array('operator' =>
'LIKE'),
);
$return =
isset($specials[$operator]) ?
$specials[$operator] :
array();
$return +=
array('operator' =>
$operator);
return $return;
}
}