You are here

public function Condition::compile in Zircon Profile 8

Same name in this branch
  1. 8 core/lib/Drupal/Core/Database/Query/Condition.php \Drupal\Core\Database\Query\Condition::compile()
  2. 8 core/lib/Drupal/Core/Config/Entity/Query/Condition.php \Drupal\Core\Config\Entity\Query\Condition::compile()
  3. 8 core/lib/Drupal/Core/Entity/Query/Sql/Condition.php \Drupal\Core\Entity\Query\Sql\Condition::compile()
  4. 8 core/lib/Drupal/Core/Entity/Query/Null/Condition.php \Drupal\Core\Entity\Query\Null\Condition::compile()
Same name and namespace in other branches
  1. 8.0 core/lib/Drupal/Core/Database/Query/Condition.php \Drupal\Core\Database\Query\Condition::compile()

Compiles the saved conditions for later retrieval.

This method does not return anything, but simply prepares data to be retrieved via __toString() and arguments().

Parameters

$connection: The database connection for which to compile the conditionals.

$queryPlaceholder: The query this condition belongs to. If not given, the current query is used.

Overrides ConditionInterface::compile

File

core/lib/Drupal/Core/Database/Query/Condition.php, line 153
Contains \Drupal\Core\Database\Query\Condition.

Class

Condition
Generic class for a series of conditions in a query.

Namespace

Drupal\Core\Database\Query

Code

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,
          );

          // Remove potentially dangerous characters.
          // If something passed in an invalid character stop early, so we
          // don't rely on a broken SQL statement when we would just replace
          // those characters.
          if (stripos($condition['operator'], 'UNION') !== FALSE || strpbrk($condition['operator'], '[-\'"();') !== FALSE) {
            $this->changed = TRUE;
            $this->arguments = [];

            // Provide a string which will result into an empty query result.
            $this->stringVersion = '( AND 1 = 0 )';

            // Conceptually throwing an exception caused by user input is bad
            // as you result into a WSOD, which depending on your webserver
            // configuration can result into the assumption that your site is
            // broken.
            // On top of that the database API relies on __toString() which
            // does not allow to throw exceptions.
            trigger_error('Invalid characters in query operator: ' . $condition['operator'], E_USER_ERROR);
            return;
          }
          $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'] && !is_array($condition['value'])) {
            $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;
  }
}