From 542c3522c082bdcc89bedaef332c9e34d42eb76e Mon Sep 17 00:00:00 2001
From: Angie Byron <webchick@24967.no-reply.drupal.org>
Date: Mon, 3 Aug 2009 06:06:23 +0000
Subject: [PATCH] #489762 by JohnAlbin: Add theme lineage information to .info
 file cache and fix several edge-case bugs.

---
 modules/system/system.admin.inc | 14 ++++++++++----
 modules/system/system.module    | 33 +++++++++++++++++++++++----------
 2 files changed, 33 insertions(+), 14 deletions(-)

diff --git a/modules/system/system.admin.inc b/modules/system/system.admin.inc
index e62799808ecf..2242c2f24e7d 100644
--- a/modules/system/system.admin.inc
+++ b/modules/system/system.admin.inc
@@ -149,13 +149,19 @@ function system_themes_form() {
 
   foreach ($themes as $theme) {
     $screenshot = NULL;
-    $theme_key = $theme->name;
-    while ($theme_key) {
-      if (file_exists($themes[$theme_key]->info['screenshot'])) {
+    // Create a list which includes the current theme and all its base themes.
+    if (isset($themes[$theme->name]->base_themes)) {
+      $theme_keys = array_keys($themes[$theme->name]->base_themes) + array($theme->name);
+    }
+    else {
+      $theme_keys = array($theme->name);
+    }
+    // Look for a screenshot in the current theme or in its closest ancestor.
+    foreach (array_reverse($theme_keys) as $theme_key) {
+      if (isset($themes[$theme_key]) && file_exists($themes[$theme_key]->info['screenshot'])) {
         $screenshot = $themes[$theme_key]->info['screenshot'];
         break;
       }
-      $theme_key = isset($themes[$theme_key]->info['base theme']) ? $themes[$theme_key]->info['base theme'] : NULL;
     }
     $screenshot = $screenshot ? theme('image', $screenshot, t('Screenshot for %theme theme', array('%theme' => $theme->info['name'])), '', array('class' => 'screenshot'), FALSE) : t('no screenshot');
 
diff --git a/modules/system/system.module b/modules/system/system.module
index b4e6ef55f180..86f0bb940691 100644
--- a/modules/system/system.module
+++ b/modules/system/system.module
@@ -1925,10 +1925,15 @@ function _system_get_theme_data() {
     // Now that we've established all our master themes, go back and fill in
     // data for subthemes.
     foreach ($sub_themes as $key) {
-      $base_key = system_find_base_theme($themes, $key);
-      if (!$base_key) {
+      $themes[$key]->base_themes = system_find_base_themes($themes, $key);
+      // Don't proceed if there was a problem with the root base theme.
+      if (!current($themes[$key]->base_themes)) {
         continue;
       }
+      $base_key = key($themes[$key]->base_themes);
+      foreach (array_keys($themes[$key]->base_themes) as $base_theme) {
+        $themes[$base_theme]->sub_themes[$key] = $themes[$key]->info['name'];
+      }
       // Copy the 'owner' and 'engine' over if the top level theme uses a
       // theme engine.
       if (isset($themes[$base_key]->owner)) {
@@ -1964,8 +1969,9 @@ function system_get_theme_data() {
 }
 
 /**
- * Recursive function to find the top level base theme. Themes can inherit
- * templates and function implementations from earlier themes.
+ * Find all the base themes for the specified theme.
+ *
+ * Themes can inherit templates and function implementations from earlier themes.
  *
  * @param $themes
  *   An array of available themes.
@@ -1974,26 +1980,33 @@ function system_get_theme_data() {
  * @param $used_keys
  *   A recursion parameter preventing endless loops.
  * @return
- *   Returns the top level parent that has no ancestor or returns NULL if there isn't a valid parent.
+ *   Returns an array of all of the theme's ancestors; the first element's value
+ *   will be NULL if an error occurred.
  */
-function system_find_base_theme($themes, $key, $used_keys = array()) {
+function system_find_base_themes($themes, $key, $used_keys = array()) {
   $base_key = $themes[$key]->info['base theme'];
   // Does the base theme exist?
   if (!isset($themes[$base_key])) {
-    return NULL;
+    return array($base_key => NULL);
   }
 
+  $current_base_theme = array($base_key => $themes[$base_key]->info['name']);
+
   // Is the base theme itself a child of another theme?
   if (isset($themes[$base_key]->info['base theme'])) {
+    // Do we already know the base themes of this theme?
+    if (isset($themes[$base_key]->base_themes)) {
+      return $themes[$base_key]->base_themes + $current_base_theme;
+    }
     // Prevent loops.
     if (!empty($used_keys[$base_key])) {
-      return NULL;
+      return array($base_key => NULL);
     }
     $used_keys[$base_key] = TRUE;
-    return system_find_base_theme($themes, $base_key, $used_keys);
+    return system_find_base_themes($themes, $base_key, $used_keys) + $current_base_theme;
   }
   // If we get here, then this is our parent theme.
-  return $base_key;
+  return $current_base_theme;
 }
 
 /**
-- 
GitLab