commit 56bd17533df999affebcb9f9851ced5f74e3526a Author: Wolfgang Ziegler // fago Date: Wed May 28 23:38:19 2014 +0200 Make deleted field tables an implementation detail of the entity storage. diff --git a/core/lib/Drupal/Core/Entity/ContentEntityDatabaseStorage.php b/core/lib/Drupal/Core/Entity/ContentEntityDatabaseStorage.php index c7c4622..a650fce 100644 --- a/core/lib/Drupal/Core/Entity/ContentEntityDatabaseStorage.php +++ b/core/lib/Drupal/Core/Entity/ContentEntityDatabaseStorage.php @@ -1285,42 +1285,96 @@ public function onBundleRename($bundle, $bundle_new) { /** * {@inheritdoc} */ - protected function readFieldItemsToPurge(EntityInterface $entity, FieldDefinitionInterface $field_definition) { - $table_name = static::_fieldTableName($field_definition); + protected function readFieldItemsToPurge(FieldDefinitionInterface $field_definition, $batch_size) { + // Check whether the whole field storage definition is gone, or just some + // bundle fields. + $is_deleted = !array_key_exists($field_definition->getName(), $this->entityManager->getFieldStorageDefinitions($this->entityTypeId)); + $table_name = static::_fieldTableName($field_definition, $is_deleted); $query = $this->database->select($table_name, 't', array('fetch' => \PDO::FETCH_ASSOC)) - ->condition('entity_id', $entity->id()) - ->orderBy('delta'); + ->fields('t') + ->condition('bundle', $field_definition->bundle) + ->orderBy('entity_id') + ->orderBy('revision_id') + ->orderBy('delta') + ->range(0, $batch_size); + + // Create a map of field data table column names to field column names. + $column_map = array(); foreach ($field_definition->getColumns() as $column_name => $data) { - $query->addField('t', static::_fieldColumnName($field_definition, $column_name), $column_name); + $column_map[static::_fieldColumnName($field_definition, $column_name)] = $column_name; + } + + $entities = array(); + $items_by_entity = array(); + foreach ($query->execute() as $row) { + if (!isset($entities[$row['revision_id']])) { + // Create entity with the right revision id and entity id combination. + $row['entity_type'] = $this->entityTypeId; + // @todo: Replace this by an entity object created via an entity + // factory, see https://drupal.org/node/1867228. + $entities[$row['revision_id']] = _field_create_entity_from_ids((object) $row); + } + $item = array(); + foreach ($column_map as $db_column => $field_column) { + $item[$field_column] = $row[$db_column]; + } + $items_by_entity[$row['revision_id']][] = $item; } - return $query->execute()->fetchAll(); + // Create field item objects and return. + foreach ($items_by_entity as $revision_id => $values) { + $items_by_entity[$revision_id] = \Drupal::typedDataManager()->create($field_definition, $values, $field_definition->getName(), $entities[$revision_id]); + } + return $items_by_entity; } /** * {@inheritdoc} */ - public function purgeFieldItems(EntityInterface $entity, FieldDefinitionInterface $field_definition) { - $table_name = static::_fieldTableName($field_definition); - $revision_name = static::_fieldRevisionTableName($field_definition); + protected function purgeFieldItems(ContentEntityInterface $entity, FieldDefinitionInterface $field_definition) { + $is_deleted = !array_key_exists($field_definition->getName(), $this->entityManager->getFieldStorageDefinitions($this->entityTypeId)); + $table_name = static::_fieldTableName($field_definition, $is_deleted); + $revision_name = static::_fieldRevisionTableName($field_definition, $is_deleted); + $revision_id = $entity->getRevisionId() !== NULL ? $entity->getRevisionId() : $entity->id(); $this->database->delete($table_name) - ->condition('entity_id', $entity->id()) + ->condition('revision_id', $revision_id) ->execute(); $this->database->delete($revision_name) - ->condition('entity_id', $entity->id()) + ->condition('revision_id', $revision_id) ->execute(); } /** * {@inheritdoc} */ - public function onFieldPurge(FieldStorageDefinitionInterface $storage_definition) { - $table_name = static::_fieldTableName($storage_definition); - $revision_name = static::_fieldRevisionTableName($storage_definition); + public function finalizePurge(FieldStorageDefinitionInterface $storage_definition) { + $table_name = static::_fieldTableName($storage_definition, TRUE); + $revision_name = static::_fieldRevisionTableName($storage_definition, TRUE); $this->database->schema()->dropTable($table_name); $this->database->schema()->dropTable($revision_name); } /** + * {@inheritdoc} + */ + public function countFieldData($storage_definition, $as_bool = FALSE) { + $is_deleted = !array_key_exists($storage_definition->getName(), $this->entityManager->getFieldStorageDefinitions($this->entityTypeId)); + $table_name = static::_fieldTableName($storage_definition, $is_deleted); + + $query = $this->database->select($table_name, 't'); + $or = $query->orConditionGroup(); + foreach ($storage_definition->getColumns() as $column_name => $data) { + $or->isNotNull(static::_fieldColumnName($storage_definition, $column_name)); + } + // If we are performing the query just to check if the field has data + // limit the number of rows. + if ($as_bool) { + $query->range(0, 1); + } + $count = $query->countQuery()->execute()->fetchField(); + return $as_bool ? (bool) $count : (int) $count; + } + + /** * Gets the SQL table schema. * * @private Calling this function circumvents the entity system and is @@ -1504,15 +1558,15 @@ public static function _fieldSqlSchema(FieldStorageDefinitionInterface $storage_ * * @param \Drupal\Core\Field\FieldStorageDefinitionInterface $storage_definition * The field storage definition. - * @param bool $deleted + * @param bool $is_deleted * (optional) Whether the table name holding the values of a deleted field * should be returned. * * @return string * A string containing the generated name for the database table. */ - static public function _fieldTableName(FieldStorageDefinitionInterface $storage_definition, $deleted = FALSE) { - if ($deleted) { + static public function _fieldTableName(FieldStorageDefinitionInterface $storage_definition, $is_deleted = FALSE) { + if ($is_deleted) { // When a field is a deleted, the table is renamed to // {field_deleted_data_FIELD_UUID}. To make sure we don't end up with // table names longer than 64 characters, we hash the unique storage @@ -1537,15 +1591,15 @@ static public function _fieldTableName(FieldStorageDefinitionInterface $storage_ * * @param \Drupal\Core\Field\FieldStorageDefinitionInterface $storage_definition * The field storage definition. - * @param bool $deleted + * @param bool $is_deleted * (optional) Whether the table name holding the values of a deleted field * should be returned. * * @return string * A string containing the generated name for the database table. */ - static public function _fieldRevisionTableName(FieldStorageDefinitionInterface $storage_definition, $deleted = FALSE) { - if ($deleted) { + static public function _fieldRevisionTableName(FieldStorageDefinitionInterface $storage_definition, $is_deleted = FALSE) { + if ($is_deleted) { // When a field is a deleted, the table is renamed to // {field_deleted_revision_FIELD_UUID}. To make sure we don't end up with // table names longer than 64 characters, we hash the unique storage diff --git a/core/lib/Drupal/Core/Entity/ContentEntityNullStorage.php b/core/lib/Drupal/Core/Entity/ContentEntityNullStorage.php index 00d3cab..12aeca3 100644 --- a/core/lib/Drupal/Core/Entity/ContentEntityNullStorage.php +++ b/core/lib/Drupal/Core/Entity/ContentEntityNullStorage.php @@ -109,13 +109,14 @@ protected function doDeleteFieldItemsRevision(EntityInterface $entity) { /** * {@inheritdoc} */ - protected function readFieldItemsToPurge(EntityInterface $entity, FieldDefinitionInterface $field_definition) { + protected function readFieldItemsToPurge(FieldDefinitionInterface $field_definition, $batch_size) { + return array(); } /** * {@inheritdoc} */ - protected function purgeFieldItems(EntityInterface $entity, FieldDefinitionInterface $field_definition) { + protected function purgeFieldItems(ContentEntityInterface $entity, FieldDefinitionInterface $field_definition) { } /** @@ -130,4 +131,11 @@ protected function doSave($id, EntityInterface $entity) { protected function has($id, EntityInterface $entity) { } + /** + * {@inheritdoc} + */ + public function countFieldData($storage_definition, $as_bool = FALSE) { + return $as_bool ? FALSE : 0; + } + } diff --git a/core/lib/Drupal/Core/Entity/ContentEntityStorageBase.php b/core/lib/Drupal/Core/Entity/ContentEntityStorageBase.php index 79bb708..946b033 100644 --- a/core/lib/Drupal/Core/Entity/ContentEntityStorageBase.php +++ b/core/lib/Drupal/Core/Entity/ContentEntityStorageBase.php @@ -324,45 +324,47 @@ public function onBundleDelete($bundle) { } /** * {@inheritdoc} */ - public function onFieldItemsPurge(EntityInterface $entity, FieldDefinitionInterface $field_definition) { - if ($values = $this->readFieldItemsToPurge($entity, $field_definition)) { - $items = \Drupal::typedDataManager()->create($field_definition, $values, $field_definition->getName(), $entity); + public function purgeFieldData(FieldDefinitionInterface $field_definition, $batch_size) { + $items_by_entity = $this->readFieldItemsToPurge($field_definition, $batch_size); + $count = 0; + foreach ($items_by_entity as $items) { $items->delete(); + $this->purgeFieldItems($items->getEntity(), $field_definition); + $count += $items->count(); } - $this->purgeFieldItems($entity, $field_definition); + return $count; } /** - * Reads values to be purged for a single field of a single entity. + * Reads values to be purged for a single field. * * This method is called during field data purge, on fields for which * onFieldDelete() or onFieldInstanceDelete() has previously run. * - * @param \Drupal\Core\Entity\EntityInterface $entity - * The entity. * @param \Drupal\Core\Field\FieldDefinitionInterface $field_definition - * The field instance. + * The field definition. + * @param $batch_size + * The maximum number of field data records to purge before returning. * - * @return array - * The field values, in their canonical array format (numerically indexed - * array of items, each item being a property/value array). + * @return \Drupal\Core\Field\FieldItemListInterface[] + * An array of field item lists, keyed by entity revision id. */ - abstract protected function readFieldItemsToPurge(EntityInterface $entity, FieldDefinitionInterface $field_definition); + abstract protected function readFieldItemsToPurge(FieldDefinitionInterface $field_definition, $batch_size); /** - * Removes field data from storage during purge. + * Removes field items from storage per entity during purge. * - * @param EntityInterface $entity - * The entity whose values are being purged. + * @param ContentEntityInterface $entity + * The entity revision, whose values are being purged. * @param \Drupal\Core\Field\FieldDefinitionInterface $field_definition * The field whose values are bing purged. */ - abstract protected function purgeFieldItems(EntityInterface $entity, FieldDefinitionInterface $field_definition); + abstract protected function purgeFieldItems(ContentEntityInterface $entity, FieldDefinitionInterface $field_definition); /** * {@inheritdoc} */ - public function onFieldPurge(FieldStorageDefinitionInterface $storage_definition) { } + public function finalizePurge(FieldStorageDefinitionInterface $storage_definition) { } /** * Checks translation statuses and invoke the related hooks if needed. diff --git a/core/lib/Drupal/Core/Entity/FieldableEntityStorageInterface.php b/core/lib/Drupal/Core/Entity/FieldableEntityStorageInterface.php index fa83ad2..5245d8f 100644 --- a/core/lib/Drupal/Core/Entity/FieldableEntityStorageInterface.php +++ b/core/lib/Drupal/Core/Entity/FieldableEntityStorageInterface.php @@ -101,17 +101,32 @@ public function onBundleRename($bundle, $bundle_new); public function onBundleDelete($bundle); /** - * Purges the field data for a single field on a single entity. + * Purges a batch of field data. * - * The entity itself is not being deleted, and it is quite possible that - * other field data will remain attached to it. - * - * @param \Drupal\Core\Entity\EntityInterface $entity - * The entity whose field data is being purged. * @param \Drupal\Core\Field\FieldDefinitionInterface $field_definition * The deleted field whose data is being purged. + * @param $batch_size + * The maximum number of field data records to purge before returning. + * + * @return int + * The number of field data records that have been purged. + */ + public function purgeFieldData(FieldDefinitionInterface $field_definition, $batch_size); + + /** + * Determines the number of field data records of a field. + * + * @param \Drupal\Core\Field\FieldStorageDefinitionInterface $storage_definition + * The field for which to count data records. + * @param bool $as_bool + * (Optional) Optimises the query for checking whether there are any records + * or not. Defaults to FALSE. + * + * @return bool|int + * The number of field data records. If $as_bool parameter is TRUE then the + * value will either be TRUE or FALSE. */ - public function onFieldItemsPurge(EntityInterface $entity, FieldDefinitionInterface $field_definition); + public function countFieldData($storage_definition, $as_bool = FALSE); /** * Performs final cleanup after all data of a field has been purged. @@ -119,6 +134,6 @@ public function onFieldItemsPurge(EntityInterface $entity, FieldDefinitionInterf * @param \Drupal\Core\Field\FieldStorageDefinitionInterface $storage_definition * The field being purged. */ - public function onFieldPurge(FieldStorageDefinitionInterface $storage_definition); + public function finalizePurge(FieldStorageDefinitionInterface $storage_definition); } diff --git a/core/lib/Drupal/Core/Entity/Query/Sql/Tables.php b/core/lib/Drupal/Core/Entity/Query/Sql/Tables.php index 54664d1..c530541 100644 --- a/core/lib/Drupal/Core/Entity/Query/Sql/Tables.php +++ b/core/lib/Drupal/Core/Entity/Query/Sql/Tables.php @@ -106,15 +106,7 @@ public function addField($field, $type, $langcode) { // This can either be the name of an entity base field or a configurable // field. $specifier = $specifiers[$key]; - // Normally it is a field name, but field_purge_batch() is passing in - // id:$field_id so check that first. - /* @var \Drupal\Core\Field\FieldDefinitionInterface $field */ - if (substr($specifier, 0, 3) == 'id:') { - if ($fields = entity_load_multiple_by_properties('field_config', array('uuid' => substr($specifier, 3), 'include_deleted' => TRUE))) { - $field = current($fields); - } - } - elseif (isset($field_storage_definitions[$specifier])) { + if (isset($field_storage_definitions[$specifier])) { $field = $field_storage_definitions[$specifier]; } else { diff --git a/core/modules/field/field.purge.inc b/core/modules/field/field.purge.inc index a19621d..fbeb80d 100644 --- a/core/modules/field/field.purge.inc +++ b/core/modules/field/field.purge.inc @@ -80,7 +80,6 @@ function field_purge_batch($batch_size, $field_uuid = NULL) { else { $instances = entity_load_multiple_by_properties('field_instance_config', array('deleted' => TRUE, 'include_deleted' => TRUE)); } - $factory = \Drupal::service('entity.query'); $info = \Drupal::entityManager()->getDefinitions(); foreach ($instances as $instance) { $entity_type = $instance->entity_type; @@ -92,36 +91,16 @@ function field_purge_batch($batch_size, $field_uuid = NULL) { continue; } - $ids = (object) array( - 'entity_type' => $entity_type, - 'bundle' => $instance->bundle, - ); - // Retrieve some entities. - $query = $factory->get($entity_type) - ->condition('id:' . $instance->getField()->uuid() . '.deleted', 1) - ->range(0, $batch_size); - // If there's no bundle key, all results will have the same bundle. - if ($bundle_key = $info[$entity_type]->getKey('bundle')) { - $query->condition($bundle_key, $ids->bundle); - } - $results = $query->execute(); - if ($results) { - foreach ($results as $revision_id => $entity_id) { - $ids->revision_id = $revision_id; - $ids->entity_id = $entity_id; - $entity = _field_create_entity_from_ids($ids); - \Drupal::entityManager()->getStorage($entity_type)->onFieldItemsPurge($entity, $instance); - $batch_size--; - } - // Only delete up to the maximum number of records. - if ($batch_size == 0) { - break; - } - } - else { + $count_purged = \Drupal::entityManager()->getStorage($entity_type)->purgeFieldData($instance, $batch_size); + if ($count_purged < $batch_size) { // No field data remains for the instance, so we can remove it. field_purge_instance($instance); } + $batch_size -= $count_purged; + // Only delete up to the maximum number of records. + if ($batch_size == 0) { + break; + } } // Retrieve all deleted fields. Any that have no instances can be purged. @@ -187,7 +166,7 @@ function field_purge_field($field) { $state->set('field.field.deleted', $deleted_fields); // Notify the storage layer. - \Drupal::entityManager()->getStorage($field->entity_type)->onFieldPurge($field); + \Drupal::entityManager()->getStorage($field->entity_type)->finalizePurge($field); // Invoke external hooks after the cache is cleared for API consistency. \Drupal::moduleHandler()->invokeAll('field_purge_field', array($field)); diff --git a/core/modules/field/src/ConfigImporterFieldPurger.php b/core/modules/field/src/ConfigImporterFieldPurger.php index db3d8b9..a83ff52 100644 --- a/core/modules/field/src/ConfigImporterFieldPurger.php +++ b/core/modules/field/src/ConfigImporterFieldPurger.php @@ -75,7 +75,8 @@ protected static function initializeSandbox(array &$context, ConfigImporter $con $context['sandbox']['field']['steps_to_delete'] = 0; $fields = static::getFieldsToPurge($context['sandbox']['field']['extensions'], $config_importer->getUnprocessedConfiguration('delete')); foreach ($fields as $field) { - $row_count = $field->entityCount(); + $row_count = \Drupal::entityManager()->getStorage($field->getTargetEntityTypeId()) + ->countFieldData($field); if ($row_count > 0) { // The number of steps to delete each field is determined by the // purge_batch_size setting. For example if the field has 9 rows and the diff --git a/core/modules/field/src/Entity/FieldConfig.php b/core/modules/field/src/Entity/FieldConfig.php index d77c1a8..838488d 100644 --- a/core/modules/field/src/Entity/FieldConfig.php +++ b/core/modules/field/src/Entity/FieldConfig.php @@ -661,59 +661,7 @@ public static function getReservedColumns() { * TRUE if the field has data for any entity; FALSE otherwise. */ public function hasData() { - return $this->entityCount(TRUE); - } - - /** - * Determines the number of entities that have field data. - * - * @param bool $as_bool - * (Optional) Optimises query for hasData(). Defaults to FALSE. - * - * @return bool|int - * The number of entities that have field data. If $as_bool parameter is - * TRUE then the value will either be TRUE or FALSE. - */ - public function entityCount($as_bool = FALSE) { - $count = 0; - $factory = \Drupal::service('entity.query'); - $entity_type = \Drupal::entityManager()->getDefinition($this->entity_type); - // Entity Query throws an exception if there is no base table. - if ($entity_type->getBaseTable()) { - if ($this->deleted) { - $query = $factory->get($this->entity_type) - ->condition('id:' . $this->uuid() . '.deleted', 1); - } - elseif ($this->getBundles()) { - $storage_details = $this->getSchema(); - $columns = array_keys($storage_details['columns']); - $query = $factory->get($this->entity_type); - $group = $query->orConditionGroup(); - foreach ($columns as $column) { - $group->exists($this->name . '.' . $column); - } - $query = $query->condition($group); - } - - if (isset($query)) { - $query - ->count() - ->accessCheck(FALSE); - // If we are performing the query just to check if the field has data - // limit the number of rows returned by the subquery. - if ($as_bool) { - $query->range(0, 1); - } - $count = $query->execute(); - } - } - - if ($as_bool) { - return (bool) $count; - } - else { - return (int) $count; - } + return \Drupal::entityManager()->getStorage($this->entity_type)->countFieldData($this, TRUE); } /** diff --git a/core/modules/field/src/Tests/BulkDeleteTest.php b/core/modules/field/src/Tests/BulkDeleteTest.php index 542139e..055aa3a 100644 --- a/core/modules/field/src/Tests/BulkDeleteTest.php +++ b/core/modules/field/src/Tests/BulkDeleteTest.php @@ -308,7 +308,7 @@ function testPurgeField() { $this->checkHooksInvocations($hooks, $actual_hooks); // Purge again to purge the instance. - field_purge_batch(0); + field_purge_batch(1); // The field still exists, not deleted. $fields = entity_load_multiple_by_properties('field_config', array('uuid' => $field->uuid, 'include_deleted' => TRUE)); @@ -340,7 +340,7 @@ function testPurgeField() { $this->assertTrue(isset($fields[$field->uuid]) && $fields[$field->uuid]->deleted, 'The field exists and is deleted'); // Purge again to purge the instance and the field. - field_purge_batch(0); + field_purge_batch(1); // The field is gone. $fields = entity_load_multiple_by_properties('field_config', array('uuid' => $field->uuid, 'include_deleted' => TRUE)); diff --git a/core/modules/field/src/Tests/FieldDataCountTest.php b/core/modules/field/src/Tests/FieldDataCountTest.php new file mode 100644 index 0000000..5dc854a --- /dev/null +++ b/core/modules/field/src/Tests/FieldDataCountTest.php @@ -0,0 +1,111 @@ + 'Field config hasData() tests.', + 'description' => 'Tests counting field data records and the hasData() method on FieldConfig entity.', + 'group' => 'Field API', + ); + } + + /** + * {@inheritdoc} + */ + public function setUp() { + parent::setUp(); + $this->storage = \Drupal::entityManager()->getStorage('entity_test'); + } + + /** + * Tests entityCount() and hadData() methods. + */ + public function testEntityCountAndHasData() { + // Create a field with a cardinality of 2 to show that we are counting + // entities and not rows in a table. + /** @var \Drupal\field\Entity\FieldConfig $field */ + $field = entity_create('field_config', array( + 'name' => 'field_int', + 'entity_type' => 'entity_test', + 'type' => 'integer', + 'cardinality' => 2, + )); + $field->save(); + entity_create('field_instance_config', array( + 'entity_type' => 'entity_test', + 'field_name' => 'field_int', + 'bundle' => 'entity_test', + ))->save(); + + $this->assertIdentical($field->hasdata(), FALSE, 'There are no entities with field data.'); + $this->assertIdentical($this->storage->countFieldData($field), 0, 'There are 0 entities with field data.'); + + // Create 1 entity without the field. + $entity = entity_create('entity_test'); + $entity->name->value = $this->randomName(); + $entity->save(); + + $this->assertIdentical($field->hasdata(), FALSE, 'There are no entities with field data.'); + $this->assertIdentical($this->storage->countFieldData($field), 0, 'There are 0 entities with field data.'); + + // Create 12 entities to ensure that the purging works as expected. + for ($i=0; $i < 12; $i++) { + $entity = entity_create('entity_test'); + $value = mt_rand(1,99); + $value2 = mt_rand(1,99); + $entity->field_int[0]->value = $value; + $entity->field_int[1]->value = $value2; + $entity->name->value = $this->randomName(); + $entity->save(); + } + + $storage = \Drupal::entityManager()->getStorage('entity_test'); + if ($storage instanceof ContentEntityDatabaseStorage) { + // Count the actual number of rows in the field table. + $field_table_name = $storage->_fieldTableName($field); + $result = db_select($field_table_name, 't') + ->fields('t') + ->countQuery() + ->execute() + ->fetchField(); + $this->assertEqual($result, 24, 'The field table has 24 rows.'); + } + + $this->assertIdentical($field->hasdata(), TRUE, 'There are entities with field data.'); + $this->assertEqual($this->storage->countFieldData($field), 24, 'There are 24 rows of field data.'); + + // Ensure the methods work on deleted fields. + $field->delete(); + $this->assertIdentical($field->hasdata(), TRUE, 'There are entities with deleted field data.'); + $this->assertEqual($this->storage->countFieldData($field), 24, 'There are 24 rows of deleted field data.'); + + field_purge_batch(6); + $this->assertIdentical($field->hasdata(), TRUE, 'There are entities with deleted field data.'); + $this->assertEqual($this->storage->countFieldData($field), 18, 'There are 18 rows of deleted field data.'); + } + +} diff --git a/core/modules/field/src/Tests/FieldEntityCountTest.php b/core/modules/field/src/Tests/FieldEntityCountTest.php deleted file mode 100644 index f08cee4..0000000 --- a/core/modules/field/src/Tests/FieldEntityCountTest.php +++ /dev/null @@ -1,95 +0,0 @@ - 'Field config entityCount() and hasData() tests.', - 'description' => 'Tests entityCount() and hasData() methods on FieldConfig entity.', - 'group' => 'Field API', - ); - } - - /** - * Tests entityCount() and hadData() methods. - */ - public function testEntityCountAndHasData() { - // Create a field with a cardinality of 2 to show that we are counting - // entities and not rows in a table. - /** @var \Drupal\field\Entity\FieldConfig $field */ - $field = entity_create('field_config', array( - 'name' => 'field_int', - 'entity_type' => 'entity_test', - 'type' => 'integer', - 'cardinality' => 2, - )); - $field->save(); - entity_create('field_instance_config', array( - 'entity_type' => 'entity_test', - 'field_name' => 'field_int', - 'bundle' => 'entity_test', - ))->save(); - - $this->assertIdentical($field->hasdata(), FALSE, 'There are no entities with field data.'); - $this->assertIdentical($field->entityCount(), 0, 'There are 0 entities with field data.'); - - // Create 1 entity without the field. - $entity = entity_create('entity_test'); - $entity->name->value = $this->randomName(); - $entity->save(); - - $this->assertIdentical($field->hasdata(), FALSE, 'There are no entities with field data.'); - $this->assertIdentical($field->entityCount(), 0, 'There are 0 entities with field data.'); - - // Create 12 entities to ensure that the purging works as expected. - for ($i=0; $i < 12; $i++) { - $entity = entity_create('entity_test'); - $value = mt_rand(1,99); - $value2 = mt_rand(1,99); - $entity->field_int[0]->value = $value; - $entity->field_int[1]->value = $value2; - $entity->name->value = $this->randomName(); - $entity->save(); - } - - $storage = \Drupal::entityManager()->getStorage('entity_test'); - if ($storage instanceof ContentEntityDatabaseStorage) { - // Count the actual number of rows in the field table. - $field_table_name = $storage->_fieldTableName($field); - $result = db_select($field_table_name, 't') - ->fields('t') - ->countQuery() - ->execute() - ->fetchField(); - $this->assertEqual($result, 24, 'The field table has 24 rows.'); - } - - $this->assertIdentical($field->hasdata(), TRUE, 'There are entities with field data.'); - $this->assertEqual($field->entityCount(), 12, 'There are 12 entities with field data.'); - - // Ensure the methods work on deleted fields. - $field->delete(); - $this->assertIdentical($field->hasdata(), TRUE, 'There are entities with deleted field data.'); - $this->assertEqual($field->entityCount(), 12, 'There are 12 entities with deleted field data.'); - - field_purge_batch(6); - $this->assertIdentical($field->hasdata(), TRUE, 'There are entities with deleted field data.'); - $this->assertEqual($field->entityCount(), 6, 'There are 6 entities with deleted field data.'); - } - -} diff --git a/core/modules/system/src/Tests/Entity/FieldSqlStorageTest.php b/core/modules/system/src/Tests/Entity/FieldSqlStorageTest.php index c252acd..ab07227 100644 --- a/core/modules/system/src/Tests/Entity/FieldSqlStorageTest.php +++ b/core/modules/system/src/Tests/Entity/FieldSqlStorageTest.php @@ -563,9 +563,9 @@ public function testTableNames() { 'deleted' => TRUE, )); $expected = 'field_deleted_data_' . substr(hash('sha256', $field->uuid), 0, 10); - $this->assertEqual(ContentEntityDatabaseStorage::_fieldTableName($field), $expected); + $this->assertEqual(ContentEntityDatabaseStorage::_fieldTableName($field, TRUE), $expected); $expected = 'field_deleted_revision_' . substr(hash('sha256', $field->uuid), 0, 10); - $this->assertEqual(ContentEntityDatabaseStorage::_fieldRevisionTableName($field), $expected); + $this->assertEqual(ContentEntityDatabaseStorage::_fieldRevisionTableName($field, TRUE), $expected); } }