Index: modules/field/field.crud.inc =================================================================== RCS file: /cvs/drupal/drupal/modules/field/field.crud.inc,v retrieving revision 1.73 diff -u -p -r1.73 field.crud.inc --- modules/field/field.crud.inc 15 Dec 2010 04:13:48 -0000 1.73 +++ modules/field/field.crud.inc 16 Dec 2010 22:41:59 -0000 @@ -583,16 +583,12 @@ function field_read_fields($params = arr */ function field_delete_field($field_name) { // Delete all non-deleted instances. - $field = field_info_field($field_name); - if (isset($field['bundles'])) { - foreach ($field['bundles'] as $entity_type => $bundles) { - foreach ($bundles as $bundle) { - $instance = field_info_instance($entity_type, $field_name, $bundle); - field_delete_instance($instance, FALSE); - } - } + $field = field_read_field($field_name, array('include_inactive' => TRUE)); + $instances = field_read_instances(array('field_id' => $field['id']), array('include_inactive' => TRUE)); + foreach ($instances as $instance) { + field_delete_instance($instance, FALSE); } - + // Mark field data for deletion. module_invoke($field['storage']['module'], 'field_storage_delete_field', $field); @@ -941,15 +937,18 @@ function field_delete_instance($instance field_cache_clear(); // Mark instance data for deletion. - $field = field_info_field($instance['field_name']); + $field = field_read_field($instance['field_name'], array('include_inactive' => TRUE)); module_invoke($field['storage']['module'], 'field_storage_delete_instance', $instance); // Let modules react to the deletion of the instance. module_invoke_all('field_delete_instance', $instance); // Delete the field itself if we just deleted its last instance. - if ($field_cleanup && count($field['bundles']) == 0) { - field_delete_field($field['field_name']); + if ($field_cleanup) { + $instances = field_read_instances(array('field_id' => $field['id']), array('include_inactive' => TRUE)); + if (empty($instances)){ + field_delete_field($field['field_name']); + } } } @@ -1037,13 +1036,17 @@ function field_delete_instance($instance * The maximum number of field data records to purge before returning. */ 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)); + // Retrieve all deleted field instances, regardless its active status. + // A field is inactive when the module providing with its field type has + // been disabled. + $instances = field_read_instances(array('deleted' => 1), array('include_deleted' => TRUE, 'include_inactive' => TRUE)); foreach ($instances as $instance) { // field_purge_data() will need the field array. - $field = field_info_field_by_id($instance['field_id']); + $field = field_read_field($instance['field_name'], array('include_deleted' => TRUE, 'include_inactive' => TRUE)); + if (empty($field['storage']['active'])){ + continue; + } // Retrieve some entities. $query = new EntityFieldQuery(); $results = $query @@ -1068,10 +1071,10 @@ function field_purge_batch($batch_size) } } - // Retrieve all deleted fields. Any that have no instances can be purged. - $fields = field_read_fields(array('deleted' => 1), array('include_deleted' => 1)); + // Retrieve all deleted fields. Any that have no bundles can be purged. + $fields = field_read_fields(array('deleted' => 1), array('include_deleted' => TRUE, 'include_inactive' => TRUE)); foreach ($fields as $field) { - $instances = field_read_instances(array('field_id' => $field['id']), array('include_deleted' => 1)); + $instances = field_read_instances(array('field_id' => $field['id']), array('include_deleted' => TRUE, 'include_inactive' => TRUE)); if (empty($instances)) { field_purge_field($field); } @@ -1125,7 +1128,7 @@ function field_purge_instance($instance) ->execute(); // Notify the storage engine. - $field = field_info_field_by_id($instance['field_id']); + $field = field_read_field($instance['field_name'], array('include_deleted' => TRUE, 'include_inactive' => TRUE)); module_invoke($field['storage']['module'], 'field_storage_purge_instance', $instance); // Clear the cache. Index: modules/field/modules/field_sql_storage/field_sql_storage.module =================================================================== RCS file: /cvs/drupal/drupal/modules/field/modules/field_sql_storage/field_sql_storage.module,v retrieving revision 1.57 diff -u -p -r1.57 field_sql_storage.module --- modules/field/modules/field_sql_storage/field_sql_storage.module 14 Dec 2010 19:50:05 -0000 1.57 +++ modules/field/modules/field_sql_storage/field_sql_storage.module 16 Dec 2010 22:42:01 -0000 @@ -437,11 +437,9 @@ function field_sql_storage_field_storage * This function deletes data for all fields for an entity from the database. */ function field_sql_storage_field_storage_delete($entity_type, $entity, $fields) { - list($id, $vid, $bundle) = entity_extract_ids($entity_type, $entity); - - foreach (field_info_instances($entity_type, $bundle) as $instance) { - if (isset($fields[$instance['field_id']])) { - $field = field_info_field_by_id($instance['field_id']); + foreach ($fields as $field_id) { + $instances = field_read_instances(array('field_id' => $field_id), array('include_inactive' => TRUE)); + foreach ($instances as $instance) { field_sql_storage_field_storage_purge($entity_type, $entity, $field, $instance); } } @@ -605,13 +603,16 @@ function field_sql_storage_field_storage if (isset($vid)) { foreach ($fields as $field_id) { - $field = field_info_field_by_id($field_id); - $revision_name = _field_sql_storage_revision_tablename($field); - db_delete($revision_name) - ->condition('entity_type', $entity_type) - ->condition('entity_id', $id) - ->condition('revision_id', $vid) - ->execute(); + $fields = field_read_fields(array('field_id' => $field_id), array('include_inactive' => TRUE)); + $field = $fields ? current($fields) : FALSE; + if ($field) { + $revision_name = _field_sql_storage_revision_tablename($field); + db_delete($revision_name) + ->condition('entity_type', $entity_type) + ->condition('entity_id', $id) + ->condition('revision_id', $vid) + ->execute(); + } } } } @@ -622,7 +623,7 @@ function field_sql_storage_field_storage * This function simply marks for deletion all data associated with the field. */ function field_sql_storage_field_storage_delete_instance($instance) { - $field = field_info_field($instance['field_name']); + $field = field_read_field($instance['field_name'], array('include_inactive' => TRUE)); $table_name = _field_sql_storage_tablename($field); $revision_name = _field_sql_storage_revision_tablename($field); db_update($table_name) Index: modules/field/tests/field.test =================================================================== RCS file: /cvs/drupal/drupal/modules/field/tests/field.test,v retrieving revision 1.47 diff -u -p -r1.47 field.test --- modules/field/tests/field.test 15 Dec 2010 04:13:48 -0000 1.47 +++ modules/field/tests/field.test 16 Dec 2010 22:42:01 -0000 @@ -2096,11 +2096,13 @@ class FieldCrudTestCase extends FieldTes function testDeleteField() { // TODO: Also test deletion of the data stored in the field ? - // Create two fields (so we can test that only one is deleted). + // Create three fields (so we can test which is deleted). $this->field = array('field_name' => 'field_1', 'type' => 'test_field'); field_create_field($this->field); $this->another_field = array('field_name' => 'field_2', 'type' => 'test_field'); field_create_field($this->another_field); + $this->inactive_field = array('field_name' => 'field_inactive', 'type' => 'test_field'); + field_create_field($this->inactive_field); // Create instances for each. $this->instance_definition = array( @@ -2112,10 +2114,21 @@ class FieldCrudTestCase extends FieldTes ), ); field_create_instance($this->instance_definition); + $this->another_instance_definition = $this->instance_definition; $this->another_instance_definition['field_name'] = $this->another_field['field_name']; field_create_instance($this->another_instance_definition); + $this->inactive_instance_definition = $this->instance_definition; + $this->inactive_instance_definition['field_name'] = $this->inactive_field['field_name']; + field_create_instance($this->inactive_instance_definition); + + // Simulate an inactive field. + db_update('field_config') + ->fields(array('active' => 0)) + ->condition('field_name', $this->inactive_field['field_name']) + ->execute(); + // Test that the first field is not deleted, and then delete it. $field = field_read_field($this->field['field_name'], array('include_deleted' => TRUE)); $this->assertTrue(!empty($field) && empty($field['deleted']), t('A new field is not marked for deletion.')); @@ -2145,6 +2158,17 @@ class FieldCrudTestCase extends FieldTes $another_instance = field_read_instance('test_entity', $this->another_instance_definition['field_name'], $this->another_instance_definition['bundle']); $this->assertTrue(!empty($another_instance) && empty($another_instance['deleted']), t('An instance of a non-deleted field is not marked for deletion.')); + // Make sure that the inactive field is marked as deleted when it is + // specifically loaded. + field_delete_field($this->inactive_field['field_name']); + $field = field_read_field($this->inactive_field['field_name'], array('include_deleted' => TRUE, 'include_inactive' => TRUE)); + $this->assertTrue(!empty($field['deleted']), t('A deleted inactive field is marked for deletion.')); + + // Try to load the instance of the inactive field normally and make sure + // it does not show up. + $instance = field_read_instance('test_entity', $this->inactive_instance_definition['field_name'], $this->inactive_instance_definition['bundle']); + $this->assertTrue(empty($instance), t('An instance for a deleted inactive field is not loaded by default.')); + // Try to create a new field the same name as a deleted field and // write data into it. field_create_field($this->field); @@ -2961,6 +2985,12 @@ class FieldBulkDeleteTestCase extends Fi $id++; } } + + // Simulate an inactive field. + db_update('field_config') + ->fields(array('active' => 0)) + ->condition('field_name', 'bf_2') + ->execute(); } /**