Same name and namespace in other branches
  1. 7.x includes/menu.inc \_menu_navigation_links_rebuild()

Helper function to build menu links for the items in the menu router.

Related topics

1 call to _menu_navigation_links_rebuild()
menu_rebuild in includes/menu.inc
(Re)populate the database tables used by various menu functions.

File

includes/menu.inc, line 1785
API for the Drupal menu system.

Code

function _menu_navigation_links_rebuild($menu) {

  // Add normal and suggested items as links.
  $menu_links = array();
  foreach ($menu as $path => $item) {
    if ($item['_visible']) {
      $item = _menu_link_build($item);
      $menu_links[$path] = $item;
      $sort[$path] = $item['_number_parts'];
    }
  }
  if ($menu_links) {

    // Make sure no child comes before its parent.
    array_multisort($sort, SORT_NUMERIC, $menu_links);
    foreach ($menu_links as $item) {
      $existing_item = db_fetch_array(db_query("SELECT mlid, menu_name, plid, customized, has_children, updated FROM {menu_links} WHERE link_path = '%s' AND module = '%s'", $item['link_path'], 'system'));
      if ($existing_item) {
        $item['mlid'] = $existing_item['mlid'];

        // A change in hook_menu may move the link to a different menu
        if (empty($item['menu_name']) || $item['menu_name'] == $existing_item['menu_name']) {
          $item['menu_name'] = $existing_item['menu_name'];
          $item['plid'] = $existing_item['plid'];
        }
        $item['has_children'] = $existing_item['has_children'];
        $item['updated'] = $existing_item['updated'];
      }
      if (!$existing_item || !$existing_item['customized']) {
        menu_link_save($item);
      }
    }
  }
  $placeholders = db_placeholders($menu, 'varchar');
  $paths = array_keys($menu);

  // Updated and customized items whose router paths are gone need new ones.
  $result = db_query("SELECT ml.link_path, ml.mlid, ml.router_path, ml.updated FROM {menu_links} ml WHERE ml.updated = 1 OR (router_path NOT IN ({$placeholders}) AND external = 0 AND customized = 1)", $paths);
  while ($item = db_fetch_array($result)) {
    $router_path = _menu_find_router_path($item['link_path']);
    if (!empty($router_path) && ($router_path != $item['router_path'] || $item['updated'])) {

      // If the router path and the link path matches, it's surely a working
      // item, so we clear the updated flag.
      $updated = $item['updated'] && $router_path != $item['link_path'];
      db_query("UPDATE {menu_links} SET router_path = '%s', updated = %d WHERE mlid = %d", $router_path, $updated, $item['mlid']);
    }
  }

  // Find any item whose router path does not exist any more.
  $result = db_query("SELECT * FROM {menu_links} WHERE router_path NOT IN ({$placeholders}) AND external = 0 AND updated = 0 AND customized = 0 ORDER BY depth DESC", $paths);

  // Remove all such items. Starting from those with the greatest depth will
  // minimize the amount of re-parenting done by menu_link_delete().
  while ($item = db_fetch_array($result)) {
    _menu_delete_item($item, TRUE);
  }
}