From 42e2c36937b3b842a13417082a1d1ba2fd0d0b6c Mon Sep 17 00:00:00 2001 From: Alex Pott <alex.a.pott@googlemail.com> Date: Fri, 24 Jan 2014 11:23:53 +0100 Subject: [PATCH] Revert "Issue #2047633 by dawehner, pwolanin, Xano, amateescu, tim.plunkett: Move definition of menu links to hook_menu_link_defaults(), decouple key name from path, and make 'parent' explicit." This reverts commit 531fd59314965728e495ea3fb737e5c5bc4b5659. --- core/includes/bootstrap.inc | 9 +- core/includes/menu.inc | 358 ++++++++++-------- core/includes/path.inc | 27 +- core/includes/theme.inc | 8 - core/modules/action/action.module | 14 - core/modules/aggregator/aggregator.module | 24 -- core/modules/ban/ban.module | 15 - core/modules/block/block.module | 14 - core/modules/book/book.module | 24 +- .../book/lib/Drupal/book/BookManager.php | 6 +- core/modules/comment/comment.module | 14 - core/modules/config/config.module | 14 - .../tests/config_test/config_test.routing.yml | 1 - .../config_translation.module | 15 - core/modules/contact/contact.module | 20 - .../content_translation.module | 9 - core/modules/dblog/dblog.module | 36 -- core/modules/editor/editor.module | 8 - core/modules/entity/entity.module | 30 -- .../EntityDisplayModeController.php | 4 +- core/modules/field_ui/field_ui.module | 14 - core/modules/filter/filter.module | 20 - core/modules/forum/forum.module | 18 - core/modules/forum/forum.routing.yml | 1 - core/modules/help/help.module | 15 - core/modules/image/image.module | 14 - core/modules/language/language.module | 23 -- core/modules/locale/locale.module | 23 -- .../lib/Drupal/menu/Form/MenuDeleteForm.php | 4 +- .../menu/lib/Drupal/menu/Tests/MenuTest.php | 2 +- core/modules/menu/menu.install | 3 +- core/modules/menu/menu.module | 13 - .../lib/Drupal/menu_link/Entity/MenuLink.php | 122 +++--- .../Drupal/menu_link/MenuLinkInterface.php | 48 ++- .../menu_link/MenuLinkStorageController.php | 33 +- .../MenuLinkStorageControllerInterface.php | 28 +- core/modules/menu_link/menu_link.api.php | 11 +- core/modules/menu_link/menu_link.install | 16 +- core/modules/node/node.module | 24 -- core/modules/path/path.module | 15 - core/modules/picture/picture.module | 15 - core/modules/search/search.module | 20 - core/modules/shortcut/shortcut.module | 14 - core/modules/simpletest/simpletest.module | 15 - core/modules/statistics/statistics.module | 15 +- .../lib/Drupal/system/SystemManager.php | 13 +- .../system/Tests/Menu/BreadcrumbTest.php | 5 +- .../Drupal/system/Tests/Menu/LinksTest.php | 7 +- .../system/Tests/Menu/MenuRouterTest.php | 108 +++++- .../Drupal/system/Tests/Menu/TrailTest.php | 136 +++++++ .../system/Tests/Menu/TreeOutputTest.php | 14 +- core/modules/system/system.admin.inc | 3 +- core/modules/system/system.api.php | 66 ---- core/modules/system/system.module | 216 +---------- core/modules/system/system.routing.yml | 3 - .../Controller/MenuTestController.php | 17 - .../tests/modules/menu_test/menu_test.module | 145 +------ .../modules/menu_test/menu_test.routing.yml | 15 +- .../Controller/TaxonomyController.php | 13 - core/modules/taxonomy/taxonomy.module | 14 - core/modules/taxonomy/taxonomy.routing.yml | 1 - .../toolbar/Tests/ToolbarAdminMenuTest.php | 1 - core/modules/toolbar/toolbar.module | 2 +- core/modules/tracker/tracker.module | 12 - core/modules/update/update.module | 15 - .../Drupal/user/Access/LoginStatusCheck.php | 2 +- .../user/Tests/UserAccountLinksTests.php | 7 +- core/modules/user/user.module | 64 +--- .../views/display/DisplayPluginBase.php | 15 - .../Plugin/views/display/PathPluginBase.php | 64 ---- .../views/lib/Drupal/views/ViewExecutable.php | 24 -- core/modules/views/views.module | 17 - core/modules/views_ui/views_ui.module | 25 -- core/themes/seven/seven.theme | 2 +- 74 files changed, 679 insertions(+), 1523 deletions(-) create mode 100644 core/modules/system/lib/Drupal/system/Tests/Menu/TrailTest.php diff --git a/core/includes/bootstrap.inc b/core/includes/bootstrap.inc index 0a7745655747..c4b0cb4aac17 100644 --- a/core/includes/bootstrap.inc +++ b/core/includes/bootstrap.inc @@ -1665,7 +1665,14 @@ function drupal_get_messages($type = NULL, $clear_queue = TRUE) { * The current page's title. */ function drupal_get_title() { - return drupal_set_title() ?: ''; + $title = drupal_set_title(); + + // During a bootstrap, menu.inc is not included and thus we cannot provide a title. + if (!isset($title) && function_exists('menu_get_active_title')) { + $title = String::checkPlain(menu_get_active_title()); + } + + return $title; } /** diff --git a/core/includes/menu.inc b/core/includes/menu.inc index 061f571a836d..ca3ed515d6a0 100644 --- a/core/includes/menu.inc +++ b/core/includes/menu.inc @@ -656,7 +656,7 @@ function _menu_item_localize(&$item, $map, $link_translate = FALSE) { // itself; can't localize. // If we are translating a router item (tabs, page, breadcrumb), then we // can always use the information from the router item. - if (!$link_translate || !isset($item['link_title']) || ($item['title'] == $item['link_title'])) { + if (!$link_translate || ($item['title'] == $item['link_title'])) { // t() is a special case. Since it is used very close to all the time, // we handle it directly instead of using indirect, slower methods. if ($title_callback == 't') { @@ -760,10 +760,7 @@ function _menu_translate(&$router_item, $map, $to_arg = FALSE) { $router_item['access'] = FALSE; return FALSE; } - // Avoid notices until we remove this function. - // @see https://drupal.org/node/2107533 - $tab_root_map = array(); - $tab_parent_map = array(); + // Generate the link path for the page request or local tasks. $link_map = explode('/', $router_item['path']); if (isset($router_item['tab_root'])) { @@ -858,51 +855,95 @@ function menu_tail_load($arg, &$map, $index) { } /** - * Provides menu link unserializing, access control, and argument handling. + * Provides menu link access control, translation, and argument handling. * * This function is similar to _menu_translate(), but it also does * link-specific preparation (such as always calling to_arg() functions). * - * @param array $item - * The passed in item has the following keys: - * - access: (optional) Becomes TRUE if the item is accessible, FALSE - * otherwise. If the key is not set, the access manager is used to - * determine the access. - * - options: (required) Is unserialized and copied to $item['localized_options']. - * - link_title: (required) The title of the menu link. - * - route_name: (required) The route name of the menu link. - * - route_parameters: (required) The unserialized route parameters of the menu link. - * The passed in item is changed by the following keys: - * - href: The actual path to the link. This path is generated from the - * link_path of the menu link entity. - * - title: The title of the link. This title is generated from the - * link_title of the menu link entity. - */ -function _menu_link_translate(&$item) { + * @param $item + * A menu link. + * @param $translate + * (optional) Whether to try to translate a link containing dynamic path + * argument placeholders (%) based on the menu router item of the current + * path. Defaults to FALSE. Internally used for breadcrumbs. + * + * @return + * Returns the map of path arguments with objects loaded as defined in the + * $item['load_functions']. + * $item['access'] becomes TRUE if the item is accessible, FALSE otherwise. + * $item['href'] is generated from link_path, possibly by to_arg functions. + * $item['title'] is generated from link_title, and may be localized. + * $item['options'] is unserialized; it is also changed within the call here + * to $item['localized_options'] by _menu_item_localize(). + */ +function _menu_link_translate(&$item, $translate = FALSE) { if (!is_array($item['options'])) { - $item['options'] = (array) unserialize($item['options']); + $item['options'] = unserialize($item['options']); } - $item['localized_options'] = $item['options']; - $item['title'] = $item['link_title']; - if ($item['external'] || empty($item['route_name'])) { + if ($item['external']) { $item['access'] = 1; + $map = array(); $item['href'] = $item['link_path']; - $item['route_parameters'] = array(); - // Set to NULL so that drupal_pre_render_link() is certain to skip it. - $item['route_name'] = NULL; + $item['title'] = $item['link_title']; + $item['localized_options'] = $item['options']; } else { - $item['href'] = NULL; - if (!is_array($item['route_parameters'])) { - $item['route_parameters'] = (array) unserialize($item['route_parameters']); + // Complete the path of the menu link with elements from the current path, + // if it contains dynamic placeholders (%). + $map = explode('/', $item['link_path']); + if (strpos($item['link_path'], '%') !== FALSE) { + // Invoke registered to_arg callbacks. + if (!empty($item['to_arg_functions'])) { + _menu_link_map_translate($map, $item['to_arg_functions']); + } + // Or try to derive the path argument map from the current router item, + // if this $item's path is within the router item's path. This means + // that if we are on the current path 'foo/%/bar/%/baz', then + // menu_get_item() will have translated the menu router item for the + // current path, and we can take over the argument map for a link like + // 'foo/%/bar'. This inheritance is only valid for breadcrumb links. + // @see _menu_tree_check_access() + elseif ($translate && ($current_router_item = menu_get_item())) { + // If $translate is TRUE, then this link is in the active trail. + // Only translate paths within the current path. + if (strpos($current_router_item['path'], $item['link_path']) === 0) { + $count = count($map); + $map = array_slice($current_router_item['original_map'], 0, $count); + $item['original_map'] = $map; + if (isset($current_router_item['map'])) { + $item['map'] = array_slice($current_router_item['map'], 0, $count); + } + // Reset access to check it (for the first time). + unset($item['access']); + } + } + } + $item['href'] = implode('/', $map); + + // Skip links containing untranslated arguments. + if (strpos($item['href'], '%') !== FALSE) { + $item['access'] = FALSE; + return FALSE; } // menu_tree_check_access() may set this ahead of time for links to nodes. if (!isset($item['access'])) { - $item['access'] = \Drupal::getContainer()->get('access_manager')->checkNamedRoute($item['route_name'], $item['route_parameters'], \Drupal::currentUser()); + if ($route = $item->getRoute()) { + $item['access'] = menu_item_route_access($route, $item['href'], $map); + } + elseif (!empty($item['load_functions']) && !_menu_load_objects($item, $map)) { + // An error occurred loading an object. + $item['access'] = FALSE; + return FALSE; + } + // Apply the access check defined in hook_menu() if there is not route + // defined. + else { + _menu_check_access($item, $map); + } } // For performance, don't localize a link the user can't access. if ($item['access']) { - _menu_item_localize($item, array(), TRUE); + _menu_item_localize($item, $map, TRUE); } } @@ -912,6 +953,8 @@ function _menu_link_translate(&$item) { if (!empty($item['options']['alter'])) { drupal_alter('translated_menu_link', $item, $map); } + + return $map; } /** @@ -923,19 +966,17 @@ function _menu_link_translate(&$item) { * Menu path as returned by $item['href'] of menu_get_item(). * @param array $map * An array of path arguments; for example, array('node', '5'). - * @param \Symfony\Component\HttpFoundation\Request $request - * The current request object, used to find the current route. * * @return bool * TRUE if the user has access or FALSE if the user should be presented * with access denied. * + * @throws \Symfony\Component\Routing\Exception\ResourceNotFoundException + * If the system path in $href does not match the $route. */ -function menu_item_route_access(Route $route, $href, &$map, Request $request = NULL) { - if (!isset($request)) { - $request = RequestHelper::duplicate(\Drupal::request(), '/' . $href); - $request->attributes->set('_system_path', $href); - } +function menu_item_route_access(Route $route, $href, &$map) { + $request = RequestHelper::duplicate(\Drupal::request(), '/' . $href); + $request->attributes->set('_system_path', $href); // Attempt to match this path to provide a fully built request to the // access checker. try { @@ -1087,14 +1128,19 @@ function menu_tree_output($tree) { $class[] = 'active-trail'; $data['link']['localized_options']['attributes']['class'][] = 'active-trail'; } + // Normally, l() compares the href of every link with the current path and + // sets the active class accordingly. But local tasks do not appear in menu + // trees, so if the current path is a local task, and this link is its + // tab root, then we have to set the class manually. + if ($data['link']['href'] == $router_item['tab_root_href'] && $data['link']['href'] != current_path()) { + $data['link']['localized_options']['attributes']['class'][] = 'active'; + } // Allow menu-specific theme overrides. $element['#theme'] = 'menu_link__' . strtr($data['link']['menu_name'], '-', '_'); $element['#attributes']['class'] = $class; $element['#title'] = $data['link']['title']; - // @todo Use route name and parameters to generate the link path, unless - // it is external. - $element['#href'] = $data['link']['link_path']; + $element['#href'] = $data['link']['href']; $element['#localized_options'] = !empty($data['link']['localized_options']) ? $data['link']['localized_options'] : array(); $element['#below'] = $data['below'] ? menu_tree_output($data['below']) : $data['below']; $element['#original_link'] = $data['link']; @@ -1831,7 +1877,7 @@ function menu_navigation_links($menu_name, $level = 0) { if (!$item['link']['hidden']) { $class = ''; $l = $item['link']['localized_options']; - $l['href'] = $item['link']['link_path']; + $l['href'] = $item['link']['href']; $l['title'] = $item['link']['title']; if ($item['link']['in_active_trail']) { $class = ' active-trail'; @@ -2258,10 +2304,10 @@ function menu_set_active_trail($new_trail = NULL) { // Try to retrieve a menu link corresponding to the current path. If more // than one exists, the link from the most preferred menu is returned. $preferred_link = menu_link_get_preferred(); + $current_item = menu_get_item(); // There is a link for the current path. if ($preferred_link) { - _menu_link_translate($preferred_link); // Pass TRUE for $only_active_trail to make menu_tree_page_data() build // a stripped down menu tree containing the active trail only, in case // the given menu has not been built in this request yet. @@ -2270,6 +2316,7 @@ function menu_set_active_trail($new_trail = NULL) { } // There is no link for the current path. else { + $preferred_link = $current_item; $curr = FALSE; } @@ -2287,7 +2334,7 @@ function menu_set_active_trail($new_trail = NULL) { // @see _menu_tree_check_access() // @see _menu_link_translate() if (strpos($link['href'], '%') !== FALSE) { - _menu_link_translate($link); + _menu_link_translate($link, TRUE); } if ($link['access']) { $trail[] = $link; @@ -2342,11 +2389,20 @@ function menu_link_get_preferred($path = NULL, $selected_menu = NULL) { // which are ordered by priority (translated hrefs are preferred over // untranslated paths). Afterwards, the most relevant path is picked from // the menus, ordered by menu preference. + $item = menu_get_item($path); $path_candidates = array(); // 1. The current item href. - // @todo simplify this code and convert to using route names. - // @see https://drupal.org/node/2154949 - $path_candidates[$path] = $path; + $path_candidates[$item['href']] = $item['href']; + // 2. The tab root href of the current item (if any). + if ($item['tab_parent'] && ($tab_root = menu_get_item($item['tab_root_href']))) { + $path_candidates[$tab_root['href']] = $tab_root['href']; + } + // 3. The current item path (with wildcards). + $path_candidates[$item['path']] = $item['path']; + // 4. The tab root path of the current item (if any). + if (!empty($tab_root)) { + $path_candidates[$tab_root['path']] = $tab_root['path']; + } // Retrieve a list of menu names, ordered by preference. $menu_names = menu_get_active_menu_names(); @@ -2412,6 +2468,19 @@ function menu_get_active_trail() { return menu_set_active_trail(); } +/** + * Gets the title of the current page, as determined by the active trail. + */ +function menu_get_active_title() { + $active_trail = menu_get_active_trail(); + + foreach (array_reverse($active_trail) as $item) { + if (!(bool) ($item['type'] & MENU_IS_LOCAL_TASK)) { + return $item['title']; + } + } +} + /** * Clears the cached cached data for a single named menu. */ @@ -2469,7 +2538,7 @@ function menu_router_rebuild() { try { list($menu) = menu_router_build(TRUE); - menu_link_rebuild_defaults(); + _menu_navigation_links_rebuild($menu); // Clear the menu, page and block caches. menu_cache_clear_all(); _menu_clear_page_cache(); @@ -2579,147 +2648,110 @@ function menu_get_router() { } /** - * Saves menu links recursively for menu_links_rebuild_defaults(). - */ -function _menu_link_save_recursive($controller, $machine_name, &$children, &$links) { - $menu_link = $links[$machine_name]; - if ($menu_link->isNew() || !$menu_link->customized) { - if (!isset($menu_link->plid) && !empty($menu_link->parent) && !empty($links[$menu_link->parent])) { - $parent = $links[$menu_link->parent]; - - if (empty($menu_link->menu_name) || $parent->menu_name == $menu_link->menu_name) { - $menu_link->plid = $parent->id(); - $menu_link->menu_name = $parent->menu_name; - } - } - $controller->save($menu_link); - } - if (!empty($children[$machine_name])) { - foreach ($children[$machine_name] as $next_name) { - _menu_link_save_recursive($controller, $next_name, $children, $links); - } - } - // Remove processed link names so we can find stragglers. - unset($children[$machine_name]); -} - -/** - * Gets all default menu link definitions. + * Builds menu links for the items in the menu router. * - * @return array - * An array of default menu links. - */ -function menu_link_get_defaults() { - $module_handler = \Drupal::moduleHandler(); - $all_links = $module_handler->invokeAll('menu_link_defaults'); - // Fill in the machine name from the array key. - foreach ($all_links as $machine_name => &$link) { - $link['machine_name'] = $machine_name; - } - $module_handler->alter('menu_link_defaults', $all_links); - return $all_links; -} - -/** - * Builds menu links for the items returned from hook_menu_link_defaults(). + * @todo This function should be removed/refactored. */ -function menu_link_rebuild_defaults() { - $module_handler = \Drupal::moduleHandler(); - if (!$module_handler->moduleExists('menu_link')) { +function _menu_navigation_links_rebuild($menu) { + if (!\Drupal::moduleHandler()->moduleExists('menu_link')) { // The Menu link module may not be available during install, so rebuild // when possible. return; } - /** @var \Drupal\menu_link\MenuLinkStorageControllerInterface $menu_link_storage */ - $menu_link_storage = \Drupal::entityManager() + $menu_link_controller = \Drupal::entityManager() ->getStorageController('menu_link'); - $links = array(); - $children = array(); - $top_links = array(); - $all_links = menu_link_get_defaults(); - if ($all_links) { - foreach ($all_links as $machine_name => $link) { + + // 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('machine_name', $machine_name) + ->condition('link_path', $router_item['path']) ->condition('module', 'system') - ->execute()->fetchObject(); + ->execute()->fetchAll(); if ($existing_item) { + $existing_item = reset($existing_item); $existing_item->options = unserialize($existing_item->options); $existing_item->route_parameters = unserialize($existing_item->route_parameters); - $link['mlid'] = $existing_item->mlid; - $link['plid'] = $existing_item->plid; - $link['uuid'] = $existing_item->uuid; - $link['customized'] = $existing_item->customized; - $link['updated'] = $existing_item->updated; - $menu_link = $menu_link_storage->createFromDefaultLink($link); - // Convert the existing item to a typed object. - /** @var \Drupal\menu_link\MenuLinkInterface $existing_item */ - $existing_item = $menu_link_storage->create(get_object_vars($existing_item)); - - if (!$existing_item->customized) { - // A change in hook_menu_link_defaults() may move the link to a - // different menu. - if (!empty($link['menu_name']) && ($link['menu_name'] != $existing_item->menu_name)) { - $menu_link->plid = NULL; - $menu_link->menu_name = $link['menu_name']; - } - - $menu_link->original = $existing_item; + $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 { - if (empty($link['route_name']) && empty($link['link_path'])) { - watchdog('error', 'Menu_link %machine_name does neither provide a route_name nor a lin_path, so it got skipped.'); - continue; - } - $menu_link = $menu_link_storage->createFromDefaultLink($link); + $existing_item = NULL; } - if (!empty($link['parent'])) { - $children[$link['parent']][$machine_name] = $machine_name; - $menu_link->parent = $link['parent']; - if (empty($link['menu_name'])) { - // Unset the default menu name so it's populated from the parent. - unset($menu_link->menu_name); - } + + if ($existing_item && $existing_item->customized) { + $parent_candidates[$existing_item->mlid] = $existing_item; } else { - // A top level link - we need them to root our tree. - $top_links[$machine_name] = $machine_name; - $menu_link->plid = 0; + $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]); } - $links[$machine_name] = $menu_link; } } - foreach ($top_links as $machine_name) { - _menu_link_save_recursive($menu_link_storage, $machine_name, $children, $links); - } - // Handle any children we didn't find starting from top-level links. - foreach ($children as $orphan_links) { - foreach ($orphan_links as $machine_name) { - // Force it to the top level. - $links[$machine_name]->plid = 0; - _menu_link_save_recursive($menu_link_storage, $machine_name, $children, $links); + + $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. - if ($all_links) { - $query = \Drupal::entityQuery('menu_link') - ->condition('machine_name', array_keys($all_links), 'NOT IN') - ->condition('external', 0) - ->condition('updated', 0) - ->condition('customized', 0) - ->sort('depth', 'DESC'); - $result = $query->execute(); - } - else { - $result = array(); - } + $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. @@ -2951,7 +2983,7 @@ function _menu_router_build($callbacks, $save = FALSE) { // previous iteration assigned one already), try to find the menu name // of the parent item in the currently stored menu links. if (!isset($parent['menu_name'])) { - $menu_name = db_query("SELECT menu_name FROM {menu_links} WHERE link_path = :link_path AND module = 'system'", array(':link_path' => $parent_path))->fetchField(); + $menu_name = db_query("SELECT menu_name FROM {menu_links} WHERE router_path = :router_path AND module = 'system'", array(':router_path' => $parent_path))->fetchField(); if ($menu_name) { $parent['menu_name'] = $menu_name; } diff --git a/core/includes/path.inc b/core/includes/path.inc index 533dcd9a7b67..975dbe8b6327 100644 --- a/core/includes/path.inc +++ b/core/includes/path.inc @@ -5,7 +5,6 @@ * Functions to handle paths in Drupal. */ -use Drupal\Core\Routing\RequestHelper; use Symfony\Component\HttpFoundation\Request; /** @@ -196,23 +195,9 @@ function drupal_valid_path($path, $dynamic_allowed = FALSE) { global $menu_admin; // We indicate that a menu administrator is running the menu access check. $menu_admin = TRUE; - /** @var $route_provider \Drupal\Core\Routing\RouteProviderInterface */ - $route_provider = \Drupal::service('router.route_provider'); - - if ($dynamic_allowed && preg_match('/\/\%/', $path)) { - $router_path = '/' . str_replace('%', '{}', $path); - } - else { - $router_path = $path; - } - if ($path == '<front>' || url_is_external($path)) { $item = array('access' => TRUE); } - elseif (($collection = $route_provider->getRoutesByPattern('/' . $router_path)) && $collection->count() > 0) { - $routes = $collection->all(); - $route_name = key($routes); - } elseif ($dynamic_allowed && preg_match('/\/\%/', $path)) { // Path is dynamic (ie 'user/%'), so check directly against menu_router table. if ($item = db_query("SELECT * FROM {menu_router} where path = :path", array(':path' => $path))->fetchAssoc()) { @@ -221,22 +206,16 @@ function drupal_valid_path($path, $dynamic_allowed = FALSE) { $item['external'] = FALSE; $item['options'] = ''; _menu_link_translate($item); - $route_name = $item['route_name']; } } else { $item = menu_get_item($path); - $route_name = $item['route_name']; } // Check the new routing system. - if (!empty($route_name)) { + if (!empty($item['route_name'])) { $map = array(); - $route = \Drupal::service('router.route_provider')->getRouteByName($route_name); - $request = RequestHelper::duplicate(\Drupal::request(), '/' . $path); - $request->attributes->set('_system_path', $path); - $request->attributes->set('_menu_admin', TRUE); - - $item['access'] = menu_item_route_access($route, $path, $map, $request); + $route = \Drupal::service('router.route_provider')->getRouteByName($item['route_name']); + $item['access'] = menu_item_route_access($route, $path, $map); } $menu_admin = FALSE; return $item && $item['access']; diff --git a/core/includes/theme.inc b/core/includes/theme.inc index f7af4331c990..d14f7f8874c6 100644 --- a/core/includes/theme.inc +++ b/core/includes/theme.inc @@ -2137,14 +2137,6 @@ function template_preprocess_html(&$variables) { 'name' => String::checkPlain($site_config->get('name')), ); } - // @todo Remove once views is not bypassing the view subscriber anymore. - // @see http://drupal.org/node/2068471 - elseif (drupal_is_front_page()) { - $head_title = array( - 'title' => t('Home'), - 'name' => String::checkPlain($site_config->get('name')), - ); - } else { $head_title = array('name' => String::checkPlain($site_config->get('name'))); if ($site_config->get('slogan')) { diff --git a/core/modules/action/action.module b/core/modules/action/action.module index 6c4b60187694..29237533a766 100644 --- a/core/modules/action/action.module +++ b/core/modules/action/action.module @@ -56,20 +56,6 @@ function action_menu() { return $items; } -/** - * Implements hook_menu_link_defaults(). - */ -function action_menu_link_defaults() { - $links['action.admin.actions'] = array( - 'link_title' => 'Actions', - 'description' => 'Manage the actions defined for your site.', - 'route_name' => 'action.admin', - 'parent' => 'system.admin.config.system', - ); - - return $links; -} - /** * Implements hook_entity_info(). */ diff --git a/core/modules/aggregator/aggregator.module b/core/modules/aggregator/aggregator.module index 39b214e30e18..6fb629f7045d 100644 --- a/core/modules/aggregator/aggregator.module +++ b/core/modules/aggregator/aggregator.module @@ -127,30 +127,6 @@ function aggregator_menu() { return $items; } -/** - * Implements hook_menu_link_defaults(). - */ -function aggregator_menu_link_defaults() { - $links = array(); - $links['aggregator.admin_overview'] = array( - 'link_title' => 'Feed aggregator', - 'description' => "Configure which content your site aggregates from other sites, how often it polls them, and how they're categorized.", - 'route_name' => 'aggregator.admin_overview', - 'weight' => 10, - ); - $links['aggregator'] = array( - 'link_title' => 'Feed aggregator', - 'weight' => 5, - 'route_name' => 'aggregator.page_last', - ); - $links['aggregator.sources'] = array( - 'link_title' => 'Sources', - 'route_name' => 'aggregator.sources', - ); - - return $links; -} - /** * Implements hook_permission(). */ diff --git a/core/modules/ban/ban.module b/core/modules/ban/ban.module index 7d09e7c64ffe..0dce1d97f2e9 100644 --- a/core/modules/ban/ban.module +++ b/core/modules/ban/ban.module @@ -53,18 +53,3 @@ function ban_menu() { ); return $items; } - -/** - * Implements hook_menu_link_defaults(). - */ -function ban_menu_link_defaults() { - $links['ban.admin.config.people'] = array( - 'link_title' => 'IP address bans', - 'description' => 'Manage banned IP addresses.', - 'route_name' => 'ban.admin_page', - 'weight' => 10, - 'parent' => 'user.admin.config.people', - ); - - return $links; -} diff --git a/core/modules/block/block.module b/core/modules/block/block.module index ae8ced672b29..dd3aa6f6b775 100644 --- a/core/modules/block/block.module +++ b/core/modules/block/block.module @@ -116,20 +116,6 @@ function block_menu() { return $items; } -/** - * Implements hook_menu_link_defaults(). - */ -function block_menu_link_defaults() { - $links['block.admin.structure'] = array( - 'link_title' => 'Blocks', - 'parent' => 'system.admin.structure', - 'description' => 'Configure what block content appears in your site\'s sidebars and other regions.', - 'route_name' => 'block.admin_display', - ); - - return $links; -} - /** * Implements hook_page_build(). * diff --git a/core/modules/book/book.module b/core/modules/book/book.module index 9bc7b72da217..0457488e1485 100644 --- a/core/modules/book/book.module +++ b/core/modules/book/book.module @@ -180,26 +180,6 @@ function book_menu() { return $items; } -/** - * Implements hook_menu_link_defaults(). - */ -function book_menu_link_defaults() { - $links['book.admin.outlines'] = array( - 'link_title' => 'Books', - 'description' => "Manage your site's book outlines.", - 'parent' => 'system.admin.structure', - 'route_name' => 'book.admin', - ); - $links['book'] = array( - 'link_title' => 'Books', - 'route_name' => 'book.render', - // @todo what to do about MENU_SUGGESTED_ITEM, maybe specify no menu_name? - 'type' => MENU_SUGGESTED_ITEM, - ); - - return $links; -} - /** * Implements hook_admin_paths(). */ @@ -669,7 +649,7 @@ function template_preprocess_book_navigation(&$variables) { $build = array(); if ($prev = book_prev($book_link)) { - $prev_href = url($prev['link_path']); + $prev_href = url($prev['href']); $build['#attached']['drupal_add_html_head_link'][][] = array( 'rel' => 'prev', 'href' => $prev_href, @@ -689,7 +669,7 @@ function template_preprocess_book_navigation(&$variables) { } if ($next = book_next($book_link)) { - $next_href = url($next['link_path']); + $next_href = url($next['href']); $build['#attached']['drupal_add_html_head_link'][][] = array( 'rel' => 'next', 'href' => $next_href, diff --git a/core/modules/book/lib/Drupal/book/BookManager.php b/core/modules/book/lib/Drupal/book/BookManager.php index 01ae28361123..9b415a8d017f 100644 --- a/core/modules/book/lib/Drupal/book/BookManager.php +++ b/core/modules/book/lib/Drupal/book/BookManager.php @@ -131,7 +131,7 @@ public function getLinkDefaults($nid) { 'menu_name' => '', 'nid' => $nid, 'bid' => 0, - 'link_path' => 'node/%', + 'router_path' => 'node/%', 'plid' => 0, 'mlid' => 0, 'has_children' => 0, @@ -211,7 +211,7 @@ public function addFormElements(array $form, array &$form_state, NodeInterface $ ), '#tree' => TRUE, ); - foreach (array('menu_name', 'mlid', 'nid', 'link_path', 'has_children', 'options', 'module', 'original_bid', 'parent_depth_limit') as $key) { + foreach (array('menu_name', 'mlid', 'nid', 'router_path', 'has_children', 'options', 'module', 'original_bid', 'parent_depth_limit') as $key) { $form['book'][$key] = array( '#type' => 'value', '#value' => $node->book[$key], @@ -660,7 +660,7 @@ public function bookTreeOutput(array $tree) { $element['#theme'] = 'menu_link__' . strtr($data['link']['menu_name'], '-', '_'); $element['#attributes']['class'] = $class; $element['#title'] = $data['link']['title']; - $element['#href'] = $data['link']['link_path']; + $element['#href'] = $data['link']['href']; $element['#localized_options'] = !empty($data['link']['localized_options']) ? $data['link']['localized_options'] : array(); $element['#below'] = $data['below'] ? $this->bookTreeOutput($data['below']) : $data['below']; $element['#original_link'] = $data['link']; diff --git a/core/modules/comment/comment.module b/core/modules/comment/comment.module index f02c70071f4e..c5b8141ff070 100644 --- a/core/modules/comment/comment.module +++ b/core/modules/comment/comment.module @@ -196,20 +196,6 @@ function comment_menu() { return $items; } -/** - * Implements hook_menu_link_defaults(). - */ -function comment_menu_link_defaults() { - $links['comment.admin.content'] = array( - 'link_title' => 'Comments', - 'route_name' => 'comment.admin', - 'parent' => 'node.admin.content', - 'description' => 'List and edit site comments and the comment approval queue.', - ); - - return $links; -} - /** * Implements hook_menu_alter(). */ diff --git a/core/modules/config/config.module b/core/modules/config/config.module index 3cb71e6bbdac..76deec4df1e8 100644 --- a/core/modules/config/config.module +++ b/core/modules/config/config.module @@ -69,17 +69,3 @@ function config_menu() { return $items; } - -/** - * Implements hook_menu_link_defaults(). - */ -function config_menu_link_defaults() { - $links['config.admin.management'] = array( - 'link_title' => 'Configuration management', - 'description' => 'Import, export, or synchronize your site configuration.', - 'route_name' => 'config.sync', - 'parent' => 'system.admin.config.development', - ); - - return $links; -} diff --git a/core/modules/config/tests/config_test/config_test.routing.yml b/core/modules/config/tests/config_test/config_test.routing.yml index b3b216f41eeb..7af61cd8ed1a 100644 --- a/core/modules/config/tests/config_test/config_test.routing.yml +++ b/core/modules/config/tests/config_test/config_test.routing.yml @@ -2,7 +2,6 @@ config_test.list_page: path: '/admin/structure/config_test' defaults: _entity_list: 'config_test' - _title: 'Test configuration' requirements: _access: 'TRUE' diff --git a/core/modules/config_translation/config_translation.module b/core/modules/config_translation/config_translation.module index da894479438c..8e91d303d87a 100644 --- a/core/modules/config_translation/config_translation.module +++ b/core/modules/config_translation/config_translation.module @@ -45,21 +45,6 @@ function config_translation_menu() { return $items; } -/** - * Implements hook_menu_link_defaults(). - */ -function config_translation_menu_link_defaults() { - $links['config_translation.admin.config-translation'] = array( - 'link_title' => 'Configuration translation', - 'parent' => 'system.admin.config.regional', - 'description' => 'Translate the configuration.', - 'route_name' => 'config_translation.mapper_list', - 'weight' => 30, - ); - - return $links; -} - /** * Implements hook_permission(). */ diff --git a/core/modules/contact/contact.module b/core/modules/contact/contact.module index 779b3da0fc89..9b06fd991bc1 100644 --- a/core/modules/contact/contact.module +++ b/core/modules/contact/contact.module @@ -79,26 +79,6 @@ function contact_menu() { return $items; } -/** - * Implements hook_menu_link_defaults(). - */ -function contact_menu_link_defaults() { - $links['contact.admin.categories'] = array( - 'link_title' => 'Contact form categories', - 'parent' => 'system.admin.structure', - 'description' => 'Create a system contact form and set up categories for the form to use.', - 'route_name' => 'contact.category_list', - ); - - $links['contact'] = array( - 'link_title' => 'Contact', - 'route_name' => 'contact.site_page', - 'menu_name' => 'footer', - 'type' => MENU_SUGGESTED_ITEM, - ); - return $links; -} - /** * Implements hook_entity_bundle_info(). */ diff --git a/core/modules/content_translation/content_translation.module b/core/modules/content_translation/content_translation.module index b210091c2e4c..a6f7987ef35f 100644 --- a/core/modules/content_translation/content_translation.module +++ b/core/modules/content_translation/content_translation.module @@ -293,15 +293,6 @@ function content_translation_menu_alter(array &$items) { } } -/** - * Implements hook_menu_link_defaults_alter(). - */ -function content_translation_menu_link_defaults_alter(array &$links) { - // Clarify where translation settings are located. - $items['admin.config.regional.language.content_settings_page']['link_title'] = 'Content language and translation'; - $items['admin.config.regional.language.content_settings_page']['description'] = 'Configure language and translation support for content.'; -} - /** * Convert an entity canonical link to a router path. * diff --git a/core/modules/dblog/dblog.module b/core/modules/dblog/dblog.module index 4060d63981b4..0f269b07728b 100644 --- a/core/modules/dblog/dblog.module +++ b/core/modules/dblog/dblog.module @@ -72,42 +72,6 @@ function dblog_menu() { return $items; } -/** - * Implements hook_menu_link_defaults(). - */ -function dblog_menu_link_defaults() { - $links['dblog.admin.reports.dblog'] = array( - 'link_title' => 'Recent log messages', - 'parent' => 'system.admin.reports', - 'description' => 'View events that have recently been logged.', - 'route_name' => 'dblog.overview', - 'weight' => -1, - ); - $links['dblog.admin.reports.page-not-found'] = array( - 'link_title' => "Top 'page not found' errors", - 'route_name' => 'dblog.page_not_found', - 'parent' => 'system.admin.reports', - 'description' => "View 'page not found' errors (404s).", - ); - $links['dblog.admin.reports.access-denied'] = array( - 'link_title' => "Top 'access denied' errors", - 'route_name' => 'dblog.access_denied', - 'description' => "View 'access denied' errors (403s).", - 'parent' => 'system.admin.reports', - ); - - if (\Drupal::moduleHandler()->moduleExists('search')) { - $links['dblog.admin.reports.search'] = array( - 'link_title' => 'Top search phrases', - 'route_name' => 'dblog.search', - 'description' => 'View most popular search phrases.', - 'parent' => 'system.admin.reports', - ); - } - - return $links; -} - /** * Implements hook_page_build(). */ diff --git a/core/modules/editor/editor.module b/core/modules/editor/editor.module index 3d9ec7c97c47..4d91c300273c 100644 --- a/core/modules/editor/editor.module +++ b/core/modules/editor/editor.module @@ -46,14 +46,6 @@ function editor_menu_alter(&$items) { $items['admin/config/content/formats']['description'] = 'Configure how user-contributed content is filtered and formatted, as well as the text editor user interface (WYSIWYGs or toolbars).'; } -/** - * Implements hook_menu_link_defaults_alter(). - */ -function editor_menu_link_defaults_alter(array &$links) { - $links['admin.config.content.formats']['link_title'] = 'Text formats and editors'; - $links['admin.config.content.formats']['description'] = 'Configure how user-contributed content is filtered and formatted, as well as the text editor user interface (WYSIWYGs or toolbars).'; -} - /** * Implements hook_element_info(). * diff --git a/core/modules/entity/entity.module b/core/modules/entity/entity.module index 5b3f414c3041..73839207e282 100644 --- a/core/modules/entity/entity.module +++ b/core/modules/entity/entity.module @@ -95,36 +95,6 @@ function entity_menu() { return $items; } -/** - * Implements hook_menu_link_defaults(). - */ -function entity_menu_link_defaults() { - $links['entity.admin.structure.display_modes'] = array( - 'link_title' => 'Display modes', - 'description' => 'Configure what displays are available for your content and forms.', - 'route_name' => 'entity.display_mode', - 'parent' => 'system.admin.structure', - ); - - // View modes. - $links['entity.admin.structure.display_modes.view'] = array( - 'link_title' => 'View modes', - 'description' => 'Manage custom view modes.', - 'route_name' => 'entity.view_mode_list', - 'parent' => 'entity.admin.structure.display_modes', - ); - - // Form modes. - $links['entity.admin.structure.display_modes.form'] = array( - 'link_title' => 'Form modes', - 'description' => 'Manage custom form modes.', - 'route_name' => 'entity.form_mode_list', - 'parent' => 'entity.admin.structure.display_modes', - ); - - return $links; -} - /** * Implements hook_entity_bundle_rename(). */ diff --git a/core/modules/entity/lib/Drupal/entity/Controller/EntityDisplayModeController.php b/core/modules/entity/lib/Drupal/entity/Controller/EntityDisplayModeController.php index 4d3ddc396869..608c4cc113c4 100644 --- a/core/modules/entity/lib/Drupal/entity/Controller/EntityDisplayModeController.php +++ b/core/modules/entity/lib/Drupal/entity/Controller/EntityDisplayModeController.php @@ -54,7 +54,7 @@ public function viewModeTypeSelection() { if ($entity_info->isFieldable() && $entity_info->hasViewBuilderClass()) { $entity_types[$entity_type] = array( 'title' => $entity_info->getLabel(), - 'link_path' => 'admin/structure/display-modes/view/add/' . $entity_type, + 'href' => 'admin/structure/display-modes/view/add/' . $entity_type, 'localized_options' => array(), ); } @@ -77,7 +77,7 @@ public function formModeTypeSelection() { if ($entity_info->isFieldable() && $entity_info->hasFormClasses()) { $entity_types[$entity_type] = array( 'title' => $entity_info->getLabel(), - 'link_path' => 'admin/structure/display-modes/form/add/' . $entity_type, + 'href' => 'admin/structure/display-modes/form/add/' . $entity_type, 'localized_options' => array(), ); } diff --git a/core/modules/field_ui/field_ui.module b/core/modules/field_ui/field_ui.module index b8b2e12c893e..9461296b05dd 100644 --- a/core/modules/field_ui/field_ui.module +++ b/core/modules/field_ui/field_ui.module @@ -66,20 +66,6 @@ function field_ui_menu() { return $items; } -/** - * Implements hook_menu_link_defaults(). - */ -function field_ui_menu_link_defaults() { - $links['field_ui.admin.reports.fields'] = array( - 'link_title' => 'Field list', - 'description' => 'Overview of fields on all entity types.', - 'route_name' => 'field_ui.list', - 'parent' => 'system.admin.reports', - ); - - return $links; -} - /** * Implements hook_permission(). */ diff --git a/core/modules/filter/filter.module b/core/modules/filter/filter.module index 7a752d267bbc..ecd4e58fc8e4 100644 --- a/core/modules/filter/filter.module +++ b/core/modules/filter/filter.module @@ -149,26 +149,6 @@ function filter_menu() { return $items; } -/** - * Implements hook_menu_link_defaults(). - */ -function filter_menu_link_defaults() { - $links['filter.tips'] = array( - 'link_title' => 'Compose tips', - 'type' => MENU_SUGGESTED_ITEM, - 'route_name' => 'filter.tips_all', - ); - - $links['filter.admin.formats'] = array( - 'link_title' => 'Text formats', - 'parent' => 'system.admin.config.content', - 'description' => 'Configure how content input by users is filtered, including allowed HTML tags. Also allows enabling of module-provided filters.', - 'route_name' => 'filter.admin_overview', - ); - - return $links; -} - /** * Implements hook_permission(). */ diff --git a/core/modules/forum/forum.module b/core/modules/forum/forum.module index 679b52a338f5..011e37e90a13 100644 --- a/core/modules/forum/forum.module +++ b/core/modules/forum/forum.module @@ -131,24 +131,6 @@ function forum_menu() { return $items; } -/** - * Implements hook_menu_link_defaults(). - */ -function forum_menu_link_defaults() { - $items['forum'] = array( - 'link_title' => 'Forums', - 'route_name' => 'forum.index', - 'menu_name' => 'tools', - ); - $items['forum.admin.overview'] = array( - 'link_title' => 'Forums', - 'parent' => 'system.admin.structure', - 'description' => 'Control forum hierarchy settings.', - 'route_name' => 'forum.overview', - ); - return $items; -} - /** * Implements hook_menu_local_tasks(). */ diff --git a/core/modules/forum/forum.routing.yml b/core/modules/forum/forum.routing.yml index aa21336c2de6..3a0b6b932c85 100644 --- a/core/modules/forum/forum.routing.yml +++ b/core/modules/forum/forum.routing.yml @@ -26,7 +26,6 @@ forum.page: path: '/forum/{taxonomy_term}' defaults: _content: '\Drupal\forum\Controller\ForumController::forumPage' - _title_callback: '\Drupal\taxonomy\Controller\TaxonomyController::termTitle' requirements: _permission: 'access content' diff --git a/core/modules/help/help.module b/core/modules/help/help.module index 6d074056c340..9ccef10dcdaf 100644 --- a/core/modules/help/help.module +++ b/core/modules/help/help.module @@ -24,21 +24,6 @@ function help_menu() { return $items; } -/** - * Implements hook_menu_link_defaults(). - */ -function help_menu_link_defaults() { - $links['help.main'] = array( - 'link_title' => 'Help', - 'description' => 'Reference for usage, configuration, and modules.', - 'route_name' => 'help.main', - 'weight' => 9, - 'parent' => 'system.admin', - ); - - return $links; -} - /** * Implements hook_help(). */ diff --git a/core/modules/image/image.module b/core/modules/image/image.module index 3751b8cf73aa..13aef890f9de 100644 --- a/core/modules/image/image.module +++ b/core/modules/image/image.module @@ -119,20 +119,6 @@ function image_menu() { return $items; } -/** - * Implements hook_menu_link_defaults(). - */ -function image_menu_link_defaults() { - $links['image.admin.media.image-styles'] = array( - 'link_title' => 'Image styles', - 'description' => 'Configure styles that can be used for resizing or adjusting images on display.', - 'parent' => 'system.admin.config.media', - 'route_name' => 'image.style_list', - ); - - return $links; -} - /** * Implements hook_theme(). */ diff --git a/core/modules/language/language.module b/core/modules/language/language.module index 37944095daa2..883ab881742e 100644 --- a/core/modules/language/language.module +++ b/core/modules/language/language.module @@ -90,29 +90,6 @@ function language_menu() { return $items; } -/** - * Implements hook_menu_link_defaults(). - */ -function language_menu_link_defaults() { - // Base language management and configuration. - $links['language.admin.language.admin_overview'] = array( - 'link_title' => 'Languages', - 'description' => 'Configure languages for content and the user interface.', - 'route_name' => 'language.admin_overview', - 'parent' => 'system.admin.config.regional', - ); - // Content language settings. - $links['language.admin.language.content_settings_page'] = array( - 'link_title' => 'Content language', - 'description' => 'Configure language support for content.', - 'route_name' => 'language.content_settings_page', - 'parent' => 'system.admin.config.regional', - 'weight' => 10, - ); - - return $links; -} - /** * Editing or deleting locked languages should not be possible. * diff --git a/core/modules/locale/locale.module b/core/modules/locale/locale.module index 8605e27543be..7a7574abacee 100644 --- a/core/modules/locale/locale.module +++ b/core/modules/locale/locale.module @@ -187,29 +187,6 @@ function locale_menu() { return $items; } -/** - * Implements hook_menu_link_defaults(). - */ -function locale_menu_link_defaults() { - // Translation functionality. - $links['locale.admin.config.regional.translate'] = array( - 'link_title' => 'User interface translation', - 'description' => 'Translate the built-in user interface.', - 'route_name' => 'locale.translate_page', - 'parent' => 'system.admin.config.regional', - 'weight' => 15, - ); - - $links['locale.admin.reports.translations'] = array( - 'link_title' => 'Available translation updates', - 'route_name' => 'locale.translate_status', - 'description' => 'Get a status report about available interface translations for your installed modules and themes.', - 'parent' => 'system.admin.reports', - ); - - return $links; -} - /** * Implements hook_permission(). */ diff --git a/core/modules/menu/lib/Drupal/menu/Form/MenuDeleteForm.php b/core/modules/menu/lib/Drupal/menu/Form/MenuDeleteForm.php index 57e45c1fa23e..35d074d8f426 100644 --- a/core/modules/menu/lib/Drupal/menu/Form/MenuDeleteForm.php +++ b/core/modules/menu/lib/Drupal/menu/Form/MenuDeleteForm.php @@ -105,8 +105,8 @@ public function submit(array $form, array &$form_state) { } // Reset all the menu links defined by the system via hook_menu(). - // @todo Convert this to an EFQ. - $result = $this->connection->query("SELECT mlid FROM {menu_links} WHERE menu_name = :menu AND module = 'system' ORDER BY depth ASC", array(':menu' => $this->entity->id()), array('fetch' => \PDO::FETCH_ASSOC))->fetchCol(); + // @todo Convert this to an EFQ once we figure out 'ORDER BY m.number_parts'. + $result = $this->connection->query("SELECT mlid FROM {menu_links} ml INNER JOIN {menu_router} m ON ml.router_path = m.path WHERE ml.menu_name = :menu AND ml.module = 'system' ORDER BY m.number_parts ASC", array(':menu' => $this->entity->id()), array('fetch' => \PDO::FETCH_ASSOC))->fetchCol(); $menu_links = $this->storageController->loadMultiple($result); foreach ($menu_links as $link) { $link->reset(); diff --git a/core/modules/menu/lib/Drupal/menu/Tests/MenuTest.php b/core/modules/menu/lib/Drupal/menu/Tests/MenuTest.php index c9f821c632e0..a1701857f52e 100644 --- a/core/modules/menu/lib/Drupal/menu/Tests/MenuTest.php +++ b/core/modules/menu/lib/Drupal/menu/Tests/MenuTest.php @@ -752,7 +752,7 @@ private function getStandardMenuLink() { // the front page. $query = \Drupal::entityQuery('menu_link') ->condition('module', 'system') - ->condition('link_path', 'user/logout'); + ->condition('router_path', 'user/logout'); $result = $query->execute(); if (!empty($result)) { $mlid = reset($result); diff --git a/core/modules/menu/menu.install b/core/modules/menu/menu.install index 3415cdcf8d88..b7dc67d65435 100644 --- a/core/modules/menu/menu.install +++ b/core/modules/menu/menu.install @@ -14,13 +14,12 @@ function menu_install() { // Add a link for each custom menu. \Drupal::service('router.builder')->rebuild(); menu_router_rebuild(); - menu_link_rebuild_defaults(); $system_link = entity_load_multiple_by_properties('menu_link', array('link_path' => 'admin/structure/menu', 'module' => 'system')); $system_link = reset($system_link); $base_link = entity_create('menu_link', array( 'menu_name' => $system_link->menu_name, - 'link_path' => 'admin/structure/menu/manage/%', + 'router_path' => 'admin/structure/menu/manage/%', 'module' => 'menu', )); diff --git a/core/modules/menu/menu.module b/core/modules/menu/menu.module index d4a885742b8d..1ffddee0fb74 100644 --- a/core/modules/menu/menu.module +++ b/core/modules/menu/menu.module @@ -92,19 +92,6 @@ function menu_menu() { return $items; } -/** - * Implements hook_menu_link_defaults(). - */ -function menu_menu_link_defaults() { - $links['menu.admin.overview'] = array( - 'link_title' => 'Menus', - 'description' => 'Add new menus to your site, edit existing menus, and rename and reorganize menu links.', - 'route_name' => 'menu.overview_page', - 'parent' => 'system.admin.structure', - ); - return $links; -} - /** * Implements hook_entity_info(). */ diff --git a/core/modules/menu_link/lib/Drupal/menu_link/Entity/MenuLink.php b/core/modules/menu_link/lib/Drupal/menu_link/Entity/MenuLink.php index 36362c8b3a1a..ba0397e82ff5 100644 --- a/core/modules/menu_link/lib/Drupal/menu_link/Entity/MenuLink.php +++ b/core/modules/menu_link/lib/Drupal/menu_link/Entity/MenuLink.php @@ -8,7 +8,9 @@ namespace Drupal\menu_link\Entity; use Drupal\Core\Entity\Entity; +use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Entity\EntityStorageControllerInterface; +use Drupal\Core\Routing\UrlMatcher; use Drupal\menu_link\MenuLinkInterface; use Symfony\Component\Routing\Route; @@ -62,13 +64,6 @@ class MenuLink extends Entity implements \ArrayAccess, MenuLinkInterface { */ public $mlid; - /** - * An optional machine name if defined via hook_menu_link_defaults(). - * - * @var string - */ - public $machine_name; - /** * The menu link UUID. * @@ -90,6 +85,14 @@ class MenuLink extends Entity implements \ArrayAccess, MenuLinkInterface { */ public $link_path; + /** + * For links corresponding to a Drupal path (external = 0), this connects the + * link to a {menu_router}.path for joins. + * + * @var string + */ + public $router_path; + /** * The entity label. * @@ -250,7 +253,7 @@ class MenuLink extends Entity implements \ArrayAccess, MenuLinkInterface { * * @var array */ - public $route_parameters = array(); + public $route_parameters; /** * The route object associated with this menu link, if any. @@ -357,17 +360,13 @@ public function setRouteObject(Route $route) { */ public function reset() { // To reset the link to its original values, we need to retrieve its - // definition from hook_menu_link_defaults(). Otherwise, for example, the - // link's menu would not be reset, because properties like the original - // 'menu_name' are not stored anywhere else. Since resetting a link happens - // rarely and this is a one-time operation, retrieving the full set of - // default menu links does little harm. - $all_links = menu_link_get_defaults(); - $original = $all_links[$this->machine_name]; - $original['machine_name'] = $this->machine_name; - /** @var \Drupal\menu_link\MenuLinkStorageControllerInterface $storage_controller */ - $storage_controller = \Drupal::entityManager()->getStorageController($this->entityType); - $new_link = $storage_controller->createFromDefaultLink($original); + // definition from hook_menu(). Otherwise, for example, the link's menu + // would not be reset, because properties like the original 'menu_name' are + // not stored anywhere else. Since resetting a link happens rarely and this + // is a one-time operation, retrieving the full menu router does no harm. + $menu = menu_get_router(); + $router_item = $menu[$this->router_path]; + $new_link = self::buildFromRouterItem($router_item); // Merge existing menu link's ID and 'has_children' property. foreach (array('mlid', 'has_children') as $key) { $new_link->{$key} = $this->{$key}; @@ -376,6 +375,30 @@ public function reset() { return $new_link; } + /** + * {@inheritdoc} + */ + public static function buildFromRouterItem(array $item) { + // Suggested items are disabled by default. + if ($item['type'] == MENU_SUGGESTED_ITEM) { + $item['hidden'] = 1; + } + // Hide all items that are not visible in the tree. + elseif (!($item['type'] & MENU_VISIBLE_IN_TREE)) { + $item['hidden'] = -1; + } + // Note, we set this as 'system', so that we can be sure to distinguish all + // the menu links generated automatically from entries in {menu_router}. + $item['module'] = 'system'; + $item += array( + 'link_title' => $item['title'], + 'link_path' => $item['path'], + 'options' => empty($item['description']) ? array() : array('attributes' => array('title' => $item['description'])), + ); + return \Drupal::entityManager() + ->getStorageController('menu_link')->create($item); + } + /** * Implements ArrayAccess::offsetExists(). */ @@ -459,11 +482,12 @@ public function preSave(EntityStorageControllerInterface $storage_controller) { parent::preSave($storage_controller); // This is the easiest way to handle the unique internal path '<front>', - // since a path marked as external does not need to match a route. + // since a path marked as external does not need to match a router path. $this->external = (url_is_external($this->link_path) || $this->link_path == '<front>') ? 1 : 0; // Try to find a parent link. If found, assign it and derive its menu. - $parent = $this->findParent($storage_controller); + $parent_candidates = !empty($this->parentCandidates) ? $this->parentCandidates : array(); + $parent = $this->findParent($storage_controller, $parent_candidates); if ($parent) { $this->plid = $parent->id(); $this->menu_name = $parent->menu_name; @@ -502,7 +526,17 @@ public function preSave(EntityStorageControllerInterface $storage_controller) { if (isset($this->original) && ($this->plid != $this->original->plid || $this->menu_name != $this->original->menu_name)) { $storage_controller->moveChildren($this); } - + // Find the router_path. + if (empty($this->router_path) || empty($this->original) || (isset($this->original) && $this->original->link_path != $this->link_path)) { + if ($this->external) { + $this->router_path = ''; + } + else { + // Find the router path which will serve this path. + $this->parts = explode('/', $this->link_path, MENU_MAX_PARTS); + $this->router_path = _menu_find_router_path($this->link_path); + } + } // Find the route_name. if (!isset($this->route_name)) { if ($result = \Drupal::service('router.matcher.final_matcher')->findRouteNameParameters($this->link_path)) { @@ -513,9 +547,6 @@ public function preSave(EntityStorageControllerInterface $storage_controller) { $this->route_parameters = array(); } } - elseif (empty($this->link_path)) { - $this->link_path = \Drupal::urlGenerator()->getPathFromRoute($this->route_name, $this->route_parameters); - } } /** @@ -547,6 +578,9 @@ public static function postLoad(EntityStorageControllerInterface $storage_contro $menu_link->options = unserialize($menu_link->options); $menu_link->route_parameters = unserialize($menu_link->route_parameters); + // Use the weight property from the menu link. + $menu_link->router_item['weight'] = $menu_link->weight; + // By default use the menu_name as type. $menu_link->bundle = $menu_link->menu_name; @@ -572,7 +606,7 @@ public static function postLoad(EntityStorageControllerInterface $storage_contro /** * {@inheritdoc} */ - protected function setParents(MenuLinkInterface $parent) { + public function setParents(EntityInterface $parent) { $i = 1; while ($i < $this->depth) { $p = 'p' . $i++; @@ -590,7 +624,7 @@ protected function setParents(MenuLinkInterface $parent) { /** * {@inheritdoc} */ - protected function findParent(EntityStorageControllerInterface $storage_controller) { + public function findParent(EntityStorageControllerInterface $storage_controller, array $parent_candidates = array()) { $parent = FALSE; // This item is explicitely top-level, skip the rest of the parenting. @@ -613,30 +647,26 @@ protected function findParent(EntityStorageControllerInterface $storage_controll } foreach ($candidates as $mlid) { - $parent = $storage_controller->load($mlid); + if (isset($parent_candidates[$mlid])) { + $parent = $parent_candidates[$mlid]; + } + else { + $parent = $storage_controller->load($mlid); + } if ($parent) { - break; + return $parent; } } + + // If everything else failed, try to derive the parent from the path + // hierarchy. This only makes sense for links derived from menu router + // items (ie. from hook_menu()). + if ($this->module == 'system') { + $parent = $storage_controller->getParentFromHierarchy($this); + } + return $parent; } - /** - * Builds and returns the renderable array for this menu link. - * - * @return array - * A renderable array representing the content of the link. - */ - public function build() { - $build = array( - '#type' => 'link', - '#title' => $this->title, - '#href' => $this->href, - '#route_name' => $this->route_name ? $this->route_name : NULL, - '#route_parameters' => $this->route_parameters, - '#options' => !empty($this->localized_options) ? $this->localized_options : array(), - ); - return $build; - } } diff --git a/core/modules/menu_link/lib/Drupal/menu_link/MenuLinkInterface.php b/core/modules/menu_link/lib/Drupal/menu_link/MenuLinkInterface.php index 9ecb3212987b..d81b1f7f6ccd 100644 --- a/core/modules/menu_link/lib/Drupal/menu_link/MenuLinkInterface.php +++ b/core/modules/menu_link/lib/Drupal/menu_link/MenuLinkInterface.php @@ -2,13 +2,15 @@ /** * @file - * Contains \Drupal\menu_link\MenuLinkInterface. + * Contains \Drupal\menu_link\Entity\MenuLinkInterface. */ namespace Drupal\menu_link; -use Drupal\Core\Entity\EntityInterface; use Symfony\Component\Routing\Route; +use Drupal\Core\Entity\ContentEntityInterface; +use Drupal\Core\Entity\EntityInterface; +use Drupal\Core\Entity\EntityStorageControllerInterface; /** * Provides an interface defining a menu link entity. @@ -37,9 +39,49 @@ public function setRouteObject(Route $route); /** * Resets a system-defined menu link. * - * @return \Drupal\menu_link\MenuLinkInterface + * @return \Drupal\Core\Entity\EntityInterface * A menu link entity. */ public function reset(); + /** + * Builds a menu link entity from a router item. + * + * @param array $item + * A menu router item. + * + * @return \Drupal\menu_link\MenuLinkInterface + * A menu link entity. + */ + public static function buildFromRouterItem(array $item); + + /** + * Sets the p1 through p9 properties for a menu link entity being saved. + * + * @param \Drupal\Core\Entity\EntityInterface $parent + * A menu link entity. + */ + public function setParents(EntityInterface $parent); + + /** + * Finds a possible parent for a given menu link entity. + * + * Because the parent of a given link might not exist anymore in the database, + * we apply a set of heuristics to determine a proper parent: + * + * - use the passed parent link if specified and existing. + * - else, use the first existing link down the previous link hierarchy + * - else, for system menu links (derived from hook_menu()), reparent + * based on the path hierarchy. + * + * @param \Drupal\Core\Entity\EntityStorageControllerInterface $storage_controller + * Storage controller object. + * @param array $parent_candidates + * An array of menu link entities keyed by mlid. + * + * @return \Drupal\Core\Entity\EntityInterface|false + * A menu link entity structure of the possible parent or FALSE if no valid + * parent has been found. + */ + public function findParent(EntityStorageControllerInterface $storage_controller, array $parent_candidates = array()); } diff --git a/core/modules/menu_link/lib/Drupal/menu_link/MenuLinkStorageController.php b/core/modules/menu_link/lib/Drupal/menu_link/MenuLinkStorageController.php index b43d2656b459..0e95f42353bb 100644 --- a/core/modules/menu_link/lib/Drupal/menu_link/MenuLinkStorageController.php +++ b/core/modules/menu_link/lib/Drupal/menu_link/MenuLinkStorageController.php @@ -26,18 +26,18 @@ class MenuLinkStorageController extends DatabaseStorageController implements MenuLinkStorageControllerInterface { /** - * Contains all {menu_router} fields without weight. + * Indicates whether the delete operation should re-parent children items. * - * @var array + * @var bool */ - protected static $routerItemFields; + protected $preventReparenting = FALSE; /** - * Indicates whether the delete operation should re-parent children items. + * Holds an array of router item schema fields. * - * @var bool + * @var array */ - protected $preventReparenting = FALSE; + protected static $routerItemFields = array(); /** * The route provider service. @@ -98,7 +98,7 @@ public static function createInstance(ContainerInterface $container, EntityTypeI protected function buildQuery($ids, $revision_id = FALSE) { $query = parent::buildQuery($ids, $revision_id); // Specify additional fields from the {menu_router} table. - $query->leftJoin('menu_router', 'm', 'base.link_path = m.path'); + $query->leftJoin('menu_router', 'm', 'base.router_path = m.path'); $query->fields('m', static::$routerItemFields); return $query; } @@ -360,23 +360,4 @@ public function getParentFromHierarchy(EntityInterface $entity) { return $parent; } - /** - * {@inheritdoc} - */ - public function createFromDefaultLink(array $item) { - // Suggested items are disabled by default. - $item += array( - 'type' => MENU_NORMAL_ITEM, - 'hidden' => 0, - 'options' => empty($item['description']) ? array() : array('attributes' => array('title' => $item['description'])), - ); - if ($item['type'] == MENU_SUGGESTED_ITEM) { - $item['hidden'] = 1; - } - // Note, we set this as 'system', so that we can be sure to distinguish all - // the menu links generated automatically from hook_menu_link_defaults(). - $item['module'] = 'system'; - return $this->create($item); - } - } diff --git a/core/modules/menu_link/lib/Drupal/menu_link/MenuLinkStorageControllerInterface.php b/core/modules/menu_link/lib/Drupal/menu_link/MenuLinkStorageControllerInterface.php index b219834ebce1..3fb408f4739a 100644 --- a/core/modules/menu_link/lib/Drupal/menu_link/MenuLinkStorageControllerInterface.php +++ b/core/modules/menu_link/lib/Drupal/menu_link/MenuLinkStorageControllerInterface.php @@ -33,6 +33,20 @@ public function setPreventReparenting($value = FALSE); */ public function getPreventReparenting(); + /** + * Loads updated and customized menu links for specific router paths. + * + * Note that this is a low-level method and it doesn't return fully populated + * menu link entities. (e.g. no fields are attached) + * + * @param array $router_paths + * An array of router paths. + * + * @return array + * An array of menu link objects indexed by their ids. + */ + public function loadUpdatedCustomized(array $router_paths); + /** * Loads system menu link as needed by system_get_module_admin_tasks(). * @@ -93,18 +107,4 @@ public function countMenuLinks($menu_name); */ public function getParentFromHierarchy(EntityInterface $entity); - /** - * Builds a menu link entity from a default item. - * - * This function should only be called for link data from - * hook_menu_link_defaults(). - * - * @param array $item - * An item returned from menu_links_get_defaults(). - * - * @return \Drupal\menu_link\MenuLinkInterface - * A menu link entity. - */ - public function createFromDefaultLink(array $item); - } diff --git a/core/modules/menu_link/menu_link.api.php b/core/modules/menu_link/menu_link.api.php index 2541eb54086d..197aee8dfa89 100644 --- a/core/modules/menu_link/menu_link.api.php +++ b/core/modules/menu_link/menu_link.api.php @@ -14,10 +14,11 @@ * Alter a menu link after it has been translated and before it is rendered. * * This hook is invoked from _menu_link_translate() after a menu link has been - * translated; i.e., after the user access to the link's target page has - * been checked. It is only invoked if $menu_link['options']['alter'] has been - * set to a non-empty value (e.g. TRUE). This flag should be set using - * hook_menu_link_presave(). + * translated; i.e., after dynamic path argument placeholders (%) have been + * replaced with actual values, the user access to the link's target page has + * been checked, and the link has been localized. It is only invoked if + * $menu_link['options']['alter'] has been set to a non-empty value (e.g. TRUE). + * This flag should be set using hook_menu_link_presave(). * * Implementations of this hook are able to alter any property of the menu link. * For example, this hook may be used to add a page-specific query string to all @@ -28,6 +29,8 @@ * * @param \Drupal\menu_link\Entity\MenuLink $menu_link * A menu link entity. + * @param array $map + * Associative array containing the menu $map (path parts and/or objects). * * @see hook_menu_link_alter() */ diff --git a/core/modules/menu_link/menu_link.install b/core/modules/menu_link/menu_link.install index c789d34ef822..976653f1523d 100644 --- a/core/modules/menu_link/menu_link.install +++ b/core/modules/menu_link/menu_link.install @@ -31,12 +31,6 @@ function menu_link_schema() { 'length' => 128, 'not null' => FALSE, ), - 'machine_name' => array( - 'description' => 'Unique machine name: Optional human-readable ID for this link.', - 'type' => 'varchar', - 'length' => 255, - 'not null' => FALSE, - ), 'plid' => array( 'description' => 'The parent link ID (plid) is the mlid of the link above in the hierarchy, or zero if the link is at the top level in its menu.', 'type' => 'int', @@ -51,6 +45,13 @@ function menu_link_schema() { 'not null' => TRUE, 'default' => '', ), + 'router_path' => array( + 'description' => 'For links corresponding to a Drupal path (external = 0), this connects the link to a {menu_router}.path for joins.', + 'type' => 'varchar', + 'length' => 255, + 'not null' => TRUE, + 'default' => '', + ), 'langcode' => array( 'description' => 'The {language}.langcode of this link.', 'type' => 'varchar', @@ -59,7 +60,7 @@ function menu_link_schema() { 'default' => '', ), 'link_title' => array( - 'description' => 'The text displayed for the link.', + 'description' => 'The text displayed for the link, which may be modified by a title callback stored in {menu_router}.', 'type' => 'varchar', 'length' => 255, 'not null' => TRUE, @@ -213,6 +214,7 @@ function menu_link_schema() { 'path_menu' => array(array('link_path', 128), 'menu_name'), 'menu_plid_expand_child' => array('menu_name', 'plid', 'expanded', 'has_children'), 'menu_parents' => array('menu_name', 'p1', 'p2', 'p3', 'p4', 'p5', 'p6', 'p7', 'p8', 'p9'), + 'router_path' => array(array('router_path', 128)), ), 'primary key' => array('mlid'), ); diff --git a/core/modules/node/node.module b/core/modules/node/node.module index ec0cd7cb7171..b457cb9b4914 100644 --- a/core/modules/node/node.module +++ b/core/modules/node/node.module @@ -973,30 +973,6 @@ function node_menu() { return $items; } -/** - * Implements hook_menu_link_defaults(). - */ -function node_menu_link_defaults() { - $links['node.admin.content'] = array( - 'link_title' => 'Content', - 'route_name' => 'node.content_overview', - 'parent' => 'system.admin', - 'description' => 'Find and manage content.', - ); - - $links['node.admin.structure.types'] = array( - 'link_title' => 'Content types', - 'parent' => 'system.admin.structure', - 'description' => 'Manage content types, including default status, front page promotion, comment settings, etc.', - 'route_name' => 'node.overview_types', - ); - $links['node.add'] = array( - 'link_title' => 'Add content', - 'route_name' => 'node.add_page', - ); - return $links; -} - /** * Implements hook_menu_local_tasks(). */ diff --git a/core/modules/path/path.module b/core/modules/path/path.module index 80eeace53cdc..8e96610ff371 100644 --- a/core/modules/path/path.module +++ b/core/modules/path/path.module @@ -75,21 +75,6 @@ function path_menu() { return $items; } -/** - * Implements hook_menu_link_defaults(). - */ -function path_menu_link_defaults() { - $links['path.admin.overview'] = array( - 'link_title' => 'URL aliases', - 'description' => "Change your site's URL paths by aliasing them.", - 'route_name' => 'path.admin_overview', - 'parent' => 'system.admin.config.search', - 'weight' => -5, - ); - - return $links; -} - /** * Implements hook_form_BASE_FORM_ID_alter() for node_form(). * diff --git a/core/modules/picture/picture.module b/core/modules/picture/picture.module index 9e5e4a36d257..d494f09c714c 100644 --- a/core/modules/picture/picture.module +++ b/core/modules/picture/picture.module @@ -71,21 +71,6 @@ function picture_menu() { return $items; } -/** - * Implements hook_menu_link_defaults(). - */ -function picture_menu_link_defaults() { - $links['picture.admin.config.picturemapping'] = array( - 'link_title' => 'Picture Mappings', - 'description' => 'Manage picture mappings', - 'weight' => 10, - 'route_name' => 'picture.mapping_page', - 'parent' => 'system.admin.config.media', - ); - - return $links; -} - /** * Implements hook_library_info(). */ diff --git a/core/modules/search/search.module b/core/modules/search/search.module index 11a5e00e1700..25f982575210 100644 --- a/core/modules/search/search.module +++ b/core/modules/search/search.module @@ -167,26 +167,6 @@ function search_menu() { return $items; } -/** - * Implements hook_menu_link_defaults(). - */ -function search_menu_link_defaults() { - $links['search'] = array( - 'link_title' => 'Search', - 'route_name' => 'search.view', - 'type' => MENU_SUGGESTED_ITEM, - ); - $links['search.admin.settings'] = array( - 'link_title' => 'Search settings', - 'parent' => 'system.admin.config.search', - 'description' => 'Configure relevance settings for search and other indexing options.', - 'route_name' => 'search.settings', - 'weight' => -10, - ); - - return $links; -} - /** * Clears either a part of, or the entire search index. * diff --git a/core/modules/shortcut/shortcut.module b/core/modules/shortcut/shortcut.module index a988cf47a57d..8c7c8695e99e 100644 --- a/core/modules/shortcut/shortcut.module +++ b/core/modules/shortcut/shortcut.module @@ -86,20 +86,6 @@ function shortcut_menu() { return $items; } -/** - * Implements hook_menu_link_defaults(). - */ -function shortcut_menu_link_defaults() { - $links['shortcut.admin.config.user-interface.shortcut'] = array( - 'link_title' => 'Shortcuts', - 'description' => 'Add and modify shortcut sets.', - 'route_name' => 'shortcut.set_admin', - 'parent' => 'system.admin.config.user-interface', - ); - - return $links; -} - /** * Implements hook_admin_paths(). */ diff --git a/core/modules/simpletest/simpletest.module b/core/modules/simpletest/simpletest.module index 6efecef52513..bd5067626011 100644 --- a/core/modules/simpletest/simpletest.module +++ b/core/modules/simpletest/simpletest.module @@ -46,21 +46,6 @@ function simpletest_menu() { return $items; } -/** - * Implements hook_menu_link_defaults(). - */ -function simpletest_menu_link_defaults() { - $links['simpletest.admin.config.development.testing'] = array( - 'link_title' => 'Testing', - 'description' => 'Run tests against Drupal core and your modules. These tests help assure that your site code is working as designed.', - 'route_name' => 'simpletest.test_form', - 'parent' => 'system.admin.config.development', - 'weight' => -5, - ); - - return $links; -} - /** * Implements hook_permission(). */ diff --git a/core/modules/statistics/statistics.module b/core/modules/statistics/statistics.module index a8a0105eda25..a5d4c479b233 100644 --- a/core/modules/statistics/statistics.module +++ b/core/modules/statistics/statistics.module @@ -86,25 +86,12 @@ function statistics_menu() { 'title' => 'Statistics', 'description' => 'Control details about what and how your site logs content statistics.', 'route_name' => 'statistics.settings', + 'access arguments' => array('administer statistics'), 'weight' => -15, ); return $items; } -/** - * Implements hook_menu_link_defaults(). - */ -function statistics_menu_link_defaults() { - $links['statistics.admin.config.system.statistics'] = array( - 'link_title' => 'Statistics', - 'description' => 'Control details about what and how your site logs content statistics.', - 'route_name' => 'statistics.settings', - 'parent' => 'system.admin.config.system', - 'weight' => -15, - ); - return $links; -} - /** * Implements hook_cron(). */ diff --git a/core/modules/system/lib/Drupal/system/SystemManager.php b/core/modules/system/lib/Drupal/system/SystemManager.php index fd8f77e0e367..07e8c0a5dabe 100644 --- a/core/modules/system/lib/Drupal/system/SystemManager.php +++ b/core/modules/system/lib/Drupal/system/SystemManager.php @@ -194,15 +194,10 @@ public function getAdminBlock($item) { } if (!isset($item['mlid'])) { - $menu_links = $this->menuLinkStorage->loadByProperties(array('link_path' => $item['path'], 'module' => 'system')); - if ($menu_links) { - $menu_link = reset($menu_links); - $item['mlid'] = $menu_link->id(); - $item['menu_name'] = $menu_link->menu_name; - } - else { - return array(); - } + $menu_links = $this->menuLinkStorage->loadByProperties(array('router_path' => $item['path'], 'module' => 'system')); + $menu_link = reset($menu_links); + $item['mlid'] = $menu_link->id(); + $item['menu_name'] = $menu_link->menu_name; } if (isset($this->menuItems[$item['mlid']])) { diff --git a/core/modules/system/lib/Drupal/system/Tests/Menu/BreadcrumbTest.php b/core/modules/system/lib/Drupal/system/Tests/Menu/BreadcrumbTest.php index 6d7699a1aa29..9ab9103dcab5 100644 --- a/core/modules/system/lib/Drupal/system/Tests/Menu/BreadcrumbTest.php +++ b/core/modules/system/lib/Drupal/system/Tests/Menu/BreadcrumbTest.php @@ -338,7 +338,10 @@ function testBreadCrumbs() { $trail += array( 'user/' . $this->web_user->id() => $this->web_user->getUsername(), ); - $this->assertBreadcrumb('user/' . $this->web_user->id() . '/edit', $trail, $this->web_user->getUsername()); + $tree = array( + 'user' => t('My account'), + ); + $this->assertBreadcrumb('user/' . $this->web_user->id() . '/edit', $trail, $this->web_user->getUsername(), $tree); // Create an only slightly privileged user being able to access site reports // but not administration pages. diff --git a/core/modules/system/lib/Drupal/system/Tests/Menu/LinksTest.php b/core/modules/system/lib/Drupal/system/Tests/Menu/LinksTest.php index cc8c4e08bb54..bcf7c9629bd4 100644 --- a/core/modules/system/lib/Drupal/system/Tests/Menu/LinksTest.php +++ b/core/modules/system/lib/Drupal/system/Tests/Menu/LinksTest.php @@ -183,7 +183,7 @@ function testMenuLinkReparenting($module = 'menu_test') { } /** - * Tests automatic reparenting of menu links derived from hook_menu_link_defaults. + * Test automatic reparenting of menu links derived from menu routers. */ function testMenuLinkRouterReparenting() { // Run all the standard parenting tests on menu links derived from @@ -224,7 +224,8 @@ function testMenuLinkRouterReparenting() { $this->assertMenuLinkParents($links, $expected_hierarchy); // Now delete 'child-2' directly from the database, simulating a database - // crash. 'child-1-2' will get reparented to the top. + // crash. 'child-1-2' will get reparented under 'child-1' based on its + // path. // Don't do that at home. db_delete('menu_links') ->condition('mlid', $links['child-2']['mlid']) @@ -232,7 +233,7 @@ function testMenuLinkRouterReparenting() { $expected_hierarchy = array( 'child-1' => FALSE, 'child-1-1' => 'child-1', - 'child-1-2' => FALSE, + 'child-1-2' => 'child-1', ); $this->assertMenuLinkParents($links, $expected_hierarchy); } diff --git a/core/modules/system/lib/Drupal/system/Tests/Menu/MenuRouterTest.php b/core/modules/system/lib/Drupal/system/Tests/Menu/MenuRouterTest.php index 3c1290381de6..ccc327dcba38 100644 --- a/core/modules/system/lib/Drupal/system/Tests/Menu/MenuRouterTest.php +++ b/core/modules/system/lib/Drupal/system/Tests/Menu/MenuRouterTest.php @@ -62,8 +62,10 @@ function setUp() { */ public function testMenuIntegration() { $this->doTestTitleMenuCallback(); + $this->doTestMenuSetItem(); $this->doTestMenuOptionalPlaceholders(); $this->doTestMenuOnRoute(); + $this->doTestMenuHidden(); $this->doTestMenuGetItemNoAncestors(); $this->doTestMenuName(); $this->doTestMenuItemTitlesCases(); @@ -176,7 +178,7 @@ protected function doTestMenuName() { $admin_user = $this->drupalCreateUser(array('administer site configuration')); $this->drupalLogin($admin_user); - $menu_links = entity_load_multiple_by_properties('menu_link', array('link_path' => 'menu_name_test')); + $menu_links = entity_load_multiple_by_properties('menu_link', array('router_path' => 'menu_name_test')); $menu_link = reset($menu_links); $this->assertEqual($menu_link->menu_name, 'original', 'Menu name is "original".'); @@ -186,7 +188,7 @@ protected function doTestMenuName() { \Drupal::service('router.builder')->rebuild(); menu_router_rebuild(); - $menu_links = entity_load_multiple_by_properties('menu_link', array('link_path' => 'menu_name_test')); + $menu_links = entity_load_multiple_by_properties('menu_link', array('router_path' => 'menu_name_test')); $menu_link = reset($menu_links); $this->assertEqual($menu_link->menu_name, 'changed', 'Menu name was successfully changed after rebuild.'); } @@ -206,6 +208,87 @@ protected function doTestMenuHierarchy() { $this->assertEqual($unattached_child_link['plid'], $parent_link['mlid'], 'The parent of a non-directly attached child is correct.'); } + /** + * Tests menu link depth and parents of local tasks and menu callbacks. + */ + protected function doTestMenuHidden() { + // Verify links for one dynamic argument. + $query = \Drupal::entityQuery('menu_link') + ->condition('router_path', 'menu-test/hidden/menu', 'STARTS_WITH') + ->sort('router_path'); + $result = $query->execute(); + $menu_links = menu_link_load_multiple($result); + + $links = array(); + foreach ($menu_links as $menu_link) { + $links[$menu_link->router_path] = $menu_link; + } + + $parent = $links['menu-test/hidden/menu']; + $depth = $parent['depth'] + 1; + $plid = $parent['mlid']; + + $link = $links['menu-test/hidden/menu/list']; + $this->assertEqual($link['depth'], $depth, format_string('%path depth @link_depth is equal to @depth.', array('%path' => $link['router_path'], '@link_depth' => $link['depth'], '@depth' => $depth))); + $this->assertEqual($link['plid'], $plid, format_string('%path plid @link_plid is equal to @plid.', array('%path' => $link['router_path'], '@link_plid' => $link['plid'], '@plid' => $plid))); + + $link = $links['menu-test/hidden/menu/settings']; + $this->assertEqual($link['depth'], $depth, format_string('%path depth @link_depth is equal to @depth.', array('%path' => $link['router_path'], '@link_depth' => $link['depth'], '@depth' => $depth))); + $this->assertEqual($link['plid'], $plid, format_string('%path plid @link_plid is equal to @plid.', array('%path' => $link['router_path'], '@link_plid' => $link['plid'], '@plid' => $plid))); + + $link = $links['menu-test/hidden/menu/manage/%']; + $this->assertEqual($link['depth'], $depth, format_string('%path depth @link_depth is equal to @depth.', array('%path' => $link['router_path'], '@link_depth' => $link['depth'], '@depth' => $depth))); + $this->assertEqual($link['plid'], $plid, format_string('%path plid @link_plid is equal to @plid.', array('%path' => $link['router_path'], '@link_plid' => $link['plid'], '@plid' => $plid))); + + $parent = $links['menu-test/hidden/menu/manage/%']; + $depth = $parent['depth'] + 1; + $plid = $parent['mlid']; + + $link = $links['menu-test/hidden/menu/manage/%/list']; + $this->assertEqual($link['depth'], $depth, format_string('%path depth @link_depth is equal to @depth.', array('%path' => $link['router_path'], '@link_depth' => $link['depth'], '@depth' => $depth))); + $this->assertEqual($link['plid'], $plid, format_string('%path plid @link_plid is equal to @plid.', array('%path' => $link['router_path'], '@link_plid' => $link['plid'], '@plid' => $plid))); + + $link = $links['menu-test/hidden/menu/manage/%/edit']; + $this->assertEqual($link['depth'], $depth, format_string('%path depth @link_depth is equal to @depth.', array('%path' => $link['router_path'], '@link_depth' => $link['depth'], '@depth' => $depth))); + $this->assertEqual($link['plid'], $plid, format_string('%path plid @link_plid is equal to @plid.', array('%path' => $link['router_path'], '@link_plid' => $link['plid'], '@plid' => $plid))); + + $link = $links['menu-test/hidden/menu/manage/%/delete']; + $this->assertEqual($link['depth'], $depth, format_string('%path depth @link_depth is equal to @depth.', array('%path' => $link['router_path'], '@link_depth' => $link['depth'], '@depth' => $depth))); + $this->assertEqual($link['plid'], $plid, format_string('%path plid @link_plid is equal to @plid.', array('%path' => $link['router_path'], '@link_plid' => $link['plid'], '@plid' => $plid))); + + // Verify links for two dynamic arguments. + $query = \Drupal::entityQuery('menu_link') + ->condition('router_path', 'menu-test/hidden/block', 'STARTS_WITH') + ->sort('router_path'); + $result = $query->execute(); + $menu_links = menu_link_load_multiple($result); + + $links = array(); + foreach ($menu_links as $menu_link) { + $links[$menu_link->router_path] = $menu_link; + } + + $parent = $links['menu-test/hidden/block']; + $depth = $parent['depth'] + 1; + $plid = $parent['mlid']; + + $link = $links['menu-test/hidden/block/list']; + $this->assertEqual($link['depth'], $depth, format_string('%path depth @link_depth is equal to @depth.', array('%path' => $link['router_path'], '@link_depth' => $link['depth'], '@depth' => $depth))); + $this->assertEqual($link['plid'], $plid, format_string('%path plid @link_plid is equal to @plid.', array('%path' => $link['router_path'], '@link_plid' => $link['plid'], '@plid' => $plid))); + + $link = $links['menu-test/hidden/block/manage/%/%']; + $this->assertEqual($link['depth'], $depth, format_string('%path depth @link_depth is equal to @depth.', array('%path' => $link['router_path'], '@link_depth' => $link['depth'], '@depth' => $depth))); + $this->assertEqual($link['plid'], $plid, format_string('%path plid @link_plid is equal to @plid.', array('%path' => $link['router_path'], '@link_plid' => $link['plid'], '@plid' => $plid))); + + $parent = $links['menu-test/hidden/block/manage/%/%']; + $depth = $parent['depth'] + 1; + $plid = $parent['mlid']; + + $link = $links['menu-test/hidden/block/manage/%/%/delete']; + $this->assertEqual($link['depth'], $depth, format_string('%path depth @link_depth is equal to @depth.', array('%path' => $link['router_path'], '@link_depth' => $link['depth'], '@depth' => $depth))); + $this->assertEqual($link['plid'], $plid, format_string('%path plid @link_plid is equal to @plid.', array('%path' => $link['router_path'], '@link_plid' => $link['plid'], '@plid' => $plid))); + } + /** * Test menu_get_item() with empty ancestors. */ @@ -214,6 +297,23 @@ protected function doTestMenuGetItemNoAncestors() { $this->drupalGet(''); } + /** + * Test menu_set_item(). + */ + protected function doTestMenuSetItem() { + $item = menu_get_item('test-page'); + + $this->assertEqual($item['path'], 'test-page', "Path from menu_get_item('test-page') is equal to 'test-page'", 'menu'); + + // Modify the path for the item then save it. + $item['path'] = 'test-page-test'; + $item['href'] = 'test-page-test'; + + menu_set_item('test-page', $item); + $compare_item = menu_get_item('test-page'); + $this->assertEqual($compare_item, $item, 'Modified menu item is equal to newly retrieved menu item.', 'menu'); + } + /** * Test menu maintenance hooks. */ @@ -264,8 +364,9 @@ protected function doTestMenuItemTitlesCases() { // Build array with string overrides. $test_data = array( 1 => array('Example title - Case 1' => 'Alternative example title - Case 1'), - 2 => array('Example title' => 'Alternative example title'), + 2 => array('Example @sub1 - Case @op2' => 'Alternative example @sub1 - Case @op2'), 3 => array('Example title' => 'Alternative example title'), + 4 => array('Example title' => 'Alternative example title'), ); foreach ($test_data as $case_no => $override) { @@ -322,6 +423,7 @@ protected function doTestMenuOnRoute() { $this->assertLinkByHref('menu-title-test/case1'); $this->assertLinkByHref('menu-title-test/case2'); $this->assertLinkByHref('menu-title-test/case3'); + $this->assertLinkByHref('menu-title-test/case4'); } /** diff --git a/core/modules/system/lib/Drupal/system/Tests/Menu/TrailTest.php b/core/modules/system/lib/Drupal/system/Tests/Menu/TrailTest.php new file mode 100644 index 000000000000..409f3aae38ec --- /dev/null +++ b/core/modules/system/lib/Drupal/system/Tests/Menu/TrailTest.php @@ -0,0 +1,136 @@ +<?php + +/** + * @file + * Definition of Drupal\system\Tests\Menu\TrailTest. + */ + +namespace Drupal\system\Tests\Menu; + +/** + * Tests active menu trails. + */ +class TrailTest extends MenuTestBase { + + /** + * Modules to enable. + * + * @var array + */ + public static $modules = array('block', 'menu_test'); + + public static function getInfo() { + return array( + 'name' => 'Active trail', + 'description' => 'Tests active menu trails and alteration functionality.', + 'group' => 'Menu', + ); + } + + function setUp() { + parent::setUp(); + + $this->admin_user = $this->drupalCreateUser(array('administer site configuration', 'access administration pages', 'administer blocks')); + $this->drupalLogin($this->admin_user); + + // This test puts menu links in the Tools and Administration menus and then + // tests for their presence on the page. + $this->drupalPlaceBlock('system_menu_block:tools'); + $this->drupalPlaceBlock('system_menu_block:admin'); + } + + /** + * Tests that the active trail works correctly on custom 403 and 404 pages. + */ + function testCustom403And404Pages() { + // Set the custom 403 and 404 pages we will use. + \Drupal::config('system.site') + ->set('page.403', 'menu-test/custom-403-page') + ->set('page.404', 'menu-test/custom-404-page') + ->save(); + + // Define the paths we'll visit to trigger 403 and 404 responses during + // this test, and the expected active trail for each case. + $paths = array( + 403 => 'admin/config', + 404 => $this->randomName(), + ); + // For the 403 page, the initial trail during the Drupal bootstrap should + // include the page that the user is trying to visit, while the final trail + // should reflect the custom 403 page that the user was redirected to. + $expected_trail[403]['initial'] = array( + '<front>' => 'Home', + 'admin/config' => 'Configuration', + ); + $expected_trail[403]['final'] = array( + '<front>' => 'Home', + 'menu-test' => 'Menu test root', + 'menu-test/custom-403-page' => 'Custom 403 page', + ); + // For the 404 page, the initial trail during the Drupal bootstrap should + // only contain the link back to "Home" (since the page the user is trying + // to visit doesn't have any menu items associated with it), while the + // final trail should reflect the custom 404 page that the user was + // redirected to. + $expected_trail[404]['initial'] = array( + '<front>' => 'Home', + ); + $expected_trail[404]['final'] = array( + '<front>' => 'Home', + 'menu-test' => 'Menu test root', + 'menu-test/custom-404-page' => 'Custom 404 page', + ); + + // Visit each path as an anonymous user so that we will actually get a 403 + // on admin/config. + $this->drupalLogout(); + foreach (array(403, 404) as $status_code) { + // Before visiting the page, trigger the code in the menu_test module + // that will record the active trail (so we can check it in this test). + \Drupal::state()->set('menu_test.record_active_trail', TRUE); + $this->drupalGet($paths[$status_code]); + $this->assertResponse($status_code); + + // Check that the initial trail (during the Drupal bootstrap) matches + // what we expect. + $initial_trail = \Drupal::state()->get('menu_test.active_trail_initial') ?: array(); + $this->assertEqual(count($initial_trail), count($expected_trail[$status_code]['initial']), format_string('The initial active trail for a @status_code page contains the expected number of items (expected: @expected, found: @found).', array( + '@status_code' => $status_code, + '@expected' => count($expected_trail[$status_code]['initial']), + '@found' => count($initial_trail), + ))); + foreach (array_keys($expected_trail[$status_code]['initial']) as $index => $path) { + $this->assertEqual($initial_trail[$index]['href'], $path, format_string('Element number @number of the initial active trail for a @status_code page contains the correct path (expected: @expected, found: @found)', array( + '@number' => $index + 1, + '@status_code' => $status_code, + '@expected' => $path, + '@found' => $initial_trail[$index]['href'], + ))); + } + + // Check that the final trail (after the user has been redirected to the + // custom 403/404 page) matches what we expect. + $final_trail = \Drupal::state()->get('menu_test.active_trail_final') ?: array(); + $this->assertEqual(count($final_trail), count($expected_trail[$status_code]['final']), format_string('The final active trail for a @status_code page contains the expected number of items (expected: @expected, found: @found).', array( + '@status_code' => $status_code, + '@expected' => count($expected_trail[$status_code]['final']), + '@found' => count($final_trail), + ))); + foreach (array_keys($expected_trail[$status_code]['final']) as $index => $path) { + $this->assertEqual($final_trail[$index]['href'], $path, format_string('Element number @number of the final active trail for a @status_code page contains the correct path (expected: @expected, found: @found)', array( + '@number' => $index + 1, + '@status_code' => $status_code, + '@expected' => $path, + '@found' => $final_trail[$index]['href'], + ))); + } + + // Check that the breadcrumb displayed on the final custom 403/404 page + // matches what we expect. (The last item of the active trail represents + // the current page, which is not supposed to appear in the breadcrumb, + // so we need to remove it from the array before checking.) + array_pop($expected_trail[$status_code]['final']); + $this->assertBreadcrumb(NULL, $expected_trail[$status_code]['final']); + } + } +} diff --git a/core/modules/system/lib/Drupal/system/Tests/Menu/TreeOutputTest.php b/core/modules/system/lib/Drupal/system/Tests/Menu/TreeOutputTest.php index d6927181657c..78a00aa77a03 100644 --- a/core/modules/system/lib/Drupal/system/Tests/Menu/TreeOutputTest.php +++ b/core/modules/system/lib/Drupal/system/Tests/Menu/TreeOutputTest.php @@ -43,21 +43,21 @@ function testMenuTreeData() { // @todo Prettify this tree buildup code, it's very hard to read. $this->tree_data = array( '1'=> array( - 'link' => $storage_controller->create(array('menu_name' => 'main-menu', 'mlid' => 1, 'hidden' => 0, 'has_children' => 1, 'title' => 'Item 1', 'in_active_trail' => 1, 'access' => 1, 'link_path' => 'a', 'localized_options' => array('attributes' => array('title' =>'')))), + 'link' => $storage_controller->create(array('menu_name' => 'main-menu', 'mlid' => 1, 'hidden' => 0, 'has_children' => 1, 'title' => 'Item 1', 'in_active_trail' => 1, 'access' => 1, 'href' => 'a', 'localized_options' => array('attributes' => array('title' =>'')))), 'below' => array( - '2' => array('link' => $storage_controller->create(array('menu_name' => 'main-menu', 'mlid' => 2, 'hidden' => 0, 'has_children' => 1, 'title' => 'Item 2', 'in_active_trail' => 1, 'access' => 1, 'link_path' => 'a/b', 'localized_options' => array('attributes' => array('title' =>'')))), + '2' => array('link' => $storage_controller->create(array('menu_name' => 'main-menu', 'mlid' => 2, 'hidden' => 0, 'has_children' => 1, 'title' => 'Item 2', 'in_active_trail' => 1, 'access' => 1, 'href' => 'a/b', 'localized_options' => array('attributes' => array('title' =>'')))), 'below' => array( - '3' => array('link' => $storage_controller->create(array('menu_name' => 'main-menu', 'mlid' => 3, 'hidden' => 0, 'has_children' => 0, 'title' => 'Item 3', 'in_active_trail' => 0, 'access' => 1, 'link_path' => 'a/b/c', 'localized_options' => array('attributes' => array('title' =>'')))), + '3' => array('link' => $storage_controller->create(array('menu_name' => 'main-menu', 'mlid' => 3, 'hidden' => 0, 'has_children' => 0, 'title' => 'Item 3', 'in_active_trail' => 0, 'access' => 1, 'href' => 'a/b/c', 'localized_options' => array('attributes' => array('title' =>'')))), 'below' => array() ), - '4' => array('link' => $storage_controller->create(array('menu_name' => 'main-menu', 'mlid' => 4, 'hidden' => 0, 'has_children' => 0, 'title' => 'Item 4', 'in_active_trail' => 0, 'access' => 1, 'link_path' => 'a/b/d', 'localized_options' => array('attributes' => array('title' =>'')))), + '4' => array('link' => $storage_controller->create(array('menu_name' => 'main-menu', 'mlid' => 4, 'hidden' => 0, 'has_children' => 0, 'title' => 'Item 4', 'in_active_trail' => 0, 'access' => 1, 'href' => 'a/b/d', 'localized_options' => array('attributes' => array('title' =>'')))), 'below' => array() ) ) ) ) ), - '5' => array('link' => $storage_controller->create(array('menu_name' => 'main-menu', 'mlid' => 5, 'hidden' => 1, 'has_children' => 0, 'title' => 'Item 5', 'in_active_trail' => 0, 'access' => 1, 'link_path' => 'e', 'localized_options' => array('attributes' => array('title' =>'')))), 'below' => array()), - '6' => array('link' => $storage_controller->create(array('menu_name' => 'main-menu', 'mlid' => 6, 'hidden' => 0, 'has_children' => 0, 'title' => 'Item 6', 'in_active_trail' => 0, 'access' => 0, 'link_path' => 'f', 'localized_options' => array('attributes' => array('title' =>'')))), 'below' => array()), - '7' => array('link' => $storage_controller->create(array('menu_name' => 'main-menu', 'mlid' => 7, 'hidden' => 0, 'has_children' => 0, 'title' => 'Item 7', 'in_active_trail' => 0, 'access' => 1, 'link_path' => 'g', 'localized_options' => array('attributes' => array('title' =>'')))), 'below' => array()) + '5' => array('link' => $storage_controller->create(array('menu_name' => 'main-menu', 'mlid' => 5, 'hidden' => 1, 'has_children' => 0, 'title' => 'Item 5', 'in_active_trail' => 0, 'access' => 1, 'href' => 'e', 'localized_options' => array('attributes' => array('title' =>'')))), 'below' => array()), + '6' => array('link' => $storage_controller->create(array('menu_name' => 'main-menu', 'mlid' => 6, 'hidden' => 0, 'has_children' => 0, 'title' => 'Item 6', 'in_active_trail' => 0, 'access' => 0, 'href' => 'f', 'localized_options' => array('attributes' => array('title' =>'')))), 'below' => array()), + '7' => array('link' => $storage_controller->create(array('menu_name' => 'main-menu', 'mlid' => 7, 'hidden' => 0, 'has_children' => 0, 'title' => 'Item 7', 'in_active_trail' => 0, 'access' => 1, 'href' => 'g', 'localized_options' => array('attributes' => array('title' =>'')))), 'below' => array()) ); $output = menu_tree_output($this->tree_data); diff --git a/core/modules/system/system.admin.inc b/core/modules/system/system.admin.inc index 679fcdb91590..1ad9b4b691ea 100644 --- a/core/modules/system/system.admin.inc +++ b/core/modules/system/system.admin.inc @@ -149,7 +149,7 @@ function theme_admin_block_content($variables) { } $output .= '<dl class="' . $class . '">'; foreach ($content as $item) { - $output .= '<dt>' . l($item['title'], $item['link_path'], $item['localized_options']) . '</dt>'; + $output .= '<dt>' . l($item['title'], $item['href'], $item['localized_options']) . '</dt>'; if (!$compact && isset($item['description'])) { $output .= '<dd>' . filter_xss_admin($item['description']) . '</dd>'; } @@ -582,4 +582,3 @@ function theme_system_themes_page($variables) { return $output; } - diff --git a/core/modules/system/system.api.php b/core/modules/system/system.api.php index ed33a05eec32..1de6b1532d77 100644 --- a/core/modules/system/system.api.php +++ b/core/modules/system/system.api.php @@ -488,72 +488,6 @@ function hook_menu_get_item_alter(&$router_item, $path, $original_map) { } } -/** - * Define links for menus. - * - * @return array - * An array of default menu links. Each link has a key that is the machine - * name, which must be unique. The corresponding array value is an - * associative array that may contain the following key-value pairs: - * - link_title: (required) The untranslated title of the menu item. - * - description: The untranslated description of the link. - * - route_name: (optional) The route name to be used to build the path. - * Either a route_name or a link_path must be provided. - * - route_parameters: (optional) The route parameters to build the path. - * - link_path: (optional) If you have an external link use link_path instead - * of providing a route_name. - * - parent: (optional) The machine name of the link that is this link's menu - * parent. - * - weight: (optional) An integer that determines the relative position of - * items in the menu; higher-weighted items sink. Defaults to 0. Menu items - * with the same weight are ordered alphabetically. - * - menu_name: (optional) The machine name of a menu to put the link in, if - * not the default Tools menu. - * - expanded: (optional) If set to TRUE, and if a menu link is provided for - * this menu item (as a result of other properties), then the menu link is - * always expanded, equivalent to its 'always expanded' checkbox being set - * in the UI. - * - type: (optional) A bitmask of flags describing properties of the menu - * item. The following two bitmasks are provided as constants in menu.inc: - * - MENU_NORMAL_ITEM: Normal menu items show up in the menu tree and can be - * moved/hidden by the administrator. - * - MENU_SUGGESTED_ITEM: Modules may "suggest" menu items that the - * administrator may enable. - * If the "type" element is omitted, MENU_NORMAL_ITEM is assumed. - * - options: (optional) An array of options to be passed to l() when - * generating a link from this menu item. - * - * @see hook_menu_link_defaults_alter() - */ -function hook_menu_link_defaults() { - $links['user'] = array( - 'link_title' => 'My account', - 'weight' => -10, - 'route_name' => 'user.page', - 'menu_name' => 'account', - ); - - $links['user.logout'] = array( - 'link_title' => 'Log out', - 'route_name' => 'user.logout', - 'weight' => 10, - 'menu_name' => 'account', - ); - - return $links; -} - -/** - * Alter links for menus. - * - * @see hook_menu_link_defaults() - */ -function hook_menu_link_defaults_alter(&$links) { - // Change the weight and title of the user.logout link. - $links['user.logout']['weight'] = -10; - $links['user.logout']['link_title'] = t('Logout'); -} - /** * Define links for menus. * diff --git a/core/modules/system/system.module b/core/modules/system/system.module index ed0efba83565..c2cf62012f6f 100644 --- a/core/modules/system/system.module +++ b/core/modules/system/system.module @@ -9,12 +9,10 @@ use Drupal\Core\Cache\Cache; use Drupal\Core\Language\Language; use Drupal\Core\Utility\ModuleInfo; -use Drupal\menu_link\MenuLinkInterface; use Drupal\user\UserInterface; use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\HttpFoundation\RedirectResponse; use Symfony\Component\HttpFoundation\Response; -use Symfony\Component\HttpFoundation\Request; use Guzzle\Http\Exception\BadResponseException; use Guzzle\Http\Exception\RequestException; @@ -817,206 +815,6 @@ function system_menu() { return $items; } -/** - * Implements hook_menu_link_defaults(). - */ -function system_menu_link_defaults() { - $items['system.admin'] = array( - 'link_title' => 'Administration', - 'route_name' => 'system.admin', - 'weight' => 9, - 'menu_name' => 'admin', - ); - - // Menu items that are basically just menu blocks. - $items['system.admin.structure'] = array( - 'route_name' => 'system.admin_structure', - 'parent' => 'system.admin', - 'description' => 'Administer blocks, content types, menus, etc.', - 'link_title' => 'Structure', - 'weight' => -8, - ); - // Appearance. - $items['system.admin.appearance'] = array( - 'route_name' => 'system.themes_page', - 'link_title' => 'Appearance', - 'parent' => 'system.admin', - 'weight' => -6, - ); - // Modules. - $items['system.admin.modules'] = array( - 'link_title' => 'Extend', - 'parent' => 'system.admin', - 'route_name' => 'system.modules_list', - 'weight' => -2, - ); - // Configuration. - $items['system.admin.config'] = array( - 'link_title' => 'Configuration', - 'parent' => 'system.admin', - 'description' => 'Administer settings.', - 'route_name' => 'system.admin_config', - ); - - // Media settings. - $items['system.admin.config.media'] = array( - 'route_name' => 'system.admin_config_media', - 'parent' => 'system.admin.config', - 'link_title' => 'Media', - 'weight' => -10, - ); - $items['system.admin.config.media.file-system'] = array( - 'link_title' => 'File system', - 'description' => 'Tell Drupal where to store uploaded files and how they are accessed.', - 'parent' => 'system.admin.config.media', - 'route_name' => 'system.file_system_settings', - ); - $items['system.admin.config.media.image-toolkit'] = array( - 'link_title' => 'Image toolkit', - 'parent' => 'system.admin.config.media', - 'route_name' => 'system.image_toolkit_settings', - 'description' => 'Choose which image toolkit to use if you have installed optional toolkits.', - 'weight' => 20, - ); - - // Service settings. - $items['system.admin.config.services'] = array( - 'link_title' => 'Web services', - 'parent' => 'system.admin.config', - 'route_name' => 'system.admin_config_services', - ); - $items['system.admin.config.services.rss-publishing'] = array( - 'link_title' => 'RSS publishing', - 'parent' => 'system.admin.config.services', - 'description' => 'Configure the site description, the number of items per feed and whether feeds should be titles/teasers/full-text.', - 'route_name' => 'system.rss_feeds_settings', - ); - - // Development settings. - $items['system.admin.config.development'] = array( - 'route_name' => 'system.admin_config_development', - 'parent' => 'system.admin.config', - 'link_title' => 'Development', - 'description' => 'Development tools.', - 'weight' => -10, - ); - $items['system.admin.config.development.maintenance'] = array( - 'link_title' => 'Maintenance mode', - 'parent' => 'system.admin.config.development', - 'description' => 'Take the site offline for maintenance or bring it back online.', - 'route_name' => 'system.site_maintenance_mode', - 'weight' => -10, - ); - $items['system.admin.config.development.performance'] = array( - 'link_title' => 'Performance', - 'parent' => 'system.admin.config.development', - 'description' => 'Enable or disable page caching for anonymous users and set CSS and JS bandwidth optimization options.', - 'route_name' => 'system.performance_settings', - 'weight' => -20, - ); - $items['system.admin.config.development.logging'] = array( - 'link_title' => 'Logging and errors', - 'parent' => 'system.admin.config.development', - 'description' => "Settings for logging and alerts modules. Various modules can route Drupal's system events to different destinations, such as syslog, database, email, etc.", - 'route_name' => 'system.logging_settings', - 'weight' => -15, - ); - - // Regional and date settings. - $items['system.admin.config.regional'] = array( - 'route_name' => 'system.admin_config_regional', - 'link_title' => 'Regional and language', - 'parent' => 'system.admin.config', - 'description' => 'Regional settings, localization and translation.', - 'weight' => -5, - ); - $items['system.admin.config.regional.settings'] = array( - 'link_title' => 'Regional settings', - 'parent' => 'system.admin.config.regional', - 'description' => "Settings for the site's default time zone and country.", - 'route_name' => 'system.regional_settings', - 'weight' => -20, - ); - $items['system.admin.config.regional.date-time'] = array( - 'link_title' => 'Date and time formats', - 'parent' => 'system.admin.config.regional', - 'description' => 'Configure display format strings for date and time.', - 'route_name' => 'system.date_format_list', - 'weight' => -9, - ); - - // Search settings. - $items['system.admin.config.search'] = array( - 'link_title' => 'Search and metadata', - 'route_name' => 'system.admin_config_search', - 'parent' => 'system.admin.config', - 'description' => 'Local site search, metadata and SEO.', - 'weight' => -10, - ); - - // System settings. - $items['system.admin.config.system'] = array( - 'link_title' => 'System', - 'route_name' => 'system.admin_config_system', - 'parent' => 'system.admin.config', - 'description' => 'General system related configuration.', - 'weight' => -20, - ); - $items['system.admin.config.system.site-information'] = array( - 'link_title' => 'Site information', - 'parent' => 'system.admin.config.system', - 'description' => 'Change site name, e-mail address, slogan, default front page, and number of posts per page, error pages.', - 'route_name' => 'system.site_information_settings', - 'weight' => -20, - ); - $items['system.admin.config.system.cron'] = array( - 'link_title' => 'Cron', - 'parent' => 'system.admin.config.system', - 'description' => 'Manage automatic site maintenance tasks.', - 'route_name' => 'system.cron_settings', - 'weight' => 20, - ); - // Additional categories - $items['system.admin.config.user-interface'] = array( - 'link_title' => 'User interface', - 'route_name' => 'system.admin_config_ui', - 'parent' => 'system.admin.config', - 'description' => 'Tools that enhance the user interface.', - 'weight' => -15, - ); - $items['system.admin.config.workflow'] = array( - 'link_title' => 'Workflow', - 'route_name' => 'system.admin_config_workflow', - 'parent' => 'system.admin.config', - 'description' => 'Content workflow, editorial workflow tools.', - 'weight' => 5, - ); - $items['system.admin.config.content'] = array( - 'link_title' => 'Content authoring', - 'route_name' => 'system.admin_config_content', - 'parent' => 'system.admin.config', - 'description' => 'Settings related to formatting and authoring content.', - 'weight' => -15, - ); - - // Reports. - $items['system.admin.reports'] = array( - 'link_title' => 'Reports', - 'route_name' => 'system.admin_reports', - 'parent' => 'system.admin', - 'description' => 'View reports, updates, and errors.', - 'weight' => 5, - ); - $items['system.admin.reports.status'] = array( - 'link_title' => 'Status report', - 'parent' => 'system.admin.reports', - 'description' => "Get a status report about your site's operation and any detected problems.", - 'route_name' => 'system.status', - ); - - return $items; -} - /** * Implements hook_theme_suggestions_HOOK(). */ @@ -2861,17 +2659,17 @@ function system_get_module_admin_tasks($module, $info) { foreach ($menu_links as $link) { _menu_link_translate($link); if ($link['access']) { - $links[$link['machine_name']] = $link; + $links[$link['router_path']] = $link; } } } $admin_tasks = array(); $titles = array(); - if ($menu = module_invoke($module, 'menu_link_defaults')) { - foreach ($menu as $machine_name => $item) { - if (isset($links[$machine_name])) { - $task = $links[$machine_name]; + if ($menu = module_invoke($module, 'menu')) { + foreach ($menu as $path => $item) { + if (isset($links[$path])) { + $task = $links[$path]; // The link description, either derived from 'description' in // hook_menu() or customized via menu module is used as title attribute. if (!empty($task['localized_options']['attributes']['title'])) { @@ -2894,10 +2692,10 @@ function system_get_module_admin_tasks($module, $info) { } } else { - $titles[$machine_name] = $task['title']; + $titles[$path] = $task['title']; } - $admin_tasks[$machine_name] = $task; + $admin_tasks[$path] = $task; } } } diff --git a/core/modules/system/system.routing.yml b/core/modules/system/system.routing.yml index 9be827e419e0..4d27aa6c1810 100644 --- a/core/modules/system/system.routing.yml +++ b/core/modules/system/system.routing.yml @@ -288,7 +288,6 @@ system.admin_index: path: '/admin/index' defaults: _content: 'Drupal\system\Controller\AdminController::index' - _title: 'Administration' requirements: _permission: 'access administration pages' @@ -342,8 +341,6 @@ system.theme_settings_theme: '<front>': path: '/' - defaults: - _title: Home requirements: _access: 'TRUE' diff --git a/core/modules/system/tests/modules/menu_test/lib/Drupal/menu_test/Controller/MenuTestController.php b/core/modules/system/tests/modules/menu_test/lib/Drupal/menu_test/Controller/MenuTestController.php index 46b2c8000c60..d315e6d42aa5 100644 --- a/core/modules/system/tests/modules/menu_test/lib/Drupal/menu_test/Controller/MenuTestController.php +++ b/core/modules/system/tests/modules/menu_test/lib/Drupal/menu_test/Controller/MenuTestController.php @@ -19,23 +19,6 @@ public function menuTestCallback() { return menu_test_callback(); } - - /** - * A title callback method for test routes. - * - * @param array $_title_arguments - * Optional array from the route defaults. - * @param string $_title - * Optional _title string from the route defaults. - * - * @return string - * The route title. - */ - public function titleCallback(array $_title_arguments = array(), $_title = '') { - $_title_arguments += array('case_number' => '2', 'title' => $_title); - return t($_title_arguments['title']) . ' - Case ' . $_title_arguments['case_number']; - } - /** * @todo Remove menu_test_custom_403_404_callback(). */ diff --git a/core/modules/system/tests/modules/menu_test/menu_test.module b/core/modules/system/tests/modules/menu_test/menu_test.module index 5eb3098aef5c..caf216bc6379 100644 --- a/core/modules/system/tests/modules/menu_test/menu_test.module +++ b/core/modules/system/tests/modules/menu_test/menu_test.module @@ -231,15 +231,24 @@ function menu_test_menu() { 'route_name' => 'menu_test.title_test_case1', ); $items['menu-title-test/case2'] = array( - 'title' => 'Example title', - 'title callback' => 'menu_test_title_callback', + 'title' => 'Example @sub1 - Case @op2', + // If '2' is not in quotes, the argument becomes arg(2). + 'title arguments' => array('@sub1' => 'title', '@op2' => '2'), 'route_name' => 'menu_test.title_test_case2', ); $items['menu-title-test/case3'] = array( - // Title gets completely ignored. Good thing, too. - 'title' => 'Bike sheds full of blue smurfs WRONG', + 'title' => 'Example title', + 'title callback' => 'menu_test_title_callback', 'route_name' => 'menu_test.title_test_case3', ); + $items['menu-title-test/case4'] = array( + // Title gets completely ignored. Good thing, too. + 'title' => 'Bike sheds full of blue smurfs', + 'title callback' => 'menu_test_title_callback', + // If '4' is not in quotes, the argument becomes arg(4). + 'title arguments' => array('Example title', '4'), + 'route_name' => 'menu_test.title_test_case4', + ); // Parent page for controller-based local tasks. $items['foo/%'] = array( @@ -286,134 +295,6 @@ function menu_test_menu() { return $items; } -/** - * Implements hook_menu_link_defaults(). - */ -function menu_test_menu_link_defaults() { - // The name of the menu changes during the course of the test. Using a $_GET. - $items['menu_test.menu_name_test'] = array( - 'link_title' => 'Test menu_name router item', - 'route_name' => 'menu_test.menu_name_test', - 'menu_name' => menu_test_menu_name(), - ); - // This item uses SystemController::systemAdminMenuBlockPage() to list child - // items. - $items['menu_test.menu_callback_description'] = array( - 'link_title' => 'Menu item title', - 'description' => 'Menu item description parent', - 'route_name' => 'menu_test.callback_description', - ); - // This item tests the description key. - $items['menu_test.menu_callback_description.description-plain'] = array( - 'link_title' => 'Menu item with a regular description', - 'description' => 'Menu item description text', - 'route_name' => 'menu_test.callback_description_plain', - 'parent' => 'menu_test.menu_callback_description', - ); - // This item tests using a description callback. - $items['menu_callback_description.description-callback'] = array( - 'link_title' => 'Menu item with a description set with a callback', - 'route_name' => 'menu_test.callback_description_callback', - 'parent' => 'menu_test.menu_callback_description', - ); - - $items['menu_test.menu_no_title_callback'] = array( - 'link_title' => 'A title with @placeholder', - 'route_name' => 'menu_test.menu_no_title_callback', - ); - - // Hierarchical tests. - $items['menu_test.hierarchy_parent'] = array( - 'link_title' => 'Parent menu router', - 'route_name' => 'menu_test.hierarchy_parent', - ); - $items['menu_test.hierarchy_parent.child'] = array( - 'link_title' => 'Child menu router', - 'route_name' => 'menu_test.hierarchy_parent_child', - 'parent' => 'menu_test.hierarchy_parent', - ); - $items['menu_test.hierarchy_parent.child2.child'] = array( - 'link_title' => 'Unattached subchild router', - 'route_name' => 'menu_test.hierarchy_parent_child2', - 'parent' => 'menu_test.hierarchy_parent.child', - ); - // Path containing "exotic" characters. - $exotic = " -._~!$'\"()*@[]?&+%#,;=:" . // "Special" ASCII characters. - "%23%25%26%2B%2F%3F" . // Characters that look like a percent-escaped string. - "éøïвβä¸åœ‹æ›¸Ûž"; // Characters from various non-ASCII alphabets. - $items['menu_test.exotic_path'] = array( - 'link_title' => '"Exotic" path', - 'route_name' => 'menu_test.exotic_path', - 'route_parameters' => array('exotic' => $exotic), - ); - - // Hidden tests; base parents. - // Same structure as in Menu and Block modules. Since those structures can - // change, we need to simulate our own in here. - $items['menu_test'] = array( - 'link_title' => 'Menu test root', - 'route_name' => 'menu_test.menu_test', - ); - $items['menu_test.hidden'] = array( - 'link_title' => 'Hidden test root', - 'route_name' => 'menu_test.hidden', - 'parent' => 'menu_test', - ); - - // Hidden tests; one dynamic argument. - $items['menu_test.hidden.menu'] = array( - 'link_title' => 'Menus', - 'route_name' => 'menu_test.hidden_menu', - 'parent' => 'menu_test.hidden', - ); - - // Hidden tests; two dynamic arguments. - $items['menu_test.hidden.block'] = array( - 'link_title' => 'Blocks', - 'route_name' => 'menu_test.hidden_block', - 'parent' => 'menu_test.hidden', - ); - - // Menu trail tests. - // @see MenuTrailTestCase - $items['menu_test.menu-trail'] = array( - 'link_title' => 'Menu trail - Case 1', - 'route_name' => 'menu_test.menu_trail', - 'parent' => 'menu_test', - ); - $items['menu_test.admin.config.development.menu-trail'] = array( - 'link_title' => 'Menu trail - Case 2', - 'description' => 'Tests menu_tree_set_path()', - 'route_name' => 'menu_test.menu_trail_admin', - 'parent' => 'system.admin.config.development', - ); - $items['menu_test.custom-403-page'] = array( - 'link_title' => 'Custom 403 page', - 'route_name' => 'menu_test.custom_403', - 'parent' => 'menu_test', - ); - $items['menu_test.custom-404-page'] = array( - 'link_title' => 'Custom 404 page', - 'route_name' => 'menu_test.custom_404', - 'parent' => 'menu_test', - ); - // Test the access key. - $items['menu_test.menu-title-test.case1'] = array( - 'link_title' => 'Example title - Case 1', - 'route_name' => 'menu_test.title_test_case1', - ); - $items['menu_test.menu-title-test.case2'] = array( - 'link_title' => 'Example title', - 'route_name' => 'menu_test.title_test_case2', - ); - $items['menu_test.menu-title-test.case3'] = array( - // Title gets completely ignored. Good thing, too. - 'link_title' => 'Bike sheds full of blue smurfs', - 'route_name' => 'menu_test.title_test_case3', - ); - return $items; -} - /** * Implements hook_menu_local_tasks(). * diff --git a/core/modules/system/tests/modules/menu_test/menu_test.routing.yml b/core/modules/system/tests/modules/menu_test/menu_test.routing.yml index a76eddabbcf5..bc8a73682c8c 100644 --- a/core/modules/system/tests/modules/menu_test/menu_test.routing.yml +++ b/core/modules/system/tests/modules/menu_test/menu_test.routing.yml @@ -519,7 +519,6 @@ menu_test.theme_callback_inheritance: menu_test.title_test_case1: path: '/menu-title-test/case1' defaults: - _title: 'Example title - Case 1' _content: '\Drupal\menu_test\Controller\MenuTestController::menuTestCallback' requirements: _access: 'TRUE' @@ -527,8 +526,6 @@ menu_test.title_test_case1: menu_test.title_test_case2: path: '/menu-title-test/case2' defaults: - _title: 'Example title' - _title_callback: '\Drupal\menu_test\Controller\MenuTestController::titleCallback' _content: '\Drupal\menu_test\Controller\MenuTestController::menuTestCallback' requirements: _access: 'TRUE' @@ -536,11 +533,13 @@ menu_test.title_test_case2: menu_test.title_test_case3: path: '/menu-title-test/case3' defaults: - _title: 'Bike sheds full of blue smurfs' # this should be ignored - _title_callback: '\Drupal\menu_test\Controller\MenuTestController::titleCallback' - _title_arguments: - title: 'Example title' - case_number: '3' + _content: '\Drupal\menu_test\Controller\MenuTestController::menuTestCallback' + requirements: + _access: 'TRUE' + +menu_test.title_test_case4: + path: '/menu-title-test/case4' + defaults: _content: '\Drupal\menu_test\Controller\MenuTestController::menuTestCallback' requirements: _access: 'TRUE' diff --git a/core/modules/taxonomy/lib/Drupal/taxonomy/Controller/TaxonomyController.php b/core/modules/taxonomy/lib/Drupal/taxonomy/Controller/TaxonomyController.php index 7685cd46f174..e79c37ce59fb 100644 --- a/core/modules/taxonomy/lib/Drupal/taxonomy/Controller/TaxonomyController.php +++ b/core/modules/taxonomy/lib/Drupal/taxonomy/Controller/TaxonomyController.php @@ -56,19 +56,6 @@ public function termTitle(TermInterface $taxonomy_term) { return Xss::filter($taxonomy_term->label()); } - /** - * Route title callback. - * - * @param \Drupal\taxonomy\VocabularyInterface $taxonomy_vocabulary - * The taxonomy term. - * - * @return string - * The term label. - */ - public function vocabularyTitle(VocabularyInterface $taxonomy_vocabulary) { - return Xss::filter($taxonomy_vocabulary->label()); - } - /** * @todo Remove taxonomy_term_feed(). */ diff --git a/core/modules/taxonomy/taxonomy.module b/core/modules/taxonomy/taxonomy.module index 3d199939d825..e41b46770f48 100644 --- a/core/modules/taxonomy/taxonomy.module +++ b/core/modules/taxonomy/taxonomy.module @@ -261,20 +261,6 @@ function taxonomy_menu() { return $items; } -/** - * Implements hook_menu_link_defaults(). - */ -function taxonomy_menu_link_defaults() { - $links['taxonomy.admin.structure.vocabulary'] = array( - 'link_title' => 'Taxonomy', - 'parent' => 'system.admin.structure', - 'description' => 'Manage tagging, categorization, and classification of your content.', - 'route_name' => 'taxonomy.vocabulary_list', - ); - - return $links; -} - /** * Implements hook_admin_paths(). */ diff --git a/core/modules/taxonomy/taxonomy.routing.yml b/core/modules/taxonomy/taxonomy.routing.yml index b5f3c2e96e40..804086001a0e 100644 --- a/core/modules/taxonomy/taxonomy.routing.yml +++ b/core/modules/taxonomy/taxonomy.routing.yml @@ -79,7 +79,6 @@ taxonomy.overview_terms: path: '/admin/structure/taxonomy/manage/{taxonomy_vocabulary}' defaults: _form: 'Drupal\taxonomy\Form\OverviewTerms' - _title_callback: 'Drupal\taxonomy\Controller\TaxonomyController::vocabularyTitle' requirements: _entity_access: 'taxonomy_vocabulary.view' diff --git a/core/modules/toolbar/lib/Drupal/toolbar/Tests/ToolbarAdminMenuTest.php b/core/modules/toolbar/lib/Drupal/toolbar/Tests/ToolbarAdminMenuTest.php index b18ad958c5b1..b3f08ccda3e9 100644 --- a/core/modules/toolbar/lib/Drupal/toolbar/Tests/ToolbarAdminMenuTest.php +++ b/core/modules/toolbar/lib/Drupal/toolbar/Tests/ToolbarAdminMenuTest.php @@ -73,7 +73,6 @@ function setUp() { 'bypass node access', 'administer themes', 'administer nodes', - 'access content overview', 'administer blocks', 'administer menu', 'administer modules', diff --git a/core/modules/toolbar/toolbar.module b/core/modules/toolbar/toolbar.module index bcb895410094..86ef5ee5d885 100644 --- a/core/modules/toolbar/toolbar.module +++ b/core/modules/toolbar/toolbar.module @@ -489,7 +489,7 @@ function toolbar_get_rendered_subtrees() { $subtree = ''; } - $id = str_replace(array('/', '<', '>'), array('-', '', ''), $item['link_path']); + $id = str_replace(array('/', '<', '>'), array('-', '', ''), $item['href']); $subtrees[$id] = $subtree; } } diff --git a/core/modules/tracker/tracker.module b/core/modules/tracker/tracker.module index c5f0c0992547..b1be0414a3e0 100644 --- a/core/modules/tracker/tracker.module +++ b/core/modules/tracker/tracker.module @@ -31,18 +31,6 @@ function tracker_help($path, $arg) { } } -/** - * Implements hook_menu_link_defaults(). - */ -function tracker_menu_link_defaults() { - $links['tracker'] = array( - 'link_title' => 'Recent content', - 'route_name' => 'tracker.page', - ); - - return $links; -} - /** * Implements hook_cron(). * diff --git a/core/modules/update/update.module b/core/modules/update/update.module index 84357cafa0a8..af8143b11a3d 100644 --- a/core/modules/update/update.module +++ b/core/modules/update/update.module @@ -177,21 +177,6 @@ function update_menu() { return $items; } -/** - * Implements hook_menu_link_defaults(). - */ -function update_menu_link_defaults() { - $links['update.admin.reports.updates'] = array( - 'link_title' => 'Available updates', - 'description' => 'Get a status report about available updates for your installed modules and themes.', - 'route_name' => 'update.status', - 'parent' => 'system.admin.reports', - 'weight' => -50, - ); - - return $links; -} - /** * Access callback: Resolves if the current user can access updater menu items. * diff --git a/core/modules/user/lib/Drupal/user/Access/LoginStatusCheck.php b/core/modules/user/lib/Drupal/user/Access/LoginStatusCheck.php index 01d7a6cbeac9..af52c1536103 100644 --- a/core/modules/user/lib/Drupal/user/Access/LoginStatusCheck.php +++ b/core/modules/user/lib/Drupal/user/Access/LoginStatusCheck.php @@ -21,7 +21,7 @@ class LoginStatusCheck implements AccessInterface { * {@inheritdoc} */ public function access(Route $route, Request $request, AccountInterface $account) { - return ($request->attributes->get('_menu_admin') || $account->isAuthenticated()) ? static::ALLOW : static::DENY; + return $account->isAuthenticated() ? static::ALLOW : static::DENY; } } diff --git a/core/modules/user/lib/Drupal/user/Tests/UserAccountLinksTests.php b/core/modules/user/lib/Drupal/user/Tests/UserAccountLinksTests.php index bbe5a71ed189..24e7244623fb 100644 --- a/core/modules/user/lib/Drupal/user/Tests/UserAccountLinksTests.php +++ b/core/modules/user/lib/Drupal/user/Tests/UserAccountLinksTests.php @@ -129,8 +129,11 @@ function testAccountPageTitles() { // Check the page title for registered users is "My Account" in menus. $this->drupalLogin($this->drupalCreateUser()); // After login, the client is redirected to /user. - $this->assertLink(t('My account'), 0, "Page title of /user is 'My Account' in menus for registered users"); - $this->assertLinkByHref(\Drupal::urlGenerator()->generate('user.page'), 0); + $link = $this->xpath('//a[contains(@class, :class)]', array( + ':class' => 'active-trail', + ) + ); + $this->assertEqual((string) $link[0], 'My account', "Page title of /user is 'My Account' in menus for registered users"); } } diff --git a/core/modules/user/user.module b/core/modules/user/user.module index 0b13fc5b9915..88862d510a2e 100644 --- a/core/modules/user/user.module +++ b/core/modules/user/user.module @@ -789,62 +789,6 @@ function user_menu() { return $items; } -/** - * Implements hook_menu_link_defaults(). - */ -function user_menu_link_defaults() { - // Registration and login pages. - $links['user'] = array( - 'link_title' => 'My account', - 'weight' => -10, - 'route_name' => 'user.page', - 'menu_name' => 'account', - ); - - $links['user.logout'] = array( - 'link_title' => 'Log out', - 'route_name' => 'user.logout', - 'weight' => 10, - 'menu_name' => 'account', - ); - - // User listing pages. - $links['user.admin.people'] = array( - 'link_title' => 'People', - 'route_name' => 'user.admin_account', - 'description' => 'Manage user accounts, roles, and permissions.', - 'parent' => 'system.admin', - 'weight' => -4, - ); - // Permissions and role forms. - $links['user.admin.people.permissions'] = array( - 'link_title' => 'Permissions', - 'parent' => 'user.admin.people', - 'description' => 'Determine access to features by selecting permissions for roles.', - 'route_name' => 'user.admin_permissions', - ); - - // Administration pages. - $links['user.admin.config.people'] = array( - 'link_title' => 'People', - 'route_name' => 'user.admin_index', - 'parent' => 'system.admin.config', - 'description' => 'Configure user accounts.', - 'position' => 'left', - 'weight' => -20, - ); - - $links['user.admin.config.people.accounts'] = array( - 'link_title' => 'Account settings', - 'parent' => 'user.admin.config.people', - 'description' => 'Configure default behavior of users, including registration requirements, e-mails, and fields.', - 'weight' => -10, - 'route_name' => 'user.account_settings', - ); - - return $links; -} - /** * Implements hook_menu_link_presave(). */ @@ -853,9 +797,15 @@ function user_menu_link_presave(MenuLink $menu_link) { // for authenticated users. Authenticated users should see "My account", but // anonymous users should not see it at all. Therefore, invoke // user_menu_link_load() to conditionally hide the link. - if ($menu_link->machine_name == 'user' && $menu_link->module == 'system') { + if ($menu_link->link_path == 'user' && $menu_link->module == 'system') { $menu_link->options['alter'] = TRUE; } + + // Force the Logout link to appear on the top-level of 'account' menu by + // default (i.e., unless it has been customized). + if ($menu_link->link_path == 'user/logout' && $menu_link->module == 'system' && empty($menu_link->customized)) { + $menu_link->plid = 0; + } } /** diff --git a/core/modules/views/lib/Drupal/views/Plugin/views/display/DisplayPluginBase.php b/core/modules/views/lib/Drupal/views/Plugin/views/display/DisplayPluginBase.php index 540e2941d1cb..83e226f2244e 100644 --- a/core/modules/views/lib/Drupal/views/Plugin/views/display/DisplayPluginBase.php +++ b/core/modules/views/lib/Drupal/views/Plugin/views/display/DisplayPluginBase.php @@ -2366,21 +2366,6 @@ public function renderMoreLink() { } } - /** - * Creates menu links, if this display provides some. - * - * @param array $existing_links - * An array of already existing menu items provided by drupal. - * - * @return array - * The menu links registers for this display. - * - * @see hook_menu_link_defaults() - */ - public function executeHookDefaultMenuLinks(array &$existing_links) { - return array(); - } - /** * If this display creates a page with a menu item, implement it here. * diff --git a/core/modules/views/lib/Drupal/views/Plugin/views/display/PathPluginBase.php b/core/modules/views/lib/Drupal/views/Plugin/views/display/PathPluginBase.php index 0baa2dea23fb..a84d603d75df 100644 --- a/core/modules/views/lib/Drupal/views/Plugin/views/display/PathPluginBase.php +++ b/core/modules/views/lib/Drupal/views/Plugin/views/display/PathPluginBase.php @@ -271,70 +271,6 @@ public function alterRoutes(RouteCollection $collection) { return $view_route_names; } - /** - * {@inheritdoc} - */ - public function executeHookDefaultMenuLinks(array &$existing_links) { - $links = array(); - - // Replace % with the link to our standard views argument loader - // views_arg_load -- which lives in views.module. - - $bits = explode('/', $this->getOption('path')); - $page_arguments = array($this->view->storage->id(), $this->display['id']); - $this->view->initHandlers(); - $view_arguments = $this->view->argument; - - // Replace % with %views_arg for menu autoloading and add to the - // page arguments so the argument actually comes through. - foreach ($bits as $pos => $bit) { - if ($bit == '%') { - // If a view requires any arguments we cannot create a static menu link. - return array(); - } - } - - $view_route_names = $this->state->get('views.view_route_names') ?: array(); - - $path = implode('/', $bits); - $menu_link_id = 'views.' . str_replace('/', '.', $path); - $links[$menu_link_id] = array(); - - if ($path) { - // Some views might override existing paths, so we have to set the route - // name based upon the altering. - $view_id_display = "{$this->view->storage->id()}.{$this->display['id']}"; - $links[$menu_link_id] = array( - 'route_name' => isset($view_route_names[$view_id_display]) ? $view_route_names[$view_id_display] : "view.$view_id_display", - // Identify URL embedded arguments and correlate them to a handler. - 'load arguments' => array($this->view->storage->id(), $this->display['id'], '%index'), - ); - - $menu = $this->getOption('menu'); - if (empty($menu)) { - $menu = array('type' => 'none'); - } - // Set the title and description if we have one. - if ($menu['type'] != 'none') { - $links[$menu_link_id]['link_title'] = $menu['title']; - $links[$menu_link_id]['description'] = $menu['description']; - } - - if (isset($menu['weight'])) { - $links[$menu_link_id]['weight'] = intval($menu['weight']); - } - - switch ($menu['type']) { - case 'normal': - // Insert item into the proper menu. - $links[$menu_link_id]['menu_name'] = $menu['name']; - break; - } - } - - return $links; - } - /** * Overrides \Drupal\views\Plugin\views\display\DisplayPluginBase::executeHookMenu(). */ diff --git a/core/modules/views/lib/Drupal/views/ViewExecutable.php b/core/modules/views/lib/Drupal/views/ViewExecutable.php index d24b10df014e..09346d3408c0 100644 --- a/core/modules/views/lib/Drupal/views/ViewExecutable.php +++ b/core/modules/views/lib/Drupal/views/ViewExecutable.php @@ -1532,30 +1532,6 @@ public function executeHookMenu($display_id = NULL, &$callbacks = array()) { } } - /** - * Returns default menu links from the view and the named display handler. - * - * @param string $display_id - * A display ID. - * @param array $links - * An array of default menu link items passed from - * views_menu_link_defaults_alter(). - * - * @return array|bool - */ - public function executeHookDefaultMenuLinks($display_id = NULL, &$links = array()) { - // Prepare the view with the information we have. This was probably already - // called, but it's good to be safe. - if (!$this->setDisplay($display_id)) { - return FALSE; - } - - // Execute the hook. - if (isset($this->display_handler)) { - return $this->display_handler->executeHookDefaultMenuLinks($links); - } - } - /** * Determine if the given user has access to the view. Note that * this sets the display handler if it hasn't been. diff --git a/core/modules/views/views.module b/core/modules/views/views.module index 5f1bc7131814..fe427b062d27 100644 --- a/core/modules/views/views.module +++ b/core/modules/views/views.module @@ -315,23 +315,6 @@ function views_menu_alter(&$callbacks) { } } -/** - * Implements hook_menu_link_defaults_alter(). - */ -function views_menu_link_defaults_alter(array &$links) { - // @todo Decide what to do with all the crazy logic in views_menu_alter() in - // https://drupal.org/node/2107533. - $views = Views::getApplicableViews('uses_hook_menu'); - foreach ($views as $data) { - /** @var \Drupal\views\ViewExecutable $view */ - list($view, $display_id) = $data; - $result = $view->executeHookDefaultMenuLinks($display_id, $links); - foreach ($result as $link_id => $link) { - $links[$link_id] = $link; - } - } -} - /** * Implements hook_page_alter(). */ diff --git a/core/modules/views_ui/views_ui.module b/core/modules/views_ui/views_ui.module index 348372d591be..f90508c009c9 100644 --- a/core/modules/views_ui/views_ui.module +++ b/core/modules/views_ui/views_ui.module @@ -60,31 +60,6 @@ function views_ui_menu() { return $items; } -/** - * Implements hook_menu_link_defaults(). - */ -function views_ui_menu_link_defaults() { - $links = array(); - - // Top-level Views module pages (not tied to a particular View). - $links['views_ui.admin.structure.views'] = array( - 'link_title' => 'Views', - 'parent' => 'system.admin.structure', - 'description' => 'Manage customized lists of content.', - 'route_name' => 'views_ui.list', - ); - - // A page in the Reports section to show usage of plugins in all views. - $links['views_ui.admin.reports.views-plugins'] = array( - 'link_title' => 'Views plugins', - 'parent' => 'system.admin.reports', - 'description' => 'Overview of plugins used in all views.', - 'route_name' => 'views_ui.reports_plugins', - ); - - return $links; -} - /** * Implements hook_entity_info(). */ diff --git a/core/themes/seven/seven.theme b/core/themes/seven/seven.theme index 2427bb72bc84..fa993245818f 100644 --- a/core/themes/seven/seven.theme +++ b/core/themes/seven/seven.theme @@ -121,7 +121,7 @@ function seven_admin_block_content($variables) { if (isset($item['description']) && !system_admin_compact_mode()) { $content .= '<div class="description">' . filter_xss_admin($item['description']) . '</div>'; } - $output .= l($content, $item['link_path'], $options); + $output .= l($content, $item['href'], $options); $output .= '</li>'; } $output .= '</ul>'; -- GitLab