diff options
Diffstat (limited to 'modules/system')
-rw-r--r-- | modules/system/system.admin.inc | 70 | ||||
-rw-r--r-- | modules/system/system.module | 2 | ||||
-rw-r--r-- | modules/system/system.test | 34 |
3 files changed, 81 insertions, 25 deletions
diff --git a/modules/system/system.admin.inc b/modules/system/system.admin.inc index 0b6e45683..647ffc5c7 100644 --- a/modules/system/system.admin.inc +++ b/modules/system/system.admin.inc @@ -1213,30 +1213,42 @@ function system_modules_uninstall($form, $form_state = NULL) { return $confirm_form; } - // Pull all disabled modules from the system table. - $disabled_modules = db_query("SELECT name, filename, info FROM {system} WHERE type = 'module' AND status = 0 AND schema_version > :schema ORDER BY name", array(':schema' => SCHEMA_UNINSTALLED)); - foreach ($disabled_modules as $module) { - // Grab the module info - $info = unserialize($module->info); - - // Load the .install file, and check for an uninstall or schema hook. - // If the hook exists, the module can be uninstalled. - module_load_install($module->name); - if (module_hook($module->name, 'uninstall') || module_hook($module->name, 'schema')) { - $form['modules'][$module->name]['name'] = array('#markup' => $info['name'] ? $info['name'] : $module->name); - $form['modules'][$module->name]['description'] = array('#markup' => t($info['description'])); - $options[$module->name] = ''; + // Get a list of disabled, installed modules. + $all_modules = system_rebuild_module_data(); + $disabled_modules = array(); + foreach ($all_modules as $name => $module) { + if (empty($module->status) && $module->schema_version > SCHEMA_UNINSTALLED) { + $disabled_modules[$name] = $module; + } + } + + // Only build the rest of the form if there are any modules available to + // uninstall. + if (!empty($disabled_modules)) { + $profile = drupal_get_profile(); + uasort($disabled_modules, 'system_sort_modules_by_info_name'); + $form['uninstall'] = array('#tree' => TRUE); + foreach ($disabled_modules as $module) { + $module_name = $module->info['name'] ? $module->info['name'] : $module->name; + $form['modules'][$module->name]['#module_name'] = $module_name; + $form['modules'][$module->name]['name']['#markup'] = $module_name; + $form['modules'][$module->name]['description']['#markup'] = t($module->info['description']); + $form['uninstall'][$module->name] = array( + '#type' => 'checkbox', + '#title' => t('Uninstall @module module', array('@module' => $module_name)), + '#title_display' => 'invisible', + ); + // All modules which depend on this one must be uninstalled first, before + // we can allow this module to be uninstalled. (The install profile is + // excluded from this list.) + foreach (array_keys($module->required_by) as $dependent) { + if ($dependent != $profile && drupal_get_installed_schema_version($dependent) != SCHEMA_UNINSTALLED) { + $dependent_name = isset($all_modules[$dependent]->info['name']) ? $all_modules[$dependent]->info['name'] : $dependent; + $form['modules'][$module->name]['#required_by'][] = $dependent_name; + $form['uninstall'][$module->name]['#disabled'] = TRUE; + } + } } - } - - // Only build the rest of the form if there are any modules available to uninstall. - if (!empty($options)) { - $form['uninstall'] = array( - '#type' => 'checkboxes', - '#title' => t('Modules'), - '#title_display' => 'invisible', - '#options' => $options, - ); $form['actions'] = array('#type' => 'actions'); $form['actions']['submit'] = array( '#type' => 'submit', @@ -2586,10 +2598,20 @@ function theme_system_modules_uninstall($variables) { // Display table. $rows = array(); foreach (element_children($form['modules']) as $module) { + if (!empty($form['modules'][$module]['#required_by'])) { + $disabled_message = format_plural(count($form['modules'][$module]['#required_by']), + 'To uninstall @module, the following module must be uninstalled first: @required_modules', + 'To uninstall @module, the following modules must be uninstalled first: @required_modules', + array('@module' => $form['modules'][$module]['#module_name'], '@required_modules' => implode(', ', $form['modules'][$module]['#required_by']))); + $disabled_message = '<div class="admin-requirements">' . $disabled_message . '</div>'; + } + else { + $disabled_message = ''; + } $rows[] = array( array('data' => drupal_render($form['uninstall'][$module]), 'align' => 'center'), '<strong><label for="' . $form['uninstall'][$module]['#id'] . '">' . drupal_render($form['modules'][$module]['name']) . '</label></strong>', - array('data' => drupal_render($form['modules'][$module]['description']), 'class' => array('description')), + array('data' => drupal_render($form['modules'][$module]['description']) . $disabled_message, 'class' => array('description')), ); } diff --git a/modules/system/system.module b/modules/system/system.module index 699f73a7f..98df4868b 100644 --- a/modules/system/system.module +++ b/modules/system/system.module @@ -113,7 +113,7 @@ function system_help($path, $arg) { } return $output; case 'admin/modules/uninstall': - return '<p>' . t('The uninstall process removes all data related to a module. To uninstall a module, you must first disable it on the main <a href="@modules">Modules page</a>. Not all modules support this feature.', array('@modules' => url('admin/modules'))) . '</p>'; + return '<p>' . t('The uninstall process removes all data related to a module. To uninstall a module, you must first disable it on the main <a href="@modules">Modules page</a>.', array('@modules' => url('admin/modules'))) . '</p>'; case 'admin/structure/block/manage': if ($arg[4] == 'system' && $arg[5] == 'powered-by') { return '<p>' . t('The <em>Powered by Drupal</em> block is an optional link to the home page of the Drupal project. While there is absolutely no requirement that sites feature this link, it may be used to show support for Drupal.') . '</p>'; diff --git a/modules/system/system.test b/modules/system/system.test index 85ac61609..d32b3ae3e 100644 --- a/modules/system/system.test +++ b/modules/system/system.test @@ -350,6 +350,40 @@ class ModuleDependencyTestCase extends ModuleTestCase { // Check the actual order which is saved by module_test_modules_enabled(). $this->assertIdentical(variable_get('test_module_enable_order', FALSE), $expected_order, t('Modules enabled in the correct order.')); } + + /** + * Tests attempting to uninstall a module that has installed dependents. + */ + function testUninstallDependents() { + // Enable the forum module. + $edit = array('modules[Core][forum][enable]' => 'forum'); + $this->drupalPost('admin/modules', $edit, t('Save configuration')); + $this->assertModules(array('forum'), TRUE); + + // Disable forum and taxonomy. Both should now be installed but disabled. + $edit = array('modules[Core][forum][enable]' => FALSE); + $this->drupalPost('admin/modules', $edit, t('Save configuration')); + $this->assertModules(array('forum'), FALSE); + $edit = array('modules[Core][taxonomy][enable]' => FALSE); + $this->drupalPost('admin/modules', $edit, t('Save configuration')); + $this->assertModules(array('taxonomy'), FALSE); + + // Check that the taxonomy module cannot be uninstalled. + $this->drupalGet('admin/modules/uninstall'); + $checkbox = $this->xpath('//input[@type="checkbox" and @disabled="disabled" and @name="uninstall[taxonomy]"]'); + $this->assert(count($checkbox) == 1, t('Checkbox for uninstalling the taxonomy module is disabled.')); + + // Uninstall the forum module, and check that taxonomy now can also be + // uninstalled. + $edit = array('uninstall[forum]' => 'forum'); + $this->drupalPost('admin/modules/uninstall', $edit, t('Uninstall')); + $this->drupalPost(NULL, NULL, t('Uninstall')); + $this->assertText(t('The selected modules have been uninstalled.'), t('Modules status has been updated.')); + $edit = array('uninstall[taxonomy]' => 'taxonomy'); + $this->drupalPost('admin/modules/uninstall', $edit, t('Uninstall')); + $this->drupalPost(NULL, NULL, t('Uninstall')); + $this->assertText(t('The selected modules have been uninstalled.'), t('Modules status has been updated.')); + } } /** |