function StringDatabaseStorage::dbStringSelect

Same name in other branches
  1. 8.9.x core/modules/locale/src/StringDatabaseStorage.php \Drupal\locale\StringDatabaseStorage::dbStringSelect()
  2. 10 core/modules/locale/src/StringDatabaseStorage.php \Drupal\locale\StringDatabaseStorage::dbStringSelect()
  3. 11.x core/modules/locale/src/StringDatabaseStorage.php \Drupal\locale\StringDatabaseStorage::dbStringSelect()

Builds a SELECT query with multiple conditions and fields.

The query uses both 'locales_source' and 'locales_target' tables. Note that by default, as we are selecting both translated and untranslated strings target field's conditions will be modified to match NULL rows too.

Parameters

array $conditions: An associative array with field => value conditions that may include NULL values. If a language condition is included it will be used for joining the 'locales_target' table.

array $options: An associative array of additional options. It may contain any of the options used by Drupal\locale\StringStorageInterface::getStrings() and these additional ones:

  • 'translation', Whether to include translation fields too. Defaults to FALSE.

Return value

\Drupal\Core\Database\Query\Select Query object with all the tables, fields and conditions.

File

core/modules/locale/src/StringDatabaseStorage.php, line 353

Class

StringDatabaseStorage
Defines a class to store localized strings in the database.

Namespace

Drupal\locale

Code

protected function dbStringSelect(array $conditions, array $options = []) {
    // Start building the query with source table and check whether we need to
    // join the target table too.
    $query = $this->connection
        ->select('locales_source', 's', $this->options)
        ->fields('s');
    // Figure out how to join and translate some options into conditions.
    if (isset($conditions['translated'])) {
        // This is a meta-condition we need to translate into simple ones.
        if ($conditions['translated']) {
            // Select only translated strings.
            $join = 'innerJoin';
        }
        else {
            // Select only untranslated strings.
            $join = 'leftJoin';
            $conditions['translation'] = NULL;
        }
        unset($conditions['translated']);
    }
    else {
        $join = !empty($options['translation']) ? 'leftJoin' : FALSE;
    }
    if ($join) {
        if (isset($conditions['language'])) {
            // If we've got a language condition, we use it for the join.
            $query->{$join}('locales_target', 't', "t.lid = s.lid AND t.language = :langcode", [
                ':langcode' => $conditions['language'],
            ]);
            unset($conditions['language']);
        }
        else {
            // Since we don't have a language, join with locale id only.
            $query->{$join}('locales_target', 't', "t.lid = s.lid");
        }
        if (!empty($options['translation'])) {
            // We cannot just add all fields because 'lid' may get null values.
            $query->fields('t', [
                'language',
                'translation',
                'customized',
            ]);
        }
    }
    // If we have conditions for location's type or name, then we need the
    // location table, for which we add a subquery. We cast any scalar value to
    // array so we can consistently use IN conditions.
    if (isset($conditions['type']) || isset($conditions['name'])) {
        $subquery = $this->connection
            ->select('locales_location', 'l', $this->options)
            ->fields('l', [
            'sid',
        ]);
        foreach ([
            'type',
            'name',
        ] as $field) {
            if (isset($conditions[$field])) {
                $subquery->condition('l.' . $field, (array) $conditions[$field], 'IN');
                unset($conditions[$field]);
            }
        }
        $query->condition('s.lid', $subquery, 'IN');
    }
    // Add conditions for both tables.
    foreach ($conditions as $field => $value) {
        $table_alias = $this->dbFieldTable($field);
        $field_alias = $table_alias . '.' . $field;
        if (is_null($value)) {
            $query->isNull($field_alias);
        }
        elseif ($table_alias == 't' && $join === 'leftJoin') {
            // Conditions for target fields when doing an outer join only make
            // sense if we add also OR field IS NULL.
            $query->condition($this->connection
                ->condition('OR')
                ->condition($field_alias, (array) $value, 'IN')
                ->isNull($field_alias));
        }
        else {
            $query->condition($field_alias, (array) $value, 'IN');
        }
    }
    // Process other options, string filter, query limit, etc.
    if (!empty($options['filters'])) {
        if (count($options['filters']) > 1) {
            $filter = $this->connection
                ->condition('OR');
            $query->condition($filter);
        }
        else {
            // If we have a single filter, just add it to the query.
            $filter = $query;
        }
        foreach ($options['filters'] as $field => $string) {
            $filter->condition($this->dbFieldTable($field) . '.' . $field, '%' . $this->connection
                ->escapeLike($string) . '%', 'LIKE');
        }
    }
    if (!empty($options['pager limit'])) {
        $query = $query->extend(PagerSelectExtender::class)
            ->limit($options['pager limit']);
    }
    return $query;
}

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