diff --git a/modules/field/field.api.php b/modules/field/field.api.php index 9c52d24..0790f0b 100644 --- a/modules/field/field.api.php +++ b/modules/field/field.api.php @@ -124,6 +124,10 @@ function hook_field_extra_fields_alter(&$info) { /** * Define Field API field types. * + * Note that fields and their instances should never be created in the same + * module that defines their field type, because disabling the module will mark + * the fields as inactive, preventing them from being removed on uninstall. + * * @return * An array whose keys are field type names and whose values are arrays * describing the field type, with the following key/value pairs: diff --git a/modules/field/field.crud.inc b/modules/field/field.crud.inc index 339e9c4..605564a 100644 --- a/modules/field/field.crud.inc +++ b/modules/field/field.crud.inc @@ -23,6 +23,10 @@ * This function does not bind the field to any bundle; use * field_create_instance() for that. * + * Note that fields and their instances should never be created in the same + * module that defines their field type, because disabling the module will mark + * the fields as inactive, preventing them from being removed on uninstall. + * * @param $field * A field definition array. The field_name and type properties are required. * Other properties, if omitted, will be given the following default values: @@ -415,6 +419,10 @@ function field_delete_field($field_name) { /** * Creates an instance of a field, binding it to a bundle. * + * Note that fields and their instances should never be created in the same + * module that defines their field type, because disabling the module will mark + * the fields as inactive, preventing them from being removed on uninstall. + * * @param $instance * A field instance definition array. The field_name, entity_type and * bundle properties are required. Other properties, if omitted, diff --git a/modules/field/field.module b/modules/field/field.module index 9e03c8d..bc5703c 100644 --- a/modules/field/field.module +++ b/modules/field/field.module @@ -415,6 +415,38 @@ function field_modules_disabled($modules) { } /** + * Implements hook_system_info_alter(). + * + * Goes through a list of all modules that provide a field type, and makes them + * required if there are any active fields of that type. + */ +function field_system_info_alter(&$info, $file, $type) { + if ($type == 'module' && module_hook($file->name, 'field_info')) { + $fields = field_read_fields(array('module' => $file->name)); + if ($fields) { + $info['required'] = TRUE; + + // Provide an explanation message (only mention pending deletions if there + // remains no actual, non-deleted fields) + $non_deleted = FALSE; + foreach ($fields as $field) { + if (empty($field['deleted'])) { + $non_deleted = TRUE; + break; + } + } + if ($non_deleted) { + $explanation = t('Field type(s) in use - see !link', array('!link' => l(t('Field list'), 'admin/reports/fields'))); + } + else { + $explanation = t('Fields pending deletion'); + } + $info['explanation'] = $explanation; + } + } +} + +/** * Allows a module to update the database for fields and columns it controls. * * @param string $module diff --git a/modules/field_ui/field_ui.admin.inc b/modules/field_ui/field_ui.admin.inc index 96beb13..db31004 100644 --- a/modules/field_ui/field_ui.admin.inc +++ b/modules/field_ui/field_ui.admin.inc @@ -12,17 +12,27 @@ function field_ui_fields_list() { $instances = field_info_instances(); $field_types = field_info_field_types(); $bundles = field_info_bundles(); + + $modules = system_rebuild_module_data(); + $header = array(t('Field name'), t('Field type'), t('Used in')); $rows = array(); foreach ($instances as $entity_type => $type_bundles) { foreach ($type_bundles as $bundle => $bundle_instances) { foreach ($bundle_instances as $field_name => $instance) { $field = field_info_field($field_name); + + // Initialize the row if we encounter the field for the first time. + if (!isset($rows[$field_name])) { + $rows[$field_name]['class'] = $field['locked'] ? array('menu-disabled') : array(''); + $rows[$field_name]['data'][0] = $field['locked'] ? t('@field_name (Locked)', array('@field_name' => $field_name)) : $field_name; + $module_name = $field_types[$field['type']]['module']; + $rows[$field_name]['data'][1] = $field_types[$field['type']]['label'] . ' ' . t('(module: !module)', array('!module' => $modules[$module_name]->info['name'])); + } + + // Add the current instance. $admin_path = _field_ui_bundle_admin_path($entity_type, $bundle); - $rows[$field_name]['data'][0] = $field['locked'] ? t('@field_name (Locked)', array('@field_name' => $field_name)) : $field_name; - $rows[$field_name]['data'][1] = $field_types[$field['type']]['label']; $rows[$field_name]['data'][2][] = $admin_path ? l($bundles[$entity_type][$bundle]['label'], $admin_path . '/fields') : $bundles[$entity_type][$bundle]['label']; - $rows[$field_name]['class'] = $field['locked'] ? array('menu-disabled') : array(''); } } } diff --git a/modules/system/system.admin.inc b/modules/system/system.admin.inc index 9e7d69d..abb796c 100644 --- a/modules/system/system.admin.inc +++ b/modules/system/system.admin.inc @@ -799,7 +799,7 @@ function system_modules($form, $form_state = array()) { $extra['enabled'] = (bool) $module->status; if (!empty($module->info['required'] )) { $extra['disabled'] = TRUE; - $extra['required_by'][] = $distribution_name; + $extra['required_by'][] = $distribution_name . (!empty($module->info['explanation']) ? ' ('. $module->info['explanation'] .')' : ''); } // If this module requires other modules, add them to the array.