diff --git a/core/lib/Drupal/Core/Extension/ThemeHandler.php b/core/lib/Drupal/Core/Extension/ThemeHandler.php
index f22fcfa..8231668 100644
--- a/core/lib/Drupal/Core/Extension/ThemeHandler.php
+++ b/core/lib/Drupal/Core/Extension/ThemeHandler.php
@@ -359,8 +359,14 @@ public function rebuildThemeData() {
}
}
- // Store the list of module dependencies separately from the full requires list.
foreach ($themes as $key => $theme) {
+ // buildModuleDependencies() adds a theme->requires array that contains
+ // both module and base theme dependencies, if they are specified. Ensure
+ // that every theme stores the list of module dependencies separately
+ // from the full requires list.
+ if (!isset($theme->requires)) {
+ $theme->requires = [];
+ }
$themes[$key]->module_dependencies = isset($theme->base_themes) ? array_diff_key($theme->requires, $theme->base_themes) : $theme->requires;
}
diff --git a/core/lib/Drupal/Core/Extension/ThemeInstaller.php b/core/lib/Drupal/Core/Extension/ThemeInstaller.php
index fbfe1e9..e12ff0b 100644
--- a/core/lib/Drupal/Core/Extension/ThemeInstaller.php
+++ b/core/lib/Drupal/Core/Extension/ThemeInstaller.php
@@ -7,6 +7,7 @@
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Config\ConfigInstallerInterface;
use Drupal\Core\Config\ConfigManagerInterface;
+use Drupal\Core\Extension\ModuleInstallerInterface;
use Drupal\Core\Routing\RouteBuilderInterface;
use Drupal\Core\State\StateInterface;
use Psr\Log\LoggerInterface;
@@ -86,6 +87,8 @@ class ThemeInstaller implements ThemeInstallerInterface {
* A logger instance.
* @param \Drupal\Core\State\StateInterface $state
* The state store.
+ * @param \Drupal\Core\Extension\ModuleInstallerInterface $module_installer
+ * The module installer.
*/
public function __construct(ThemeHandlerInterface $theme_handler, ConfigFactoryInterface $config_factory, ConfigInstallerInterface $config_installer, ModuleHandlerInterface $module_handler, ConfigManagerInterface $config_manager, AssetCollectionOptimizerInterface $css_collection_optimizer, RouteBuilderInterface $route_builder, LoggerInterface $logger, StateInterface $state, ModuleInstallerInterface $module_installer = NULL) {
$this->themeHandler = $theme_handler;
@@ -136,10 +139,12 @@ public function install(array $theme_list, $install_dependencies = TRUE) {
while (list($theme) = each($theme_list)) {
$module_dependencies = $theme_data[$theme]->module_dependencies;
$theme_dependencies = array_diff_key($theme_data[$theme]->requires, $module_dependencies);
+
+ // Install the module dependencies.
$this->getModuleInstaller()->install(array_keys($module_dependencies));
- // Add dependencies to the list. The new themes will be processed as
- // the while loop continues.
+ // Add dependencies to the list of themes to install. The new themes
+ // will be processed as the while loop continues.
foreach (array_keys($theme_dependencies) as $dependency) {
if (!isset($theme_data[$dependency])) {
// The dependency does not exist.
diff --git a/core/modules/system/src/Controller/ThemeController.php b/core/modules/system/src/Controller/ThemeController.php
index e135356..62e0b5e 100644
--- a/core/modules/system/src/Controller/ThemeController.php
+++ b/core/modules/system/src/Controller/ThemeController.php
@@ -107,8 +107,22 @@ public function install(Request $request) {
if (isset($theme)) {
try {
if ($this->themeHandler->install(array($theme))) {
- $themes = $this->themeHandler->listInfo();
- drupal_set_message($this->t('The %theme theme has been installed.', array('%theme' => $themes[$theme]->info['name'])));
+ $theme_data = $this->themeHandler->listInfo();
+ if ($theme_data[$theme]->module_dependencies) {
+ $module_data = system_rebuild_module_data();
+ $module_names = [];
+ foreach(array_keys($theme_data[$theme]->module_dependencies) as $key) {
+ $module_names[] = $module_data[$key]->info['name'];
+ }
+ drupal_set_message($this->formatPlural(count($module_names), 'The %theme theme and its module dependency, %name, have been installed.', 'The %theme theme and its @count module dependencies have been installed: %names', array(
+ '%theme' => $theme_data[$theme]->info['name'],
+ '%name' => $module_names[0],
+ '%names' => implode(', ', $module_names),
+ )));
+ }
+ else {
+ drupal_set_message($this->t('The %theme theme has been installed.', array('%theme' => $theme_data[$theme]->info['name'])));
+ }
}
else {
drupal_set_message($this->t('The %theme theme was not found.', array('%theme' => $theme)), 'error');
diff --git a/core/modules/system/src/Form/ModulesListForm.php b/core/modules/system/src/Form/ModulesListForm.php
index 256b94c..30b5fd4 100644
--- a/core/modules/system/src/Form/ModulesListForm.php
+++ b/core/modules/system/src/Form/ModulesListForm.php
@@ -187,22 +187,25 @@ public function buildForm(array $form, FormStateInterface $form_state) {
}
/**
+ * Checks a single module dependency of a module or theme that has the given
+ * module version requirements.
+ *
* @param array $modules
* The list of existing modules.
- * @param $dependency
+ * @param string $dependency
* The dependency to check.
- * @param $version
- * Version information from the module whose dependency we are checking.
+ * @param array $version
+ * Version requirement data from the module or theme declaring the
+ * dependency we are checking.
*
- * @return
+ * @return string|null
* NULL if compatible, otherwise a string describing the incompatibility.
*/
public static function checkDependency(array $modules, $dependency, $version) {
if (!isset($modules[$dependency])) {
return t('@module (missing)', array('@module' => Unicode::ucfirst($dependency)));
}
- // Only display visible modules.
- elseif (empty($modules[$dependency]->hidden)) {
+ else {
$name = $modules[$dependency]->info['name'];
// Check if it is incompatible with the dependency's version.
if ($incompatible_version = drupal_check_incompatibility($version, str_replace(\Drupal::CORE_COMPATIBILITY . '-', '', $modules[$dependency]->info['version']))) {
@@ -332,18 +335,20 @@ protected function buildRow(array $modules, Extension $module, $distribution) {
// If this module requires other modules, add them to the array.
foreach ($module->requires as $dependency => $version) {
- if ($incompatible = $this->checkDependency($modules, $dependency, $version)) {
- $row['#requires'][$dependency] = $incompatible;
- $row['enable']['#disabled'] = TRUE;
- }
- // Only display visible modules.
- elseif (empty($modules[$dependency]->hidden)) {
- $name = $modules[$dependency]->info['name'];
- if ($modules[$dependency]->status) {
- $row['#requires'][$dependency] = $this->t('@module', array('@module' => $name));
+ // Only display missing or visible modules.
+ if (empty($modules[$dependency]->hidden)) {
+ if ($incompatible = $this->checkDependency($modules, $dependency, $version)) {
+ $row['#requires'][$dependency] = $incompatible;
+ $row['enable']['#disabled'] = TRUE;
}
else {
- $row['#requires'][$dependency] = $this->t('@module (disabled)', array('@module' => $name));
+ $name = $modules[$dependency]->info['name'];
+ if ($modules[$dependency]->status) {
+ $row['#requires'][$dependency] = $this->t('@module', array('@module' => $name));
+ }
+ else {
+ $row['#requires'][$dependency] = $this->t('@module (disabled)', array('@module' => $name));
+ }
}
}
}
diff --git a/core/modules/system/tests/themes/test_theme_depending_on_module/test_module_required_by_theme/src/Service.php b/core/modules/system/tests/themes/test_theme_depending_on_module/test_module_required_by_theme/src/Service.php
new file mode 100644
index 0000000..3e7d7ee
--- /dev/null
+++ b/core/modules/system/tests/themes/test_theme_depending_on_module/test_module_required_by_theme/src/Service.php
@@ -0,0 +1,7 @@
+assertFalse($this->moduleHandler()->moduleExists('test_theme_dependency'));
- $this->themeInstaller()->install(['test_theme_module_dependency']);
- $this->assertTrue($this->moduleHandler()->moduleExists('test_theme_dependency'));
+ $this->assertFalse($this->moduleHandler()->moduleExists('test_module_required_by_theme'));
+ $this->themeInstaller()->install(['test_theme_depending_on_module']);
+ $this->assertTrue($this->moduleHandler()->moduleExists('test_module_required_by_theme'));
- $service = \Drupal::service('test_theme_dependency.service');
+ $service = \Drupal::service('test_module_required_by_theme.service');
$this->assertInstanceOf(Service::class, $service);
}