summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNathaniel Catchpole2016-08-28 17:53:57 +0100
committerNathaniel Catchpole2016-08-28 18:08:47 +0100
commit8ed5d65160342595290e372d4d9e4eb1e01b8e94 (patch)
treee3ce293b9f820c3bdb585d015172996088ea9da1
parent82bece91c3a3b28c25c8dc3817188a87b1942a14 (diff)
Issue #2782009 by alexpott, swentel, reblutus: Create a field with the same name as one being purged results in data destruction of the new field
(cherry picked from commit b6a64fc02d12603a067e8715d766424bccc92146)
-rw-r--r--core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php9
-rw-r--r--core/modules/field/tests/src/Kernel/BulkDeleteTest.php92
2 files changed, 101 insertions, 0 deletions
diff --git a/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php b/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php
index e115bd2..b2be1c0 100644
--- a/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php
+++ b/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php
@@ -1543,6 +1543,7 @@ class SqlContentEntityStorage extends ContentEntityStorageBase implements SqlEnt
$item_query = $this->database->select($table_name, 't', array('fetch' => \PDO::FETCH_ASSOC))
->fields('t')
->condition('entity_id', $row['entity_id'])
+ ->condition('deleted', 1)
->orderBy('delta');
foreach ($item_query->execute() as $item_row) {
@@ -1581,10 +1582,12 @@ class SqlContentEntityStorage extends ContentEntityStorageBase implements SqlEnt
$revision_id = $this->entityType->isRevisionable() ? $entity->getRevisionId() : $entity->id();
$this->database->delete($table_name)
->condition('revision_id', $revision_id)
+ ->condition('deleted', 1)
->execute();
if ($this->entityType->isRevisionable()) {
$this->database->delete($revision_name)
->condition('revision_id', $revision_id)
+ ->condition('deleted', 1)
->execute();
}
}
@@ -1684,6 +1687,12 @@ class SqlContentEntityStorage extends ContentEntityStorageBase implements SqlEnt
* Whether the field has been already deleted.
*/
protected function storageDefinitionIsDeleted(FieldStorageDefinitionInterface $storage_definition) {
+ // Configurable fields are marked for deletion.
+ if ($storage_definition instanceOf FieldStorageConfigInterface) {
+ return $storage_definition->isDeleted();
+ }
+ // For non configurable fields check whether they are still in the last
+ // installed schema repository.
return !array_key_exists($storage_definition->getName(), $this->entityManager->getLastInstalledFieldStorageDefinitions($this->entityTypeId));
}
diff --git a/core/modules/field/tests/src/Kernel/BulkDeleteTest.php b/core/modules/field/tests/src/Kernel/BulkDeleteTest.php
index 41fedfc..ae3d4e1 100644
--- a/core/modules/field/tests/src/Kernel/BulkDeleteTest.php
+++ b/core/modules/field/tests/src/Kernel/BulkDeleteTest.php
@@ -211,6 +211,98 @@ class BulkDeleteTest extends FieldKernelTestBase {
}
/**
+ * Tests that recreating a field with the name as a deleted field works.
+ */
+ public function testPurgeWithDeletedAndActiveField() {
+ $bundle = reset($this->bundles);
+ // Create another field storage.
+ $field_name = 'bf_3';
+ $deleted_field_storage = FieldStorageConfig::create(array(
+ 'field_name' => $field_name,
+ 'entity_type' => $this->entityTypeId,
+ 'type' => 'test_field',
+ 'cardinality' => 1
+ ));
+ $deleted_field_storage->save();
+ // Create the field.
+ FieldConfig::create([
+ 'field_storage' => $deleted_field_storage,
+ 'bundle' => $bundle,
+ ])->save();
+
+ for ($i = 0; $i < 20; $i++) {
+ $entity = $this->container->get('entity_type.manager')
+ ->getStorage($this->entityTypeId)
+ ->create(array('type' => $bundle));
+ $entity->{$field_name}->setValue($this->_generateTestFieldValues(1));
+ $entity->save();
+ }
+
+ // Delete the field.
+ $deleted_field = FieldConfig::loadByName($this->entityTypeId, $bundle, $field_name);
+ $deleted_field->delete();
+ $deleted_field_uuid = $deleted_field->uuid();
+
+ // Reload the field storage.
+ $field_storages = entity_load_multiple_by_properties('field_storage_config', array('uuid' => $deleted_field_storage->uuid(), 'include_deleted' => TRUE));
+ $deleted_field_storage = reset($field_storages);
+
+ // Create the field again.
+ $field_storage = FieldStorageConfig::create(array(
+ 'field_name' => $field_name,
+ 'entity_type' => $this->entityTypeId,
+ 'type' => 'test_field',
+ 'cardinality' => 1
+ ));
+ $field_storage->save();
+ FieldConfig::create([
+ 'field_storage' => $field_storage,
+ 'bundle' => $bundle,
+ ])->save();
+
+ // The field still exists, deleted, with the same field name.
+ $fields = entity_load_multiple_by_properties('field_config', array('uuid' => $deleted_field_uuid, 'include_deleted' => TRUE));
+ $this->assertTrue(isset($fields[$deleted_field_uuid]) && $fields[$deleted_field_uuid]->isDeleted(), 'The field exists and is deleted');
+ $this->assertTrue(isset($fields[$deleted_field_uuid]) && $fields[$deleted_field_uuid]->getName() == $field_name);
+
+ for ($i = 0; $i < 10; $i++) {
+ $entity = $this->container->get('entity_type.manager')
+ ->getStorage($this->entityTypeId)
+ ->create(array('type' => $bundle));
+ $entity->{$field_name}->setValue($this->_generateTestFieldValues(1));
+ $entity->save();
+ }
+
+ // Check that the two field storages have different tables.
+ $storage = \Drupal::entityManager()->getStorage($this->entityTypeId);
+ /** @var \Drupal\Core\Entity\Sql\DefaultTableMapping $table_mapping */
+ $table_mapping = $storage->getTableMapping();
+ $deleted_table_name = $table_mapping->getDedicatedDataTableName($deleted_field_storage, TRUE);
+ $active_table_name = $table_mapping->getDedicatedDataTableName($field_storage);
+
+ field_purge_batch(50);
+
+ // Ensure the new field still has its table and the deleted one has been
+ // removed.
+ $this->assertTrue(\Drupal::database()->schema()->tableExists($active_table_name));
+ $this->assertFalse(\Drupal::database()->schema()->tableExists($deleted_table_name));
+
+ // The field has been removed from the system.
+ $fields = entity_load_multiple_by_properties('field_config', array('field_storage_uuid' => $deleted_field_storage->uuid(), 'deleted' => TRUE, 'include_deleted' => TRUE));
+ $this->assertEqual(count($fields), 0, 'The field is gone');
+
+ // Verify there are still 10 entries in the main table.
+ $count = \Drupal::database()
+ ->select('entity_test__' . $field_name, 'f')
+ ->fields('f', array('entity_id'))
+ ->condition('bundle', $bundle)
+ ->countQuery()
+ ->execute()
+ ->fetchField();
+ $this->assertEqual($count, 10);
+ }
+
+ /**
* Verify that field data items and fields are purged when a field storage is
* deleted.
*/