Index: theme.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/theme.inc,v
retrieving revision 1.554
diff -u -r1.554 includes/theme.inc
--- includes/theme.inc	26 Nov 2009 18:57:16 -0000	1.554
+++ includes/theme.inc	30 Nov 2009 15:55:32 -0000
@@ -337,18 +337,69 @@
  * @see list_themes()
  */
 function _theme_process_registry(&$cache, $name, $type, $theme, $path) {
-  $result = array();
-  $function = $name . '_theme';
 
   // Processor functions work in two distinct phases with the process
   // functions always being executed after the preprocess functions.
-  $variable_process_phases = array(
+  static $variable_process_phases = array(
     'preprocess functions' => 'preprocess',
     'process functions'    => 'process',
   );
+  
+  // keep a list of _process_ and _preprocess_ functions,
+  // keyed by $phase_key, $hook and $prefix
+  static $phase_functions;
+  if (!isset($phase_functions)) {
+    $phase_functions = array();
+    $all_functions = get_defined_functions();
+    $functions = $all_functions['user'];
+    foreach ($variable_process_phases as $phase_key => $phase) {
+      foreach (preg_grep('/_' . $phase . '_/', $functions) as $function) {
+        list($prefix, $themehook) = explode('_' . $phase . '_', $function, 2);
+        if ($prefix && $themehook) {
+          $phase_functions[$phase_key][$themehook][$prefix] = $function;
+        }
+      }
+      foreach (preg_grep('/_' . $phase . '$/', $functions) as $function) {
+        $prefix = substr($function, 0, -(1+strlen($phase)));
+        if ($prefix) {
+          $phase_functions[$phase_key][''][$prefix] = $function;
+        }
+      }
+    }
+  }
+  
+
+  $result = array();
+  $function = $name . '_theme';
 
   if (function_exists($function)) {
     $result = $function($cache, $type, $theme, $path);
+    
+    $prefixes = array();
+    if ($type == 'module') {
+      // Default variable processor prefix.
+      $prefixes[] = 'template';
+      // Add all modules so they can intervene with their own variable
+      // processors. This allows them to provide variable processors even
+      // if they are not the owner of the current hook.
+      $prefixes += module_list();
+    }
+    elseif ($type == 'theme_engine' || $type == 'base_theme_engine') {
+      // Theme engines get an extra set that come before the normally
+      // named variable processors.
+      $prefixes[] = $name . '_engine';
+      // The theme engine registers on behalf of the theme using the
+      // theme's name.
+      $prefixes[] = $theme;
+    }
+    else {
+      // This applies when the theme manually registers their own variable
+      // processors.
+      $prefixes[] = $name;
+    }
+    $prefixes = array_unique($prefixes);
+    $prefixes = array_combine($prefixes, $prefixes);
+    
     foreach ($result as $hook => $info) {
       $result[$hook]['type'] = $type;
       $result[$hook]['theme path'] = $path;
@@ -398,43 +449,27 @@
         // Check for sub-directories.
         $result[$hook]['theme paths'][] = isset($info['path']) ? $info['path'] : $path;
       }
-
+      
       // Allow variable processors for all theming hooks, whether the hook is
       // implemented as a template or as a function.
       foreach ($variable_process_phases as $phase_key => $phase) {
         // Check for existing variable processors. Ensure arrayness.
         if (!isset($info[$phase_key]) || !is_array($info[$phase_key])) {
           $info[$phase_key] = array();
-          $prefixes = array();
-          if ($type == 'module') {
-            // Default variable processor prefix.
-            $prefixes[] = 'template';
-            // Add all modules so they can intervene with their own variable
-            // processors. This allows them to provide variable processors even
-            // if they are not the owner of the current hook.
-            $prefixes += module_list();
-          }
-          elseif ($type == 'theme_engine' || $type == 'base_theme_engine') {
-            // Theme engines get an extra set that come before the normally
-            // named variable processors.
-            $prefixes[] = $name . '_engine';
-            // The theme engine registers on behalf of the theme using the
-            // theme's name.
-            $prefixes[] = $theme;
-          }
-          else {
-            // This applies when the theme manually registers their own variable
-            // processors.
-            $prefixes[] = $name;
-          }
-          foreach ($prefixes as $prefix) {
-            // Only use non-hook-specific variable processors for theming hooks
-            // implemented as templates. @see theme().
-            if (isset($info['template']) && function_exists($prefix . '_' . $phase)) {
-              $info[$phase_key][] = $prefix . '_' . $phase;
+          if (isset($info['template'] && isset($phase_functions[$phase_key][''])) {
+            foreach ($phase_functions[$phase_key][''] as $prefix => $function) {
+              // Only use non-hook-specific variable processors for theming hooks
+              // implemented as templates. @see theme().
+              if (isset($prefixes[$prefix])) {
+                $info[$phase_key][] = $function;
+              }
             }
-            if (function_exists($prefix . '_' . $phase . '_' . $hook)) {
-              $info[$phase_key][] = $prefix . '_' . $phase . '_' . $hook;
+          }
+          if (isset($phase_functions[$phase_key][''])) {
+            foreach ($phase_functions[$phase_key][$hook] as $prefix => $function) {
+              if (isset($prefixes[$prefix])) {
+                $info[$phase_key][] = $function;
+              }
             }
           }
         }

