Index: includes/common.inc =================================================================== RCS file: /cvs/drupal/drupal/includes/common.inc,v retrieving revision 1.1038 diff -u -p -r1.1038 common.inc --- includes/common.inc 2 Nov 2009 03:46:43 -0000 1.1038 +++ includes/common.inc 2 Nov 2009 20:56:49 -0000 @@ -4552,27 +4552,37 @@ function drupal_system_listing($mask, $d * keyed array as described above. */ function drupal_alter($type, &$data, &$context1 = NULL, &$context2 = NULL) { - $hook = $type . '_alter'; - foreach (module_implements($hook) as $module) { - $function = $module . '_' . $hook; - $function($data, $context1, $context2); - } - // Allow the theme to alter variables after the theme system has been - // initialized. - global $theme, $base_theme_info; - if (isset($theme)) { - $theme_keys = array(); - foreach ($base_theme_info as $base) { - $theme_keys[] = $base->name; - } - $theme_keys[] = $theme; - foreach ($theme_keys as $theme_key) { - $function = $theme_key . '_' . $hook; - if (function_exists($function)) { - $function($data, $context1, $context2); + $functions = &drupal_static(__FUNCTION__, array()); + + // Some alter hooks are invoked many times per page request, so statically + // cache the list of functions to call, and on subsequent calls, iterate + // through them quickly. + if (!isset($functions[$type])) { + $functions[$type] = array(); + $hook = $type . '_alter'; + foreach (module_implements($hook) as $module) { + $functions[$type][] = $module . '_' . $hook; + } + // Allow the theme to alter variables after the theme system has been + // initialized. + global $theme, $base_theme_info; + if (isset($theme)) { + $theme_keys = array(); + foreach ($base_theme_info as $base) { + $theme_keys[] = $base->name; + } + $theme_keys[] = $theme; + foreach ($theme_keys as $theme_key) { + $function = $theme_key . '_' . $hook; + if (function_exists($function)) { + $functions[$type][] = $function; + } } } } + foreach ($functions[$type] as $function) { + $function($data, $context1, $context2); + } } /** Index: includes/module.inc =================================================================== RCS file: /cvs/drupal/drupal/includes/module.inc,v retrieving revision 1.164 diff -u -p -r1.164 module.inc --- includes/module.inc 1 Nov 2009 22:10:07 -0000 1.164 +++ includes/module.inc 2 Nov 2009 20:56:50 -0000 @@ -383,6 +383,7 @@ function module_implements($hook, $sort $implementations = array(); cache_set('module_implements', array()); drupal_static_reset('module_hook_info'); + drupal_static_reset('drupal_alter'); cache_clear_all('hook_info', 'cache'); return; } Index: includes/theme.inc =================================================================== RCS file: /cvs/drupal/drupal/includes/theme.inc,v retrieving revision 1.545 diff -u -p -r1.545 theme.inc --- includes/theme.inc 2 Nov 2009 00:25:32 -0000 1.545 +++ includes/theme.inc 2 Nov 2009 20:56:50 -0000 @@ -85,6 +85,9 @@ function drupal_theme_initialize() { $ancestor = $themes[$ancestor]->base_theme; } _drupal_theme_initialize($themes[$theme], array_reverse($base_theme)); + + // Themes can have alter functions, so reset the drupal_alter() cache. + drupal_static_reset('drupal_alter'); } /** Index: modules/node/node.test =================================================================== RCS file: /cvs/drupal/drupal/modules/node/node.test,v retrieving revision 1.51 diff -u -p -r1.51 node.test --- modules/node/node.test 30 Oct 2009 22:33:35 -0000 1.51 +++ modules/node/node.test 2 Nov 2009 20:56:52 -0000 @@ -758,7 +758,8 @@ class NodeAccessRecordsUnitTest extends $web_user = $this->drupalCreateUser(array('access content')); foreach ($operations as $op) { $grants = node_test_node_grants($op, $web_user); - $altered_grants = drupal_alter($grants, $web_user, $op); + $altered_grants = $grants; + drupal_alter('node_grants', $altered_grants, $web_user, $op); $this->assertNotEqual($grants, $altered_grants, t('Altered the %op grant for a user.', array('%op' => $op))); } }