From 22ef552a9a54111aad62f80644d5f34933626c88 Mon Sep 17 00:00:00 2001
From: Lee Rowlands <lee.rowlands@previousnext.com.au>
Date: Tue, 24 Dec 2024 06:59:48 +1000
Subject: [PATCH] Issue #3478628 by oily, alexpott, catch, sheshsharma,
 osopolar, dunx, shane birley, joegl: Fatal error: Uncaught TypeError:
 Drupal\Core\Extension\ThemeHandler::addTheme()

---
 core/lib/Drupal/Core/Extension/ThemeHandler.php     | 13 ++++++++++---
 .../Tests/Core/Extension/ThemeHandlerTest.php       | 12 +++++++++++-
 2 files changed, 21 insertions(+), 4 deletions(-)

diff --git a/core/lib/Drupal/Core/Extension/ThemeHandler.php b/core/lib/Drupal/Core/Extension/ThemeHandler.php
index 6ea873af2b5e..2dd0e05e485c 100644
--- a/core/lib/Drupal/Core/Extension/ThemeHandler.php
+++ b/core/lib/Drupal/Core/Extension/ThemeHandler.php
@@ -67,11 +67,18 @@ public function getDefault() {
   public function listInfo() {
     if (!isset($this->list)) {
       $this->list = [];
-      $installed_themes = $this->configFactory->get('core.extension')->get('theme');
+      $installed_themes = array_keys($this->configFactory->get('core.extension')->get('theme'));
       if (!empty($installed_themes)) {
         $list = $this->themeList->getList();
-        foreach (array_keys($installed_themes) as $theme_name) {
-          $this->addTheme($list[$theme_name]);
+        foreach ($installed_themes as $theme) {
+          // Do not add installed themes that cannot be found by the
+          // extension.list.theme service. If a theme does go missing from the
+          // file system any call to ::getTheme() will result in an exception
+          // and an error being logged. Ignoring the problem here allows the
+          // theme system to fix itself while updating.
+          if (isset($list[$theme])) {
+            $this->addTheme($list[$theme]);
+          }
         }
       }
     }
diff --git a/core/tests/Drupal/Tests/Core/Extension/ThemeHandlerTest.php b/core/tests/Drupal/Tests/Core/Extension/ThemeHandlerTest.php
index 2196741063cc..1b9d68185ac8 100644
--- a/core/tests/Drupal/Tests/Core/Extension/ThemeHandlerTest.php
+++ b/core/tests/Drupal/Tests/Core/Extension/ThemeHandlerTest.php
@@ -46,7 +46,7 @@ protected function setUp(): void {
     $this->configFactory = $this->getConfigFactoryStub([
       'core.extension' => [
         'module' => [],
-        'theme' => [],
+        'theme' => ['stark' => 'stark'],
         'disabled' => [
           'theme' => [],
         ],
@@ -108,6 +108,16 @@ public function testThemeLibrariesEmpty(): void {
     }
   }
 
+  /**
+   * Test that a missing theme doesn't break ThemeHandler::listInfo().
+   *
+   * @covers ::listInfo
+   */
+  public function testMissingTheme(): void {
+    $themes = $this->themeHandler->listInfo();
+    $this->assertSame([], $themes);
+  }
+
 }
 
 /**
-- 
GitLab