diff --git a/core/lib/Drupal/Core/Extension/ThemeInstaller.php b/core/lib/Drupal/Core/Extension/ThemeInstaller.php index 4993fa1cad..59adbae578 100644 --- a/core/lib/Drupal/Core/Extension/ThemeInstaller.php +++ b/core/lib/Drupal/Core/Extension/ThemeInstaller.php @@ -126,12 +126,12 @@ public function install(array $theme_list, $install_dependencies = TRUE) { foreach ($theme_list as $theme => $value) { $module_dependencies = $theme_data[$theme]->module_dependencies; $theme_dependencies = array_diff_key($theme_data[$theme]->requires, $module_dependencies); - $missing_module_dependencies = array_diff_key($module_dependencies, $installed_modules); + $unmet_module_dependencies = array_diff_key($module_dependencies, $installed_modules); // Prevent themes with unmet module dependencies from being installed. - if (!empty($missing_module_dependencies)) { - $missing_module_dependencies_list = implode(', ', array_keys($missing_module_dependencies)); - throw new MissingDependencyException("Unable to install theme: '$theme' due to missing module dependencies: '$missing_module_dependencies_list.'"); + if (!empty($unmet_module_dependencies)) { + $unmet_module_dependencies_list = implode(', ', array_keys($unmet_module_dependencies)); + throw new MissingDependencyException("Unable to install theme: '$theme' due to unmet module dependencies: '$unmet_module_dependencies_list.'"); } // Add dependencies to the list of themes to install. The new themes diff --git a/core/modules/system/src/Controller/SystemController.php b/core/modules/system/src/Controller/SystemController.php index 578a8c743f..dd16ce349a 100644 --- a/core/modules/system/src/Controller/SystemController.php +++ b/core/modules/system/src/Controller/SystemController.php @@ -261,19 +261,19 @@ public function themesPage() { $modules = $this->moduleExtensionList->getList(); foreach ($theme->module_dependencies as $dependency => $dependency_object) { if ($incompatible = $this->checkDependencyMessage($modules, $dependency, $dependency_object)) { - $theme->module_dependencies[$dependency] = $incompatible; + $theme->module_dependencies_list[$dependency] = $incompatible; $theme->incompatible_module = TRUE; continue; } // Only display visible modules. if (!empty($modules[$dependency]->hidden)) { - unset($theme->module_dependencies[$dependency]); continue; } $module_name = $modules[$dependency]->info['name']; - $theme->module_dependencies[$dependency] = $modules[$dependency]->status ? $this->t('@module_name', ['@module_name' => $module_name]) : $this->t('@module_name (disabled)', ['@module_name' => $module_name]); + $theme->module_dependencies_list[$dependency] = $modules[$dependency]->status ? $this->t('@module_name', ['@module_name' => $module_name]) : $this->t('@module_name (disabled)', ['@module_name' => $module_name]); + // Create an additional property that contains only disabled module // dependencies. This will determine if it is possible to install the // theme, or if modules must first be enabled. diff --git a/core/modules/system/system.admin.inc b/core/modules/system/system.admin.inc index ea33414fe9..206ed3cdf3 100644 --- a/core/modules/system/system.admin.inc +++ b/core/modules/system/system.admin.inc @@ -304,9 +304,9 @@ function template_preprocess_system_themes_page(&$variables) { $current_theme['is_default'] = $theme->is_default; $current_theme['is_admin'] = $theme->is_admin; - $current_theme['module_dependencies'] = !empty($theme->module_dependencies) ? [ + $current_theme['module_dependencies'] = !empty($theme->module_dependencies_list) ? [ '#theme' => 'item_list', - '#items' => $theme->module_dependencies, + '#items' => $theme->module_dependencies_list, '#context' => ['list_style' => 'comma-list'], ] : []; diff --git a/core/modules/system/tests/src/Functional/Form/ModulesListFormWebTest.php b/core/modules/system/tests/src/Functional/Form/ModulesListFormWebTest.php index a210cd37a9..cef12ffcc7 100644 --- a/core/modules/system/tests/src/Functional/Form/ModulesListFormWebTest.php +++ b/core/modules/system/tests/src/Functional/Form/ModulesListFormWebTest.php @@ -33,13 +33,7 @@ protected function setUp() { * Tests the module list form. */ public function testModuleListForm() { - $this->drupalLogin( - $this->drupalCreateUser( - ['administer modules', 'administer permissions'] - ) - ); - $this->drupalGet('admin/modules'); - $this->assertResponse('200'); + $this->createUserAdministerModules(); // Check that system_test's configure link was rendered correctly. $this->assertFieldByXPath("//a[contains(@href, '/system-test/configure/bar') and text()='Configure ']/span[contains(@class, 'visually-hidden') and text()='the System test module']"); @@ -65,13 +59,7 @@ public function testModulesListFormWithInvalidInfoFile() { mkdir($path, 0777, TRUE); file_put_contents("$path/broken.info.yml", $broken_info_yml); - $this->drupalLogin( - $this->drupalCreateUser( - ['administer modules', 'administer permissions'] - ) - ); - $this->drupalGet('admin/modules'); - $this->assertSession()->statusCodeEquals(200); + $this->createUserAdministerModules(); // Confirm that the error message is shown. $this->assertSession() @@ -81,4 +69,33 @@ public function testModulesListFormWithInvalidInfoFile() { $this->assertSession()->elementExists('xpath', '//input[@name="text"]'); } + /** + * Confirm that module 'Required By' descriptions include dependent themes. + */ + public function testRequiredByThemeMessage() { + $this->createUserAdministerModules(); + $module_theme_depends_on_description = $this->getSession()->getPage()->findAll('css', '#edit-modules-test-module-required-by-theme-enable-description .admin-requirements li:contains("Test Theme Depending on Modules (Theme) (Disabled)")'); + + // Confirm that that 'Test Theme Depending on Modules' is listed as being + // required by the module 'Test Module Required by Theme'. + $this->assertCount(1, $module_theme_depends_on_description); + + // Confirm that the required by message does not appear anywhere else. + $this->assertSession()->pageTextContains('Test Theme Depending on Modules (Theme) (Disabled)'); + } + + /** + * Creates user that can administer modules then visits `admin/modules`. + */ + protected function createUserAdministerModules() { + $this->drupalLogin( + $this->drupalCreateUser( + ['administer modules', 'administer permissions'] + ) + ); + + $this->drupalGet('admin/modules'); + $this->assertSession()->statusCodeEquals(200); + } + }