function ThemeInstaller::install

Same name and namespace in other branches
  1. 9 core/lib/Drupal/Core/Extension/ThemeInstaller.php \Drupal\Core\Extension\ThemeInstaller::install()
  2. 8.9.x core/lib/Drupal/Core/Extension/ThemeInstaller.php \Drupal\Core\Extension\ThemeInstaller::install()
  3. 10 core/lib/Drupal/Core/Extension/ThemeInstaller.php \Drupal\Core\Extension\ThemeInstaller::install()

Overrides ThemeInstallerInterface::install

File

core/lib/Drupal/Core/Extension/ThemeInstaller.php, line 124

Class

ThemeInstaller
Manages theme installation/uninstallation.

Namespace

Drupal\Core\Extension

Code

public function install(array $theme_list, $install_dependencies = TRUE) {
    $extension_config = $this->configFactory
        ->getEditable('core.extension');
    $theme_data = $this->themeExtensionList
        ->reset()
        ->getList();
    $installed_themes = $extension_config->get('theme') ?: [];
    $installed_modules = $extension_config->get('module') ?: [];
    if ($install_dependencies) {
        $theme_list = array_combine($theme_list, $theme_list);
        if ($missing = array_diff_key($theme_list, $theme_data)) {
            // One or more of the given themes doesn't exist.
            throw new UnknownExtensionException('Unknown themes: ' . implode(', ', $missing) . '.');
        }
        // Only process themes that are not installed currently.
        if (!($theme_list = array_diff_key($theme_list, $installed_themes))) {
            // Nothing to do. All themes already installed.
            return TRUE;
        }
        $module_list = $this->moduleExtensionList
            ->getList();
        foreach ($theme_list as $theme => $value) {
            $module_dependencies = $theme_data[$theme]->module_dependencies;
            // $theme_data[$theme]->requires contains both theme and module
            // dependencies keyed by the extension machine names.
            // $theme_data[$theme]->module_dependencies contains only the module
            // dependencies keyed by the module extension machine name. Therefore,
            // we can find the theme dependencies by finding array keys for
            // 'requires' that are not in $module_dependencies.
            $theme_dependencies = array_diff_key($theme_data[$theme]->requires, $module_dependencies);
            // We can find the unmet module dependencies by finding the module
            // machine names keys that are not in $installed_modules keys.
            $unmet_module_dependencies = array_diff_key($module_dependencies, $installed_modules);
            if ($theme_data[$theme]->info[ExtensionLifecycle::LIFECYCLE_IDENTIFIER] === ExtensionLifecycle::DEPRECATED) {
                // phpcs:ignore Drupal.Semantics.FunctionTriggerError
                @trigger_error("The theme '{$theme}' is deprecated. See " . $theme_data[$theme]->info['lifecycle_link'], E_USER_DEPRECATED);
            }
            // Prevent themes with unmet module dependencies from being installed.
            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}'.");
            }
            foreach ($module_dependencies as $dependency => $dependency_object) {
                if ($incompatible = $this->checkDependencyMessage($module_list, $dependency, $dependency_object)) {
                    $sanitized_message = Html::decodeEntities(strip_tags($incompatible));
                    throw new MissingDependencyException("Unable to install theme: {$sanitized_message}");
                }
            }
            // Add dependencies to the list of themes to install. The new themes
            // will be processed as the parent foreach loop continues.
            foreach (array_keys($theme_dependencies) as $dependency) {
                if (!isset($theme_data[$dependency])) {
                    // The dependency does not exist.
                    return FALSE;
                }
                // Skip already installed themes.
                if (!isset($theme_list[$dependency]) && !isset($installed_themes[$dependency])) {
                    $theme_list[$dependency] = $dependency;
                }
            }
        }
        // Set the actual theme weights.
        $theme_list = array_map(function ($theme) use ($theme_data) {
            return $theme_data[$theme]->sort;
        }, $theme_list);
        // Sort the theme list by their weights (reverse).
        arsort($theme_list);
        $theme_list = array_keys($theme_list);
    }
    $themes_installed = [];
    foreach ($theme_list as $key) {
        // Only process themes that are not already installed.
        $installed = $extension_config->get("theme.{$key}") !== NULL;
        if ($installed) {
            continue;
        }
        // Throw an exception if the theme name is too long.
        if (strlen($key) > DRUPAL_EXTENSION_NAME_MAX_LENGTH) {
            throw new ExtensionNameLengthException("Theme name {$key} is over the maximum allowed length of " . DRUPAL_EXTENSION_NAME_MAX_LENGTH . ' characters.');
        }
        // Throw an exception if a module with the same name is enabled.
        $installed_modules = $extension_config->get('module') ?: [];
        if (isset($installed_modules[$key])) {
            throw new ExtensionNameReservedException("Theme name {$key} is already in use by an installed module.");
        }
        // Validate default configuration of the theme. If there is existing
        // configuration then stop installing.
        $this->configInstaller
            ->checkConfigurationToInstall('theme', $key);
        // The value is not used; the weight is ignored for themes currently. Do
        // not check schema when saving the configuration.
        $extension_config->set("theme.{$key}", 0)
            ->save(TRUE);
        // Reset theme settings.
        $theme_settings =& drupal_static('theme_get_setting');
        unset($theme_settings[$key]);
        // Reset theme listing.
        $this->themeHandler
            ->reset();
        // Only install default configuration if this theme has not been installed
        // already.
        if (!isset($installed_themes[$key])) {
            // Install default configuration of the theme.
            $this->configInstaller
                ->installDefaultConfig('theme', $key);
        }
        $themes_installed[] = $key;
        // Record the fact that it was installed.
        $this->logger
            ->info('%theme theme installed.', [
            '%theme' => $key,
        ]);
    }
    $this->cssCollectionOptimizer
        ->deleteAll();
    $this->resetSystem();
    // Invoke hook_themes_installed() after the themes have been installed.
    $this->moduleHandler
        ->invokeAll('themes_installed', [
        $themes_installed,
    ]);
    return !empty($themes_installed);
}

Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.