Index: includes/menu.inc =================================================================== RCS file: /cvs/drupal/drupal/includes/menu.inc,v retrieving revision 1.429 diff -u -p -r1.429 menu.inc --- includes/menu.inc 17 Dec 2010 01:08:15 -0000 1.429 +++ includes/menu.inc 31 Dec 2010 04:07:40 -0000 @@ -2688,19 +2688,15 @@ function _menu_navigation_links_rebuild( } } if ($menu_links) { + // Keep an array of processed menu links, to allow menu_link_save() to + // check this for parents instead of querying the database. + $parent_candidates = array(); // Make sure no child comes before its parent. array_multisort($sort, SORT_NUMERIC, $menu_links); - foreach ($menu_links as $item) { + foreach ($menu_links as $key => $item) { $existing_item = db_select('menu_links') - ->fields('menu_links', array( - 'mlid', - 'menu_name', - 'plid', - 'customized', - 'has_children', - 'updated', - )) + ->fields('menu_links') ->condition('link_path', $item['path']) ->condition('module', 'system') ->execute()->fetchAssoc(); @@ -2721,7 +2717,12 @@ function _menu_navigation_links_rebuild( } if (!$existing_item || !$existing_item['customized']) { $item = _menu_link_build($item); - menu_link_save($item); + menu_link_save($item, $existing_item, $parent_candidates); + $parent_candidates[$item['mlid']] = $item; + unset($menu_links[$key]); + } + elseif ($existing_item['customized']) { + $parent_candidates[$existing_item['mlid']] = $existing_item; } } } @@ -2910,12 +2911,17 @@ function _menu_delete_item($item, $force * - mlid: Set to an existing value, or 0 or NULL to insert a new link. * - plid: The mlid of the parent. * - router_path: The path of the relevant router item. + * @param $existing_item + * Optional, the current record from the {menu_links} table as an array. + * @param $parent_candidates + * Optional array of menu links keyed by mlid. Used by + * _menu_navigation_links_rebuild() only. * * @return * The mlid of the saved menu link, or FALSE if the menu link could not be * saved. */ -function menu_link_save(&$item) { +function menu_link_save(&$item, $existing_item = array(), $parent_candidates = array()) { drupal_alter('menu_link', $item); // This is the easiest way to handle the unique internal path '', @@ -2934,15 +2940,17 @@ function menu_link_save(&$item) { 'customized' => 0, 'updated' => 0, ); - $existing_item = FALSE; if (isset($item['mlid'])) { - if ($existing_item = db_query("SELECT * FROM {menu_links} WHERE mlid = :mlid", array(':mlid' => $item['mlid']))->fetchAssoc()) { + if ($existing_item || $existing_item = db_query('SELECT * FROM {menu_links} WHERE mlid = :mlid', array('mlid' => $item['mlid']))->fetchAssoc()) { $existing_item['options'] = unserialize($existing_item['options']); } } + else { + $existing_item = FALSE; + } // Try to find a parent link. If found, assign it and derive its menu. - $parent = _menu_link_find_parent($item); + $parent = _menu_link_find_parent($item, $parent_candidates); if (!empty($parent['mlid'])) { $item['plid'] = $parent['mlid']; $item['menu_name'] = $parent['menu_name']; @@ -3076,11 +3084,13 @@ function menu_link_save(&$item) { * * @param $menu_link * A menu link. + * @param $parent_candidates + * An array of menu links keyed by mlid. * @return * A menu link structure of the possible parent or FALSE if no valid parent * has been found. */ -function _menu_link_find_parent($menu_link) { +function _menu_link_find_parent($menu_link, $parent_candidates = array()) { $parent = FALSE; // This item is explicitely top-level, skip the rest of the parenting. @@ -3102,7 +3112,12 @@ function _menu_link_find_parent($menu_li } foreach ($candidates as $mlid) { - $parent = db_query("SELECT * FROM {menu_links} WHERE mlid = :mlid", array(':mlid' => $mlid))->fetchAssoc(); + if (isset($parent_candidates[$mlid])) { + $parent = $parent_candidates[$mlid]; + } + if (!$parent) { + $parent = db_query("SELECT * FROM {menu_links} WHERE mlid = :mlid", array(':mlid' => $mlid))->fetchAssoc(); + } if ($parent) { return $parent; }