Index: modules/system/system.admin.inc =================================================================== RCS file: /cvs/drupal/drupal/modules/system/system.admin.inc,v retrieving revision 1.30 diff -u -r1.30 system.admin.inc --- modules/system/system.admin.inc 27 Nov 2007 21:06:28 -0000 1.30 +++ modules/system/system.admin.inc 3 Dec 2007 01:56:26 -0000 @@ -566,6 +566,8 @@ * The form array. */ function system_modules($form_state = array()) { + // For uninstallation checks + include_once './includes/install.inc'; drupal_rebuild_theme_registry(); node_types_rebuild(); menu_rebuild(); @@ -585,6 +587,28 @@ // Create storage for disabled modules as browser will disable checkboxes. $form['disabled_modules'] = array('#type' => 'value', '#value' => array()); + + // Create links for module dashboard + $form['module_menu'] = array('#type' => 'value', '#value' => array()); + + // Retrieve help links that 'help' knows about + $help_menu = module_invoke('help', 'menu'); + $help_links = array(); + if (is_array($help_menu)) { + foreach ($help_menu as $path => $info) { + if (!isset($info['title'])) continue; + $help_links[$info['title']] = $path; + } + } + + // Determine which modules can be uninstalled + $db_result = _system_modules_get_uninstallable_modules(); + $uninstallable_modules = array(); + while ($module = db_fetch_object($db_result)) { + $uninstallable_modules[$module->name] = true; + } + + // Traverse the files, checking for compatibility $incompatible_core = array(); @@ -621,6 +645,21 @@ if ($file->throttle) { $throttle[] = $file->name; } + + $menu = system_get_module_admin_tasks($filename); + if (isset($help_links[$filename])) { + $form['module_menu']['#value'][$filename][] = ''. t('Help') .''; + } + foreach ($menu as $link) { + $form['module_menu']['#value'][$filename][] = $link; + } + // Checking if module was previously enabled mitigates security risk + if (isset($uninstallable_modules[$filename])) { + module_load_install($filename); + if (module_hook($filename, 'uninstall')) { + $form['module_menu']['#value'][$filename][] = ''. t('Uninstall') .''; + } + } $dependencies = array(); // Check for missing dependencies. @@ -716,7 +755,6 @@ '#value' => t('Save configuration'), ); $form['#action'] = url('admin/build/modules/list/confirm'); - return $form; } @@ -936,7 +974,7 @@ $form = array(); // 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 > %d ORDER BY name", SCHEMA_UNINSTALLED); + $disabled_modules = _system_modules_get_uninstallable_modules(); while ($module = db_fetch_object($disabled_modules)) { // Grab the module info @@ -951,6 +989,18 @@ $options[$module->name] = ''; } } + + if (arg(4) == 'confirm' && $module = arg(5)) { + if (isset($form['modules'][$module])) { + $storage['uninstall'][$module] = $module; + if ($confirm_form = system_modules_uninstall_confirm_form($storage)) { + return $confirm_form; + } + } + else { + form_set_error('system_modules_uninstall', 'Cannot uninstall '. $module .'; module either does not exist or is active.'); + } + } // Only build the rest of the form if there are any modules available to uninstall. if (!empty($options)) { @@ -1055,6 +1105,14 @@ } /** + * Returns a list of modules that have been deactivated, and thus + * are eligible for uninstallation. + */ +function _system_modules_get_uninstallable_modules() { + return db_query("SELECT name, filename, info FROM {system} WHERE type = 'module' AND status = 0 AND schema_version > %d ORDER BY name", SCHEMA_UNINSTALLED); +} + +/** * Form builder; The general site information form. * * @ingroup forms @@ -1931,6 +1989,10 @@ foreach ($modules as $key => $module) { $row = array(); $description = drupal_render($form['description'][$key]); + if (isset($form['module_menu']['#value'][$key])) { + // Add module links + $description .= '
'; + } if (isset($form['status']['#incompatible_modules_core'][$key])) { unset($form['status'][$key]); $status = theme('image', 'misc/watchdog-error.png', t('incompatible'), t('Incompatible with this version of Drupal core')); @@ -1963,7 +2025,11 @@ $row[] = drupal_render($form['version'][$key]); $row[] = array('data' => $description, 'class' => 'description'); - $rows[] = $row; + + $extended_row = array('data' => $row); + if (!empty($form['status'][$key]['#value'])) $extended_row['class'] = 'selected'; + + $rows[] = $extended_row; } $fieldset = array( '#title' => t($package), Index: modules/system/system.css =================================================================== RCS file: /cvs/drupal/drupal/modules/system/system.css,v retrieving revision 1.41 diff -u -r1.41 system.css --- modules/system/system.css 20 Nov 2007 10:18:43 -0000 1.41 +++ modules/system/system.css 2 Dec 2007 17:41:54 -0000 @@ -495,6 +495,24 @@ font-weight: bold; } +#system-modules div.menu { + color: #444444; + font-size: 0.9em; +} + +#system-modules tr.selected div.menu, +#system-modules tr.selected div.admin-dependencies, +#system-modules tr.selected div.admin-required { + color: #FFFFFF; +} + +#system-modules tr.selected span.admin-disabled { + color: #FFAAAA; +} +#system-modules tr.selected span.admin-enabled { + color: #AAFFAA; +} + /* ** Styles for the system themes page (admin/build/themes) */ Index: modules/system/system.install =================================================================== RCS file: /cvs/drupal/drupal/modules/system/system.install,v retrieving revision 1.200 diff -u -r1.200 system.install --- modules/system/system.install 30 Nov 2007 18:11:29 -0000 1.200 +++ modules/system/system.install 2 Dec 2007 05:39:35 -0000 @@ -263,14 +263,14 @@ \'SELECT greatest($1, greatest($2, $3));\' LANGUAGE \'sql\'' ); - if (!db_result(db_query("SELECT COUNT(*) FROM pg_proc WHERE proname = 'rand'"))) { + if (!db_result(db_query("SELECT COUNT(*) FROM {pg_proc} WHERE proname = 'rand'"))) { db_query('CREATE OR REPLACE FUNCTION "rand"() RETURNS float AS \'SELECT random();\' LANGUAGE \'sql\'' ); } - if (!db_result(db_query("SELECT COUNT(*) FROM pg_proc WHERE proname = 'concat'"))) { + if (!db_result(db_query("SELECT COUNT(*) FROM {pg_proc} WHERE proname = 'concat'"))) { db_query('CREATE OR REPLACE FUNCTION "concat"(text, text) RETURNS text AS \'SELECT $1 || $2;\' LANGUAGE \'sql\'' @@ -2602,7 +2602,7 @@ while ($role = db_fetch_object($result)) { $renamed_permission = preg_replace('/administer access control/', 'administer permissions', $role->perm); if ($renamed_permission != $role->perm) { - $ret[] = update_sql("UPDATE {permission} SET perm = '$renamed_permission' WHERE rid = $role->rid"); + $ret[] = update_sql("UPDATE {permission} SET perm = '%s' WHERE rid = %d", $renamed_permission, $role->rid); } } return $ret; @@ -2713,7 +2713,7 @@ $renamed_permission = preg_replace('/(?<=^|,\ )edit\ ([a-zA-Z0-9_\-]+)\ content(?=,|$)/', 'edit any $1 content', $role->perm); $renamed_permission = preg_replace('/(?<=^|,\ )create\ polls(?=,|$)/', 'create poll content', $renamed_permission); if ($renamed_permission != $role->perm) { - $ret[] = update_sql("UPDATE {permission} SET perm = '$renamed_permission' WHERE rid = $role->rid"); + $ret[] = update_sql("UPDATE {permission} SET perm = '%s' WHERE rid = %d", $renamed_permission, $role->rid); } } return $ret; Index: modules/system/system.module =================================================================== RCS file: /cvs/drupal/drupal/modules/system/system.module,v retrieving revision 1.556 diff -u -r1.556 system.module --- modules/system/system.module 30 Nov 2007 12:19:10 -0000 1.556 +++ modules/system/system.module 3 Dec 2007 01:55:59 -0000 @@ -136,7 +136,7 @@ // Inputs $type['submit'] = array('#input' => TRUE, '#name' => 'op', '#button_type' => 'submit', '#executes_submit_callback' => TRUE, '#process' => array('form_expand_ahah')); $type['button'] = array('#input' => TRUE, '#name' => 'op', '#button_type' => 'submit', '#executes_submit_callback' => FALSE, '#process' => array('form_expand_ahah')); - $type['image_button'] = array('#input' => TRUE, '#button_type' => 'submit','#executes_submit_callback' => TRUE, '#process' => array('form_expand_ahah'), '#return_value' => TRUE, '#has_garbage_value' => TRUE, '#src' => NULL); + $type['image_button'] = array('#input' => TRUE, '#button_type' => 'submit', '#executes_submit_callback' => TRUE, '#process' => array('form_expand_ahah'), '#return_value' => TRUE, '#has_garbage_value' => TRUE, '#src' => NULL); $type['textfield'] = array('#input' => TRUE, '#size' => 60, '#maxlength' => 128, '#autocomplete_path' => FALSE, '#process' => array('form_expand_ahah')); $type['password'] = array('#input' => TRUE, '#size' => 60, '#maxlength' => 128, '#process' => array('form_expand_ahah')); $type['password_confirm'] = array('#input' => TRUE, '#process' => array('expand_password_confirm')); @@ -507,7 +507,7 @@ * Generate a block with a promotional link to Drupal.org. */ function system_block($op = 'list', $delta = 0, $edit = NULL) { - switch($op) { + switch ($op) { case 'list': $blocks[0] = array( 'info' => t('Powered by Drupal'),