diff --git a/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php b/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php index 7d87a32..910e870 100644 --- a/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php +++ b/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php @@ -1669,7 +1669,16 @@ public function countFieldData($storage_definition, $as_bool = FALSE) { elseif ($table_mapping->allowsSharedTableStorage($storage_definition)) { // Ascertain the table this field is mapped too. $field_name = $storage_definition->getName(); - $table_name = $table_mapping->getFieldTableName($field_name); + try { + $table_name = $table_mapping->getFieldTableName($field_name); + } + catch (SqlContentEntityStorageException $e) { + // This may happen when changing field storage schema, since we are not + // able to use a table mapping matching the passed storage definition. + // @todo Revisit this once we are able to instantiate the table mapping + // properly. See https://www.drupal.org/node/2274017. + $table_name = $this->dataTable ?: $this->baseTable; + } $query = $this->database->select($table_name, 't'); $or = $query->orConditionGroup(); foreach (array_keys($storage_definition->getColumns()) as $property_name) { diff --git a/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorageSchema.php b/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorageSchema.php index f854550..cf3b635 100644 --- a/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorageSchema.php +++ b/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorageSchema.php @@ -3,6 +3,7 @@ namespace Drupal\Core\Entity\Sql; use Drupal\Core\Database\Connection; +use Drupal\Core\Database\DatabaseExceptionWrapper; use Drupal\Core\DependencyInjection\DependencySerializationTrait; use Drupal\Core\Entity\ContentEntityTypeInterface; use Drupal\Core\Entity\EntityManagerInterface; @@ -440,9 +441,20 @@ public function onFieldStorageDefinitionUpdate(FieldStorageDefinitionInterface $ * {@inheritdoc} */ public function onFieldStorageDefinitionDelete(FieldStorageDefinitionInterface $storage_definition) { + try { + $has_data = $this->storage->countFieldData($storage_definition, TRUE); + } + catch (DatabaseExceptionWrapper $e) { + // This may happen when changing field storage schema, since we are not + // able to use a table mapping matching the passed storage definition. + // @todo Revisit this once we are able to instantiate the table mapping + // properly. See https://www.drupal.org/node/2274017. + return; + } + // If the field storage does not have any data, we can safely delete its // schema. - if (!$this->storage->countFieldData($storage_definition, TRUE)) { + if (!$has_data) { $this->performFieldSchemaOperation('delete', $storage_definition); return; } diff --git a/core/lib/Drupal/Core/Field/DeletedFieldsRepository.php b/core/lib/Drupal/Core/Field/DeletedFieldsRepository.php index 363e71f..650c674 100644 --- a/core/lib/Drupal/Core/Field/DeletedFieldsRepository.php +++ b/core/lib/Drupal/Core/Field/DeletedFieldsRepository.php @@ -32,6 +32,24 @@ public function __construct(StateInterface $state) { public function getFieldDefinitions($field_storage_unique_id = NULL) { $deleted_field_definitions = $this->state->get('field.field.deleted', []); + $deleted_storage_definitions = $this->getFieldStorageDefinitions(); + /** @var \Drupal\Core\Field\FieldDefinitionInterface $field_definition */ + foreach ($deleted_field_definitions as $id => $field_definition) { + // Configurable fields have an internal reference to their field storage + // which we must keep in sync if the storage itself is also deleted. + if ($field_definition instanceof FieldConfigBase && isset($deleted_storage_definitions[$field_definition->field_storage_unique_id])) { + $config = $field_definition->toArray(); + $config['fieldStorage'] = $deleted_storage_definitions[$field_definition->field_storage_unique_id]; + $updated_field_definition = get_class($field_definition)::create($config); + + // Re-assign the 'field_storage_unique_id' property since it was lost + // above while re-initializing the configurable field object. + $updated_field_definition->field_storage_unique_id = $field_definition->field_storage_unique_id; + + $deleted_field_definitions[$id] = $updated_field_definition; + } + } + if ($field_storage_unique_id) { $deleted_field_definitions = array_filter($deleted_field_definitions, function (FieldDefinitionInterface $field_definition) use ($field_storage_unique_id) { return $field_definition->getFieldStorageDefinition()->getUniqueStorageIdentifier() === $field_storage_unique_id; @@ -54,6 +72,10 @@ public function getFieldStorageDefinitions() { public function addFieldDefinition(FieldDefinitionInterface $field_definition) { $deleted_field_definitions = $this->state->get('field.field.deleted', []); + // Add a helper property that allows us to filter by the field storage + // unique identifier in getFieldsByFieldStorageId(). + $field_definition->field_storage_unique_id = $field_definition->getFieldStorageDefinition()->getUniqueStorageIdentifier(); + $deleted_field_definitions[$field_definition->getUniqueIdentifier()] = $field_definition; $this->state->set('field.field.deleted', $deleted_field_definitions); diff --git a/core/modules/field/src/Entity/FieldStorageConfig.php b/core/modules/field/src/Entity/FieldStorageConfig.php index 5f8cb64..ca0baa5 100644 --- a/core/modules/field/src/Entity/FieldStorageConfig.php +++ b/core/modules/field/src/Entity/FieldStorageConfig.php @@ -419,18 +419,6 @@ public static function preDelete(EntityStorageInterface $storage, array $field_s $storage = clone $field_storage; $storage->deleted = TRUE; $deleted_fields_repository->addFieldStorageDefinition($storage); - - // We also need to update the definitions of all the deleted fields that - // were using this field storage. - $deleted_fields = $deleted_fields_repository->getFieldDefinitions($storage->getUniqueStorageIdentifier()); - foreach ($deleted_fields as $deleted_field) { - $config = $deleted_field->toArray(); - $config['deleted'] = TRUE; - $config['field_storage'] = $storage; - $updated_field = FieldConfig::create($config); - - $deleted_fields_repository->addFieldDefinition($updated_field); - } } } }