diff --git a/modules/field/field.attach.inc b/modules/field/field.attach.inc index c643e40..e08e154 100644 --- a/modules/field/field.attach.inc +++ b/modules/field/field.attach.inc @@ -1341,7 +1341,8 @@ function field_attach_delete_bundle($entity_type, $bundle) { // disabled entity types or bundles. $instances = field_read_instances(array('entity_type' => $entity_type, 'bundle' => $bundle), array('include_inactive' => 1)); foreach ($instances as $instance) { - field_delete_instance($instance); + // Delete fields as we go along, but do not perform purges. + field_delete_instance($instance, TRUE, FALSE); } // Clear the cache. diff --git a/modules/field/field.crud.inc b/modules/field/field.crud.inc index a6aaab1..e218c8f 100644 --- a/modules/field/field.crud.inc +++ b/modules/field/field.crud.inc @@ -384,8 +384,11 @@ function field_read_fields($params = array(), $include_additional = array()) { * * @param $field_name * The field name to delete. + * @param $purge + * (optional) If TRUE, the field deletion will be followed by a purge pass. + * Defaults to TRUE. */ -function field_delete_field($field_name) { +function field_delete_field($field_name, $purge = TRUE) { // Delete all non-deleted instances. $field = field_info_field($field_name); if (isset($field['bundles'])) { @@ -410,6 +413,16 @@ function field_delete_field($field_name) { field_cache_clear(TRUE); module_invoke_all('field_delete_field', $field); + + // Fields are purged on cron. However field module prevents disabling modules + // when field types they provided are used in a field until it is fully + // purged. In the case that a field has minimal or no content, a single call + // to field_purge_batch() will remove it from the system at once and avoid + // administrators having to wait for cron runs when removing instances that + // meet this criteria. + if ($purge) { + field_purge_batch(10, $field['id']); + } } /** @@ -726,11 +739,14 @@ function field_read_instances($params = array(), $include_additional = array()) * @param $instance * An instance structure. * @param $field_cleanup - * If TRUE, the field will be deleted as well if its last instance is being - * deleted. If FALSE, it is the caller's responsability to handle the case of - * fields left without instances. Defaults to TRUE. + * (optional) If TRUE, the field will be deleted as well if its last instance + * is being deleted. If FALSE, it is the caller's responsability to handle the + * case of fields left without instances. Defaults to TRUE. + * @param $purge + * (optional) If TRUE and $field_cleanup is TRUE, the field deletion will be + * followed by a purge pass. Defaults to TRUE. */ -function field_delete_instance($instance, $field_cleanup = TRUE) { +function field_delete_instance($instance, $field_cleanup = TRUE, $purge = TRUE) { // Mark the field instance for deletion. db_update('field_config_instance') ->fields(array('deleted' => 1)) @@ -751,7 +767,7 @@ function field_delete_instance($instance, $field_cleanup = TRUE) { // Delete the field itself if we just deleted its last instance. if ($field_cleanup && count($field['bundles']) == 0) { - field_delete_field($field['field_name']); + field_delete_field($field['field_name'], $purge); } } @@ -837,11 +853,17 @@ function field_delete_instance($instance, $field_cleanup = TRUE) { * * @param $batch_size * The maximum number of field data records to purge before returning. + * @param $field_id + * @todo */ -function field_purge_batch($batch_size) { +function field_purge_batch($batch_size, $field_id = NULL) { // 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)); + $options = array('deleted' => 1); + if ($field_id) { + $options['field_id'] = $field_id; + } + $instances = field_read_instances($options, array('include_deleted' => 1)); foreach ($instances as $instance) { // field_purge_data() will need the field array. @@ -855,23 +877,27 @@ function field_purge_batch($batch_size) { ->range(0, $batch_size) ->execute(); - if ($results) { - foreach ($results as $entity_type => $stub_entities) { - field_attach_load($entity_type, $stub_entities, FIELD_LOAD_CURRENT, array('field_id' => $field['id'], 'deleted' => 1)); - foreach ($stub_entities as $stub_entity) { - // Purge the data for the entity. - field_purge_data($entity_type, $stub_entity, $field, $instance); - } + $count = 0; + foreach ($results as $entity_type => $stub_entities) { + field_attach_load($entity_type, $stub_entities, FIELD_LOAD_CURRENT, array('field_id' => $field['id'], 'deleted' => 1)); + foreach ($stub_entities as $stub_entity) { + // Purge the data for the entity. + field_purge_data($entity_type, $stub_entity, $field, $instance); } + $count++; } - else { + if ($count < $batch_size) { // 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. - $fields = field_read_fields(array('deleted' => 1), array('include_deleted' => 1)); + $options = array('deleted' => 1); + if ($field_id) { + $options['id'] = $field_id; + } + $fields = field_read_fields($options, array('include_deleted' => 1)); foreach ($fields as $field) { $instances = field_read_instances(array('field_id' => $field['id']), array('include_deleted' => 1)); if (empty($instances)) { diff --git a/modules/field/tests/field.test b/modules/field/tests/field.test index b361637..22264d4 100644 --- a/modules/field/tests/field.test +++ b/modules/field/tests/field.test @@ -3147,13 +3147,6 @@ class FieldBulkDeleteTestCase extends FieldTestCase { } $this->assertEqual(count($stubs), $count-10, 'hook_field_delete was called with each entity once'); - // The instance still exists, deleted. - $instances = field_read_instances(array('field_id' => $field['id'], 'deleted' => 1), array('include_deleted' => 1, 'include_inactive' => 1)); - $this->assertEqual(count($instances), 1, 'There is one deleted instance'); - - // Purge the instance. - field_purge_batch($batch_size); - // The instance is gone. $instances = field_read_instances(array('field_id' => $field['id'], 'deleted' => 1), array('include_deleted' => 1, 'include_inactive' => 1)); $this->assertEqual(count($instances), 0, 'The instance is gone'); @@ -3177,9 +3170,6 @@ class FieldBulkDeleteTestCase extends FieldTestCase { // Purge the data. field_purge_batch(10); - // Purge again to purge the instance. - field_purge_batch(0); - // The field still exists, not deleted. $fields = field_read_fields(array('id' => $field['id']), array('include_deleted' => 1)); $this->assertTrue(isset($fields[$field['id']]) && !$fields[$field['id']]['deleted'], 'The field exists and is not deleted'); @@ -3188,15 +3178,12 @@ class FieldBulkDeleteTestCase extends FieldTestCase { $instance = field_info_instance($this->entity_type, $field['field_name'], 'bb_2'); field_delete_instance($instance); - // Purge the data. - field_purge_batch(10); - // The field still exists, deleted. $fields = field_read_fields(array('id' => $field['id']), array('include_deleted' => 1)); $this->assertTrue(isset($fields[$field['id']]) && $fields[$field['id']]['deleted'], 'The field exists and is deleted'); - // Purge again to purge the instance and the field. - field_purge_batch(0); + // Purge the data. + field_purge_batch(10); // The field is gone. $fields = field_read_fields(array('id' => $field['id']), array('include_deleted' => 1, 'include_inactive' => 1)); diff --git a/modules/field_ui/field_ui.admin.inc b/modules/field_ui/field_ui.admin.inc index 3f60085..811e0f5 100644 --- a/modules/field_ui/field_ui.admin.inc +++ b/modules/field_ui/field_ui.admin.inc @@ -1727,14 +1727,6 @@ function field_ui_field_delete_form_submit($form, &$form_state) { $admin_path = _field_ui_bundle_admin_path($entity_type, $bundle); $form_state['redirect'] = field_ui_get_destinations(array($admin_path . '/fields')); - - // Fields are purged on cron. However field module prevents disabling modules - // when field types they provided are used in a field until it is fully - // purged. In the case that a field has minimal or no content, a single call - // to field_purge_batch() will remove it from the system. Call this with a - // low batch limit to avoid administrators having to wait for cron runs when - // removing instances that meet this criteria. - field_purge_batch(10); } /** diff --git a/modules/forum/forum.install b/modules/forum/forum.install index 2eebd7f..68bf209 100644 --- a/modules/forum/forum.install +++ b/modules/forum/forum.install @@ -115,9 +115,6 @@ function forum_uninstall() { variable_del('node_options_forum'); field_delete_field('taxonomy_forums'); - // Purge field data now to allow taxonomy module to be uninstalled - // if this is the only field remaining. - field_purge_batch(10); } /**