Index: includes/common.inc =================================================================== RCS file: /cvs/drupal/drupal/includes/common.inc,v retrieving revision 1.1279 diff -u -p -r1.1279 common.inc --- includes/common.inc 21 Dec 2010 19:16:31 -0000 1.1279 +++ includes/common.inc 31 Dec 2010 17:08:17 -0000 @@ -2326,15 +2326,15 @@ function l($text, $path, array $options // rendering. if (variable_get('theme_link', TRUE)) { drupal_theme_initialize(); - $registry = theme_get_registry(); + $hook_info = theme_get_hook('link'); // We don't want to duplicate functionality that's in theme(), so any // hint of a module or theme doing anything at all special with the 'link' // theme hook should simply result in theme() being called. This includes // the overriding of theme_link() with an alternate function or template, // the presence of preprocess or process functions, or the presence of // include files. - $use_theme = !isset($registry['link']['function']) || ($registry['link']['function'] != 'theme_link'); - $use_theme = $use_theme || !empty($registry['link']['preprocess functions']) || !empty($registry['link']['process functions']) || !empty($registry['link']['includes']); + $use_theme = !$hook_info['function'] || ($hook_info['function'] != 'theme_link'); + $use_theme = $use_theme || !empty($hook_info['preprocess functions']) || !empty($hook_info['process functions']) || !empty($hook_info['includes']); } else { $use_theme = FALSE; Index: includes/theme.inc =================================================================== RCS file: /cvs/drupal/drupal/includes/theme.inc,v retrieving revision 1.626 diff -u -p -r1.626 theme.inc --- includes/theme.inc 11 Dec 2010 02:06:25 -0000 1.626 +++ includes/theme.inc 31 Dec 2010 17:08:20 -0000 @@ -736,7 +736,7 @@ function list_themes($refresh = FALSE) { * An HTML string representing the themed output. */ function theme($hook, $variables = array()) { - static $hooks = NULL; + static $initialized; // If called before all modules are loaded, we do not necessarily have a full // theme registry to work with, and therefore cannot process the theme @@ -744,17 +744,16 @@ function theme($hook, $variables = array if (!module_load_all(NULL) && !defined('MAINTENANCE_MODE')) { throw new Exception(t('theme() may not be called until all modules are loaded.')); } - - if (!isset($hooks)) { + if (!isset($initialized)) { drupal_theme_initialize(); - $hooks = theme_get_registry(); + $initialized = TRUE; } // If an array of hook candidates were passed, use the first one that has an // implementation. if (is_array($hook)) { foreach ($hook as $candidate) { - if (isset($hooks[$candidate])) { + if (theme_get_hook($candidate)) { break; } } @@ -763,16 +762,16 @@ function theme($hook, $variables = array // If there's no implementation, check for more generic fallbacks. If there's // still no implementation, log an error and return an empty string. - if (!isset($hooks[$hook])) { + if (!theme_get_hook($hook)) { // Iteratively strip everything after the last '__' delimiter, until an // implementation is found. while ($pos = strrpos($hook, '__')) { $hook = substr($hook, 0, $pos); - if (isset($hooks[$hook])) { + if (theme_get_hook($hook)) { break; } } - if (!isset($hooks[$hook])) { + if (!theme_get_hook($hook)) { // Only log a message when not trying theme suggestions ($hook being an // array). if (!isset($candidate)) { @@ -782,7 +781,7 @@ function theme($hook, $variables = array } } - $info = $hooks[$hook]; + $info = theme_get_hook($hook); global $theme_path; $temp = $theme_path; // point path_to_theme() to the currently used theme path: @@ -827,7 +826,7 @@ function theme($hook, $variables = array // be used unless overridden by a variable processor function. if (isset($info['base hook'])) { $base_hook = $info['base hook']; - $base_hook_info = $hooks[$base_hook]; + $base_hook_info = theme_get_hook($base_hook); if (isset($base_hook_info['preprocess functions']) || isset($base_hook_info['process functions'])) { $variables['theme_hook_suggestion'] = $hook; $hook = $base_hook; @@ -930,6 +929,44 @@ function theme($hook, $variables = array } /** + * Find the theme definition for a hook. + * + * This function maintains a cached subset of the theme registry which is built + * during calls to theme. To avoid loading the entire theme registry on every + * request for hooks which may not be called during normal site usage. + * + * @param $hook + * The theme hook being requested. + * @return + * The registry entry for the hook, or FALSE if none was found. + */ +function theme_get_hook($hook) { + global $theme; + static $hooks = array(); + if (empty($hooks)) { + if ($cached = cache_get("theme_registry:hooks:$theme")) { + $hooks = $cached->data; + } + } + if (isset($hooks[$hook])) { + return $hooks[$hook]; + } + else { + $registry = theme_get_registry(); + if (isset($registry[$hook])) { + $hooks[$hook] = $registry[$hook]; + cache_set("theme_registry:hooks:$theme", $hooks); + return $hooks[$hook]; + } + else { + $hooks[$hook] = FALSE; + cache_set("theme_registry:hooks:$theme", $hooks); + } + } + return FALSE; +} + +/** * Return the path to the current themed element. * * It can point to the active theme or the module handling a themed implementation. Index: modules/contextual/contextual.module =================================================================== RCS file: /cvs/drupal/drupal/modules/contextual/contextual.module,v retrieving revision 1.9 diff -u -p -r1.9 contextual.module --- modules/contextual/contextual.module 31 Oct 2010 03:56:46 -0000 1.9 +++ modules/contextual/contextual.module 31 Dec 2010 17:08:20 -0000 @@ -83,24 +83,19 @@ function contextual_element_info() { * @see contextual_pre_render_links() */ function contextual_preprocess(&$variables, $hook) { - static $hooks; - // Nothing to do here if the user is not permitted to access contextual links. if (!user_access('access contextual links')) { return; } - - if (!isset($hooks)) { - $hooks = theme_get_registry(); - } + $hook_info = theme_get_hook($hook); // Determine the primary theme function argument. - if (!empty($hooks[$hook]['variables'])) { - $keys = array_keys($hooks[$hook]['variables']); + if (!empty($hook_info['variables'])) { + $keys = array_keys($hook_info['variables']); $key = $keys[0]; } - elseif (!empty($hooks[$hook]['render element'])) { - $key = $hooks[$hook]['render element']; + elseif (!empty($hook_info['render element'])) { + $key = $hook_info['render element']; } if (!empty($key) && isset($variables[$key])) { $element = $variables[$key];