--- includes/menu.inc.old	Sun Dec 28 02:22:35 2008
+++ includes/menu.inc	Mon Dec 29 01:35:31 2008
@@ -767,8 +767,8 @@
   static $menu_output = array();
 
   if (!isset($menu_output[$menu_name])) {
-    $tree = menu_tree_page_data($menu_name);
-    $menu_output[$menu_name] = menu_tree_output($tree);
+    $tree = menu_tree_page_data($menu_name, TRUE);
+    $menu_output[$menu_name] = menu_tree_output($tree, FALSE);
   }
   return $menu_output[$menu_name];
 }
@@ -778,18 +778,26 @@
  *
  * @param $tree
  *   A data structure representing the tree as returned from menu_tree_data.
+ * @param $filter_hidden_items
+ *   Optional, use FALSE if hidden menu items have been filtered already.
  * @return
  *   The rendered HTML of that data structure.
  */
-function menu_tree_output($tree) {
+function menu_tree_output($tree, $filter_hidden_items = TRUE) {
   $output = '';
   $items = array();
 
-  // Pull out just the menu items we are going to render so that we
-  // get an accurate count for the first/last classes.
-  foreach ($tree as $data) {
-    if (!$data['link']['hidden']) {
-      $items[] = $data;
+  if (!$filter_hidden_items) {
+    // Hidden menu items are already filtered by the caller.
+    $items = $tree;
+  }
+  else {
+    // Pull out just the menu items we are going to render so that we
+    // get an accurate count for the first/last classes.
+    foreach ($tree as $data) {
+      if (!$data['link']['hidden']) {
+        $items[] = $data;
+      }
     }
   }
 
@@ -804,7 +812,7 @@
     }
     $link = theme('menu_item_link', $data['link']);
     if ($data['below']) {
-      $output .= theme('menu_item', $link, $data['link']['has_children'], menu_tree_output($data['below']), $data['link']['in_active_trail'], $extra_class);
+      $output .= theme('menu_item', $link, $data['link']['has_children'], menu_tree_output($data['below'], $filter_hidden_items), $data['link']['in_active_trail'], $extra_class);
     }
     else {
       $output .= theme('menu_item', $link, $data['link']['has_children'], '', $data['link']['in_active_trail'], $extra_class);
@@ -825,18 +833,25 @@
  *   A fully loaded menu link, or NULL. If a link is supplied, only the
  *   path to root will be included in the returned tree- as if this link
  *   represented the current page in a visible menu.
+ * @param $filter_hidden_items
+ *   Optional, TRUE to prevent from checking user access for hidden items.
  * @return
  *   An tree of menu links in an array, in the order they should be rendered.
  */
-function menu_tree_all_data($menu_name = 'navigation', $item = NULL) {
+function menu_tree_all_data($menu_name = 'navigation', $item = NULL, $filter_hidden_items = FALSE) {
   static $tree = array();
 
   // Use $mlid as a flag for whether the data being loaded is for the whole tree.
   $mlid = isset($item['mlid']) ? $item['mlid'] : 0;
   // Generate a cache ID (cid) specific for this $menu_name and $item.
   $cid = 'links:' . $menu_name . ':all-cid:' . $mlid;
+  // Use separate static storage depending on filter hidden items argument.
+  $hid = ($filter_hidden_items ? 1 : 0);
+  if (!isset($tree[$hid])) {
+    $tree[$hid] = array();
+  }
 
-  if (!isset($tree[$cid])) {
+  if (!isset($tree[$hid][$cid])) {
     // If the static variable doesn't have the data, check {cache_menu}.
     $cache = cache_get($cid, 'cache_menu');
     if ($cache && isset($cache->data)) {
@@ -901,12 +916,21 @@
       // Cache the cid of the (shared) data using the menu and item-specific cid.
       cache_set($cid, $tree_cid, 'cache_menu');
     }
+    if ($filter_hidden_items) {
+      $items = array();
+      foreach ($data['tree'] as $item) {
+        if (!$item['link']['hidden']) {
+          $items[] = $item;
+        }
+      }
+      $data['tree'] = $items;
+    }
     // Check access for the current user to each item in the tree.
     menu_tree_check_access($data['tree'], $data['node_links']);
-    $tree[$cid] = $data['tree'];
+    $tree[$hid][$cid] = $data['tree'];
   }
 
-  return $tree[$cid];
+  return $tree[$hid][$cid];
 }
 
 /**
@@ -917,6 +941,8 @@
  *
  * @param $menu_name
  *   The named menu links to return
+ * @param $filter_hidden_items
+ *   Optional, TRUE to prevent from checking user access for hidden items.
  * @return
  *   An array of menu links, in the order they should be rendered. The array
  *   is a list of associative arrays -- these have two keys, link and below.
@@ -924,15 +950,20 @@
  *   submenu below the link if there is one, and it is a subtree that has the
  *   same structure described for the top-level array.
  */
-function menu_tree_page_data($menu_name = 'navigation') {
+function menu_tree_page_data($menu_name = 'navigation', $filter_hidden_items = FALSE) {
   static $tree = array();
 
   // Load the menu item corresponding to the current page.
   if ($item = menu_get_item()) {
     // Generate a cache ID (cid) specific for this page.
     $cid = 'links:' . $menu_name . ':page-cid:' . $item['href'] . ':' . (int)$item['access'];
+    // Use separate static storage depending on filter hidden items argument.
+    $hid = ($filter_hidden_items ? 1 : 0);
+    if (!isset($tree[$hid])) {
+      $tree[$hid] = array();
+    }
 
-    if (!isset($tree[$cid])) {
+    if (!isset($tree[$hid][$cid])) {
       // If the static variable doesn't have the data, check {cache_menu}.
       $cache = cache_get($cid, 'cache_menu');
       if ($cache && isset($cache->data)) {
@@ -1052,11 +1083,20 @@
         // Cache the cid of the (shared) data using the page-specific cid.
         cache_set($cid, $tree_cid, 'cache_menu');
       }
+      if ($filter_hidden_items) {
+        $items = array();
+        foreach ($data['tree'] as $item) {
+          if (!$item['link']['hidden']) {
+            $items[] = $item;
+          }
+        }
+        $data['tree'] = $items;
+      }
       // Check access for the current user to each item in the tree.
       menu_tree_check_access($data['tree'], $data['node_links']);
-      $tree[$cid] = $data['tree'];
+      $tree[$hid][$cid] = $data['tree'];
     }
-    return $tree[$cid];
+    return $tree[$hid][$cid];
   }
 
   return array();
@@ -1361,7 +1401,7 @@
   }
 
   // Get the menu hierarchy for the current page.
-  $tree = menu_tree_page_data($menu_name);
+  $tree = menu_tree_page_data($menu_name, TRUE);
 
   // Go down the active trail until the right level is reached.
   while ($level-- > 0 && $tree) {
@@ -1378,17 +1418,15 @@
   // Create a single level of links.
   $links = array();
   foreach ($tree as $item) {
-    if (!$item['link']['hidden']) {
-      $class = '';
-      $l = $item['link']['localized_options'];
-      $l['href'] = $item['link']['href'];
-      $l['title'] = $item['link']['title'];
-      if ($item['link']['in_active_trail']) {
-        $class = ' active-trail';
-      }
-      // Keyed with the unique mlid to generate classes in theme_links().
-      $links['menu-' . $item['link']['mlid'] . $class] = $l;
+    $class = '';
+    $l = $item['link']['localized_options'];
+    $l['href'] = $item['link']['href'];
+    $l['title'] = $item['link']['title'];
+    if ($item['link']['in_active_trail']) {
+      $class = ' active-trail';
     }
+    // Keyed with the unique mlid to generate classes in theme_links().
+    $links['menu-' . $item['link']['mlid'] . $class] = $l;
   }
   return $links;
 }
--- modules/book/book.module.old	Sun Dec 28 02:22:36 2008
+++ modules/book/book.module	Mon Dec 29 01:43:54 2008
@@ -216,7 +216,7 @@
       if ($book['bid'] == $current_bid) {
         // If the current page is a node associated with a book, the menu
         // needs to be retrieved.
-        $book_menus[$book_id] = menu_tree_output(menu_tree_all_data($node->book['menu_name'], $node->book));
+        $book_menus[$book_id] = menu_tree_output(menu_tree_all_data($node->book['menu_name'], $node->book, TRUE), FALSE);
       }
       else {
         // Since we know we will only display a link to the top node, there
@@ -237,11 +237,11 @@
     $title = $select->execute()->fetchField();
     // Only show the block if the user has view access for the top-level node.
     if ($title) {
-      $tree = menu_tree_all_data($node->book['menu_name'], $node->book);
+      $tree = menu_tree_all_data($node->book['menu_name'], $node->book, TRUE);
       // There should only be one element at the top level.
       $data = array_shift($tree);
       $block['subject'] = theme('book_title_link', $data['link']);
-      $block['content'] = ($data['below']) ? menu_tree_output($data['below']) : '';
+      $block['content'] = ($data['below']) ? menu_tree_output($data['below'], FALSE) : '';
     }
   }
 
@@ -583,7 +583,7 @@
 
   if (!isset($flat[$book_link['mlid']])) {
     // Call menu_tree_all_data() to take advantage of the menu system's caching.
-    $tree = menu_tree_all_data($book_link['menu_name'], $book_link);
+    $tree = menu_tree_all_data($book_link['menu_name'], $book_link, TRUE);
     $flat[$book_link['mlid']] = array();
     _book_flatten_menu($tree, $flat[$book_link['mlid']]);
   }
@@ -596,11 +596,9 @@
  */
 function _book_flatten_menu($tree, &$flat) {
   foreach ($tree as $data) {
-    if (!$data['link']['hidden']) {
-      $flat[$data['link']['mlid']] = $data['link'];
-      if ($data['below']) {
-        _book_flatten_menu($data['below'], $flat);
-      }
+    $flat[$data['link']['mlid']] = $data['link'];
+    if ($data['below']) {
+      _book_flatten_menu($data['below'], $flat);
     }
   }
 }
@@ -698,7 +696,7 @@
     $trail = array();
     $trail[] = array('title' => t('Home'), 'href' => '<front>', 'localized_options' => array());
 
-    $tree = menu_tree_all_data($book_link['menu_name'], $book_link);
+    $tree = menu_tree_all_data($book_link['menu_name'], $book_link, TRUE);
     $curr = array_shift($tree);
 
     while ($curr) {
@@ -975,7 +973,7 @@
  *   An array of mlid, title pairs for use as options for selecting a book page.
  */
 function book_toc($bid, $exclude = array(), $depth_limit) {
-  $tree = menu_tree_all_data(book_menu_name($bid));
+  $tree = menu_tree_all_data(book_menu_name($bid), NULL, TRUE);
   $toc = array();
   _book_toc_recurse($tree, '', $toc, $exclude, $depth_limit);
 
