function SqlFieldableEntityTypeListenerTrait::copyData
Same name in other branches
- 8.9.x core/lib/Drupal/Core/Entity/Sql/SqlFieldableEntityTypeListenerTrait.php \Drupal\Core\Entity\Sql\SqlFieldableEntityTypeListenerTrait::copyData()
- 10 core/lib/Drupal/Core/Entity/Sql/SqlFieldableEntityTypeListenerTrait.php \Drupal\Core\Entity\Sql\SqlFieldableEntityTypeListenerTrait::copyData()
- 11.x core/lib/Drupal/Core/Entity/Sql/SqlFieldableEntityTypeListenerTrait.php \Drupal\Core\Entity\Sql\SqlFieldableEntityTypeListenerTrait::copyData()
Copies entity data from the original storage to the temporary one.
Parameters
\Drupal\Core\Entity\EntityTypeInterface $entity_type: The updated entity type definition.
\Drupal\Core\Entity\EntityTypeInterface $original: The original entity type definition.
\Drupal\Core\Field\FieldStorageDefinitionInterface[] $field_storage_definitions: The updated field storage definitions, including possibly new ones.
\Drupal\Core\Field\FieldStorageDefinitionInterface[] $original_field_storage_definitions: The original field storage definitions.
array &$sandbox: The sandbox array from a hook_update_N() implementation.
1 call to SqlFieldableEntityTypeListenerTrait::copyData()
- SqlFieldableEntityTypeListenerTrait::onFieldableEntityTypeUpdate in core/
lib/ Drupal/ Core/ Entity/ Sql/ SqlFieldableEntityTypeListenerTrait.php
File
-
core/
lib/ Drupal/ Core/ Entity/ Sql/ SqlFieldableEntityTypeListenerTrait.php, line 137
Class
- SqlFieldableEntityTypeListenerTrait
- Helper methods for EntityTypeListenerInterface.
Namespace
Drupal\Core\Entity\SqlCode
protected function copyData(EntityTypeInterface $entity_type, EntityTypeInterface $original, array $field_storage_definitions, array $original_field_storage_definitions, array &$sandbox) {
/** @var \Drupal\Core\Entity\ContentEntityTypeInterface $entity_type */
$id_key = $entity_type->getKey('id');
$revision_id_key = $entity_type->getKey('revision');
$revision_default_key = $entity_type->getRevisionMetadataKey('revision_default');
$langcode_key = $entity_type->getKey('langcode');
$default_langcode_key = $entity_type->getKey('default_langcode');
$revision_translation_affected_key = $entity_type->getKey('revision_translation_affected');
// If 'progress' is not set, then this will be the first run of the batch.
if (!isset($sandbox['progress'])) {
$sandbox['progress'] = 0;
$sandbox['current_id'] = -1;
}
// If the original entity type is revisionable, we need to copy all the
// revisions.
$load_revisions = $original->isRevisionable();
if ($load_revisions) {
$table_name = $original->getRevisionTable();
$identifier_field = $revision_id_key;
}
else {
$table_name = $original->getBaseTable();
$identifier_field = $id_key;
}
// Get the next entity identifiers to migrate.
// @todo Use an entity query when it is able to use the last installed
// entity type and field storage definitions.
// @see https://www.drupal.org/project/drupal/issues/2554235
$step_size = Settings::get('entity_update_batch_size', 50);
$entity_identifiers = $this->database
->select($table_name, 't')
->condition("t.{$identifier_field}", $sandbox['current_id'], '>')
->fields('t', [
$identifier_field,
])
->orderBy($identifier_field, 'ASC')
->range(0, $step_size)
->execute()
->fetchCol();
/** @var \Drupal\Core\Entity\ContentEntityInterface[] $entities */
$entities = $load_revisions ? $this->storage
->loadMultipleRevisions($entity_identifiers) : $this->storage
->loadMultiple($entity_identifiers);
/** @var \Drupal\Core\Entity\Sql\SqlContentEntityStorage $temporary_storage */
$temporary_storage = $this->entityTypeManager
->createHandlerInstance($entity_type->getStorageClass(), $entity_type);
$temporary_storage->setEntityType($entity_type);
$temporary_storage->setFieldStorageDefinitions($field_storage_definitions);
$temporary_storage->setTableMapping($sandbox['temporary_table_mapping']);
foreach ($entities as $identifier => $entity) {
try {
if (!$original->isRevisionable() && $entity_type->isRevisionable()) {
// Set the revision ID to be same as the entity ID.
$entity->set($revision_id_key, $entity->id());
// We had no revisions so far, so the existing data belongs to the
// default revision now.
$entity->set($revision_default_key, TRUE);
}
// Set the 'langcode' and 'default_langcode' values as needed.
if (!$original->isTranslatable() && $entity_type->isTranslatable()) {
if ($entity->get($langcode_key)
->isEmpty()) {
$entity->set($langcode_key, \Drupal::languageManager()->getDefaultLanguage()
->getId());
}
$entity->set($default_langcode_key, TRUE);
}
// Set the 'revision_translation_affected' field to TRUE to match the
// return value of the case when the field does not exist.
if ((!$original->isRevisionable() || !$original->isTranslatable()) && $entity_type->isRevisionable() && $entity_type->isTranslatable()) {
$entity->set($revision_translation_affected_key, TRUE);
}
// Finally, save the entity in the temporary storage.
$temporary_storage->restore($entity);
} catch (\Exception $e) {
$this->handleEntityTypeSchemaUpdateExceptionOnDataCopy($entity_type, $original, $sandbox);
// Re-throw the original exception with a helpful message.
$error_revision_id = $load_revisions ? ", revision ID: {$entity->getLoadedRevisionId()}" : '';
throw new EntityStorageException("The entity update process failed while processing the entity type {$entity_type->id()}, ID: {$entity->id()}{$error_revision_id}.", $e->getCode(), $e);
}
$sandbox['progress']++;
$sandbox['current_id'] = $identifier;
}
// Reset the cache in order to free memory as we progress.
\Drupal::service('entity.memory_cache')->deleteAll();
// Get an updated count of entities that still need to migrated to the new
// storage.
$missing = $this->database
->select($table_name, 't')
->condition("t.{$identifier_field}", $sandbox['current_id'], '>')
->orderBy($identifier_field, 'ASC')
->countQuery()
->execute()
->fetchField();
$sandbox['#finished'] = $missing ? $sandbox['progress'] / ($sandbox['progress'] + (int) $missing) : 1;
}
Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.