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 03:16:24 -0000 @@ -2086,6 +2086,9 @@ function _menu_delete_item($item, $force */ function menu_link_save(&$item) { + // Get the router if it's 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 +2114,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'); @@ -2144,6 +2146,14 @@ function menu_link_save(&$item) { $parent = $new_query->fields('menu_links')->execute()->fetchAssoc(); } } while ($parent === FALSE && $parent_path); + + // Whenever we retrieve a menu link for a router item from the database, we + // need to update the menu link 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 the previous rebuild. + if ($parent && !empty($parent['router_path']) && isset($menu[$parent['router_path']])) { + $parent = array_merge($parent, _menu_link_build($parent)); + } } if ($parent !== FALSE) { $item['menu_name'] = $parent['menu_name'];