From da7f1151899bbc8b789cd6bf4887f624eadbab82 Mon Sep 17 00:00:00 2001
From: Mark Carver <mark.carver@me.com>
Date: Sat, 10 Jan 2015 14:45:28 -0600
Subject: [PATCH] Issue #2098551 by robertom, neardark, markcarver: Registry
 alter does not respect core's auto-discovery of functions in template.php

---
 includes/registry.inc | 49 +++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 49 insertions(+)

diff --git a/includes/registry.inc b/includes/registry.inc
index 3f4190d..35697d5 100644
--- a/includes/registry.inc
+++ b/includes/registry.inc
@@ -244,6 +244,10 @@ function _bootstrap_process_theme_registry(&$registry, $themes) {
         // Correct the type that is implementing this override.
         $registry[$hook]['type'] = $GLOBALS['theme_path'] === $registry[$hook]['theme path'] ? 'theme' : 'base_theme';
 
+        // Sort the phase functions.
+        // @see https://www.drupal.org/node/2098551
+        _bootstrap_registry_sort_phase_functions($registry[$hook][$phase_key], $hook, $phase, $themes);
+
         // Setup a default "context" variable. This allows #context to be passed
         // to every template and theme function.
         // @see https://drupal.org/node/2035055
@@ -266,6 +270,51 @@ function _bootstrap_process_theme_registry(&$registry, $themes) {
 }
 
 /**
+ * Ensures the phase functions are invoked in the correct order.
+ *
+ * @param array $functions
+ *   The phase functions to iterate over.
+ * @param string $hook
+ *   The current hook being processed.
+ * @param string $phase
+ *   The current phase being processed.
+ * @param array $themes
+ *   An indexed array of current themes.
+ *
+ * @see https://www.drupal.org/node/2098551
+ */
+function _bootstrap_registry_sort_phase_functions(&$functions, $hook, $phase, $themes) {
+  // Immediately return if there is nothing to sort.
+  if (count($functions) < 2) {
+    return;
+  }
+
+  // Create an associative array of theme functions to ensure sort order.
+  $theme_functions = array_fill_keys($themes, array());
+
+  // Iterate over all the themes.
+  foreach ($themes as $theme) {
+    // Only add the function to the array of theme functions if it currently
+    // exists in the $functions array.
+    $function = $theme . '_' . $phase . '_' . $hook;
+    $key = array_search($function, $functions);
+    if ($key !== FALSE) {
+      // Save the theme function to be added later, but sorted.
+      $theme_functions[$theme][] = $function;
+
+      // Remove it from the current $functions array.
+      unset($functions[$key]);
+    }
+  }
+
+  // Iterate over all the captured theme functions and place them back into
+  // the phase functions array.
+  foreach ($theme_functions as $array) {
+    $functions = array_merge($functions, $array);
+  }
+}
+
+/**
  * Processes registered hooks in the theme registry against list of themes.
  *
  * This is used to add the necessary phased functions to theme hook suggestions.
-- 
2.0.1

