From c5c1cdf66a4873575d996e13591637db46a43f8d Mon Sep 17 00:00:00 2001
From: Nathaniel Catchpole <catch@35733.no-reply.drupal.org>
Date: Tue, 27 Sep 2016 16:00:36 +0100
Subject: [PATCH] Issue #2608408 by nlisgo, dagmar, aleevas, neclimdul, BR0kEN,
 gaydabura, pfrenssen, zuuperman: Call to a member function getPath() when
 installing Profiles with unknown modules as requirement

---
 core/includes/install.inc                     | 32 +++++++++------
 .../InstallerMissingDependenciesTest.php      | 39 +++++++++++++++++++
 .../testing_missing_dependencies.info.yml     | 10 +++++
 3 files changed, 69 insertions(+), 12 deletions(-)
 create mode 100644 core/modules/system/tests/src/Kernel/Installer/InstallerMissingDependenciesTest.php
 create mode 100644 core/profiles/testing_missing_dependencies/testing_missing_dependencies.info.yml

diff --git a/core/includes/install.inc b/core/includes/install.inc
index 3a9c2bce730a..e243c184f0bb 100644
--- a/core/includes/install.inc
+++ b/core/includes/install.inc
@@ -930,27 +930,35 @@ function drupal_requirements_url($severity) {
  */
 function drupal_check_profile($profile) {
   $info = install_profile_info($profile);
-
   // Collect requirement testing results.
   $requirements = array();
-
   // Performs an ExtensionDiscovery scan as the system module is unavailable and
   // we don't yet know where all the modules are located.
   // @todo Remove as part of https://www.drupal.org/node/2186491
-  $listing = new ExtensionDiscovery(\Drupal::root());
-  $module_list = $listing->scan('module');
+  $drupal_root = \Drupal::root();
+  $module_list = (new ExtensionDiscovery($drupal_root))->scan('module');
+
   foreach ($info['dependencies'] as $module) {
-    $file = \Drupal::root() . '/' . $module_list[$module]->getPath() . "/$module.install";
-    if (is_file($file)) {
-      require_once $file;
-    }
-    $function = $module . '_requirements';
+    // If the module is in the module list we know it exists and we can continue
+    // including and registering it.
+    // @see \Drupal\Core\Extension\ExtensionDiscovery::scanDirectory()
+    if (isset($module_list[$module])) {
+      $function = $module . '_requirements';
+      $module_path = $module_list[$module]->getPath();
+      $install_file = "$drupal_root/$module_path/$module.install";
+
+      if (is_file($install_file)) {
+        require_once $install_file;
+      }
+
+      drupal_classloader_register($module, $module_path);
 
-    drupal_classloader_register($module, $module_list[$module]->getPath());
-    if (function_exists($function)) {
-      $requirements = array_merge($requirements, $function('install'));
+      if (function_exists($function)) {
+        $requirements = array_merge($requirements, $function('install'));
+      }
     }
   }
+
   return $requirements;
 }
 
diff --git a/core/modules/system/tests/src/Kernel/Installer/InstallerMissingDependenciesTest.php b/core/modules/system/tests/src/Kernel/Installer/InstallerMissingDependenciesTest.php
new file mode 100644
index 000000000000..052c0afb8002
--- /dev/null
+++ b/core/modules/system/tests/src/Kernel/Installer/InstallerMissingDependenciesTest.php
@@ -0,0 +1,39 @@
+<?php
+
+namespace Drupal\Tests\system\Kernel\Installer;
+
+use Drupal\KernelTests\KernelTestBase;
+
+/**
+ * Tests that we handle the absence of a module dependency during install.
+ *
+ * @group Installer
+ */
+class InstallerMissingDependenciesTest extends KernelTestBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public static $modules = ['system'];
+
+  /**
+   * Verifies that the exception message in the profile step is correct.
+   */
+  public function testSetUpWithMissingDependencies() {
+    // Prime the drupal_get_filename() static cache with the location of the
+    // testing profile as it is not the currently active profile and we don't
+    // yet have any cached way to retrieve its location.
+    // @todo Remove as part of https://www.drupal.org/node/2186491
+    drupal_get_filename('profile', 'testing_missing_dependencies', 'core/profiles/testing_missing_dependencies/testing_missing_dependencies.info.yml');
+
+    $info = drupal_verify_profile([
+      'parameters' => ['profile' => 'testing_missing_dependencies'],
+      'profile_info' => install_profile_info('testing_missing_dependencies'),
+    ]);
+
+    $message = $info['required_modules']['description']->render();
+    $this->assertContains('Missing_module1', $message);
+    $this->assertContains('Missing_module2', $message);
+  }
+
+}
diff --git a/core/profiles/testing_missing_dependencies/testing_missing_dependencies.info.yml b/core/profiles/testing_missing_dependencies/testing_missing_dependencies.info.yml
new file mode 100644
index 000000000000..442e934211d6
--- /dev/null
+++ b/core/profiles/testing_missing_dependencies/testing_missing_dependencies.info.yml
@@ -0,0 +1,10 @@
+name: 'Testing missing dependencies'
+type: profile
+description: 'Minimal profile for running a test when dependencies are listed but missing.'
+version: VERSION
+core: 8.x
+hidden: true
+dependencies:
+  - missing_module1
+  - missing_module2
+keep_english: true
-- 
GitLab