class Condition

Same name in this branch

Generic class for a series of conditions in a query.

Hierarchy

Expanded class hierarchy of Condition

6 files declare their use of Condition
Condition.php in drupal/core/modules/field_sql_storage/lib/Drupal/field_sql_storage/Entity/Condition.php
Definition of Drupal\field_sql_storage\Query\ConditionSql.
database.inc in drupal/core/includes/database.inc
Core systems for the database layer.
Schema.php in drupal/core/lib/Drupal/Core/Database/Schema.php
Definition of Drupal\Core\Database\Schema
Schema.php in drupal/core/lib/Drupal/Core/Database/Driver/mysql/Schema.php
Definition of Drupal\Core\Database\Driver\mysql\Schema
Schema.php in drupal/core/lib/Drupal/Core/Database/Driver/pgsql/Schema.php
Definition of Drupal\Core\Database\Driver\pgsql\Schema

... See full list

1 string reference to 'Condition'
ConditionManager::__construct in drupal/core/lib/Drupal/Core/Condition/ConditionManager.php
Constructs aa ConditionManager object.

File

drupal/core/lib/Drupal/Core/Database/Query/Condition.php, line 17
Definition of Drupal\Core\Database\Query\Condition

Namespace

Drupal\Core\Database\Query
View source
class Condition implements ConditionInterface, Countable {

  /**
   * Array of conditions.
   *
   * @var array
   */
  protected $conditions = array();

  /**
   * Array of arguments.
   *
   * @var array
   */
  protected $arguments = array();

  /**
   * Whether the conditions have been changed.
   *
   * TRUE if the condition has been changed since the last compile.
   * FALSE if the condition has been compiled and not changed.
   *
   * @var bool
   */
  protected $changed = TRUE;

  /**
   * The identifier of the query placeholder this condition has been compiled against.
   */
  protected $queryPlaceholderIdentifier;

  /**
   * Constructs a Condition object.
   *
   * @param string $conjunction
   *   The operator to use to combine conditions: 'AND' or 'OR'.
   */
  public function __construct($conjunction) {
    $this->conditions['#conjunction'] = $conjunction;
  }

  /**
   * Implements Countable::count().
   *
   * Returns the size of this conditional. 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;
  }

  /**
   * Implements Drupal\Core\Database\Query\ConditionInterface::condition().
   */
  public function condition($field, $value = NULL, $operator = NULL) {
    if (!isset($operator)) {
      if (is_array($value)) {
        $operator = 'IN';
      }
      else {
        $operator = '=';
      }
    }
    $this->conditions[] = array(
      'field' => $field,
      'value' => $value,
      'operator' => $operator,
    );
    $this->changed = TRUE;
    return $this;
  }

  /**
   * Implements Drupal\Core\Database\Query\ConditionInterface::where().
   */
  public function where($snippet, $args = array()) {
    $this->conditions[] = array(
      'field' => $snippet,
      'value' => $args,
      'operator' => NULL,
    );
    $this->changed = TRUE;
    return $this;
  }

  /**
   * Implements Drupal\Core\Database\Query\ConditionInterface::isNull().
   */
  public function isNull($field) {
    return $this
      ->condition($field, NULL, 'IS NULL');
  }

  /**
   * Implements Drupal\Core\Database\Query\ConditionInterface::isNotNull().
   */
  public function isNotNull($field) {
    return $this
      ->condition($field, NULL, 'IS NOT NULL');
  }

  /**
   * Implements Drupal\Core\Database\Query\ConditionInterface::exists().
   */
  public function exists(SelectInterface $select) {
    return $this
      ->condition('', $select, 'EXISTS');
  }

  /**
   * Implements Drupal\Core\Database\Query\ConditionInterface::notExists().
   */
  public function notExists(SelectInterface $select) {
    return $this
      ->condition('', $select, 'NOT EXISTS');
  }

  /**
   * Implements Drupal\Core\Database\Query\ConditionInterface::conditions().
   */
  public function &conditions() {
    return $this->conditions;
  }

  /**
   * Implements Drupal\Core\Database\Query\ConditionInterface::arguments().
   */
  public function arguments() {

    // If the caller forgot to call compile() first, refuse to run.
    if ($this->changed) {
      return NULL;
    }
    return $this->arguments;
  }

  /**
   * Implements Drupal\Core\Database\Query\ConditionInterface::compile().
   */
  public function compile(Connection $connection, PlaceholderInterface $queryPlaceholder) {

    // Re-compile if this condition changed or if we are compiled against a
    // different query placeholder object.
    if ($this->changed || isset($this->queryPlaceholderIdentifier) && $this->queryPlaceholderIdentifier != $queryPlaceholder
      ->uniqueIdentifier()) {
      $this->queryPlaceholderIdentifier = $queryPlaceholder
        ->uniqueIdentifier();
      $condition_fragments = array();
      $arguments = array();
      $conditions = $this->conditions;
      $conjunction = $conditions['#conjunction'];
      unset($conditions['#conjunction']);
      foreach ($conditions as $condition) {
        if (empty($condition['operator'])) {

          // This condition is a literal string, so let it through as is.
          $condition_fragments[] = ' (' . $condition['field'] . ') ';
          $arguments += $condition['value'];
        }
        else {

          // It's a structured condition, so parse it out accordingly.
          // Note that $condition['field'] will only be an object for a dependent
          // DatabaseCondition object, not for a dependent subquery.
          if ($condition['field'] instanceof ConditionInterface) {

            // Compile the sub-condition recursively and add it to the list.
            $condition['field']
              ->compile($connection, $queryPlaceholder);
            $condition_fragments[] = '(' . (string) $condition['field'] . ')';
            $arguments += $condition['field']
              ->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'],
              'use_value' => TRUE,
            );
            $operator = $connection
              ->mapConditionOperator($condition['operator']);
            if (!isset($operator)) {
              $operator = $this
                ->mapConditionOperator($condition['operator']);
            }
            $operator += $operator_defaults;
            $placeholders = array();
            if ($condition['value'] instanceof SelectInterface) {
              $condition['value']
                ->compile($connection, $queryPlaceholder);
              $placeholders[] = (string) $condition['value'];
              $arguments += $condition['value']
                ->arguments();

              // Subqueries are the actual value of the operator, we don't
              // need to add another below.
              $operator['use_value'] = FALSE;
            }
            elseif (!$operator['delimiter']) {
              $condition['value'] = array(
                $condition['value'],
              );
            }
            if ($operator['use_value']) {
              foreach ($condition['value'] as $value) {
                $placeholder = ':db_condition_placeholder_' . $queryPlaceholder
                  ->nextPlaceholder();
                $arguments[$placeholder] = $value;
                $placeholders[] = $placeholder;
              }
            }
            $condition_fragments[] = ' (' . $connection
              ->escapeField($condition['field']) . ' ' . $operator['operator'] . ' ' . $operator['prefix'] . implode($operator['delimiter'], $placeholders) . $operator['postfix'] . ') ';
          }
        }
      }
      $this->changed = FALSE;
      $this->stringVersion = implode($conjunction, $condition_fragments);
      $this->arguments = $arguments;
    }
  }

  /**
   * Implements Drupal\Core\Database\Query\ConditionInterface::compiled().
   */
  public function compiled() {
    return !$this->changed;
  }

  /**
   * Implements PHP magic __toString method to convert the conditions to string.
   *
   * @return string
   *   A string version of the conditions.
   */
  public function __toString() {

    // If the caller forgot to call compile() first, refuse to run.
    if ($this->changed) {
      return '';
    }
    return $this->stringVersion;
  }

  /**
   * PHP magic __clone() method.
   *
   * Only copies fields that implement Drupal\Core\Database\Query\ConditionInterface. Also sets
   * $this->changed to TRUE.
   */
  function __clone() {
    $this->changed = TRUE;
    foreach ($this->conditions as $key => $condition) {
      if ($key !== '#conjunction') {
        if ($condition['field'] instanceof ConditionInterface) {
          $this->conditions[$key]['field'] = clone $condition['field'];
        }
        if ($condition['value'] instanceof SelectInterface) {
          $this->conditions[$key]['value'] = clone $condition['value'];
        }
      }
    }
  }

  /**
   * 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) {

    // $specials does not use drupal_static as its value never changes.
    static $specials = array(
      'BETWEEN' => array(
        'delimiter' => ' AND ',
      ),
      'IN' => array(
        'delimiter' => ', ',
        'prefix' => ' (',
        'postfix' => ')',
      ),
      'NOT IN' => array(
        'delimiter' => ', ',
        'prefix' => ' (',
        'postfix' => ')',
      ),
      'EXISTS' => array(
        'prefix' => ' (',
        'postfix' => ')',
      ),
      'NOT EXISTS' => array(
        'prefix' => ' (',
        'postfix' => ')',
      ),
      'IS NULL' => array(
        'use_value' => FALSE,
      ),
      'IS NOT NULL' => array(
        'use_value' => FALSE,
      ),
      // Use backslash for escaping wildcard characters.
      'LIKE' => array(
        'postfix' => " ESCAPE '\\\\'",
      ),
      'NOT LIKE' => array(
        'postfix' => " ESCAPE '\\\\'",
      ),
      // These ones are here for performance reasons.
      '=' => array(),
      '<' => array(),
      '>' => array(),
      '>=' => array(),
      '<=' => array(),
    );
    if (isset($specials[$operator])) {
      $return = $specials[$operator];
    }
    else {

      // We need to upper case because PHP index matches are case sensitive but
      // do not need the more expensive drupal_strtoupper because SQL statements are ASCII.
      $operator = strtoupper($operator);
      $return = isset($specials[$operator]) ? $specials[$operator] : array();
    }
    $return += array(
      'operator' => $operator,
    );
    return $return;
  }

}

Members

Namesort descending Modifiers Type Description Overrides
Condition::$arguments protected property Array of arguments.
Condition::$changed protected property Whether the conditions have been changed.
Condition::$conditions protected property Array of conditions.
Condition::$queryPlaceholderIdentifier protected property The identifier of the query placeholder this condition has been compiled against.
Condition::arguments public function Implements Drupal\Core\Database\Query\ConditionInterface::arguments(). Overrides ConditionInterface::arguments
Condition::compile public function Implements Drupal\Core\Database\Query\ConditionInterface::compile(). Overrides ConditionInterface::compile
Condition::compiled public function Implements Drupal\Core\Database\Query\ConditionInterface::compiled(). Overrides ConditionInterface::compiled
Condition::condition public function Implements Drupal\Core\Database\Query\ConditionInterface::condition(). Overrides ConditionInterface::condition
Condition::conditions public function Implements Drupal\Core\Database\Query\ConditionInterface::conditions(). Overrides ConditionInterface::conditions
Condition::count public function Implements Countable::count().
Condition::exists public function Implements Drupal\Core\Database\Query\ConditionInterface::exists(). Overrides ConditionInterface::exists
Condition::isNotNull public function Implements Drupal\Core\Database\Query\ConditionInterface::isNotNull(). Overrides ConditionInterface::isNotNull
Condition::isNull public function Implements Drupal\Core\Database\Query\ConditionInterface::isNull(). Overrides ConditionInterface::isNull
Condition::mapConditionOperator protected function Gets any special processing requirements for the condition operator.
Condition::notExists public function Implements Drupal\Core\Database\Query\ConditionInterface::notExists(). Overrides ConditionInterface::notExists
Condition::where public function Implements Drupal\Core\Database\Query\ConditionInterface::where(). Overrides ConditionInterface::where
Condition::__clone function PHP magic __clone() method.
Condition::__construct public function Constructs a Condition object.
Condition::__toString public function Implements PHP magic __toString method to convert the conditions to string.