From daa59856c3642c192be43104ff945f3182d026d9 Mon Sep 17 00:00:00 2001
From: Angie Byron <webchick@24967.no-reply.drupal.org>
Date: Tue, 8 Dec 2009 06:39:34 +0000
Subject: [PATCH] #375352 by Damien Tournoud, sun, and chx: Fixed errors caused
 by adding dependency to non-existing module (with tests).

---
 .../tests/system_dependencies_test.info       |  9 +++
 .../tests/system_dependencies_test.module     |  2 +
 modules/simpletest/tests/system_test.module   |  5 ++
 modules/system/system.admin.inc               | 59 +++++++++++--------
 modules/system/system.test                    | 26 ++++++++
 5 files changed, 76 insertions(+), 25 deletions(-)
 create mode 100644 modules/simpletest/tests/system_dependencies_test.info
 create mode 100644 modules/simpletest/tests/system_dependencies_test.module

diff --git a/modules/simpletest/tests/system_dependencies_test.info b/modules/simpletest/tests/system_dependencies_test.info
new file mode 100644
index 000000000000..c5748cff2efc
--- /dev/null
+++ b/modules/simpletest/tests/system_dependencies_test.info
@@ -0,0 +1,9 @@
+; $Id$
+name = "System dependency test"
+description = "Support module for testing system dependencies."
+package = Testing
+version = VERSION
+core = 7.x
+files[] = system_dependencies_test.module
+hidden = TRUE
+dependencies[] = _missing_dependency
diff --git a/modules/simpletest/tests/system_dependencies_test.module b/modules/simpletest/tests/system_dependencies_test.module
new file mode 100644
index 000000000000..13bb990c402e
--- /dev/null
+++ b/modules/simpletest/tests/system_dependencies_test.module
@@ -0,0 +1,2 @@
+<?php
+// $Id$
diff --git a/modules/simpletest/tests/system_test.module b/modules/simpletest/tests/system_test.module
index 213dd1fc0e5e..5c57ee20d9bc 100644
--- a/modules/simpletest/tests/system_test.module
+++ b/modules/simpletest/tests/system_test.module
@@ -252,6 +252,11 @@ function system_test_system_info_alter(&$info, $file, $type) {
       $info['version'] = '7.x-2.4-beta3';
     }
   }
+
+  // Make the system_dependencies_test visible by default.
+  if ($file->name == 'system_dependencies_test') {
+    $info['hidden'] = FALSE;
+  }
 }
 
 /**
diff --git a/modules/system/system.admin.inc b/modules/system/system.admin.inc
index f49c71f6f703..c8c3d01b7bb3 100644
--- a/modules/system/system.admin.inc
+++ b/modules/system/system.admin.inc
@@ -992,6 +992,15 @@ function system_modules_confirm_form($modules, $storage) {
     );
     $items[] = format_plural(count($info['requires']), 'You must enable the @required module to install @module.', 'You must enable the @required modules to install @module.', $t_argument);
   }
+
+  foreach ($storage['missing_modules'] as $name => $info) {
+    $t_argument = array(
+      '@module' => $name,
+      '@depends' => implode(', ', $info['depends']),
+    );
+    $items[] = format_plural(count($info['depends']), 'The @module module is missing, so the following module will be disabled: @depends.', 'The @module module is missing, so the following module will be disabled: @depends.', $t_argument);
+  }
+
   $form['text'] = array('#markup' => theme('item_list', array('items' => $items)));
 
   if ($form) {
@@ -1000,7 +1009,7 @@ function system_modules_confirm_form($modules, $storage) {
       $form,
       t('Some required modules must be enabled'),
       'admin/config/modules',
-      t('Would you like to continue with enabling the above?'),
+      t('Would you like to continue with the above?'),
       t('Continue'),
       t('Cancel'));
     return $form;
@@ -1039,6 +1048,8 @@ function system_modules_submit($form, &$form_state) {
   $new_modules = array();
   // Modules that need to be switched on because other modules require them.
   $more_modules = array();
+  $missing_modules = array();
+
   // Go through each module, finding out if we should enable, install, or
   // disable it. Also, we find out if there are modules it requires that are
   // not enabled.
@@ -1052,18 +1063,26 @@ function system_modules_submit($form, &$form_state) {
       elseif (!module_exists($name)) {
         $modules_to_be_enabled[$name] = $name;
       }
+
       // If we're not coming from a confirmation form, search for modules the
       // new ones require and see whether there are any that additionally
       // need to be switched on.
       if (empty($form_state['storage'])) {
         foreach ($form['modules'][$module['group']][$name]['#requires'] as $requires => $v) {
-          if (!$modules[$requires]['enabled']) {
-            if (!isset($more_modules[$name])) {
-              $more_modules[$name]['name'] = $files[$name]->info['name'];
+          if (!isset($files[$requires])) {
+            // The required module is missing, mark this module as disabled.
+            $missing_modules[$requires]['depends'][] = $name;
+            $modules[$name]['enabled'] = FALSE;
+          }
+          else {
+            if (!$modules[$requires]['enabled']) {
+              if (!isset($more_modules[$name])) {
+                $more_modules[$name]['name'] = $files[$name]->info['name'];
+              }
+              $more_modules[$name]['requires'][$requires] = $files[$requires]->info['name'];
             }
-            $more_modules[$name]['requires'][$requires] = $files[$requires]->info['name'];
+            $modules[$requires] = array('group' => $files[$requires]->info['package'], 'enabled' => TRUE);
           }
-          $modules[$requires] = array('group' => $files[$requires]->info['package'], 'enabled' => TRUE);
         }
       }
     }
@@ -1075,28 +1094,18 @@ function system_modules_submit($form, &$form_state) {
       $disable_modules[$name] = $name;
     }
   }
-  if ($more_modules) {
+
+  if ($more_modules || $missing_modules) {
     // If we need to switch on more modules because other modules require
     // them and they haven't confirmed, don't process the submission yet. Store
     // the form submission data needed later.
-    if (!isset($form_state['values']['confirm'])) {
-      $form_state['storage'] = array('more_modules' => $more_modules, 'modules' => $modules);
-      $form_state['rebuild'] = TRUE;
-      return;
-    }
-    // Otherwise, install or enable the modules.
-    else {
-      foreach ($form_state['storage']['more_modules'] as $info) {
-        foreach ($info['requires'] as $requires => $name) {
-          if (drupal_get_installed_schema_version($name) == SCHEMA_UNINSTALLED) {
-            $new_modules[$name] = $name;
-          }
-          else {
-            $modules_to_be_enabled[$name] = $name;
-          }
-        }
-      }
-    }
+    $form_state['storage'] = array(
+      'more_modules' => $more_modules,
+      'missing_modules' => $missing_modules,
+      'modules' => $modules
+    );
+    $form_state['rebuild'] = TRUE;
+    return;
   }
 
   $old_module_list = module_list();
diff --git a/modules/system/system.test b/modules/system/system.test
index 522f96b0ad89..8f94d0c56e13 100644
--- a/modules/system/system.test
+++ b/modules/system/system.test
@@ -195,6 +195,32 @@ class ModuleDependencyTestCase extends ModuleTestCase {
     $this->assertTableCount('languages', TRUE);
     $this->assertTableCount('locale', TRUE);
   }
+
+  /**
+   * Attempt to enable a module with a missing dependency.
+   */
+  function testMissingModules() {
+    // Test that the system_dependencies_test module is marked
+    // as missing a dependency.
+    $this->drupalGet('admin/config/modules');
+    $this->assertRaw(t('@module (<span class="admin-missing">missing</span>)', array('@module' => drupal_ucfirst('_missing_dependency'))), t('A module with missing dependencies is marked as such.'));
+    $checkbox = $this->xpath('//input[@type="checkbox" and @disabled="disabled" and @name="modules[Testing][system_dependencies_test][enable]"]');
+    $this->assert(count($checkbox) == 1, t('Checkbox for the module is disabled.'));
+
+    // Force enable the system_dependencies_test module.
+    module_enable(array('system_dependencies_test'));
+
+    // Verify that the module is forced to be disabled when submitting
+    // the module page.
+    $this->drupalPost('admin/config/modules', array(), t('Save configuration'));
+    $this->assertText(t('The @module module is missing, so the following module will be disabled: @depends.', array('@module' => '_missing_dependency', '@depends' => 'system_dependencies_test')), t('The module missing dependencies will be disabled.'));
+
+    // Confirm.
+    $this->drupalPost(NULL, NULL, t('Continue'));
+
+    // Verify that the module has been disabled.
+    $this->assertModules(array('system_dependencies_test'), FALSE);
+  }
 }
 
 /**
-- 
GitLab