function exclude() { foreach (func_get_args() as $Q) { $this->constraints[] = $Q instanceof Util\Q ? $Q->negate() : Util\Q::not($Q); } return $this; }
/** * compileQ * * Build a constraint represented in an arbitrarily nested Q instance. * The placement of the compiled constraint is also considered and * represented in the resulting CompiledExpression instance. * * Parameters: * $Q - (Util\Q) constraint represented in a Q instance * $model - (string) root model class for all the field references in * the Util\Q instance * $slot - (int) slot for inputs to be placed. Useful to differenciate * inputs placed in the joins and where clauses for SQL backends * which do not support named parameters. * * Returns: * (CompiledExpression) object containing the compiled expression (with * AND, OR, and NOT operators added). Furthermore, the $type attribute * of the CompiledExpression will allow the compiler to place the * constraint properly in the WHERE or HAVING clause appropriately. */ function compileQ(Util\Q $Q, $model, $slot = false) { $filter = array(); $type = CompiledExpression::TYPE_WHERE; foreach ($Q->constraints as $field => $value) { // Handle nested constraints if ($value instanceof Util\Q) { $filter[] = $T = $this->compileQ($value, $model, $slot); // Bubble up HAVING constraints if ($T instanceof CompiledExpression && $T->type == CompiledExpression::TYPE_HAVING) { $type = $T->type; } } elseif ($value instanceof Model\ModelBase) { $criteria = array(); foreach ($value->pk as $f => $v) { $f = $field . '__' . $f; $criteria[$f] = $v; } $filter[] = $this->compileQ(new Util\Q($criteria), $model, $slot); } else { list($field, $op) = $this->getField($field, $model); if ($field instanceof Util\Aggregate) { // This constraint has to go in the HAVING clause $field = $field->toSql($this, $model); $type = CompiledExpression::TYPE_HAVING; } if ($value === null) { $filter[] = sprintf('%s IS NULL', $field); } elseif ($value instanceof Util\Field) { $filter[] = sprintf($op, $field, $value->toSql($this, $model)); } elseif (is_callable($op)) { $filter[] = call_user_func($op, $field, $value, $model); } else { $filter[] = sprintf($op, $field, $this->input($value, $slot)); } } } $glue = $Q->isOred() ? ' OR ' : ' AND '; $clause = implode($glue, $filter); if (count($filter) > 1) { $clause = '(' . $clause . ')'; } if ($Q->isNegated()) { $clause = 'NOT ' . $clause; } return new CompiledExpression($clause, $type); }