You are here

protected function SqlContentEntityStorage::saveToDedicatedTables in Drupal 9

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

Saves values of fields that use dedicated tables.

Parameters

\Drupal\Core\Entity\ContentEntityInterface $entity: The entity.

bool $update: TRUE if the entity is being updated, FALSE if it is being inserted.

string[] $names: (optional) The names of the fields to be stored. Defaults to all the available fields.

3 calls to SqlContentEntityStorage::saveToDedicatedTables()
EntityTestUpdateStorage::saveToDedicatedTables in core/modules/system/tests/modules/entity_test_update/src/EntityTestUpdateStorage.php
Saves values of fields that use dedicated tables.
SqlContentEntityStorage::doSaveFieldItems in core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php
Writes entity field values to the storage.
SqlContentEntityStorage::restore in core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php
Restores a previously saved entity.
1 method overrides SqlContentEntityStorage::saveToDedicatedTables()
EntityTestUpdateStorage::saveToDedicatedTables in core/modules/system/tests/modules/entity_test_update/src/EntityTestUpdateStorage.php
Saves values of fields that use dedicated tables.

File

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

Class

SqlContentEntityStorage
A content entity database storage implementation.

Namespace

Drupal\Core\Entity\Sql

Code

protected function saveToDedicatedTables(ContentEntityInterface $entity, $update = TRUE, $names = []) {
  $vid = $entity
    ->getRevisionId();
  $id = $entity
    ->id();
  $bundle = $entity
    ->bundle();
  $entity_type = $entity
    ->getEntityTypeId();
  $default_langcode = $entity
    ->getUntranslated()
    ->language()
    ->getId();
  $translation_langcodes = array_keys($entity
    ->getTranslationLanguages());
  $table_mapping = $this
    ->getTableMapping();
  if (!isset($vid)) {
    $vid = $id;
  }
  $original = !empty($entity->original) ? $entity->original : NULL;

  // Determine which fields should be actually stored.
  $definitions = $this->entityFieldManager
    ->getFieldDefinitions($entity_type, $bundle);
  if ($names) {
    $definitions = array_intersect_key($definitions, array_flip($names));
  }
  foreach ($definitions as $field_name => $field_definition) {
    $storage_definition = $field_definition
      ->getFieldStorageDefinition();
    if (!$table_mapping
      ->requiresDedicatedTableStorage($storage_definition)) {
      continue;
    }

    // When updating an existing revision, keep the existing records if the
    // field values did not change.
    if (!$entity
      ->isNewRevision() && $original && !$this
      ->hasFieldValueChanged($field_definition, $entity, $original)) {
      continue;
    }
    $table_name = $table_mapping
      ->getDedicatedDataTableName($storage_definition);
    $revision_name = $table_mapping
      ->getDedicatedRevisionTableName($storage_definition);

    // Delete and insert, rather than update, in case a value was added.
    if ($update) {

      // Only overwrite the field's base table if saving the default revision
      // of an entity.
      if ($entity
        ->isDefaultRevision()) {
        $this->database
          ->delete($table_name)
          ->condition('entity_id', $id)
          ->execute();
      }
      if ($this->entityType
        ->isRevisionable()) {
        $this->database
          ->delete($revision_name)
          ->condition('entity_id', $id)
          ->condition('revision_id', $vid)
          ->execute();
      }
    }

    // Prepare the multi-insert query.
    $do_insert = FALSE;
    $columns = [
      'entity_id',
      'revision_id',
      'bundle',
      'delta',
      'langcode',
    ];
    foreach ($storage_definition
      ->getColumns() as $column => $attributes) {
      $columns[] = $table_mapping
        ->getFieldColumnName($storage_definition, $column);
    }
    $query = $this->database
      ->insert($table_name)
      ->fields($columns);
    if ($this->entityType
      ->isRevisionable()) {
      $revision_query = $this->database
        ->insert($revision_name)
        ->fields($columns);
    }
    $langcodes = $field_definition
      ->isTranslatable() ? $translation_langcodes : [
      $default_langcode,
    ];
    foreach ($langcodes as $langcode) {
      $delta_count = 0;
      $items = $entity
        ->getTranslation($langcode)
        ->get($field_name);
      $items
        ->filterEmptyItems();
      foreach ($items as $delta => $item) {

        // We now know we have something to insert.
        $do_insert = TRUE;
        $record = [
          'entity_id' => $id,
          'revision_id' => $vid,
          'bundle' => $bundle,
          'delta' => $delta,
          'langcode' => $langcode,
        ];
        foreach ($storage_definition
          ->getColumns() as $column => $attributes) {
          $column_name = $table_mapping
            ->getFieldColumnName($storage_definition, $column);

          // Serialize the value if specified in the column schema.
          $value = $item->{$column};
          if (!empty($attributes['serialize'])) {
            $value = serialize($value);
          }
          $record[$column_name] = SqlContentEntityStorageSchema::castValue($attributes, $value);
        }
        $query
          ->values($record);
        if ($this->entityType
          ->isRevisionable()) {
          $revision_query
            ->values($record);
        }
        if ($storage_definition
          ->getCardinality() != FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED && ++$delta_count == $storage_definition
          ->getCardinality()) {
          break;
        }
      }
    }

    // Execute the query if we have values to insert.
    if ($do_insert) {

      // Only overwrite the field's base table if saving the default revision
      // of an entity.
      if ($entity
        ->isDefaultRevision()) {
        $query
          ->execute();
      }
      if ($this->entityType
        ->isRevisionable()) {
        $revision_query
          ->execute();
      }
    }
  }
}