Index: includes/cache.inc =================================================================== RCS file: /cvs/drupal/drupal/includes/cache.inc,v retrieving revision 1.38 diff -u -p -r1.38 cache.inc --- includes/cache.inc 1 Jul 2009 12:47:30 -0000 1.38 +++ includes/cache.inc 4 Aug 2009 10:59:35 -0000 @@ -162,6 +162,9 @@ function cache_clear_all($cid = NULL, $b cache_clear_all(NULL, 'cache_block'); } cache_clear_all(NULL, 'cache_page'); + + // Invoke hook_cache_clear_all() to allow other modules to clear caches. + module_invoke_all('cache_clear_all'); return; } return _cache_get_object($bin)->clear($cid, $wildcard); Index: modules/system/system.api.php =================================================================== RCS file: /cvs/drupal/drupal/modules/system/system.api.php,v retrieving revision 1.58 diff -u -p -r1.58 system.api.php --- modules/system/system.api.php 2 Aug 2009 11:25:18 -0000 1.58 +++ modules/system/system.api.php 4 Aug 2009 10:59:46 -0000 @@ -2057,5 +2057,14 @@ function hook_profile_tasks() { } /** + * Allows modules to respond when cache_clear_all() is called without arguments. + */ +function hook_cache_clear_all() { + // Clear the system_admin_menu_block() cache. + cache_clear_all('system:admin:links:', 'cache_menu', TRUE); +} + + +/** * @} End of "addtogroup hooks". */ Index: modules/system/system.module =================================================================== RCS file: /cvs/drupal/drupal/modules/system/system.module,v retrieving revision 1.735 diff -u -p -r1.735 system.module --- modules/system/system.module 3 Aug 2009 06:06:23 -0000 1.735 +++ modules/system/system.module 4 Aug 2009 10:59:50 -0000 @@ -1552,14 +1552,26 @@ function system_block_view($delta = '') */ function system_admin_menu_block($item) { $cache = &drupal_static(__FUNCTION__, array()); + + // This function is called on every page request if administrative links are + // displayed, so we cache by path to improve the performance of + // system_admin_menu_block_access(). While path is not guaranteed to be + // unique if users configure their administrative menu using the menu + // interface, we don't support two top level items with the same path + // here since this would require an additional query, or duplicate cache to + // be implemented. + if (isset($cache[$item['path']])) { + return $cache[$item['path']]; + } + global $user; + $cid = 'system:admin:links:' . implode('|', array_keys($user->roles)) . $item['path']; + if ($cached = cache_get($cid, 'cache_menu')) { + $cache[$item['path']] = $cached->data; + return $cached->data; + } if (!isset($item['mlid'])) { $item += db_query("SELECT mlid, menu_name FROM {menu_links} ml WHERE ml.router_path = :path AND module = 'system'", array(':path' => $item['path']))->fetchAssoc(); } - - if (isset($cache[$item['mlid']])) { - return $cache[$item['mlid']]; - } - $content = array(); $result = db_query(" SELECT m.load_functions, m.to_arg_functions, m.access_callback, m.access_arguments, m.page_callback, m.page_arguments, m.title, m.title_callback, m.title_arguments, m.type, m.description, ml.* @@ -1581,7 +1593,8 @@ function system_admin_menu_block($item) $content[(50000 + $link['weight']) . ' ' . $link['title'] . ' ' . $link['mlid']] = $link; } ksort($content); - $cache[$item['mlid']] = $content; + cache_set($cid, $content, 'cache_menu'); + $cache[$item['path']] = $content; return $content; } Index: modules/toolbar/toolbar.module =================================================================== RCS file: /cvs/drupal/drupal/modules/toolbar/toolbar.module,v retrieving revision 1.4 diff -u -p -r1.4 toolbar.module --- modules/toolbar/toolbar.module 28 Jul 2009 10:35:56 -0000 1.4 +++ modules/toolbar/toolbar.module 4 Aug 2009 10:59:52 -0000 @@ -111,6 +111,17 @@ function toolbar_build() { * Get only the top level items below the 'admin' path. */ function toolbar_get_menu_tree() { + global $user; + // Since generating the key can take 25% of page execution time, cache this + // for each combination of user roles. This guarantees a unique set of + // permissions for the minimum number of cache entries. We use the + // {cache_menu} bin to ensure this cache is cleared when the menu is updated. + // Also use the same $cid prefix as system_admin_menu_block() since we want + // this to be cleared in the same situations (changes to role permissions). + $cid = 'system:admin:links:toolbar:' . implode('|', array_keys($user->roles)); + if ($cached = cache_get($cid, 'cache_menu')) { + return $cached->data; + } $tree = menu_tree_all_data('management'); foreach ($tree as $item) { if ($item['link']['link_path'] == 'admin' && !empty($item['below'])) { @@ -124,6 +135,7 @@ function toolbar_get_menu_tree() { // Get rid of subitems to have a leaner data structure. unset($tree[$key]['below']); } + cache_set($cid, $tree, 'cache_menu'); return $tree; }