diff --git a/core/modules/comment/lib/Drupal/comment/Tests/CommentFieldsTest.php b/core/modules/comment/lib/Drupal/comment/Tests/CommentFieldsTest.php index ab03d41..c0f806f 100644 --- a/core/modules/comment/lib/Drupal/comment/Tests/CommentFieldsTest.php +++ b/core/modules/comment/lib/Drupal/comment/Tests/CommentFieldsTest.php @@ -117,4 +117,41 @@ function testCommentFormat() { $edit = array('comment_body[und][0][value]' => $this->randomName(8)); $this->drupalPost('node/' . $this->node->nid, $edit, t('Save')); } + + /** + * Tests that comment fields can be managed through the UI. + */ + function testCommentFieldUI() { + // Log in as the administrative user. + $this->drupalLogin($this->admin_user); + + // Create a test node type and a node of that type. + $this->drupalCreateContentType(array('type' => 'test_node_type')); + $node = $this->drupalCreateNode(array('type' => 'test_node_type')); + + // Add a field to the comments for this node type through the UI. + $edit = array( + 'fields[_add_new_field][label]' => t('Test field label'), + 'fields[_add_new_field][field_name]' => 'test_field', + 'fields[_add_new_field][type]' => 'text', + 'fields[_add_new_field][widget_type]' => 'text_textfield', + ); + $this->drupalPost('admin/structure/types/manage/test_node_type/comment/fields', $edit, t('Save')); + + // Confirm that the field is present + $this->drupalGet('comment/reply/' . $node->nid); + $this->assertText(t('Test field label')); + + $this->drupalGet('admin/structure/types/manage/test_node_type/comment/fields'); + + // Delete the field through the UI. + $this->drupalPost('admin/structure/types/manage/test_node_type/comment/fields/field_test_field/delete', array(), t('Delete')); + $this->assertResponse(200); + + // Confirm that the field is no longer present + $this->drupalGet('comment/reply/' . $node->nid); + $this->assertNoText(t('Test field label')); + + } + } diff --git a/core/modules/field/field.crud.inc b/core/modules/field/field.crud.inc index a5e582b..6541392 100644 --- a/core/modules/field/field.crud.inc +++ b/core/modules/field/field.crud.inc @@ -853,44 +853,51 @@ function field_delete_instance($instance, $field_cleanup = TRUE) { function field_purge_batch($batch_size) { // Retrieve all deleted field instances. We cannot use field_info_instances() // because that function does not return deleted instances. - $instances = field_read_instances(array('deleted' => 1), array('include_deleted' => 1)); + $all_instances = field_read_instances(array('deleted' => 1), array('include_deleted' => 1)); + $instances = array(); + foreach ($all_instances as $instance) { + $instances[$instance['entity_type']][$instance['field_id']][$instance['bundle']] = $instance; + } $factory = drupal_container()->get('entity.query'); - $info = entity_get_info(); - foreach ($instances as $instance) { - $entity_type = $instance['entity_type']; - $ids = (object) array( - 'entity_type' => $entity_type, - 'bundle' => $instance['bundle'], - ); - // field_purge_data() will need the field array. - $field = field_info_field_by_id($instance['field_id']); - // Retrieve some entities. - $results = $factory->get($entity_type) - ->condition('id:' . $field['id'] . '.deleted', 1) - ->condition($info[$entity_type]['entity_keys']['bundle'], $ids->bundle) - ->range(0, $batch_size) - ->execute(); - - if ($results) { - $entities = array(); - foreach ($results as $revision_id => $entity_id) { - // This might not be the revision id if the entity type does not support - // revisions but _field_create_entity_from_ids() checks that and - // disregards this value so there is no harm setting it. - $ids->revision_id = $revision_id; - $ids->entity_id = $entity_id; - $entities[$entity_id] = _field_create_entity_from_ids($ids); + foreach ($instances as $entity_type => $data) { + foreach ($data as $field_id => $instances) { + $ids = (object) array( + 'entity_type' => $entity_type, + ); + // field_purge_data() will need the field array. + $field = field_info_field_by_id($field_id); + // Retrieve some entities. + $results = $factory->get($entity_type) + ->condition('id:' . $field['id'] . '.deleted', 1) + ->range(0, $batch_size) + ->execute(); + + if ($results) { + $bundles = module_invoke($field['storage']['module'], 'field_storage_bundles', $field, $results); + $entities = array(); + foreach ($results as $revision_id => $entity_id) { + // This might not be the revision id if the entity type does not support + // revisions but _field_create_entity_from_ids() checks that and + // disregards this value so there is no harm setting it. + $ids->revision_id = $revision_id; + $ids->entity_id = $entity_id; + $ids->bundle = $bundles[$entity_id]; + $entities[$entity_id] = _field_create_entity_from_ids($ids); + } + field_attach_load($entity_type, $entities, FIELD_LOAD_CURRENT, array('field_id' => $field['id'], 'deleted' => 1)); + foreach ($entities as $entity) { + // Purge the data for the entity. + field_purge_data($entity, $field, $instances[$bundles[$entity->id()]]); + } } - field_attach_load($entity_type, $entities, FIELD_LOAD_CURRENT, array('field_id' => $field['id'], 'deleted' => 1)); - foreach ($entities as $entity) { - // Purge the data for the entity. - field_purge_data($entity, $field, $instance); + else { + // There are no results in any bundle for this so just purge all the + // instances of this field on this entity type. + foreach ($instances as $instance) { + field_purge_instance($instance); + } } } - else { - // No field data remains for the instance, so we can remove it. - field_purge_instance($instance); - } } // Retrieve all deleted fields. Any that have no instances can be purged. diff --git a/core/modules/field_sql_storage/field_sql_storage.module b/core/modules/field_sql_storage/field_sql_storage.module index accca35..43fef53 100644 --- a/core/modules/field_sql_storage/field_sql_storage.module +++ b/core/modules/field_sql_storage/field_sql_storage.module @@ -504,6 +504,19 @@ function field_sql_storage_field_storage_delete(EntityInterface $entity, $fields } } + +/** + * Implements hook_field_storage_bundles(). + */ +function field_sql_storage_field_storage_bundles($field, $entity_ids) { + $table_name = _field_sql_storage_tablename($field); + return db_select($table_name, 'f') + ->fields('f', array('entity_id', 'bundle')) + ->condition('entity_id', $entity_ids) + ->execute() + ->fetchAllKeyed(); +} + /** * Implements hook_field_storage_purge(). * diff --git a/core/modules/field_ui/lib/Drupal/field_ui/Tests/FieldUiTestBase.php b/core/modules/field_ui/lib/Drupal/field_ui/Tests/FieldUiTestBase.php index aa923f1..588e186 100644 --- a/core/modules/field_ui/lib/Drupal/field_ui/Tests/FieldUiTestBase.php +++ b/core/modules/field_ui/lib/Drupal/field_ui/Tests/FieldUiTestBase.php @@ -137,6 +137,7 @@ function fieldUIDeleteField($bundle_path, $field_name, $label, $bundle_label) { // Submit confirmation form. $this->drupalPost(NULL, array(), t('Delete')); + $this->assertResponse(200); $this->assertRaw(t('The field %label has been deleted from the %type content type.', array('%label' => $label, '%type' => $bundle_label)), 'Delete message was found.'); // Check that the field does not appear in the overview form. diff --git a/core/modules/field_ui/lib/Drupal/field_ui/Tests/ManageFieldsTest.php b/core/modules/field_ui/lib/Drupal/field_ui/Tests/ManageFieldsTest.php index 7298c36..14677eb 100644 --- a/core/modules/field_ui/lib/Drupal/field_ui/Tests/ManageFieldsTest.php +++ b/core/modules/field_ui/lib/Drupal/field_ui/Tests/ManageFieldsTest.php @@ -450,4 +450,27 @@ function testWidgetChange() { $this->assertFieldByXPath("//select[@name='widget_type']", 'options_buttons'); } + /** + * Tests that deletion removes fields and instances as expected for a term. + */ + function testDeleteTaxonomyField() { + // Create a new field. + $bundle_path = 'admin/structure/taxonomy/tags'; + $edit1 = array( + 'fields[_add_new_field][label]' => $this->field_label, + 'fields[_add_new_field][field_name]' => $this->field_name_input, + ); + $this->fieldUIAddNewField($bundle_path, $edit1); + + // Delete the field. + $this->fieldUIDeleteField($bundle_path, $this->field_name, $this->field_label, 'Tags'); + + // Reset the fields info. + field_info_cache_clear(); + // Check that the field instance was deleted. + $this->assertNull(field_info_instance('taxonomy_term', $this->field_name, 'tags'), 'Field instance was deleted.'); + // Check that the field was deleted too. + $this->assertNull(field_info_field($this->field_name), 'Field was deleted.'); + } + }