diff --git a/core/lib/Drupal/Core/Extension/ThemeInstaller.php b/core/lib/Drupal/Core/Extension/ThemeInstaller.php index b3b391e..e93777b 100644 --- a/core/lib/Drupal/Core/Extension/ThemeInstaller.php +++ b/core/lib/Drupal/Core/Extension/ThemeInstaller.php @@ -61,6 +61,11 @@ class ThemeInstaller implements ThemeInstallerInterface { */ protected $logger; + /** + * @var \Drupal\Core\Extension\ModuleInstallerInterface|NULL + */ + protected $moduleInstaller; + /** * Constructs a new ThemeInstaller. @@ -87,7 +92,7 @@ class ThemeInstaller implements ThemeInstallerInterface { * @param \Drupal\Core\State\StateInterface $state * The state store. */ - 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) { + 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; $this->configFactory = $config_factory; $this->configInstaller = $config_installer; @@ -97,6 +102,17 @@ public function __construct(ThemeHandlerInterface $theme_handler, ConfigFactoryI $this->routeBuilder = $route_builder; $this->logger = $logger; $this->state = $state; + $this->moduleInstaller = $module_installer; + } + + /** + * @return \Drupal\Core\Extension\ModuleInstallerInterface + */ + protected function getModuleInstaller() { + if (!isset($this->moduleInstaller)) { + $this->moduleInstaller = \Drupal::service('module_installer'); + } + return $this->moduleInstaller; } /** @@ -123,6 +139,11 @@ public function install(array $theme_list, $install_dependencies = TRUE) { } while (list($theme) = each($theme_list)) { + $module_dependencies = array_diff_key($theme_data[$theme]->requires, $theme_data); + $theme_dependencies = array_diff_key($theme_data[$theme]->requires, $module_dependencies); + $this->getModuleInstaller()->install(array_keys($module_dependencies)); + $theme_data[$theme]->requires = $theme_dependencies; + // Add dependencies to the list. The new themes will be processed as // the while loop continues. foreach (array_keys($theme_data[$theme]->requires) as $dependency) { diff --git a/core/modules/system/src/Tests/Extension/ThemeInstallerTest.php b/core/modules/system/src/Tests/Extension/ThemeInstallerTest.php index 6fe81f7..8451ee4 100644 --- a/core/modules/system/src/Tests/Extension/ThemeInstallerTest.php +++ b/core/modules/system/src/Tests/Extension/ThemeInstallerTest.php @@ -9,7 +9,8 @@ use Drupal\Core\DependencyInjection\ContainerBuilder; use Drupal\Core\Extension\ExtensionNameLengthException; -use Drupal\simpletest\KernelTestBase; +use Drupal\KernelTests\KernelTestBase; +use Drupal\test_theme_dependency\Service; /** * Tests installing and uninstalling of themes. @@ -25,14 +26,16 @@ class ThemeInstallerTest extends KernelTestBase { */ public static $modules = array('system'); - public function containerBuild(ContainerBuilder $container) { - parent::containerBuild($container); + public function register(ContainerBuilder $container) { + parent::register($container); + // Some test methods involve ModuleHandler operations, which attempt to // rebuild and dump routes. $container ->register('router.dumper', 'Drupal\Core\Routing\NullMatcherDumper'); } + protected function setUp() { parent::setUp(); $this->installConfig(array('system')); @@ -352,6 +355,15 @@ function testThemeInfoAlter() { $this->assertFalse(isset($system_list[$name]->info['regions']['test_region'])); } + public function testThemeWithModuleDependency() { + $this->assertFalse($this->moduleHandler()->moduleExists('test_theme_dependency')); + $this->themeInstaller()->install(['test_theme_module_dependency']); + $this->assertTrue($this->moduleHandler()->moduleExists('test_theme_dependency')); + + $service = \Drupal::service('test_theme_dependency.service'); + $this->assertInstanceOf(Service::class, $service); + } + /** * Returns the theme handler service. * diff --git a/core/modules/system/tests/themes/test_theme_module_dependency/test_theme_dependency/src/Service.php b/core/modules/system/tests/themes/test_theme_module_dependency/test_theme_dependency/src/Service.php new file mode 100644 index 0000000..6313712 --- /dev/null +++ b/core/modules/system/tests/themes/test_theme_module_dependency/test_theme_dependency/src/Service.php @@ -0,0 +1,12 @@ +