Index: modules/forum/forum.info
===================================================================
RCS file: /cvs/drupal/drupal/modules/forum/forum.info,v
retrieving revision 1.1
diff -u -p -r1.1 forum.info
--- modules/forum/forum.info	31 Aug 2006 20:22:35 -0000	1.1
+++ modules/forum/forum.info	6 Sep 2006 16:16:14 -0000
@@ -1,4 +1,4 @@
 ; $Id: forum.info,v 1.1 2006/08/31 20:22:35 dries Exp $
 name = Forum
 description = Enables threaded discussions about general topics.
-
+dependencies = taxonomy comment
Index: modules/system/admin.css
===================================================================
RCS file: /cvs/drupal/drupal/modules/system/admin.css,v
retrieving revision 1.7
diff -u -p -r1.7 admin.css
--- modules/system/admin.css	6 Sep 2006 08:35:59 -0000	1.7
+++ modules/system/admin.css	6 Sep 2006 16:16:14 -0000
@@ -39,6 +39,11 @@ div.admin .expert-link {
   padding-right: 4px;
 }
 
+div.admin-missing, div.admin-required {
+  font-size:  1.1em;
+  color: #444;
+}
+
 /**
  * Formatting for status report
  */
@@ -63,3 +68,4 @@ table.system-status-report tr.warning th
 table.system-status-report tr.ok th {
   background-image: url('../../misc/watchdog-ok.png');
 }
+
Index: modules/system/system.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/system/system.module,v
retrieving revision 1.366
diff -u -p -r1.366 system.module
--- modules/system/system.module	6 Sep 2006 06:53:39 -0000	1.366
+++ modules/system/system.module	6 Sep 2006 16:16:15 -0000
@@ -1211,12 +1211,29 @@ function system_themes_submit($form_id, 
 }
 
 /**
- * Menu callback; displays a listing of all modules.
+ * Menu callback; provides module enable/disable interface.
+ * 
+ * Modules can be enabled or disabled and set for throttling if the throttle module is enabled. 
+ * The list of modules gets populated by module.info files, which contain each module's name
+ * and description. 
+ *
+ * Dependency checking is performed both forward and reverse to enforce that both dependents and
+ * dependencies are availible. Dependencies are added to the info file space delimited.
+ * 
+ * Example of .info file:
+ *   name = Forum
+ *   description = Enables threaded discussions about general topics.
+ *   dependencies = taxonomy comment
+ * 
+ * @return 
+ *    The form array.
  */
 function system_modules() {
-  // Get current list of modules
+  // Get current list of modules.
   $files = module_rebuild_cache();
 
+  // Traverse the files retrieved and populate a collection of modules.
+  // Check if module is enabled for dependency checking.
   foreach ($files as $filename => $file) {
     $info = $file->info;
     $form['name'][$file->name] = array('#value' => $info['name']);
@@ -1224,23 +1241,74 @@ function system_modules() {
     $options[$file->name] = '';
     if ($file->status) {
       $status[] = $file->name;
+      $info['enabled'] = TRUE;
     }
     if ($file->throttle) {
       $throttle[] = $file->name;
     }
+    $modules[$file->name] = $info;
+  }
+
+  // Store modules list for validation hook.
+  $form['validation_modules'] = array('#type' => 'value', '#value' => $modules);
+  $disabled = array();
+
+  // Forward dependency check. 
+  // See if all dependencies are enabled. Build reverse dependency collections.
+  $form['reverse_dependencies'] = array('#type' => 'value', '#value' => array());
+  foreach ($form['validation_modules']['#value'] as $filename => $info) {
+    $missing_dependencies = array();
+    // Check missing dependencies.
+    if (isset($info['dependencies'])) {
+      foreach (explode(' ', $info['dependencies']) as $dependency) {
+        if (!isset($modules[$dependency]) || !isset($modules[$dependency]['enabled'])) {
+          $disabled[] = $filename;
+          $missing_dependencies[] = isset($modules[$dependency]) ? $modules[$dependency]['name'] : $dependency;
+        }
+        elseif (isset($info['enabled'])) {
+          $disabled[] = $dependency;
+          $form['reverse_dependencies']['#value'][$dependency][] = $info['name'];
+        }
+      }
+
+      // Add text for missing dependencies.
+      if (!empty($missing_dependencies)) {
+        $form['description'][$filename]['missing_dependencies'] = array(
+          '#value' => t('Missing dependencies: %missing_dependencies', array('%missing_dependencies' => implode(', ', $missing_dependencies))),
+          '#prefix' => '<div class="admin-missing">',
+          '#suffix' => '</div>',
+        );
+      }
+    }
+  }
+
+  // Reverse dependency check. 
+  // Check if module has enabled dependents.
+  foreach ($form['reverse_dependencies']['#value'] as $filename => $dependency) {
+    $form['description'][$filename]['required'] = array(
+      '#value' => t('Required by: %required', array('%required' => implode(', ', $dependency))),
+      '#prefix' => '<div class="admin-required">',
+      '#suffix' => '</div>',
+    );
   }
 
-  // Handle status checkboxes, including overriding the generated
-  // checkboxes for required modules.
-  $form['status'] = array('#type' => 'checkboxes', '#default_value' => $status, '#options' => $options);
+  // Handle status checkboxes, including overriding the generated checkboxes for required modules.
+  $form['status'] = array(
+    '#type' => 'checkboxes', 
+    '#default_value' => $status, 
+    '#options' => $options, 
+    '#process' => array( 
+      'expand_checkboxes' => array(), 
+      'system_module_disable' => array($disabled),
+    ),
+  );
+
   $required = array('block', 'filter', 'node', 'system', 'user', 'watchdog');
   foreach ($required as $require) {
     $form['status'][$require] = array('#type' => 'hidden', '#value' => 1, '#suffix' => t('required'));
   }
 
-  /**
-   * Handle throttle checkboxes, including overriding the generated checkboxes for required modules.
-   */
+  // Handle throttle checkboxes, including overriding the generated checkboxes for required modules.
   if (module_exists('throttle')) {
     $form['throttle'] = array('#type' => 'checkboxes', '#default_value' => $throttle, '#options' => $options);
     $throttle_required = array_merge($required, array('throttle'));
@@ -1254,6 +1322,58 @@ function system_modules() {
   return $form;
 }
 
+/**
+ * Form process callback function to disbale check boxes.
+ */
+function system_module_disable($form, $form_values, $disabled) {
+  foreach ($disabled as $key) {
+    $form[$key]['#attributes']['disabled'] = 'disabled';
+  }
+  return $form;
+}
+
+/**
+ * Valiate callback; performs dependency integrity checks to ensure that modules don't get added
+ * if dependencies fail.
+ */
+function system_modules_validate($form_id, $form_values, $form) {
+  // Recheck values for submitted dependency errors.
+  foreach ($form_values['validation_modules'] as $filename => $info) {
+    $failed_dependencies = array();
+     if (!isset($info['enabled']) && $form_values['status'][$filename] && !empty($info['dependencies'])) {
+       foreach (explode(' ', $info['dependencies']) as $dependency) {
+         if (!isset($form['status'][$dependency]) || !($form_values['status'][$dependency])) {
+          $failed_dependencies[] = isset($form_values['modules'][$dependency]) ? $form_values['modules'][$dependency]['name'] : $dependency;
+        }
+      }
+    }
+    if (!empty($failed_dependencies)) {
+      // Check if dependencies are installed
+      foreach ($failed_dependencies as $dependent) {
+        $installed = FALSE;	
+        foreach ($form_values['validation_modules'] as $module) {
+          if (strcasecmp($dependent, $module['name']) == 0) {
+             $installed = TRUE;
+             break;
+          }
+        }         
+        if ($installed) {
+          $tasks[] = t('Please enable %dependent module to continue.', array('%dependent' => $dependent));
+        } else {
+          $tasks[] = t('Could not find @dependent module. This module must be <a href="http://drupal.org/project/Modules">downloaded</a>, <a href="http://drupal.org/node/70151">installed</a>, and then enabled.', array('@dependent' => $dependent));
+        }
+      }
+      form_set_error("status][$filename", t('Could not enable %module module, as it depends on %dependency.', array('%module' => $info['name'], '%dependency' => implode(', ', $failed_dependencies))));
+      foreach ($tasks as $task) {
+        drupal_set_message($task, 'error');
+      }
+    }
+  }
+}
+
+/**
+ * Theme call back for the modules form.
+ */
 function theme_system_modules($form) {
   foreach (element_children($form['name']) as $key) {
     $row = array();
@@ -1279,13 +1399,18 @@ function theme_system_modules($form) {
   return $output;
 }
 
-
+/**
+ * Submit callback; handles modules form submission.
+ */
 function system_modules_submit($form_id, $edit) {
   include_once './includes/install.inc';
   $new_modules = array();
 
-  // Enable/disable modules that have already been installed
-  foreach ($edit['status'] as $key => $choice) {
+  // Merge in reverse dependencies since they should be enabled.
+  // They don't appear because disabled checkboxes are not submited
+  // by browsers.
+  $modules = array_merge($edit['status'], $edit['reverse_dependencies']);
+  foreach ($modules as $key => $choice) {
     if ($choice) {
       if (drupal_get_installed_schema_version($key) == SCHEMA_UNINSTALLED) {
         $new_modules[] = $key;
