Index: includes/menu.inc =================================================================== RCS file: /cvs/drupal/drupal/includes/menu.inc,v retrieving revision 1.333 diff -u -p -r1.333 menu.inc --- includes/menu.inc 11 Aug 2009 17:26:33 -0000 1.333 +++ includes/menu.inc 16 Aug 2009 16:42:41 -0000 @@ -2085,7 +2085,9 @@ function _menu_delete_item($item, $force * saved. */ function menu_link_save(&$item) { - + // Get the router if it is already in memory. $menu will be NULL, unless this + // is during a menu rebuild + $menu = _menu_router_cache(); drupal_alter('menu_link', $item); // This is the easiest way to handle the unique internal path '', @@ -2111,14 +2113,13 @@ function menu_link_save(&$item) { } } - if (isset($item['plid'])) { - if ($item['plid']) { - $parent = db_query("SELECT * FROM {menu_links} WHERE mlid = :mlid", array(':mlid' => $item['plid']))->fetchAssoc(); - } - else { - // Don't bother with the query - mlid can never equal zero.. - $parent = FALSE; - } + // If no explicit plid is defined as parent, then the the re-parenting process + // is always invoked, since there is no guarantee that a plid of 0 is not + // caused by a re-parenting process that went wrong previously. For example, + // local tasks may be re-parented to the top-level (0) when tab_root points to + // an item of type MENU_CALLBACK. + if (!empty($item['plid'])) { + $parent = db_query("SELECT * FROM {menu_links} WHERE mlid = :mlid", array(':mlid' => $item['plid']))->fetchAssoc(); } else { $query = db_select('menu_links'); @@ -2146,7 +2147,16 @@ function menu_link_save(&$item) { } while ($parent === FALSE && $parent_path); } if ($parent !== FALSE) { + // If a parent link was found, derive its menu. $item['menu_name'] = $parent['menu_name']; + + // Whenever we retrieve a parent link for a router item from the database, + // we need to update the parent link's properties according to the new + // router item. Otherwise, the re-parenting process gets stuck on the menu + // router data that was stored in {menu_links} in a previous menu rebuild. + if (isset($menu) && !empty($parent['router_path']) && isset($menu[$parent['router_path']])) { + $parent = array_merge($parent, _menu_link_build($menu[$parent['router_path']])); + } } $menu_name = $item['menu_name']; // Menu callbacks need to be in the links table for breadcrumbs, but can't