Builds menu links for the items in the menu router.
@todo This function should be removed/refactored.
function _menu_navigation_links_rebuild($menu) {
if (module_exists('menu_link')) {
$menu_link_controller = Drupal::entityManager()
->getStorageController('menu_link');
}
else {
// The Menu link module is not available at install time, so we need to
// hardcode the default storage controller.
$menu_link_controller = new MenuLinkStorageController('menu_link', Drupal::service('database'), Drupal::service('router.route_provider'));
}
// Add normal and suggested items as links.
$router_items = array();
foreach ($menu as $path => $router_item) {
if ($router_item['_visible']) {
$router_items[$path] = $router_item;
$sort[$path] = $router_item['_number_parts'];
}
}
if ($router_items) {
// Keep an array of processed menu links, to allow
// Drupal\menu_link\MenuLinkStorageController::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, $router_items);
foreach ($router_items as $key => $router_item) {
// For performance reasons, do a straight query now and convert to a menu
// link entity later.
// @todo revisit before release.
$existing_item = db_select('menu_links')
->fields('menu_links')
->condition('link_path', $router_item['path'])
->condition('module', 'system')
->execute()
->fetchAll();
if ($existing_item) {
$existing_item = reset($existing_item);
$existing_item->options = unserialize($existing_item->options);
$router_item['mlid'] = $existing_item->mlid;
$router_item['uuid'] = $existing_item->uuid;
// A change in hook_menu may move the link to a different menu
if (empty($router_item['menu_name']) || $router_item['menu_name'] == $existing_item->menu_name) {
$router_item['menu_name'] = $existing_item->menu_name;
$router_item['plid'] = $existing_item->plid;
}
else {
// It moved to a new menu.
// Let Drupal\menu_link\MenuLinkStorageController::save() try to find
// a new parent based on the path.
unset($router_item['plid']);
}
$router_item['has_children'] = $existing_item->has_children;
$router_item['updated'] = $existing_item->updated;
// Convert the existing item to a typed object.
$existing_item = $menu_link_controller
->create(get_object_vars($existing_item));
}
else {
$existing_item = NULL;
}
if ($existing_item && $existing_item->customized) {
$parent_candidates[$existing_item->mlid] = $existing_item;
}
else {
$menu_link = MenuLink::buildFromRouterItem($router_item);
$menu_link->original = $existing_item;
$menu_link->parentCandidates = $parent_candidates;
$menu_link_controller
->save($menu_link);
$parent_candidates[$menu_link
->id()] = $menu_link;
unset($router_items[$key]);
}
}
}
$paths = array_keys($menu);
// Updated and customized items whose router paths are gone need new ones.
$menu_links = $menu_link_controller
->loadUpdatedCustomized($paths);
foreach ($menu_links as $menu_link) {
$router_path = _menu_find_router_path($menu_link->link_path);
if (!empty($router_path) && ($router_path != $menu_link->router_path || $menu_link->updated)) {
// If the router path and the link path matches, it's surely a working
// item, so we clear the updated flag.
$updated = $menu_link->updated && $router_path != $menu_link->link_path;
$menu_link->router_path = $router_path;
$menu_link->updated = (int) $updated;
$menu_link_controller
->save($menu_link);
}
}
// Find any item whose router path does not exist any more.
$query = Drupal::entityQuery('menu_link')
->condition('router_path', $paths, 'NOT IN')
->condition('external', 0)
->condition('updated', 0)
->condition('customized', 0)
->sort('depth', 'DESC');
$result = $query
->execute();
// Remove all such items. Starting from those with the greatest depth will
// minimize the amount of re-parenting done by the menu link controller.
if (!empty($result)) {
menu_link_delete_multiple($result, TRUE);
}
}