Verified Commit e8c0942e authored by Lee Rowlands's avatar Lee Rowlands
Browse files

Issue #3522505 by godotislate, nicxvan, acbramley, mherchel, deviantintegral,...

Issue #3522505 by godotislate, nicxvan, acbramley, mherchel, deviantintegral, penyaskito: New SDC components are not available when enabling themes through the UI

(cherry picked from commit 9ee9a05f)
parent 69852494
Loading
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -709,7 +709,7 @@ services:
  Drupal\Core\Extension\ThemeHandlerInterface: '@theme_handler'
  theme_installer:
    class: Drupal\Core\Extension\ThemeInstaller
    arguments: ['@theme_handler', '@config.factory', '@config.installer', '@module_handler', '@config.manager', '@asset.css.collection_optimizer', '@router.builder', '@logger.channel.default', '@state', '@extension.list.module', '@theme.registry', '@extension.list.theme']
    arguments: ['@theme_handler', '@config.factory', '@config.installer', '@module_handler', '@config.manager', '@asset.css.collection_optimizer', '@router.builder', '@logger.channel.default', '@state', '@extension.list.module', '@theme.registry', '@extension.list.theme', '@plugin.manager.sdc']
  Drupal\Core\Extension\ThemeInstallerInterface: '@theme_installer'
  entity.memory_cache:
    class: Drupal\Core\Cache\MemoryCache\LruMemoryCache
+22 −98
Original line number Diff line number Diff line
@@ -2,6 +2,7 @@

namespace Drupal\Core\Extension;

use Drupal\Component\Plugin\Discovery\CachedDiscoveryInterface;
use Drupal\Component\Utility\Html;
use Drupal\Core\Asset\AssetCollectionOptimizerInterface;
use Drupal\Core\Config\ConfigFactoryInterface;
@@ -22,100 +23,25 @@ class ThemeInstaller implements ThemeInstallerInterface {
  use ModuleDependencyMessageTrait;
  use StringTranslationTrait;

  /**
   * @var \Drupal\Core\Extension\ThemeHandlerInterface
   */
  protected $themeHandler;

  /**
   * @var \Drupal\Core\Config\ConfigFactoryInterface
   */
  protected $configFactory;

  /**
   * @var \Drupal\Core\Config\ConfigInstallerInterface
   */
  protected $configInstaller;

  /**
   * @var \Drupal\Core\Extension\ModuleHandlerInterface
   */
  protected $moduleHandler;

  /**
   * @var \Drupal\Core\State\StateInterface
   */
  protected $state;

  /**
   * @var \Drupal\Core\Config\ConfigManagerInterface
   */
  protected $configManager;

  /**
   * @var \Drupal\Core\Asset\AssetCollectionOptimizerInterface
   */
  protected $cssCollectionOptimizer;

  /**
   * @var \Drupal\Core\Routing\RouteBuilderInterface
   */
  protected $routeBuilder;

  /**
   * @var \Psr\Log\LoggerInterface
   */
  protected $logger;

  /**
   * The module extension list.
   *
   * @var \Drupal\Core\Extension\ModuleExtensionList
   */
  protected $moduleExtensionList;

  /**
   * Constructs a new ThemeInstaller.
   *
   * @param \Drupal\Core\Extension\ThemeHandlerInterface $theme_handler
   *   The theme handler.
   * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
   *   The config factory to get the installed themes.
   * @param \Drupal\Core\Config\ConfigInstallerInterface $config_installer
   *   (optional) The config installer to install configuration. This optional
   *   to allow the theme handler to work before Drupal is installed and has a
   *   database.
   * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
   *   The module handler to fire themes_installed/themes_uninstalled hooks.
   * @param \Drupal\Core\Config\ConfigManagerInterface $config_manager
   *   The config manager used to uninstall a theme.
   * @param \Drupal\Core\Asset\AssetCollectionOptimizerInterface $css_collection_optimizer
   *   The CSS asset collection optimizer service.
   * @param \Drupal\Core\Routing\RouteBuilderInterface $route_builder
   *   (optional) The route builder service to rebuild the routes if a theme is
   *   installed.
   * @param \Psr\Log\LoggerInterface $logger
   *   A logger instance.
   * @param \Drupal\Core\State\StateInterface $state
   *   The state store.
   * @param \Drupal\Core\Extension\ModuleExtensionList $module_extension_list
   *   The module extension list.
   * @param \Drupal\Core\Theme\Registry|null $themeRegistry
   *   The theme registry.
   * @param \Drupal\Core\Extension\ThemeExtensionList|null $themeExtensionList
   *   The theme extension list.
   */
  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, ModuleExtensionList $module_extension_list, protected Registry $themeRegistry, protected ThemeExtensionList $themeExtensionList) {
    $this->themeHandler = $theme_handler;
    $this->configFactory = $config_factory;
    $this->configInstaller = $config_installer;
    $this->moduleHandler = $module_handler;
    $this->configManager = $config_manager;
    $this->cssCollectionOptimizer = $css_collection_optimizer;
    $this->routeBuilder = $route_builder;
    $this->logger = $logger;
    $this->state = $state;
    $this->moduleExtensionList = $module_extension_list;
  public function __construct(
    protected readonly ThemeHandlerInterface $themeHandler,
    protected readonly ConfigFactoryInterface $configFactory,
    protected readonly ConfigInstallerInterface $configInstaller,
    protected readonly ModuleHandlerInterface $moduleHandler,
    protected readonly ConfigManagerInterface $configManager,
    protected readonly AssetCollectionOptimizerInterface $cssCollectionOptimizer,
    protected readonly RouteBuilderInterface $routeBuilder,
    protected readonly LoggerInterface $logger,
    protected readonly StateInterface $state,
    protected readonly ModuleExtensionList $moduleExtensionList,
    protected readonly Registry $themeRegistry,
    protected readonly ThemeExtensionList $themeExtensionList,
    protected ?CachedDiscoveryInterface $componentPluginManager = NULL,
  ) {
    if ($this->componentPluginManager === NULL) {
      @trigger_error('Calling ' . __METHOD__ . ' without the $componentPluginManager argument is deprecated in drupal:11.2.0 and it will be required in drupal:12.0.0. See https://www.drupal.org/node/3525649', E_USER_DEPRECATED);
      $this->componentPluginManager = \Drupal::service('plugin.manager.sdc');
    }
  }

  /**
@@ -311,11 +237,9 @@ public function uninstall(array $theme_list) {
   * Resets some other systems like rebuilding the route information or caches.
   */
  protected function resetSystem() {
    if ($this->routeBuilder) {
    $this->routeBuilder->setRebuildNeeded();
    }

    $this->themeRegistry->reset();
    $this->componentPluginManager->clearCachedDefinitions();
  }

}
+4 −0
Original line number Diff line number Diff line
@@ -164,6 +164,10 @@ public function getAllComponents(): array {
  public function clearCachedDefinitions(): void {
    parent::clearCachedDefinitions();
    $this->componentNegotiator->clearCache();
    // When clearing cached definitions from theme install or uninstall, the
    // container is not rebuilt. Unset discovery so it will be re-instantiated
    // in getDiscovery() with the updated list of theme directories.
    $this->discovery = NULL;
  }

  /**
+38 −0
Original line number Diff line number Diff line
<?php

declare(strict_types=1);

namespace Drupal\KernelTests\Components;

/**
 * Tests discovery of components in a theme being installed or uninstalled.
 *
 * @group sdc
 */
class ComponentPluginManagerCachedDiscoveryTest extends ComponentKernelTestBase {

  /**
   * {@inheritdoc}
   */
  protected static $themes = ['stark'];

  /**
   * Tests cached component plugin discovery on theme install and uninstall.
   */
  public function testComponentDiscoveryOnThemeInstall(): void {
    // Component in sdc_theme should not be found without sdc_theme installed.
    $definitions = \Drupal::service('plugin.manager.sdc')->getDefinitions();
    $this->assertArrayNotHasKey('sdc_theme_test:bar', $definitions);

    // Component in sdc_theme should be found once sdc_theme is installed.
    \Drupal::service('theme_installer')->install(['sdc_theme_test']);
    $definitions = \Drupal::service('plugin.manager.sdc')->getDefinitions();
    $this->assertArrayHasKey('sdc_theme_test:bar', $definitions);

    // Component in sdc_theme should not be found once sdc_theme is uninstalled.
    \Drupal::service('theme_installer')->uninstall(['sdc_theme_test']);
    $definitions = \Drupal::service('plugin.manager.sdc')->getDefinitions();
    $this->assertArrayNotHasKey('sdc_theme_test:bar', $definitions);
  }

}