Condition.php

Same filename in this branch
  1. 8.9.x core/lib/Drupal/Core/Database/Query/Condition.php
  2. 8.9.x core/lib/Drupal/Core/Entity/Query/Sql/Condition.php
  3. 8.9.x core/lib/Drupal/Core/Entity/Query/Sql/pgsql/Condition.php
  4. 8.9.x core/lib/Drupal/Core/Entity/Query/Null/Condition.php
  5. 8.9.x core/lib/Drupal/Core/Entity/KeyValueStore/Query/Condition.php
  6. 8.9.x core/lib/Drupal/Core/Condition/Annotation/Condition.php
Same filename in other branches
  1. 9 core/tests/fixtures/database_drivers/module/corefake/src/Driver/Database/corefakeWithAllCustomClasses/Condition.php
  2. 9 core/lib/Drupal/Core/Config/Entity/Query/Condition.php
  3. 9 core/lib/Drupal/Core/Database/Query/Condition.php
  4. 9 core/lib/Drupal/Core/Entity/Query/Sql/Condition.php
  5. 9 core/lib/Drupal/Core/Entity/Query/Sql/pgsql/Condition.php
  6. 9 core/lib/Drupal/Core/Entity/Query/Null/Condition.php
  7. 9 core/lib/Drupal/Core/Entity/KeyValueStore/Query/Condition.php
  8. 9 core/lib/Drupal/Core/Condition/Annotation/Condition.php
  9. 10 core/tests/fixtures/database_drivers/module/core_fake/src/Driver/Database/CoreFakeWithAllCustomClasses/Condition.php
  10. 10 core/lib/Drupal/Core/Config/Entity/Query/Condition.php
  11. 10 core/lib/Drupal/Core/Database/Query/Condition.php
  12. 10 core/lib/Drupal/Core/Entity/Query/Sql/Condition.php
  13. 10 core/lib/Drupal/Core/Entity/Query/Sql/pgsql/Condition.php
  14. 10 core/lib/Drupal/Core/Entity/Query/Null/Condition.php
  15. 10 core/lib/Drupal/Core/Entity/KeyValueStore/Query/Condition.php
  16. 10 core/lib/Drupal/Core/Condition/Attribute/Condition.php
  17. 10 core/lib/Drupal/Core/Condition/Annotation/Condition.php
  18. 11.x core/tests/fixtures/database_drivers/module/core_fake/src/Driver/Database/CoreFakeWithAllCustomClasses/Condition.php
  19. 11.x core/lib/Drupal/Core/Config/Entity/Query/Condition.php
  20. 11.x core/lib/Drupal/Core/Database/Query/Condition.php
  21. 11.x core/lib/Drupal/Core/Entity/Query/Sql/Condition.php
  22. 11.x core/lib/Drupal/Core/Entity/Query/Sql/pgsql/Condition.php
  23. 11.x core/lib/Drupal/Core/Entity/Query/Null/Condition.php
  24. 11.x core/lib/Drupal/Core/Entity/KeyValueStore/Query/Condition.php
  25. 11.x core/lib/Drupal/Core/Condition/Attribute/Condition.php
  26. 11.x core/lib/Drupal/Core/Condition/Annotation/Condition.php

Namespace

Drupal\Core\Config\Entity\Query

File

core/lib/Drupal/Core/Config/Entity/Query/Condition.php

View source
<?php

namespace Drupal\Core\Config\Entity\Query;

use Drupal\Core\Entity\Query\ConditionBase;
use Drupal\Core\Entity\Query\ConditionInterface;
use Drupal\Core\Entity\Query\QueryException;

/**
 * Defines the condition class for the config entity query.
 *
 * @see \Drupal\Core\Config\Entity\Query\Query
 */
class Condition extends ConditionBase {
    
    /**
     * {@inheritdoc}
     */
    public function compile($configs) {
        $and = strtoupper($this->conjunction) == 'AND';
        $single_conditions = [];
        $condition_groups = [];
        foreach ($this->conditions as $condition) {
            if ($condition['field'] instanceof ConditionInterface) {
                $condition_groups[] = $condition;
            }
            else {
                if (!isset($condition['operator'])) {
                    $condition['operator'] = is_array($condition['value']) ? 'IN' : '=';
                }
                // Lowercase condition value(s) for case-insensitive matches.
                if (is_array($condition['value'])) {
                    $condition['value'] = array_map('mb_strtolower', $condition['value']);
                }
                elseif (!is_bool($condition['value'])) {
                    $condition['value'] = mb_strtolower($condition['value']);
                }
                $single_conditions[] = $condition;
            }
        }
        $return = [];
        if ($single_conditions) {
            foreach ($configs as $config_name => $config) {
                foreach ($single_conditions as $condition) {
                    $match = $this->matchArray($condition, $config, explode('.', $condition['field']));
                    // If AND and it's not matching, then the rest of conditions do not
                    // matter and this config object does not match.
                    // If OR and it is matching, then the rest of conditions do not
                    // matter and this config object does match.
                    if ($and != $match) {
                        break;
                    }
                }
                if ($match) {
                    $return[$config_name] = $config;
                }
            }
        }
        elseif (!$condition_groups || $and) {
            // If there were no single conditions then either:
            // - Complex conditions, OR: need to start from no entities.
            // - Complex conditions, AND: need to start from all entities.
            // - No complex conditions (AND/OR doesn't matter): need to return all
            //   entities.
            $return = $configs;
        }
        foreach ($condition_groups as $condition) {
            $group_entities = $condition['field']->compile($configs);
            if ($and) {
                $return = array_intersect_key($return, $group_entities);
            }
            else {
                $return = $return + $group_entities;
            }
        }
        return $return;
    }
    
    /**
     * {@inheritdoc}
     */
    public function exists($field, $langcode = NULL) {
        return $this->condition($field, NULL, 'IS NOT NULL', $langcode);
    }
    
    /**
     * {@inheritdoc}
     */
    public function notExists($field, $langcode = NULL) {
        return $this->condition($field, NULL, 'IS NULL', $langcode);
    }
    
    /**
     * Matches for an array representing one or more config paths.
     *
     * @param array $condition
     *   The condition array as created by the condition() method.
     * @param array $data
     *   The config array or part of it.
     * @param array $needs_matching
     *   The list of config array keys needing a match. Can contain config keys
     *   and the * wildcard.
     * @param array $parents
     *   The current list of parents.
     *
     * @return bool
     *   TRUE when the condition matched to the data else FALSE.
     */
    protected function matchArray(array $condition, array $data, array $needs_matching, array $parents = []) {
        $parent = array_shift($needs_matching);
        if ($parent === '*') {
            $candidates = array_keys($data);
        }
        else {
            // Avoid a notice when calling match() later.
            if (!isset($data[$parent])) {
                $data[$parent] = NULL;
            }
            $candidates = [
                $parent,
            ];
        }
        foreach ($candidates as $key) {
            if ($needs_matching) {
                if (is_array($data[$key])) {
                    $new_parents = $parents;
                    $new_parents[] = $key;
                    if ($this->matchArray($condition, $data[$key], $needs_matching, $new_parents)) {
                        return TRUE;
                    }
                }
                elseif ($condition['operator'] === 'IS NULL') {
                    return TRUE;
                }
            }
            elseif ($this->match($condition, $data[$key])) {
                return TRUE;
            }
        }
        return FALSE;
    }
    
    /**
     * Perform the actual matching.
     *
     * @param array $condition
     *   The condition array as created by the condition() method.
     * @param string $value
     *   The value to match against.
     *
     * @return bool
     *   TRUE when matches else FALSE.
     */
    protected function match(array $condition, $value) {
        // "IS NULL" and "IS NOT NULL" conditions can also deal with array values,
        // so we return early for them to avoid problems.
        if (in_array($condition['operator'], [
            'IS NULL',
            'IS NOT NULL',
        ], TRUE)) {
            $should_be_set = $condition['operator'] === 'IS NOT NULL';
            return $should_be_set === isset($value);
        }
        if (isset($value)) {
            // We always want a case-insensitive match.
            if (!is_bool($value)) {
                $value = mb_strtolower($value);
            }
            switch ($condition['operator']) {
                case '=':
                    return $value == $condition['value'];
                case '>':
                    return $value > $condition['value'];
                case '<':
                    return $value < $condition['value'];
                case '>=':
                    return $value >= $condition['value'];
                case '<=':
                    return $value <= $condition['value'];
                case '<>':
                    return $value != $condition['value'];
                case 'IN':
                    return array_search($value, $condition['value']) !== FALSE;
                case 'NOT IN':
                    return array_search($value, $condition['value']) === FALSE;
                case 'STARTS_WITH':
                    return strpos($value, $condition['value']) === 0;
                case 'CONTAINS':
                    return strpos($value, $condition['value']) !== FALSE;
                case 'ENDS_WITH':
                    return substr($value, -strlen($condition['value'])) === (string) $condition['value'];
                default:
                    throw new QueryException('Invalid condition operator.');
            }
        }
        return FALSE;
    }

}

Classes

Title Deprecated Summary
Condition Defines the condition class for the config entity query.

Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.