From c1ac44516aedc4a9d290c4796e2ca6d62f79d0a8 Mon Sep 17 00:00:00 2001
From: catch <catch@35733.no-reply.drupal.org>
Date: Thu, 29 Feb 2024 12:32:29 +0000
Subject: [PATCH] Issue #2942001 by dimitriskr, alexpott, gaurav.kapoor,
 smustgrave, andypost, almaudoh: Deprecate
 ThemeHandlerInterface::rebuildThemeData() and use extension.list.theme
 service instead

---
 core/core.services.yml                        |  4 +--
 .../ConfigImportSubscriber.php                | 18 ++++++------
 .../Drupal/Core/Extension/ThemeHandler.php    |  1 +
 .../Core/Extension/ThemeHandlerInterface.php  |  7 +++++
 .../Drupal/Core/Extension/ThemeInstaller.php  | 11 +++++--
 core/lib/Drupal/Core/Updater/Theme.php        |  2 +-
 .../src/Functional/ConfigImportUITest.php     |  2 +-
 core/modules/locale/locale.compare.inc        |  2 +-
 .../src/Controller/SystemController.php       | 29 +++++++++----------
 .../tests/src/Functional/System/ThemeTest.php |  4 +--
 .../Theme/EntityFilteringThemeTest.php        |  2 +-
 .../Kernel/Extension/ModuleHandlerTest.php    |  2 +-
 core/modules/update/src/UpdateManager.php     | 17 +++++++++--
 .../src/Functional/UpdateContribTest.php      |  2 +-
 core/modules/update/update.services.yml       |  2 +-
 .../Core/Theme/ThemeInstallerTest.php         | 12 +++++++-
 .../Tests/Core/Extension/ThemeHandlerTest.php |  2 ++
 17 files changed, 78 insertions(+), 41 deletions(-)

diff --git a/core/core.services.yml b/core/core.services.yml
index 20c03e16815f..ef0caadceadf 100644
--- a/core/core.services.yml
+++ b/core/core.services.yml
@@ -684,7 +684,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']
+    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']
   Drupal\Core\Extension\ThemeInstallerInterface: '@theme_installer'
   entity.memory_cache:
     class: Drupal\Core\Cache\MemoryCache\MemoryCache
@@ -1395,7 +1395,7 @@ services:
     class: Drupal\Core\EventSubscriber\ConfigImportSubscriber
     tags:
       - { name: service_collector, tag: 'module_install.uninstall_validator', call: addUninstallValidator }
-    arguments: ['@theme_handler', '@extension.list.module']
+    arguments: ['@extension.list.theme', '@extension.list.module']
   config_snapshot_subscriber:
     class: Drupal\Core\EventSubscriber\ConfigSnapshotSubscriber
     arguments: ['@config.manager', '@config.storage', '@config.storage.snapshot']
diff --git a/core/lib/Drupal/Core/EventSubscriber/ConfigImportSubscriber.php b/core/lib/Drupal/Core/EventSubscriber/ConfigImportSubscriber.php
index 38cdd4df3b56..29d78a24dadd 100644
--- a/core/lib/Drupal/Core/EventSubscriber/ConfigImportSubscriber.php
+++ b/core/lib/Drupal/Core/EventSubscriber/ConfigImportSubscriber.php
@@ -10,7 +10,7 @@
 use Drupal\Core\Extension\ConfigImportModuleUninstallValidatorInterface;
 use Drupal\Core\Extension\ModuleExtensionList;
 use Drupal\Core\Extension\ModuleUninstallValidatorInterface;
-use Drupal\Core\Extension\ThemeHandlerInterface;
+use Drupal\Core\Extension\ThemeExtensionList;
 use Drupal\Core\Installer\InstallerKernel;
 
 /**
@@ -33,11 +33,11 @@ class ConfigImportSubscriber extends ConfigImportValidateEventSubscriberBase {
   protected $moduleExtensionList;
 
   /**
-   * The theme handler.
+   * The theme extension list.
    *
-   * @var \Drupal\Core\Extension\ThemeHandlerInterface
+   * @var \Drupal\Core\Extension\ThemeExtensionList
    */
-  protected $themeHandler;
+  protected ThemeExtensionList $themeList;
 
   /**
    * The uninstall validators.
@@ -49,13 +49,13 @@ class ConfigImportSubscriber extends ConfigImportValidateEventSubscriberBase {
   /**
    * Constructs the ConfigImportSubscriber.
    *
-   * @param \Drupal\Core\Extension\ThemeHandlerInterface $theme_handler
-   *   The theme handler.
+   * @param \Drupal\Core\Extension\ThemeExtensionList $theme_extension_list
+   *   The theme extension list.
    * @param \Drupal\Core\Extension\ModuleExtensionList $extension_list_module
    *   The module extension list.
    */
-  public function __construct(ThemeHandlerInterface $theme_handler, ModuleExtensionList $extension_list_module) {
-    $this->themeHandler = $theme_handler;
+  public function __construct(ThemeExtensionList $theme_extension_list, ModuleExtensionList $extension_list_module) {
+    $this->themeList = $theme_extension_list;
     $this->moduleExtensionList = $extension_list_module;
   }
 
@@ -353,7 +353,7 @@ protected function validateDependencies(ConfigImporter $config_importer) {
    */
   protected function getThemeData() {
     if (!isset($this->themeData)) {
-      $this->themeData = $this->themeHandler->rebuildThemeData();
+      $this->themeData = $this->themeList->reset()->getList();
     }
     return $this->themeData;
   }
diff --git a/core/lib/Drupal/Core/Extension/ThemeHandler.php b/core/lib/Drupal/Core/Extension/ThemeHandler.php
index 19716f5c50da..cb6037c818ba 100644
--- a/core/lib/Drupal/Core/Extension/ThemeHandler.php
+++ b/core/lib/Drupal/Core/Extension/ThemeHandler.php
@@ -125,6 +125,7 @@ public function reset() {
    * {@inheritdoc}
    */
   public function rebuildThemeData() {
+    @trigger_error("\Drupal\Core\Extension\ThemeHandlerInterface::rebuildThemeData() is deprecated in drupal:10.3.0 and is removed from drupal:12.0.0. Use \Drupal::service('extension.list.theme')->reset()->getList() instead. See https://www.drupal.org/node/3413196", E_USER_DEPRECATED);
     return $this->themeList->reset()->getList();
   }
 
diff --git a/core/lib/Drupal/Core/Extension/ThemeHandlerInterface.php b/core/lib/Drupal/Core/Extension/ThemeHandlerInterface.php
index d690b5a59941..20d3db78957f 100644
--- a/core/lib/Drupal/Core/Extension/ThemeHandlerInterface.php
+++ b/core/lib/Drupal/Core/Extension/ThemeHandlerInterface.php
@@ -74,6 +74,13 @@ public function reset();
    *
    * @return \Drupal\Core\Extension\Extension[]
    *   An associative array of theme extensions.
+   *
+   * @deprecated in drupal:10.3.0 and is removed from drupal:12.0.0. Use
+   *   \Drupal::service('extension.list.theme')->reset()->getList() instead.
+   *
+   * @see https://www.drupal.org/node/3413196
+   * @see \Drupal\Core\Extension\ThemeExtensionList::reset()
+   * @see \Drupal\Core\Extension\ThemeExtensionList::getList()
    */
   public function rebuildThemeData();
 
diff --git a/core/lib/Drupal/Core/Extension/ThemeInstaller.php b/core/lib/Drupal/Core/Extension/ThemeInstaller.php
index 50b4a853cc64..99cd65c43964 100644
--- a/core/lib/Drupal/Core/Extension/ThemeInstaller.php
+++ b/core/lib/Drupal/Core/Extension/ThemeInstaller.php
@@ -102,8 +102,10 @@ class ThemeInstaller implements ThemeInstallerInterface {
    *   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 = NULL) {
+  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 = NULL, protected ?ThemeExtensionList $themeExtensionList = NULL) {
     $this->themeHandler = $theme_handler;
     $this->configFactory = $config_factory;
     $this->configInstaller = $config_installer;
@@ -118,6 +120,11 @@ public function __construct(ThemeHandlerInterface $theme_handler, ConfigFactoryI
       @trigger_error('Calling ' . __METHOD__ . '() without the $themeRegistry argument is deprecated in drupal:10.1.0 and will be required in drupal:11.0.0. See https://www.drupal.org/node/3350906', E_USER_DEPRECATED);
       $this->themeRegistry = \Drupal::service('theme.registry');
     }
+    if ($this->themeExtensionList === NULL) {
+      @trigger_error('Calling ' . __METHOD__ . '() without the $themeExtensionList argument is deprecated in drupal:10.3.0 and will be required in drupal:11.0.0. See https://www.drupal.org/node/3413308', E_USER_DEPRECATED);
+      $this->themeExtensionList = \Drupal::service('extension.list.theme');
+    }
+
   }
 
   /**
@@ -126,7 +133,7 @@ public function __construct(ThemeHandlerInterface $theme_handler, ConfigFactoryI
   public function install(array $theme_list, $install_dependencies = TRUE) {
     $extension_config = $this->configFactory->getEditable('core.extension');
 
-    $theme_data = $this->themeHandler->rebuildThemeData();
+    $theme_data = $this->themeExtensionList->reset()->getList();
     $installed_themes = $extension_config->get('theme') ?: [];
     $installed_modules = $extension_config->get('module') ?: [];
 
diff --git a/core/lib/Drupal/Core/Updater/Theme.php b/core/lib/Drupal/Core/Updater/Theme.php
index cd913fb76196..a3dfb872645d 100644
--- a/core/lib/Drupal/Core/Updater/Theme.php
+++ b/core/lib/Drupal/Core/Updater/Theme.php
@@ -83,7 +83,7 @@ public static function canUpdate($project_name) {
   public function postInstall() {
     // Update the theme info.
     clearstatcache();
-    \Drupal::service('theme_handler')->rebuildThemeData();
+    \Drupal::service('extension.list.theme')->reset();
   }
 
   /**
diff --git a/core/modules/config/tests/src/Functional/ConfigImportUITest.php b/core/modules/config/tests/src/Functional/ConfigImportUITest.php
index 1215be7b4c95..9e54269460cf 100644
--- a/core/modules/config/tests/src/Functional/ConfigImportUITest.php
+++ b/core/modules/config/tests/src/Functional/ConfigImportUITest.php
@@ -519,7 +519,7 @@ public function testExtensionValidation() {
     $module_data = $this->container->get('extension.list.module')->getList();
     $this->assertTrue(isset($module_data['node']->requires['text']), 'The Node module depends on the Text module.');
     unset($core['theme']['test_basetheme']);
-    $theme_data = \Drupal::service('theme_handler')->rebuildThemeData();
+    $theme_data = \Drupal::service('extension.list.theme')->reset()->getList();
     $this->assertTrue(isset($theme_data['test_subtheme']->requires['test_basetheme']), 'The Test Subtheme theme depends on the Test Basetheme theme.');
     // This module does not exist.
     $core['module']['does_not_exist'] = 0;
diff --git a/core/modules/locale/locale.compare.inc b/core/modules/locale/locale.compare.inc
index 634679e9fbb7..f36eb0beac72 100644
--- a/core/modules/locale/locale.compare.inc
+++ b/core/modules/locale/locale.compare.inc
@@ -105,7 +105,7 @@ function locale_translation_project_list() {
       'interface translation server pattern',
     ];
     $module_data = _locale_translation_prepare_project_list(\Drupal::service('extension.list.module')->getList(), 'module');
-    $theme_data = _locale_translation_prepare_project_list(\Drupal::service('theme_handler')->rebuildThemeData(), 'theme');
+    $theme_data = _locale_translation_prepare_project_list(\Drupal::service('extension.list.theme')->reset()->getList(), 'theme');
     $project_info = new ProjectInfo();
     $project_info->processInfoList($projects, $module_data, 'module', TRUE, $additional_whitelist);
     $project_info->processInfoList($projects, $theme_data, 'theme', TRUE, $additional_whitelist);
diff --git a/core/modules/system/src/Controller/SystemController.php b/core/modules/system/src/Controller/SystemController.php
index afb715dad9a1..f5532093197f 100644
--- a/core/modules/system/src/Controller/SystemController.php
+++ b/core/modules/system/src/Controller/SystemController.php
@@ -8,7 +8,6 @@
 use Drupal\Core\Extension\ModuleDependencyMessageTrait;
 use Drupal\Core\Extension\ModuleExtensionList;
 use Drupal\Core\Extension\ThemeExtensionList;
-use Drupal\Core\Extension\ThemeHandlerInterface;
 use Drupal\Core\Form\FormBuilderInterface;
 use Drupal\Core\Link;
 use Drupal\Core\Menu\MenuLinkTreeInterface;
@@ -46,13 +45,6 @@ class SystemController extends ControllerBase {
    */
   protected $formBuilder;
 
-  /**
-   * The theme handler service.
-   *
-   * @var \Drupal\Core\Extension\ThemeHandlerInterface
-   */
-  protected $themeHandler;
-
   /**
    * The menu link tree service.
    *
@@ -67,6 +59,13 @@ class SystemController extends ControllerBase {
    */
   protected $moduleExtensionList;
 
+  /**
+   * The theme extension list.
+   *
+   * @var \Drupal\Core\Extension\ThemeExtensionList
+   */
+  protected ThemeExtensionList $themeExtensionList;
+
   /**
    * Constructs a new SystemController.
    *
@@ -76,20 +75,20 @@ class SystemController extends ControllerBase {
    *   The theme access checker service.
    * @param \Drupal\Core\Form\FormBuilderInterface $form_builder
    *   The form builder.
-   * @param \Drupal\Core\Extension\ThemeHandlerInterface $theme_handler
-   *   The theme handler.
    * @param \Drupal\Core\Menu\MenuLinkTreeInterface $menu_link_tree
    *   The menu link tree service.
    * @param \Drupal\Core\Extension\ModuleExtensionList $module_extension_list
    *   The module extension list.
+   * @param \Drupal\Core\Extension\ThemeExtensionList $theme_extension_list
+   *   The theme extension list.
    */
-  public function __construct(SystemManager $systemManager, ThemeAccessCheck $theme_access, FormBuilderInterface $form_builder, ThemeHandlerInterface $theme_handler, MenuLinkTreeInterface $menu_link_tree, ModuleExtensionList $module_extension_list) {
+  public function __construct(SystemManager $systemManager, ThemeAccessCheck $theme_access, FormBuilderInterface $form_builder, MenuLinkTreeInterface $menu_link_tree, ModuleExtensionList $module_extension_list, ThemeExtensionList $theme_extension_list) {
     $this->systemManager = $systemManager;
     $this->themeAccess = $theme_access;
     $this->formBuilder = $form_builder;
-    $this->themeHandler = $theme_handler;
     $this->menuLinkTree = $menu_link_tree;
     $this->moduleExtensionList = $module_extension_list;
+    $this->themeExtensionList = $theme_extension_list;
   }
 
   /**
@@ -100,9 +99,9 @@ public static function create(ContainerInterface $container) {
       $container->get('system.manager'),
       $container->get('access_check.theme'),
       $container->get('form_builder'),
-      $container->get('theme_handler'),
       $container->get('menu.link_tree'),
-      $container->get('extension.list.module')
+      $container->get('extension.list.module'),
+      $container->get('extension.list.theme'),
     );
   }
 
@@ -204,7 +203,7 @@ public function systemAdminMenuBlockPage() {
   public function themesPage() {
     $config = $this->config('system.theme');
     // Get all available themes.
-    $themes = $this->themeHandler->rebuildThemeData();
+    $themes = $this->themeExtensionList->reset()->getList();
 
     // Remove obsolete themes.
     $themes = array_filter($themes, function ($theme) {
diff --git a/core/modules/system/tests/src/Functional/System/ThemeTest.php b/core/modules/system/tests/src/Functional/System/ThemeTest.php
index 0a88272bb183..202cd0be7b62 100644
--- a/core/modules/system/tests/src/Functional/System/ThemeTest.php
+++ b/core/modules/system/tests/src/Functional/System/ThemeTest.php
@@ -343,7 +343,7 @@ public function testAdministrationTheme() {
     $this->submitForm($edit, 'Save configuration');
 
     // Check the display of non stable themes.
-    $themes = \Drupal::service('theme_handler')->rebuildThemeData();
+    $themes = \Drupal::service('extension.list.theme')->reset()->getList();
     $experimental_version = $themes['experimental_theme_test']->info['version'];
     $deprecated_version = $themes['deprecated_theme_test']->info['version'];
     $this->drupalGet('admin/appearance');
@@ -531,7 +531,7 @@ public function testInstallAndSetAsDefault() {
       // This checks for a regression. See https://www.drupal.org/node/2498691.
       $this->assertSession()->pageTextNotContains("The $theme_machine_name theme was not found.");
 
-      $themes = \Drupal::service('theme_handler')->rebuildThemeData();
+      $themes = \Drupal::service('extension.list.theme')->reset()->getList();
       $version = $themes[$theme_machine_name]->info['version'];
 
       // Confirm the theme is indicated as the default theme and administration
diff --git a/core/modules/system/tests/src/Functional/Theme/EntityFilteringThemeTest.php b/core/modules/system/tests/src/Functional/Theme/EntityFilteringThemeTest.php
index 3245ee042a7b..825bc5ffd83c 100644
--- a/core/modules/system/tests/src/Functional/Theme/EntityFilteringThemeTest.php
+++ b/core/modules/system/tests/src/Functional/Theme/EntityFilteringThemeTest.php
@@ -88,7 +88,7 @@ protected function setUp(): void {
     $listing = new ExtensionDiscovery(\Drupal::root());
     $this->themes = $listing->scan('theme', FALSE);
     /** @var \Drupal\Core\Extension\ThemeHandlerInterface $theme_handler */
-    $theme_data = \Drupal::service('theme_handler')->rebuildThemeData();
+    $theme_data = \Drupal::service('extension.list.theme')->reset()->getList();
     foreach (array_keys($this->themes) as $theme) {
       // Skip obsolete and deprecated themes.
       $info = $theme_data[$theme]->info;
diff --git a/core/modules/system/tests/src/Kernel/Extension/ModuleHandlerTest.php b/core/modules/system/tests/src/Kernel/Extension/ModuleHandlerTest.php
index 09718581e4c3..faf58cb8f49a 100644
--- a/core/modules/system/tests/src/Kernel/Extension/ModuleHandlerTest.php
+++ b/core/modules/system/tests/src/Kernel/Extension/ModuleHandlerTest.php
@@ -333,7 +333,7 @@ public function testModuleStreamWrappers() {
    */
   public function testThemeMetaData() {
     // Generate the list of available themes.
-    $themes = \Drupal::service('theme_handler')->rebuildThemeData();
+    $themes = \Drupal::service('extension.list.theme')->reset()->getList();
     // Check that the mtime field exists for the olivero theme.
     $this->assertNotEmpty($themes['olivero']->info['mtime'], 'The olivero.info.yml file modification time field is present.');
     // Use 0 if mtime isn't present, to avoid an array index notice.
diff --git a/core/modules/update/src/UpdateManager.php b/core/modules/update/src/UpdateManager.php
index 330a803a14a7..287f421061f9 100644
--- a/core/modules/update/src/UpdateManager.php
+++ b/core/modules/update/src/UpdateManager.php
@@ -6,6 +6,7 @@
 use Drupal\Core\DependencyInjection\DependencySerializationTrait;
 use Drupal\Core\Extension\ModuleExtensionList;
 use Drupal\Core\Extension\ModuleHandlerInterface;
+use Drupal\Core\Extension\ThemeExtensionList;
 use Drupal\Core\Extension\ThemeHandlerInterface;
 use Drupal\Core\KeyValueStore\KeyValueFactoryInterface;
 use Drupal\Core\StringTranslation\TranslationInterface;
@@ -75,6 +76,13 @@ class UpdateManager implements UpdateManagerInterface {
    */
   protected $moduleExtensionList;
 
+  /**
+   * The theme extension list.
+   *
+   * @var \Drupal\Core\Extension\ThemeExtensionList
+   */
+  protected ThemeExtensionList $themeExtensionList;
+
   /**
    * Constructs an UpdateManager.
    *
@@ -90,10 +98,12 @@ class UpdateManager implements UpdateManagerInterface {
    *   The expirable key/value factory.
    * @param \Drupal\Core\Extension\ThemeHandlerInterface $theme_handler
    *   The theme handler.
-   * @param \Drupal\Core\Extension\ModuleExtensionList|null $extension_list_module
+   * @param \Drupal\Core\Extension\ModuleExtensionList $extension_list_module
    *   The module extension list.
+   * @param \Drupal\Core\Extension\ThemeExtensionList $extension_list_theme
+   *   The theme extension list.
    */
-  public function __construct(ConfigFactoryInterface $config_factory, ModuleHandlerInterface $module_handler, UpdateProcessorInterface $update_processor, TranslationInterface $translation, KeyValueFactoryInterface $key_value_expirable_factory, ThemeHandlerInterface $theme_handler, ModuleExtensionList $extension_list_module) {
+  public function __construct(ConfigFactoryInterface $config_factory, ModuleHandlerInterface $module_handler, UpdateProcessorInterface $update_processor, TranslationInterface $translation, KeyValueFactoryInterface $key_value_expirable_factory, ThemeHandlerInterface $theme_handler, ModuleExtensionList $extension_list_module, ThemeExtensionList $extension_list_theme) {
     $this->updateSettings = $config_factory->get('update.settings');
     $this->moduleHandler = $module_handler;
     $this->updateProcessor = $update_processor;
@@ -103,6 +113,7 @@ public function __construct(ConfigFactoryInterface $config_factory, ModuleHandle
     $this->availableReleasesTempStore = $key_value_expirable_factory->get('update_available_releases');
     $this->projects = [];
     $this->moduleExtensionList = $extension_list_module;
+    $this->themeExtensionList = $extension_list_theme;
   }
 
   /**
@@ -141,7 +152,7 @@ public function getProjects() {
       if (empty($this->projects)) {
         // Still empty, so we have to rebuild.
         $module_data = $this->moduleExtensionList->reset()->getList();
-        $theme_data = $this->themeHandler->rebuildThemeData();
+        $theme_data = $this->themeExtensionList->reset()->getList();
         $project_info = new ProjectInfo();
         $project_info->processInfoList($this->projects, $module_data, 'module', TRUE);
         $project_info->processInfoList($this->projects, $theme_data, 'theme', TRUE);
diff --git a/core/modules/update/tests/src/Functional/UpdateContribTest.php b/core/modules/update/tests/src/Functional/UpdateContribTest.php
index dfde2d412135..70ce45ed557c 100644
--- a/core/modules/update/tests/src/Functional/UpdateContribTest.php
+++ b/core/modules/update/tests/src/Functional/UpdateContribTest.php
@@ -425,7 +425,7 @@ public function testUpdateHiddenBaseTheme() {
       ],
     ]);
     $projects = \Drupal::service('update.manager')->getProjects();
-    $theme_data = \Drupal::service('theme_handler')->rebuildThemeData();
+    $theme_data = \Drupal::service('extension.list.theme')->reset()->getList();
     $project_info = new ProjectInfo();
     $project_info->processInfoList($projects, $theme_data, 'theme', TRUE);
 
diff --git a/core/modules/update/update.services.yml b/core/modules/update/update.services.yml
index 56ff7c1cee93..d8089e809df3 100644
--- a/core/modules/update/update.services.yml
+++ b/core/modules/update/update.services.yml
@@ -6,7 +6,7 @@ services:
       - { name: access_check, applies_to: _access_update_manager }
   update.manager:
     class: Drupal\update\UpdateManager
-    arguments: ['@config.factory', '@module_handler', '@update.processor', '@string_translation', '@keyvalue.expirable', '@theme_handler', '@extension.list.module']
+    arguments: ['@config.factory', '@module_handler', '@update.processor', '@string_translation', '@keyvalue.expirable', '@theme_handler', '@extension.list.module', '@extension.list.theme']
   Drupal\update\UpdateManagerInterface: '@update.manager'
   update.processor:
     class: Drupal\update\UpdateProcessor
diff --git a/core/tests/Drupal/KernelTests/Core/Theme/ThemeInstallerTest.php b/core/tests/Drupal/KernelTests/Core/Theme/ThemeInstallerTest.php
index 2ba2622a6e80..9eb4bd24575c 100644
--- a/core/tests/Drupal/KernelTests/Core/Theme/ThemeInstallerTest.php
+++ b/core/tests/Drupal/KernelTests/Core/Theme/ThemeInstallerTest.php
@@ -8,6 +8,7 @@
 use Drupal\Core\Extension\MissingDependencyException;
 use Drupal\Core\Extension\ModuleUninstallValidatorException;
 use Drupal\Core\Extension\Exception\UnknownExtensionException;
+use Drupal\Core\Extension\ThemeExtensionList;
 use Drupal\KernelTests\KernelTestBase;
 
 /**
@@ -54,7 +55,7 @@ public function testEmpty() {
     $this->assertEmpty(array_keys(\Drupal::service('theme_handler')->listInfo()));
 
     // Rebuilding available themes should always yield results though.
-    $this->assertNotEmpty($this->themeHandler()->rebuildThemeData()['stark'], 'ThemeHandler::rebuildThemeData() yields all available themes.');
+    $this->assertNotEmpty($this->extensionListTheme()->reset()->getList()['stark'], 'ThemeExtensionList::getList() yields all available themes.');
 
     // theme_get_setting() should return global default theme settings.
     $this->assertTrue(theme_get_setting('features.favicon'));
@@ -488,4 +489,13 @@ protected function moduleInstaller() {
     return $this->container->get('module_installer');
   }
 
+  /**
+   * Returns the ThemeExtensionList.
+   *
+   * @return \Drupal\Core\Extension\ThemeExtensionList
+   */
+  protected function extensionListTheme(): ThemeExtensionList {
+    return $this->container->get('extension.list.theme');
+  }
+
 }
diff --git a/core/tests/Drupal/Tests/Core/Extension/ThemeHandlerTest.php b/core/tests/Drupal/Tests/Core/Extension/ThemeHandlerTest.php
index 935a28142174..b8c71ba4d778 100644
--- a/core/tests/Drupal/Tests/Core/Extension/ThemeHandlerTest.php
+++ b/core/tests/Drupal/Tests/Core/Extension/ThemeHandlerTest.php
@@ -69,8 +69,10 @@ protected function setUp(): void {
    * Tests rebuilding the theme data.
    *
    * @see \Drupal\Core\Extension\ThemeHandler::rebuildThemeData()
+   * @group legacy
    */
   public function testRebuildThemeData() {
+    $this->expectDeprecation("\Drupal\Core\Extension\ThemeHandlerInterface::rebuildThemeData() is deprecated in drupal:10.3.0 and is removed from drupal:12.0.0. Use \Drupal::service('extension.list.theme')->reset()->getList() instead. See https://www.drupal.org/node/3413196");
     $this->themeList->expects($this->once())
       ->method('reset')
       ->willReturnSelf();
-- 
GitLab