function SqlContentEntityStorage::loadMultipleCardinalityFields

Same name and namespace in other branches
  1. 11.x core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php \Drupal\Core\Entity\Sql\SqlContentEntityStorage::loadMultipleCardinalityFields()

Load multiple cardinality fields.

Parameters

array &$values: The entity values populated so far.

string $id_key: The ID key depending on whether regular entities or revisions are being loaded.

bool $load_from_revision: Whether we're loading from revisions.

array $multiple_cardinality_fields: The multiple cardinality fields to load.

array $definitions: The field definitions.

array $field_columns: The field columns.

array $field_definition_columns: The field definition columns.

array $default_langcodes: The default langcodes.

array $ids: The entity or revision IDs being loaded.

1 call to SqlContentEntityStorage::loadMultipleCardinalityFields()
SqlContentEntityStorage::loadFromDedicatedTables in core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php
Loads values of fields stored in dedicated tables for a group of entities.

File

core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php, line 1557

Class

SqlContentEntityStorage
A content entity database storage implementation.

Namespace

Drupal\Core\Entity\Sql

Code

private function loadMultipleCardinalityFields(array &$values, string $id_key, bool $load_from_revision, array $multiple_cardinality_fields, array $definitions, array $field_columns, array $field_definition_columns, array $default_langcodes, array $ids) : void {
  $table_mapping = $this->getTableMapping();
  $delta_keys = [];
  if (count($multiple_cardinality_fields) > 1) {
    // Each field table holds one row per delta, and different fields can have
    // different deltas. Left joining several field tables directly would
    // multiply their rows together (a cartesian product). To avoid this,
    // build a "delta spine": the set of (ID, langcode, delta) combinations
    // that exist across the fields in this chunk. Every field table is then
    // left joined on that delta, so each delta produces one row and the field
    // values line up.
    $query = $delta_query = NULL;
    foreach ($multiple_cardinality_fields as $field_name => $storage_definition) {
      $table = !$load_from_revision ? $table_mapping->getDedicatedDataTableName($storage_definition) : $table_mapping->getDedicatedRevisionTableName($storage_definition);
      $select = $this->database
        ->select($table, $table);
      $select->addField($table, $id_key, 'id');
      if ($this->langcodeKey) {
        $select->addField($table, 'langcode', 'langcode');
      }
      $select->addField($table, 'delta', 'delta');
      $select->condition("[{$table}].[{$id_key}]", $ids, 'IN');
      $select->condition("[{$table}].[deleted]", 0);
      if ($delta_query === NULL) {
        $delta_query = $select;
      }
      else {
        $delta_query->union($select);
      }
      if (!$query) {
        $query = $this->database
          ->select($delta_query, 'delta_join');
        $query->addField('delta_join', 'id', 'id');
        if ($this->langcodeKey) {
          $query->addField('delta_join', 'langcode', 'langcode');
        }
        // Sort by the delta provided by the delta spine.
        $query->orderBy('[delta_join].[delta]');
      }
      $table = !$load_from_revision ? $table_mapping->getDedicatedDataTableName($storage_definition) : $table_mapping->getDedicatedRevisionTableName($storage_definition);
      // Left join the field table to the delta spine on ID, langcode and
      // delta.
      if ($this->langcodeKey) {
        $query->leftJoin($table, $table, "[{$table}].[{$id_key}] = [delta_join].[id] AND [{$table}].[langcode] = [delta_join].[langcode] AND [{$table}].[delta] = [delta_join].[delta] AND [{$table}].[deleted] = 0");
      }
      else {
        $query->leftJoin($table, $table, "[{$table}].[{$id_key}] = [delta_join].[id] AND [{$table}].[delta] = [delta_join].[delta] AND [{$table}].[deleted] = 0");
      }
      $query->fields($table, $field_columns[$field_name]);
      $delta_keys[$field_name] = $query->addField($table, 'delta', $field_name . '_delta');
    }
  }
  else {
    // A single field table cannot multiply, so select from it directly.
    $field_name = key($multiple_cardinality_fields);
    $table = !$load_from_revision ? $table_mapping->getDedicatedDataTableName($multiple_cardinality_fields[$field_name]) : $table_mapping->getDedicatedRevisionTableName($multiple_cardinality_fields[$field_name]);
    $query = $this->database
      ->select($table, $table);
    $query->addField($table, $id_key, 'id');
    if ($this->langcodeKey) {
      $query->addField($table, 'langcode', 'langcode');
    }
    $query->condition("[{$table}].[{$id_key}]", $ids, 'IN');
    $query->condition("[{$table}].[deleted]", 0);
    $query->orderBy("[{$table}].[delta]");
    $query->fields($table, $field_columns[$field_name]);
    $delta_keys[$field_name] = $query->addField($table, 'delta', $field_name . '_delta');
  }
  $results = $query->execute();
  foreach ($results as $row) {
    $row = (array) $row;
    $value_key = $row['id'];
    // Field values in default language are stored with
    // LanguageInterface::LANGCODE_DEFAULT as key.
    $langcode = LanguageInterface::LANGCODE_DEFAULT;
    if ($this->langcodeKey && isset($default_langcodes[$value_key]) && $row['langcode'] != $default_langcodes[$value_key]) {
      $langcode = $row['langcode'];
    }
    foreach ($multiple_cardinality_fields as $field_name => $storage_definition) {
      $delta_key = $delta_keys[$field_name];
      $bundle = $this->bundleKey ? $values[$value_key][$this->bundleKey][LanguageInterface::LANGCODE_DEFAULT] : $this->entityTypeId;
      // If the delta is null then there are no values at this delta for
      // this field.
      if (!isset($row[$delta_key])) {
        continue;
      }
      if (!isset($values[$value_key][$field_name][$langcode])) {
        $values[$value_key][$field_name][$langcode] = [];
      }
      // Ensure that records for non-translatable fields having invalid
      // languages are skipped.
      if ($langcode == LanguageInterface::LANGCODE_DEFAULT || $definitions[$bundle][$field_name]->isTranslatable()) {
        if ($storage_definition->getCardinality() === FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED || $row[$delta_key] < $storage_definition->getCardinality()) {
          $item = [];
          // For each column declared by the field, populate the item from
          // the prefixed database column.
          foreach ($field_definition_columns[$field_name] as $column => $attributes) {
            $column_name = $field_columns[$field_name][$column];
            // Unserialize the value if specified in the column schema.
            $item[$column] = !empty($attributes['serialize']) ? $this->handleNullableFieldUnserialize($row[$column_name]) : $row[$column_name];
          }
          // Add the item to the field values for the entity.
          $values[$value_key][$field_name][$langcode][(int) $row[$delta_key]] = $item;
        }
      }
    }
  }
}

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