diff --git a/core/core.services.yml b/core/core.services.yml index e8b6464e8bc916505f6e420425b984446f3eca59..d2de794128788bc4aacb1a82cb5669d068df520a 100644 --- a/core/core.services.yml +++ b/core/core.services.yml @@ -326,7 +326,7 @@ services: arguments: ['@router.dumper', '@lock', '@event_dispatcher', '@module_handler', '@controller_resolver', '@state'] router.rebuild_subscriber: class: Drupal\Core\EventSubscriber\RouterRebuildSubscriber - arguments: ['@router.builder'] + arguments: ['@router.builder', '@lock'] tags: - { name: event_subscriber } path.alias_manager.cached: diff --git a/core/includes/menu.inc b/core/includes/menu.inc index 1d3adf62fcfe7a71ab20832711f77e62cc22d161..a1c8a01449a671a679608db31a8a02be27040faa 100644 --- a/core/includes/menu.inc +++ b/core/includes/menu.inc @@ -5,19 +5,12 @@ * API for the Drupal menu system. */ -use Drupal\Component\Utility\NestedArray; use Drupal\Component\Utility\String; use Drupal\Core\Cache\Cache; use Drupal\Core\Language\Language; -use Drupal\Core\ParamConverter\ParamNotConvertedException; -use Drupal\Core\Routing\RequestHelper; use Drupal\Core\Template\Attribute; -use Drupal\menu_link\Entity\MenuLink; use Drupal\menu_link\MenuLinkInterface; -use Drupal\menu_link\MenuLinkStorageController; use Symfony\Cmf\Component\Routing\RouteObjectInterface; -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\Routing\Route; /** * @defgroup menu Menu and routing system @@ -44,9 +37,9 @@ * the stuff in the routing.yml file means. * * @section Defining menu links - * Once you have a route defined, you can use hook_menu() to define links - * for your module's paths in the main Navigation menu or other menus. See - * the hook_menu() documentation for more details. + * Once you have a route defined, you can use hook_menu_link_defaults() to + * define links for your module's paths in the main Navigation menu or other + * menus. See the hook_menu_link_defaults() documentation for more details. * * @todo The rest of this topic has not been reviewed or updated for Drupal 8.x * and is not correct! @@ -125,11 +118,6 @@ */ const MENU_VISIBLE_IN_TREE = 0x0002; -/** - * Internal menu flag -- menu item is visible in the breadcrumb. - */ -const MENU_VISIBLE_IN_BREADCRUMB = 0x0004; - /** * Internal menu flag -- menu item links back to its parent. */ @@ -170,7 +158,7 @@ * the administrator. Use this for most menu items. It is the default value if * no menu item type is specified. */ -define('MENU_NORMAL_ITEM', MENU_VISIBLE_IN_TREE | MENU_VISIBLE_IN_BREADCRUMB); +define('MENU_NORMAL_ITEM', MENU_VISIBLE_IN_TREE); /** * Menu type -- A hidden, internal callback, typically used for API calls. @@ -188,76 +176,18 @@ * Note for the value: 0x0010 was a flag which is no longer used, but this way * the values of MENU_CALLBACK and MENU_SUGGESTED_ITEM are separate. */ -define('MENU_SUGGESTED_ITEM', MENU_VISIBLE_IN_BREADCRUMB | 0x0010); - -/** - * Menu type -- A task specific to the parent item, usually rendered as a tab. - * - * Local tasks are menu items that describe actions to be performed on their - * parent item. An example is the path "node/52/edit", which performs the - * "edit" task on "node/52". - */ -define('MENU_LOCAL_TASK', MENU_IS_LOCAL_TASK | MENU_VISIBLE_IN_BREADCRUMB); - -/** - * Menu type -- The "default" local task, which is initially active. - * - * Every set of local tasks should provide one "default" task, that links to the - * same path as its parent when clicked. - */ -define('MENU_DEFAULT_LOCAL_TASK', MENU_IS_LOCAL_TASK | MENU_LINKS_TO_PARENT | MENU_VISIBLE_IN_BREADCRUMB); - -/** - * Menu type -- A task specific to the parent, which is never rendered. - * - * Sibling local tasks are not rendered themselves, but affect the active - * trail and need their sibling tasks rendered as tabs. - */ -define('MENU_SIBLING_LOCAL_TASK', MENU_IS_LOCAL_TASK | MENU_VISIBLE_IN_BREADCRUMB); +define('MENU_SUGGESTED_ITEM', 0x0010); /** * @} End of "defgroup menu_item_types". */ -/** - * @defgroup menu_context_types Menu context types - * @{ - * Flags for use in the "context" attribute of menu router items. - */ - -/** - * Internal menu flag: Invisible local task. - * - * This flag may be used for local tasks like "Delete", so custom modules and - * themes can alter the default context and expose the task by altering menu. - */ -const MENU_CONTEXT_NONE = 0x0000; - -/** - * Internal menu flag: Local task should be displayed in page context. - */ -const MENU_CONTEXT_PAGE = 0x0001; - -/** - * @} End of "defgroup menu_context_types". - */ - /** * @defgroup menu_status_codes Menu status codes * @{ * Status codes for menu callbacks. */ -/** - * Internal menu status code -- Menu item was not found. - */ -const MENU_NOT_FOUND = 404; - -/** - * Internal menu status code -- Menu item access is denied. - */ -const MENU_ACCESS_DENIED = 403; - /** * Internal menu status code -- Menu item inaccessible because site is offline. */ @@ -278,12 +208,6 @@ * Parameters for a menu tree. */ - /** - * The maximum number of path elements for a menu callback - */ -const MENU_MAX_PARTS = 9; - - /** * The maximum depth of a menu links tree - matches the number of p columns. * @@ -312,260 +236,17 @@ const MENU_PREFERRED_LINK = '1cf698d64d1aa4b83907cf6ed55db3a7f8e92c91'; /** - * Returns the ancestors (and relevant placeholders) for any given path. - * - * For example, the ancestors of node/12345/edit are: - * - node/12345/edit - * - node/12345/% - * - node/%/edit - * - node/%/% - * - node/12345 - * - node/% - * - node - * - * To generate these, we will use binary numbers. Each bit represents a - * part of the path. If the bit is 1, then it represents the original - * value while 0 means wildcard. If the path is node/12/edit/foo - * then the 1011 bitstring represents node/%/edit/foo where % means that - * any argument matches that part. We limit ourselves to using binary - * numbers that correspond the patterns of wildcards of router items that - * actually exists. This list of 'masks' is built in menu_router_rebuild(). - * - * @param $parts - * An array of path parts, for the above example - * array('node', '12345', 'edit'). - * - * @return - * An array which contains the ancestors and placeholders. Placeholders - * simply contain as many '%s' as the ancestors. - */ -function menu_get_ancestors($parts) { - $number_parts = count($parts); - $ancestors = array(); - $length = $number_parts - 1; - $end = (1 << $number_parts) - 1; - $masks = \Drupal::state()->get('menu.masks'); - // If the optimized menu.masks array is not available use brute force to get - // the correct $ancestors and $placeholders returned. Do not use this as the - // default value of the menu.masks variable to avoid building such a big - // array. - if (!$masks) { - $masks = range(511, 1); - } - // Only examine patterns that actually exist as router items (the masks). - foreach ($masks as $i) { - if ($i > $end) { - // Only look at masks that are not longer than the path of interest. - continue; - } - elseif ($i < (1 << $length)) { - // We have exhausted the masks of a given length, so decrease the length. - --$length; - } - $current = ''; - for ($j = $length; $j >= 0; $j--) { - // Check the bit on the $j offset. - if ($i & (1 << $j)) { - // Bit one means the original value. - $current .= $parts[$length - $j]; - } - else { - // Bit zero means means wildcard. - $current .= '%'; - } - // Unless we are at offset 0, add a slash. - if ($j) { - $current .= '/'; - } - } - $ancestors[] = $current; - } - return $ancestors; -} - -/** - * Unserializes menu data, using a map to replace path elements. - * - * The menu system stores various path-related information (such as the 'page - * arguments' and 'access arguments' components of a menu item) in the database - * using serialized arrays, where integer values in the arrays represent - * arguments to be replaced by values from the path. This function first - * unserializes such menu information arrays, and then does the path - * replacement. - * - * The path replacement acts on each integer-valued element of the unserialized - * menu data array ($data) using a map array ($map, which is typically an array - * of path arguments) as a list of replacements. For instance, if there is an - * element of $data whose value is the number 2, then it is replaced in $data - * with $map[2]; non-integer values in $data are left alone. - * - * As an example, an unserialized $data array with elements ('node_load', 1) - * represents instructions for calling the node_load() function. Specifically, - * this instruction says to use the path component at index 1 as the input - * parameter to node_load(). If the path is 'node/123', then $map will be the - * array ('node', 123), and the returned array from this function will have - * elements ('node_load', 123), since $map[1] is 123. This return value will - * indicate specifically that node_load(123) is to be called to load the node - * whose ID is 123 for this menu item. - * - * @param $data - * A serialized array of menu data, as read from the database. - * @param $map - * A path argument array, used to replace integer values in $data; an integer - * value N in $data will be replaced by value $map[N]. Typically, the $map - * array is generated from a call to the arg() function. - * - * @return - * The unserialized $data array, with path arguments replaced. - */ -function menu_unserialize($data, $map) { - if ($data = unserialize($data)) { - foreach ($data as $k => $v) { - if (is_int($v)) { - $data[$k] = isset($map[$v]) ? $map[$v] : ''; - } - } - return $data; - } - else { - return array(); - } -} - -/** - * Loads objects into the map as defined in the $item['load_functions']. - * - * @param $item - * A menu router or menu link item - * @param $map - * An array of path arguments; for example, array('node', '5'). - * - * @return - * Returns TRUE for success, FALSE if an object cannot be loaded. - * Names of object loading functions are placed in $item['load_functions']. - * Loaded objects are placed in $map[]; keys are the same as keys in the - * $item['load_functions'] array. - * $item['access'] is set to FALSE if an object cannot be loaded. - */ -function _menu_load_objects(&$item, &$map) { - if ($load_functions = $item['load_functions']) { - // If someone calls this function twice, then unserialize will fail. - if (!is_array($load_functions)) { - $load_functions = unserialize($load_functions); - } - $path_map = $map; - foreach ($load_functions as $index => $function) { - if ($function) { - $value = isset($path_map[$index]) ? $path_map[$index] : ''; - if (is_array($function)) { - // Set up arguments for the load function. These were pulled from - // 'load arguments' in the hook_menu() entry, but they need - // some processing. In this case the $function is the key to the - // load_function array, and the value is the list of arguments. - list($function, $args) = each($function); - $load_functions[$index] = $function; - - // Some arguments are placeholders for dynamic items to process. - foreach ($args as $i => $arg) { - if ($arg === '%index') { - // Pass on argument index to the load function, so multiple - // occurrences of the same placeholder can be identified. - $args[$i] = $index; - } - if ($arg === '%map') { - // Pass on menu map by reference. The accepting function must - // also declare this as a reference if it wants to modify - // the map. - $args[$i] = &$map; - } - if (is_int($arg)) { - $args[$i] = isset($path_map[$arg]) ? $path_map[$arg] : ''; - } - } - array_unshift($args, $value); - $return = call_user_func_array($function, $args); - } - else { - $return = $function($value); - } - // If callback returned an error or there is no callback, trigger 404. - if (empty($return)) { - $item['access'] = FALSE; - $map = FALSE; - return FALSE; - } - $map[$index] = $return; - } - } - $item['load_functions'] = $load_functions; - } - return TRUE; -} - -/** - * Checks access to a menu item using the access callback. - * - * @param $item - * A menu router or menu link item - * @param $map - * An array of path arguments; for example, array('node', '5'). - * - * @return - * $item['access'] becomes TRUE if the item is accessible, FALSE otherwise. - */ -function _menu_check_access(&$item, $map) { - // Determine access callback, which will decide whether or not the current - // user has access to this path. - $callback = empty($item['access_callback']) ? 0 : trim($item['access_callback']); - // Check for a TRUE or FALSE value. - if (is_numeric($callback)) { - $item['access'] = (bool) $callback; - } - else { - $arguments = menu_unserialize($item['access_arguments'], $map); - // As call_user_func_array is quite slow and user_access is a very common - // callback, it is worth making a special case for it. - if ($callback == 'user_access') { - $item['access'] = (count($arguments) == 1) ? user_access($arguments[0]) : user_access($arguments[0], $arguments[1]); - } - else { - $item['access'] = call_user_func_array($callback, $arguments); - } - } -} - -/** - * Localizes the router item title using t() or another callback. + * Localizes a menu link title using t() if possible. * * Translate the title and description to allow storage of English title * strings in the database, yet display of them in the language required * by the current user. * * @param $item - * A menu router item or a menu link item. - * @param $map - * The path as an array with objects already replaced. E.g., for path - * node/123 $map would be array('node', $node) where $node is the node - * object for node 123. - * @param $link_translate - * TRUE if we are translating a menu link item; FALSE if we are - * translating a menu router item. - * - * @return - * No return value. - * $item['title'] is localized according to $item['title_callback']. - * If an item's callback is check_plain(), $item['options']['html'] becomes - * TRUE. - * $item['description'] is computed using $item['description_callback'] if - * specified; otherwise it is translated using t(). - * When doing link translation and the $item['options']['attributes']['title'] - * (link title attribute) matches the description, it is translated as well. - */ -function _menu_item_localize(&$item, $map, $link_translate = FALSE) { + * A menu link entity. + */ +function _menu_item_localize(&$item) { // Allow default menu links to be translated. - // @todo Figure out a proper way to support translations of menu links, see - // https://drupal.org/node/2193777. - $title_callback = $item instanceof MenuLinkInterface && !$item->customized ? 't' : $item['title_callback']; $item['localized_options'] = $item['options']; // All 'class' attributes are assumed to be an array during rendering, but // links stored in the database may use an old string value. @@ -575,221 +256,20 @@ function _menu_item_localize(&$item, $map, $link_translate = FALSE) { if (isset($item['options']['attributes']['class']) && is_string($item['options']['attributes']['class'])) { $item['localized_options']['attributes']['class'] = explode(' ', $item['options']['attributes']['class']); } - // If we are translating the title of a menu link, and its title is the same - // as the corresponding router item, then we can use the title information - // from the router. If it's customized, then we need to use the link title - // 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'])) { - // 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. - // @todo Recheck this line once https://drupal.org/node/2084421 is in. - $item['title'] = isset($item['link_title']) ? $item['link_title'] : $item['title']; - if ($title_callback == 't') { - if (empty($item['title_arguments'])) { - $item['title'] = t($item['title']); - } - else { - $item['title'] = t($item['title'], menu_unserialize($item['title_arguments'], $map)); - } - } - elseif ($title_callback) { - if (empty($item['title_arguments'])) { - $item['title'] = $title_callback($item['title']); - } - else { - $item['title'] = call_user_func_array($title_callback, menu_unserialize($item['title_arguments'], $map)); - } - // Avoid calling check_plain again on l() function. - if ($title_callback == 'check_plain') { - $item['localized_options']['html'] = TRUE; - } - } - } - elseif ($link_translate) { - $item['title'] = $item['link_title']; - } - - // Translate description, see the motivation above. - if (!empty($item['description'])) { - $original_description = $item['description']; - } - if (!empty($item['description_arguments']) || !empty($item['description'])) { - $description_callback = $item['description_callback']; - // If the description callback is t(), call it directly. - if ($description_callback == 't') { - if (empty($item['description_arguments'])) { - $item['description'] = t($item['description']); - } - else { - $item['description'] = t($item['description'], menu_unserialize($item['description_arguments'], $map)); - } - } - elseif ($description_callback) { - // If there are no arguments, call the description callback directly. - if (empty($item['description_arguments'])) { - $item['description'] = $description_callback($item['description']); - } - // Otherwise, use call_user_func_array() to pass the arguments. - else { - $item['description'] = call_user_func_array($description_callback, menu_unserialize($item['description_arguments'], $map)); - } - } - } - // If the title and description are the same, use the translated description - // as a localized title. - if ($link_translate && isset($original_description) && isset($item['options']['attributes']['title']) && $item['options']['attributes']['title'] == $original_description) { - $item['localized_options']['attributes']['title'] = $item['description']; - } -} - -/** - * Handles dynamic path translation and menu access control. - * - * When a user arrives on a page such as node/5, this function determines - * what "5" corresponds to, by inspecting the page's menu path definition, - * node/%node. This will call node_load(5) to load the corresponding node - * object. - * - * It also works in reverse, to allow the display of tabs and menu items which - * contain these dynamic arguments, translating node/%node to node/5. - * - * Translation of menu item titles and descriptions are done here to - * allow for storage of English strings in the database, and translation - * to the language required to generate the current page. - * - * @param $router_item - * A menu router item - * @param $map - * An array of path arguments; for example, array('node', '5'). - * @param $to_arg - * Execute $item['to_arg_functions'] or not. Use only if you want to render a - * path from the menu table, for example tabs. - * - * @return - * Returns the map with objects loaded as defined in the - * $item['load_functions']. $item['access'] becomes TRUE if the item is - * accessible, FALSE otherwise. $item['href'] is set according to the map. - * If an error occurs during calling the load_functions (like trying to load - * a non-existent node) then this function returns FALSE. - */ -function _menu_translate(&$router_item, $map, $to_arg = FALSE) { - if ($to_arg && !empty($router_item['to_arg_functions'])) { - // Fill in missing path elements, such as the current uid. - _menu_link_map_translate($map, $router_item['to_arg_functions']); - } - // The $path_map saves the pieces of the path as strings, while elements in - // $map may be replaced with loaded objects. - $path_map = $map; - if (!empty($router_item['load_functions']) && !_menu_load_objects($router_item, $map)) { - // An error occurred loading an object. - $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'])) { - $tab_root_map = explode('/', $router_item['tab_root']); - } - if (isset($router_item['tab_parent'])) { - $tab_parent_map = explode('/', $router_item['tab_parent']); - } - for ($i = 0; $i < $router_item['number_parts']; $i++) { - if ($link_map[$i] == '%') { - $link_map[$i] = $path_map[$i]; - } - if (isset($tab_root_map[$i]) && $tab_root_map[$i] == '%') { - $tab_root_map[$i] = $path_map[$i]; - } - if (isset($tab_parent_map[$i]) && $tab_parent_map[$i] == '%') { - $tab_parent_map[$i] = $path_map[$i]; - } - } - $router_item['href'] = implode('/', $link_map); - $router_item['tab_root_href'] = implode('/', $tab_root_map); - $router_item['tab_parent_href'] = implode('/', $tab_parent_map); - $router_item['options'] = array(); - if (!empty($router_item['route_name'])) { - // Route-provided menu items do not have menu loaders, so replace the map - // with the link map. - $map = $link_map; - - $route_provider = \Drupal::getContainer()->get('router.route_provider'); - $route = $route_provider->getRouteByName($router_item['route_name']); - $router_item['access'] = menu_item_route_access($route, $router_item['href'], $map); + // If the menu link is defined in code and not customized, we can use t(). + if (!empty($item['machine_name']) && !$item['customized']) { + // @todo Figure out a proper way to support translations of menu links, see + // https://drupal.org/node/2193777. + $item['title'] = t($item['link_title']); } else { - // @todo: Remove once all routes are converted. - _menu_check_access($router_item, $map); - } - - // For performance, don't localize an item the user can't access. - if ($router_item['access']) { - _menu_item_localize($router_item, $map); - } - - return $map; -} - -/** - * Translates the path elements in the map using any to_arg helper function. - * - * @param $map - * An array of path arguments; for example, array('node', '5'). - * @param $to_arg_functions - * An array of helper functions; for example, array(2 => 'menu_tail_to_arg'). - * - * @see hook_menu() - */ -function _menu_link_map_translate(&$map, $to_arg_functions) { - $to_arg_functions = unserialize($to_arg_functions); - foreach ($to_arg_functions as $index => $function) { - // Translate place-holders into real values. - $arg = $function(!empty($map[$index]) ? $map[$index] : '', $map, $index); - if (!empty($map[$index]) || isset($arg)) { - $map[$index] = $arg; - } - else { - unset($map[$index]); - } + $item['title'] = $item['link_title']; } } -/** - * Returns a string containing the path relative to the current index. - */ -function menu_tail_to_arg($arg, $map, $index) { - return implode('/', array_slice($map, $index)); -} - -/** - * Loads the path as one string relative to the current index. - * - * To use this load function, you must specify the load arguments - * in the router item as: - * @code - * $item['load arguments'] = array('%map', '%index'); - * @endcode - * - * @see search_menu(). - */ -function menu_tail_load($arg, &$map, $index) { - $arg = implode('/', array_slice($map, $index)); - $map = array_slice($map, 0, $index); - return $arg; -} - /** * Provides menu link unserializing, access control, 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 @@ -829,7 +309,7 @@ function _menu_link_translate(&$item) { } // 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); } } @@ -841,62 +321,9 @@ function _menu_link_translate(&$item) { } } -/** - * Checks access to a menu item by mocking a request for a path. - * - * @param \Symfony\Component\Routing\Route $route - * Router for the given menu item. - * @param string $href - * The menu path with '%' replaced by arguments. - * @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. - * - */ -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); - } - // Attempt to match this path to provide a fully built request to the - // access checker. - try { - $request->attributes->add(\Drupal::service('router')->matchRequest($request)); - } - catch (ParamNotConvertedException $e) { - return FALSE; - } - - // Populate the map with any matching values from the request. - $path_bits = explode('/', trim($route->getPath(), '/')); - foreach ($map as $index => $map_item) { - $matches = array(); - // Search for placeholders wrapped by curly braces. For example, a path - // 'foo/{bar}/baz' would return 'bar'. - if (isset($path_bits[$index]) && preg_match('/{(?<placeholder>.*)}/', $path_bits[$index], $matches)) { - // If that placeholder is present on the request attributes, replace the - // placeholder in the map with the value. - if ($request->attributes->has($matches['placeholder'])) { - $map[$index] = $request->attributes->get($matches['placeholder']); - } - } - } - - return \Drupal::service('access_manager')->check($route, $request, \Drupal::currentUser()); -} - /** * Renders a menu tree based on the current path. * - * The tree is expanded based on the current path and dynamic paths are also - * changed according to the defined to_arg functions (for example the 'My - * account' link is changed from user/% to a link with the current user's uid). - * * @param $menu_name * The name of the menu. * @@ -1124,7 +551,7 @@ function menu_tree_page_data($menu_name, $max_depth = NULL, $only_active_trail = // Check if the active trail has been overridden for this menu tree. $active_path = menu_tree_get_path($menu_name); - // Load the router item corresponding to the current page. + // Load the request corresponding to the current page. $request = \Drupal::request(); $system_path = NULL; if ($route_name = $request->attributes->get(RouteObjectInterface::ROUTE_NAME)) { @@ -2064,9 +1491,9 @@ function menu_link_get_preferred($path = NULL, $selected_menu = NULL) { foreach ($menu_names as $menu_name) { if (empty($preferred_links[$path][$menu_name]) && isset($candidates[$link_path][$menu_name])) { $candidate_item = $candidates[$link_path][$menu_name]; - $map = explode('/', $path); - _menu_translate($candidate_item, $map); + $candidate_item['access'] = \Drupal::service('access_manager')->checkNamedRoute($candidate_item['route_name'], $candidate_item['route_parameters'], \Drupal::currentUser()); if ($candidate_item['access']) { + _menu_item_localize($candidate_item); $preferred_links[$path][$menu_name] = $candidate_item; if (empty($preferred_links[$path][MENU_PREFERRED_LINK])) { // Store the most specific link. @@ -2128,139 +1555,6 @@ function menu_reset_static_cache() { drupal_static_reset('menu_link_get_preferred'); } -/** - * Populates the database tables used by various menu functions. - * - * This function will clear and populate the {menu_router} table, add entries - * to {menu_links} for new router items, and then remove stale items from - * {menu_links}. - * - * @return - * TRUE if the menu was rebuilt, FALSE if another thread was rebuilding - * in parallel and the current thread just waited for completion. - */ -function menu_router_rebuild() { - if (!\Drupal::lock()->acquire(__FUNCTION__)) { - // Wait for another request that is already doing this work. - // We choose to block here since otherwise the router item may not - // be available during routing resulting in a 404. - \Drupal::lock()->wait(__FUNCTION__); - return FALSE; - } - - $transaction = db_transaction(); - - try { - // Ensure the route based router is up to date. - \Drupal::service('router.builder')->rebuildIfNeeded(); - list($menu) = menu_router_build(TRUE); - menu_link_rebuild_defaults(); - // Clear the menu, page and block caches. - menu_cache_clear_all(); - _menu_clear_page_cache(); - } - catch (Exception $e) { - $transaction->rollback(); - watchdog_exception('menu', $e); - } - - \Drupal::lock()->release(__FUNCTION__); - return TRUE; -} - -/** - * Collects and alters the menu definitions. - * - * @param bool $save - * (optional) Save the new router to the database. Defaults to FALSE. - */ -function menu_router_build($save = FALSE) { - // Ensure that all configuration used to build the menu items are loaded - // without overrides. - $old_state = \Drupal::configFactory()->getOverrideState(); - \Drupal::configFactory()->setOverrideState(FALSE); - // We need to manually call each module so that we can know which module - // a given item came from. - $callbacks = array(); - foreach (\Drupal::moduleHandler()->getImplementations('menu') as $module) { - $router_items = call_user_func($module . '_menu'); - if (isset($router_items) && is_array($router_items)) { - foreach (array_keys($router_items) as $path) { - $router_items[$path]['module'] = $module; - } - $callbacks = array_merge($callbacks, $router_items); - } - } - // Alter the menu as defined in modules, keys are like user/%user. - \Drupal::moduleHandler()->alter('menu', $callbacks); - \Drupal::configFactory()->setOverrideState($old_state); - foreach ($callbacks as $path => $router_item) { - // If the menu item is a default local task and incorrectly references a - // route, remove it. - // @todo This may be removed later depending on the outcome of - // http://drupal.org/node/1889790 - if (isset($router_item['type']) && $router_item['type'] == MENU_DEFAULT_LOCAL_TASK) { - unset($callbacks[$path]['route_name']); - } - // If the menu item references a route, normalize the route information - // into the old structure. Note that routes are keyed by name, not path, - // so the path of the route takes precedence. - if (isset($router_item['route_name'])) { - $router_item['page callback'] = 'USES_ROUTE'; - $router_item['access callback'] = TRUE; - $new_path = _menu_router_translate_route($router_item['route_name']); - - unset($callbacks[$path]); - $callbacks[$new_path] = $router_item; - } - } - list($menu, $masks) = _menu_router_build($callbacks, $save); - _menu_router_cache($menu); - - return array($menu, $masks); -} - -/** - * Translates a route name to its router item path. - * - * @param string $route_name - * The route name to translate. - * - * @return string - * The translated path pattern from the route. - */ -function _menu_router_translate_route($route_name) { - $outline = \Drupal::service('router.route_provider') - ->getRouteByName($route_name) - ->compile() - ->getPatternOutline(); - return trim($outline, '/'); -} - -/** - * Stores the menu router if we have it in memory. - */ -function _menu_router_cache($new_menu = NULL) { - $menu = &drupal_static(__FUNCTION__); - - if (isset($new_menu)) { - $menu = $new_menu; - } - return $menu; -} - -/** - * Gets the menu router. - */ -function menu_get_router() { - // Check first if we have it in memory already. - $menu = _menu_router_cache(); - if (empty($menu)) { - list($menu) = menu_router_build(); - } - return $menu; -} - /** * Saves menu links recursively for menu_links_rebuild_defaults(). */ @@ -2487,358 +1781,6 @@ function _menu_set_expanded_menus() { \Drupal::state()->set('menu_expanded', $names); } -/** - * Finds the router path which will serve this path. - * - * @param $link_path - * The path for we are looking up its router path. - * - * @return - * A path from $menu keys or empty if $link_path points to a nonexisting - * place. - */ -function _menu_find_router_path($link_path) { - // $menu will only have data during a menu rebuild. - $menu = _menu_router_cache(); - - $router_path = $link_path; - $parts = explode('/', $link_path, MENU_MAX_PARTS); - $ancestors = menu_get_ancestors($parts); - - if (empty($menu)) { - // Not during a menu rebuild, so look up in the database. - $router_path = (string) db_select('menu_router') - ->fields('menu_router', array('path')) - ->condition('path', $ancestors, 'IN') - ->orderBy('fit', 'DESC') - ->range(0, 1) - ->execute()->fetchField(); - } - elseif (!isset($menu[$router_path])) { - // Add an empty router path as a fallback. - $ancestors[] = ''; - foreach ($ancestors as $router_path) { - if (isset($menu[$router_path])) { - // Exit the loop leaving $router_path as the first match. - break; - } - } - // If we did not find the path, $router_path will be the empty string - // at the end of $ancestors. - } - return $router_path; -} - -/** - * Builds the router table based on the data from hook_menu(). - */ -function _menu_router_build($callbacks, $save = FALSE) { - // First pass: separate callbacks from paths, making paths ready for - // matching. Calculate fitness, and fill some default values. - $menu = array(); - $masks = array(); - $path_roots = array(); - foreach ($callbacks as $path => $item) { - $load_functions = array(); - $to_arg_functions = array(); - $fit = 0; - $move = FALSE; - - $parts = explode('/', $path, MENU_MAX_PARTS); - $path_roots[$parts[0]] = $parts[0]; - $number_parts = count($parts); - // We store the highest index of parts here to save some work in the fit - // calculation loop. - $slashes = $number_parts - 1; - // Extract load and to_arg functions. - foreach ($parts as $k => $part) { - $match = FALSE; - // Look for wildcards in the form allowed to be used in PHP functions, - // because we are using these to construct the load function names. - if (preg_match('/^%(|' . DRUPAL_PHP_FUNCTION_PATTERN . ')$/', $part, $matches)) { - if (empty($matches[1])) { - $match = TRUE; - $load_functions[$k] = NULL; - } - else { - if (function_exists($matches[1] . '_to_arg')) { - $to_arg_functions[$k] = $matches[1] . '_to_arg'; - $load_functions[$k] = NULL; - $match = TRUE; - } - if (function_exists($matches[1] . '_load')) { - $function = $matches[1] . '_load'; - // Create an array of arguments that will be passed to the _load - // function when this menu path is checked, if 'load arguments' - // exists. - $load_functions[$k] = isset($item['load arguments']) ? array($function => $item['load arguments']) : $function; - $match = TRUE; - } - } - } - if ($match) { - $parts[$k] = '%'; - } - else { - $fit |= 1 << ($slashes - $k); - } - } - if ($fit) { - $move = TRUE; - } - else { - // If there is no %, it fits maximally. - $fit = (1 << $number_parts) - 1; - } - $masks[$fit] = 1; - $item['_load_functions'] = $load_functions; - $item['to_arg_functions'] = empty($to_arg_functions) ? '' : serialize($to_arg_functions); - $item += array( - 'title' => '', - 'type' => MENU_NORMAL_ITEM, - 'module' => '', - '_number_parts' => $number_parts, - '_parts' => $parts, - '_fit' => $fit, - ); - $item += array( - // Default MENU_DEFAULT_LOCAL_TASKs to a weight of -10, so they appear as - // first tab by default. - 'weight' => ($item['type'] & MENU_DEFAULT_LOCAL_TASK) == MENU_DEFAULT_LOCAL_TASK ? -10 : 0, - '_visible' => (bool) ($item['type'] & MENU_VISIBLE_IN_BREADCRUMB), - '_tab' => (bool) ($item['type'] & MENU_IS_LOCAL_TASK), - ); - if ($move) { - $new_path = implode('/', $item['_parts']); - $menu[$new_path] = $item; - $sort[$new_path] = $number_parts; - } - else { - $menu[$path] = $item; - $sort[$path] = $number_parts; - } - } - array_multisort($sort, SORT_NUMERIC, $menu); - // Apply inheritance rules. - foreach ($menu as $path => $v) { - $item = &$menu[$path]; - if (!$item['_tab']) { - // Non-tab items. - $item['tab_parent'] = ''; - $item['tab_root'] = $path; - } - // If not specified, assign the default tab type for local tasks. - elseif (!isset($item['context'])) { - $item['context'] = MENU_CONTEXT_PAGE; - } - for ($i = $item['_number_parts'] - 1; $i; $i--) { - $parent_path = implode('/', array_slice($item['_parts'], 0, $i)); - if (isset($menu[$parent_path])) { - - $parent = &$menu[$parent_path]; - - // If we have no menu name, try to inherit it from parent items. - if (!isset($item['menu_name'])) { - // If the parent item of this item does not define a menu name (and no - // 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(); - if ($menu_name) { - $parent['menu_name'] = $menu_name; - } - } - // If the parent item defines a menu name, inherit it. - if (!empty($parent['menu_name'])) { - $item['menu_name'] = $parent['menu_name']; - } - } - if (!isset($item['tab_parent'])) { - // Parent stores the parent of the path. - $item['tab_parent'] = $parent_path; - } - if (!isset($item['tab_root']) && !$parent['_tab']) { - $item['tab_root'] = $parent_path; - } - // If an access callback is not found for a default local task we use - // the callback from the parent, since we expect them to be identical. - // In all other cases, the access parameters must be specified. - if (($item['type'] == MENU_DEFAULT_LOCAL_TASK) && !isset($item['access callback']) && isset($parent['access callback'])) { - $item['access callback'] = $parent['access callback']; - if (!isset($item['access arguments']) && isset($parent['access arguments'])) { - $item['access arguments'] = $parent['access arguments']; - } - } - // Same for page callbacks. - if (!isset($item['page callback']) && isset($parent['page callback'])) { - $item['page callback'] = $parent['page callback']; - if (!isset($item['page arguments']) && isset($parent['page arguments'])) { - $item['page arguments'] = $parent['page arguments']; - } - if (!isset($item['file path']) && isset($parent['file path'])) { - $item['file path'] = $parent['file path']; - } - if (!isset($item['file']) && isset($parent['file'])) { - $item['file'] = $parent['file']; - if (empty($item['file path']) && isset($item['module']) && isset($parent['module']) && $item['module'] != $parent['module']) { - $item['file path'] = drupal_get_path('module', $parent['module']); - } - } - } - // Same for load arguments: if a loader doesn't have any explict - // arguments, try to find arguments in the parent. - if (!isset($item['load arguments'])) { - foreach ($item['_load_functions'] as $k => $function) { - // This loader doesn't have any explict arguments... - if (!is_array($function)) { - // ... check the parent for a loader at the same position - // using the same function name and defining arguments... - if (isset($parent['_load_functions'][$k]) && is_array($parent['_load_functions'][$k]) && key($parent['_load_functions'][$k]) === $function) { - // ... and inherit the arguments on the child. - $item['_load_functions'][$k] = $parent['_load_functions'][$k]; - } - } - } - } - } - } - if (!isset($item['access callback']) && isset($item['access arguments'])) { - // Default callback. - $item['access callback'] = 'user_access'; - } - if (!isset($item['access callback']) || empty($item['page callback'])) { - $item['access callback'] = 0; - } - if (is_bool($item['access callback'])) { - $item['access callback'] = intval($item['access callback']); - } - - $item['load_functions'] = empty($item['_load_functions']) ? '' : serialize($item['_load_functions']); - $item += array( - 'access arguments' => array(), - 'access callback' => '', - 'page arguments' => array(), - 'page callback' => '', - 'title arguments' => array(), - 'title callback' => 't', - 'description' => '', - 'description arguments' => array(), - 'description callback' => 't', - 'position' => '', - 'context' => 0, - 'tab_parent' => '', - 'tab_root' => $path, - 'path' => $path, - 'file' => '', - 'file path' => '', - 'include file' => '', - 'route_name' => '', - ); - - // Calculate out the file to be included for each callback, if any. - if ($item['file']) { - $file_path = $item['file path'] ? $item['file path'] : drupal_get_path('module', $item['module']); - $item['include file'] = $file_path . '/' . $item['file']; - } - } - - // Sort the masks so they are in order of descending fit. - $masks = array_keys($masks); - rsort($masks); - - if ($save) { - $path_roots = array_values($path_roots); - // Update the path roots variable and reset the path alias whitelist cache - // if the list has changed. - if ($path_roots != \Drupal::state()->get('menu_path_roots')) { - \Drupal::state()->set('menu_path_roots', array_values($path_roots)); - \Drupal::service('path.alias_manager')->cacheClear(); - } - _menu_router_save($menu, $masks); - } - - return array($menu, $masks); -} - -/** - * Saves data from menu_router_build() to the router table. - */ -function _menu_router_save($menu, $masks) { - // Delete the existing router since we have some data to replace it. - db_truncate('menu_router')->execute(); - - // Prepare insert object. - $insert = db_insert('menu_router') - ->fields(array( - 'path', - 'load_functions', - 'to_arg_functions', - 'access_callback', - 'access_arguments', - 'page_callback', - 'page_arguments', - 'fit', - 'number_parts', - 'context', - 'tab_parent', - 'tab_root', - 'title', - 'title_callback', - 'title_arguments', - 'type', - 'description', - 'description_callback', - 'description_arguments', - 'position', - 'weight', - 'include_file', - 'route_name', - )); - - $num_records = 0; - - foreach ($menu as $item) { - // Fill in insert object values. - $insert->values(array( - 'path' => $item['path'], - 'load_functions' => $item['load_functions'], - 'to_arg_functions' => $item['to_arg_functions'], - 'access_callback' => $item['access callback'], - 'access_arguments' => serialize($item['access arguments']), - 'page_callback' => $item['page callback'], - 'page_arguments' => serialize($item['page arguments']), - 'fit' => $item['_fit'], - 'number_parts' => $item['_number_parts'], - 'context' => $item['context'], - 'tab_parent' => $item['tab_parent'], - 'tab_root' => $item['tab_root'], - 'title' => $item['title'], - 'title_callback' => $item['title callback'], - 'title_arguments' => ($item['title arguments'] ? serialize($item['title arguments']) : ''), - 'type' => $item['type'], - 'description' => $item['description'], - 'description_callback' => $item['description callback'], - 'description_arguments' => ($item['description arguments'] ? serialize($item['description arguments']) : ''), - 'position' => $item['position'], - 'weight' => $item['weight'], - 'include_file' => $item['include file'], - 'route_name' => $item['route_name'], - )); - - // Execute in batches to avoid the memory overhead of all of those records - // in the query object. - if (++$num_records == 20) { - $insert->execute(); - $num_records = 0; - } - } - // Insert any remaining records. - $insert->execute(); - // Store the masks. - \Drupal::state()->set('menu.masks', $masks); - - return $menu; -} /** * Checks whether the site is in maintenance mode. diff --git a/core/includes/path.inc b/core/includes/path.inc index 912610d9886f9ece4d38e970d608fc84c08d55f9..3193d0ea3ddfaad661d662513f5d83e891eabc58 100644 --- a/core/includes/path.inc +++ b/core/includes/path.inc @@ -5,8 +5,9 @@ * Functions to handle paths in Drupal. */ +use Drupal\Component\Utility\Url; +use Drupal\Core\ParamConverter\ParamNotConvertedException; use Drupal\Core\Routing\RequestHelper; -use Symfony\Component\HttpFoundation\Request; /** * Check if the current page is the front page. @@ -183,57 +184,42 @@ function path_get_admin_paths() { /** * Checks a path exists and the current user has access to it. * - * @param $path + * @param string $path * The path to check. - * @param $dynamic_allowed - * Whether paths with menu wildcards (like user/%) should be allowed. * - * @return + * @return bool * TRUE if it is a valid path AND the current user has access permission, * FALSE otherwise. */ -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; +function drupal_valid_path($path) { + // External URLs and the front page are always valid. + if ($path == '<front>' || Url::isExternal($path)) { + return TRUE; } - 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); + // Check the routing system. + $collection = \Drupal::service('router.route_provider')->getRoutesByPattern('/' . $path); + if ($collection->count() == 0) { + return FALSE; } - 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()) { - $item['link_path'] = $item['path']; - $item['link_title'] = $item['title']; - $item['external'] = FALSE; - $item['options'] = ''; - _menu_link_translate($item); - $route_name = $item['route_name']; - } + + $request = RequestHelper::duplicate(\Drupal::request(), '/' . $path); + $request->attributes->set('_system_path', $path); + + // We indicate that a menu administrator is running the menu access check. + $request->attributes->set('_menu_admin', TRUE); + + // Attempt to match this path to provide a fully built request to the + // access checker. + try { + $request->attributes->add(\Drupal::service('router')->matchRequest($request)); } - // Check the new routing system. - if (!empty($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); + catch (ParamNotConvertedException $e) { + return FALSE; } - $menu_admin = FALSE; - return !empty($item['access']); + + // Consult the accsss manager. + $routes = $collection->all(); + $route = reset($routes); + return \Drupal::service('access_manager')->check($route, $request, \Drupal::currentUser()); } diff --git a/core/lib/Drupal/Core/EventSubscriber/RouterRebuildSubscriber.php b/core/lib/Drupal/Core/EventSubscriber/RouterRebuildSubscriber.php index d432656bf05acbb03d4b48006cef56c43d0dfe4a..98bf05c5422a7dd55df4159c4775d3c93b54c5e4 100644 --- a/core/lib/Drupal/Core/EventSubscriber/RouterRebuildSubscriber.php +++ b/core/lib/Drupal/Core/EventSubscriber/RouterRebuildSubscriber.php @@ -8,6 +8,7 @@ namespace Drupal\Core\EventSubscriber; use Drupal\Core\Cache\Cache; +use Drupal\Core\Lock\LockBackendInterface; use Drupal\Core\Routing\RouteBuilderInterface; use Drupal\Core\Routing\RoutingEvents; use Symfony\Component\EventDispatcher\Event; @@ -16,7 +17,7 @@ use Symfony\Component\HttpKernel\KernelEvents; /** - * Rebuilds the router and menu_router if necessary. + * Rebuilds the default menu links and runs menu-specific code if necessary. */ class RouterRebuildSubscriber implements EventSubscriberInterface { @@ -25,14 +26,22 @@ class RouterRebuildSubscriber implements EventSubscriberInterface { */ protected $routeBuilder; + /** + * @var \Drupal\Core\Lock\LockBackendInterface + */ + protected $lock; + /** * Constructs the RouterRebuildSubscriber object. * * @param \Drupal\Core\Routing\RouteBuilderInterface $route_builder * The route builder. + * @param \Drupal\Core\Lock\LockBackendInterface $lock + * The lock backend. */ - public function __construct(RouteBuilderInterface $route_builder) { + public function __construct(RouteBuilderInterface $route_builder, LockBackendInterface $lock) { $this->routeBuilder = $route_builder; + $this->lock = $lock; } /** @@ -46,16 +55,44 @@ public function onKernelTerminate(PostResponseEvent $event) { } /** - * Rebuilds the menu_router and deletes the local_task cache tag. + * Rebuilds the menu links and deletes the local_task cache tag. * * @param \Symfony\Component\EventDispatcher\Event $event * The event object. */ public function onRouterRebuild(Event $event) { - menu_router_rebuild(); + $this->menuLinksRebuild(); Cache::deleteTags(array('local_task' => 1)); } + /** + * Perform menu-specific rebuilding. + */ + protected function menuLinksRebuild() { + if ($this->lock->acquire(__FUNCTION__)) { + $transaction = db_transaction(); + try { + // Ensure the menu links are up to date. + menu_link_rebuild_defaults(); + // Clear the menu, page and block caches. + menu_cache_clear_all(); + _menu_clear_page_cache(); + } + catch (\Exception $e) { + $transaction->rollback(); + watchdog_exception('menu', $e); + } + + $this->lock->release(__FUNCTION__); + } + else { + // Wait for another request that is already doing this work. + // We choose to block here since otherwise the router item may not + // be available during routing resulting in a 404. + $this->lock->wait(__FUNCTION__); + } + } + /** * Registers the methods in this class that should be listeners. * diff --git a/core/modules/basic_auth/lib/Drupal/basic_auth/Authentication/Provider/BasicAuth.php b/core/modules/basic_auth/lib/Drupal/basic_auth/Authentication/Provider/BasicAuth.php index 79fe59f62053b40e2e7ead65eb6952f776d855b3..282b89102dcd2fe077fa9ad08b6bbcd071c57623 100644 --- a/core/modules/basic_auth/lib/Drupal/basic_auth/Authentication/Provider/BasicAuth.php +++ b/core/modules/basic_auth/lib/Drupal/basic_auth/Authentication/Provider/BasicAuth.php @@ -70,7 +70,7 @@ public function cleanup(Request $request) {} */ public function handleException(GetResponseForExceptionEvent $event) { $exception = $event->getException(); - if (user_is_anonymous() && $exception instanceof AccessDeniedHttpException) { + if ($GLOBALS['user']->isAnonymous() && $exception instanceof AccessDeniedHttpException) { if (!$this->applies($event->getRequest())) { $site_name = $this->configFactory->get('system.site')->get('name'); global $base_url; diff --git a/core/modules/block/custom_block/lib/Drupal/custom_block/Tests/CustomBlockTypeTest.php b/core/modules/block/custom_block/lib/Drupal/custom_block/Tests/CustomBlockTypeTest.php index 7593adb461b80355d4c3cb821955ea470ddba79a..82cb852056626367740e846678ef91efb3c593f5 100644 --- a/core/modules/block/custom_block/lib/Drupal/custom_block/Tests/CustomBlockTypeTest.php +++ b/core/modules/block/custom_block/lib/Drupal/custom_block/Tests/CustomBlockTypeTest.php @@ -158,7 +158,7 @@ public function testsCustomBlockAddTypes() { foreach ($themes as $default_theme) { // Change the default theme. $theme_settings->set('default', $default_theme)->save(); - menu_router_rebuild(); + \Drupal::service('router.builder')->rebuild(); // For each enabled theme, go to its block page and test the redirects. $themes = array('bartik', 'stark', 'seven'); diff --git a/core/modules/book/lib/Drupal/book/BookManager.php b/core/modules/book/lib/Drupal/book/BookManager.php index 8edd4d70da4141583a00f5efb952d2574db3a919..0c8dfd42ad5f274d2a08d164a5d30590d68a6863 100644 --- a/core/modules/book/lib/Drupal/book/BookManager.php +++ b/core/modules/book/lib/Drupal/book/BookManager.php @@ -865,7 +865,7 @@ protected function _menu_tree_check_access(&$tree) { * 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). + * link-specific preparation. * * @param $item * A menu link. diff --git a/core/modules/contact/contact.module b/core/modules/contact/contact.module index fe9079990f75a38d6b0a8afd990963786646cbee..6a96f4de7e01d70b417d96d6552146e663c26efc 100644 --- a/core/modules/contact/contact.module +++ b/core/modules/contact/contact.module @@ -228,7 +228,7 @@ function contact_form_user_form_alter(&$form, &$form_state) { '#weight' => 5, ); $account = $form_state['controller']->getEntity(); - $account_data = !user_is_anonymous() ? \Drupal::service('user.data')->get('contact', $account->id(), 'enabled') : NULL; + $account_data = !\Drupal::currentUser()->isAnonymous() ? \Drupal::service('user.data')->get('contact', $account->id(), 'enabled') : NULL; $form['contact']['contact'] = array( '#type' => 'checkbox', '#title' => t('Personal contact form'), diff --git a/core/modules/content_translation/content_translation.module b/core/modules/content_translation/content_translation.module index 8c65f1e9f37c6bdffe34f86765ff91dbb8814a23..a866a282bbd5f1bd64c2d9ca119ab7f8f9c2d042 100644 --- a/core/modules/content_translation/content_translation.module +++ b/core/modules/content_translation/content_translation.module @@ -181,62 +181,6 @@ function content_translation_entity_operation_alter(array &$operations, \Drupal\ } } -/** - * Implements hook_menu(). - * - * @todo Split this into route definition and menu link definition. See - * https://drupal.org/node/1987882 and https://drupal.org/node/2047633. - */ -function content_translation_menu() { - $items = array(); - - // Create tabs for all possible entity types. - foreach (\Drupal::entityManager()->getDefinitions() as $entity_type_id => $entity_type) { - // Provide the translation UI only for enabled types. - if (content_translation_enabled($entity_type_id)) { - $path = _content_translation_link_to_router_path($entity_type_id, $entity_type->getLinkTemplate('canonical')); - $entity_position = count(explode('/', $path)) - 1; - $keys = array_flip(array('load_arguments')); - $translation = $entity_type->get('translation'); - $menu_info = array_intersect_key($translation['content_translation'], $keys) + array('file' => 'content_translation.pages.inc'); - $item = array(); - - // Plugin annotations cannot contain spaces, thus we need to restore them - // from underscores. - foreach ($menu_info as $key => $value) { - $item[str_replace('_', ' ', $key)] = $value; - } - - // Add translation callback. - // @todo Add the access callback instead of replacing it as soon as the - // routing system supports multiple callbacks. - $language_position = $entity_position + 3; - $args = array($entity_position, $language_position, $language_position + 1); - $items["$path/translations/add/%language/%language"] = array( - 'title' => 'Add', - 'route_name' => "content_translation.translation_add_$entity_type_id", - 'weight' => 1, - ); - - // Edit translation callback. - $args = array($entity_position, $language_position); - $items["$path/translations/edit/%language"] = array( - 'title' => 'Edit', - 'route_name' => "content_translation.translation_edit_$entity_type_id", - 'weight' => 1, - ); - - // Delete translation callback. - $items["$path/translations/delete/%language"] = array( - 'title' => 'Delete', - 'route_name' => "content_translation.delete_$entity_type_id", - ) + $item; - } - } - - return $items; -} - /** * Implements hook_menu_alter(). * @@ -973,7 +917,7 @@ function content_translation_language_configuration_element_submit(array $form, if (content_translation_enabled($context['entity_type'], $context['bundle']) != $enabled) { content_translation_set_config($context['entity_type'], $context['bundle'], 'enabled', $enabled); entity_info_cache_clear(); - menu_router_rebuild(); + \Drupal::service('router.builder')->setRebuildNeeded(); } } @@ -1041,5 +985,5 @@ function content_translation_save_settings($settings) { // Ensure entity and menu router information are correctly rebuilt. entity_info_cache_clear(); - menu_router_rebuild(); + \Drupal::service('router.builder')->setRebuildNeeded(); } diff --git a/core/modules/content_translation/lib/Drupal/content_translation/Tests/ContentTranslationTestBase.php b/core/modules/content_translation/lib/Drupal/content_translation/Tests/ContentTranslationTestBase.php index c753114dcab4486b6d06b9eb23e90894f02715c8..09afe8ca762fb6de6988f9abdfe22dc0ba0a763a 100644 --- a/core/modules/content_translation/lib/Drupal/content_translation/Tests/ContentTranslationTestBase.php +++ b/core/modules/content_translation/lib/Drupal/content_translation/Tests/ContentTranslationTestBase.php @@ -166,7 +166,7 @@ protected function enableTranslation() { content_translation_set_config($this->entityTypeId, $this->bundle, 'enabled', TRUE); drupal_static_reset(); entity_info_cache_clear(); - menu_router_rebuild(); + \Drupal::service('router.builder')->rebuild(); } /** diff --git a/core/modules/menu/lib/Drupal/menu/Form/MenuDeleteForm.php b/core/modules/menu/lib/Drupal/menu/Form/MenuDeleteForm.php index 57e45c1fa23e73d9e51cb03edc93a8e09c7c0a00..709c71bb041f7f0d7cc619006084227980602c0b 100644 --- a/core/modules/menu/lib/Drupal/menu/Form/MenuDeleteForm.php +++ b/core/modules/menu/lib/Drupal/menu/Form/MenuDeleteForm.php @@ -104,7 +104,7 @@ public function submit(array $form, array &$form_state) { return; } - // Reset all the menu links defined by the system via hook_menu(). + // Reset all the menu links defined by the system via hook_menu_link_defaults(). // @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(); $menu_links = $this->storageController->loadMultiple($result); diff --git a/core/modules/menu/lib/Drupal/menu/MenuFormController.php b/core/modules/menu/lib/Drupal/menu/MenuFormController.php index c054484311b8f324adf742ef7b0fee0273aa3410..d6720a7a408271986d1354073afadf5b21dbc667 100644 --- a/core/modules/menu/lib/Drupal/menu/MenuFormController.php +++ b/core/modules/menu/lib/Drupal/menu/MenuFormController.php @@ -235,8 +235,6 @@ public function save(array $form, array &$form_state) { * their form submit handler. */ protected function buildOverviewForm(array &$form, array &$form_state) { - global $menu_admin; - // Ensure that menu_overview_form_submit() knows the parents of this form // section. $form['#tree'] = TRUE; @@ -261,10 +259,11 @@ protected function buildOverviewForm(array &$form, array &$form_state) { $tree = menu_tree_data($links); $node_links = array(); menu_tree_collect_node_links($tree, $node_links); + // We indicate that a menu administrator is running the menu access check. - $menu_admin = TRUE; + $this->getRequest()->attributes->set('_menu_admin', TRUE); menu_tree_check_access($tree, $node_links); - $menu_admin = FALSE; + $this->getRequest()->attributes->set('_menu_admin', FALSE); $form = array_merge($form, $this->buildOverviewTreeForm($tree, $delta)); $form['#empty_text'] = t('There are no menu links yet. <a href="@link">Add link</a>.', array('@link' => url('admin/structure/menu/manage/' . $this->entity->id() .'/add'))); diff --git a/core/modules/menu/menu.install b/core/modules/menu/menu.install index c1615921aec8a567c4eea9af5bb864d50c078393..037fc62531174982df4780c8463de9c69ca094a0 100644 --- a/core/modules/menu/menu.install +++ b/core/modules/menu/menu.install @@ -17,7 +17,6 @@ function menu_install() { // \Drupal\Core\Extension\ModuleHandler::install(). // @see https://drupal.org/node/2181151 \Drupal::service('router.builder')->rebuild(); - menu_router_rebuild(); if (\Drupal::moduleHandler()->moduleExists('node')) { $node_types = array_keys(node_type_get_names()); foreach ($node_types as $type_id) { @@ -33,5 +32,5 @@ function menu_install() { * Implements hook_uninstall(). */ function menu_uninstall() { - menu_router_rebuild(); + \Drupal::service('router.builder')->setRebuildNeeded(); } 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 10d998e5c27fc2b29a8670206cb716b92b150dbd..ee9d0b8584c6f57fec118ded1f4da44f2ad3ae11 100644 --- a/core/modules/menu_link/lib/Drupal/menu_link/MenuLinkStorageController.php +++ b/core/modules/menu_link/lib/Drupal/menu_link/MenuLinkStorageController.php @@ -7,15 +7,9 @@ namespace Drupal\menu_link; -use Drupal\Component\Uuid\UuidInterface; use Drupal\Core\Entity\DatabaseStorageController; use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Entity\EntityStorageException; -use Drupal\Core\Database\Connection; -use Drupal\Core\Entity\EntityTypeInterface; -use Drupal\field\FieldInfo; -use Symfony\Component\DependencyInjection\ContainerInterface; -use Symfony\Cmf\Component\Routing\RouteProviderInterface; /** * Controller class for menu links. @@ -25,13 +19,6 @@ */ class MenuLinkStorageController extends DatabaseStorageController implements MenuLinkStorageControllerInterface { - /** - * Contains all {menu_router} fields without weight. - * - * @var array - */ - protected static $routerItemFields; - /** * Indicates whether the delete operation should re-parent children items. * @@ -39,35 +26,6 @@ class MenuLinkStorageController extends DatabaseStorageController implements Men */ protected $preventReparenting = FALSE; - /** - * The route provider service. - * - * @var \Symfony\Cmf\Component\Routing\RouteProviderInterface - */ - protected $routeProvider; - - /** - * Overrides DatabaseStorageController::__construct(). - * - * @param \Drupal\Core\Entity\EntityTypeInterface $entity_type - * The entity type definition. - * @param \Drupal\Core\Database\Connection $database - * The database connection to be used. - * @param \Drupal\Component\Uuid\UuidInterface $uuid_service - * The UUID Service. - * @param \Symfony\Cmf\Component\Routing\RouteProviderInterface $route_provider - * The route provider service. - */ - public function __construct(EntityTypeInterface $entity_type, Connection $database, UuidInterface $uuid_service, RouteProviderInterface $route_provider) { - parent::__construct($entity_type, $database, $uuid_service); - - $this->routeProvider = $route_provider; - - if (empty(static::$routerItemFields)) { - static::$routerItemFields = array_diff(drupal_schema_fields_sql('menu_router'), array('weight')); - } - } - /** * {@inheritdoc} */ @@ -80,29 +38,6 @@ public function create(array $values = array()) { return parent::create($values); } - /** - * {@inheritdoc} - */ - public static function createInstance(ContainerInterface $container, EntityTypeInterface $entity_type) { - return new static( - $entity_type, - $container->get('database'), - $container->get('uuid'), - $container->get('router.route_provider') - ); - } - - /** - * Overrides DatabaseStorageController::buildQuery(). - */ - 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->fields('m', static::$routerItemFields); - return $query; - } - /** * Overrides DatabaseStorageController::save(). */ diff --git a/core/modules/options/lib/Drupal/options/Tests/OptionsFieldUnitTestBase.php b/core/modules/options/lib/Drupal/options/Tests/OptionsFieldUnitTestBase.php index f084a9c91a919908c9ba3320a5dd4ddf9d5092e7..5468547eb9da207c55a24bdb333c3d4ab07b9db4 100644 --- a/core/modules/options/lib/Drupal/options/Tests/OptionsFieldUnitTestBase.php +++ b/core/modules/options/lib/Drupal/options/Tests/OptionsFieldUnitTestBase.php @@ -55,7 +55,7 @@ class OptionsFieldUnitTestBase extends FieldUnitTestBase { */ public function setUp() { parent::setUp(); - $this->installSchema('system', array('router', 'menu_router')); + $this->installSchema('system', array('router')); $this->fieldDefinition = array( 'name' => $this->fieldName, diff --git a/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php b/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php index e62405709ff02a6f6baa69739c97719ee0e8d503..a442dd076611068e039369be831b3fd4d8dc2187 100644 --- a/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php +++ b/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php @@ -324,7 +324,7 @@ protected function drupalCreateContentType(array $values = array()) { ); $type = entity_create('node_type', $values); $status = $type->save(); - menu_router_rebuild(); + \Drupal::service('router.builder')->rebuild(); $this->assertEqual($status, SAVED_NEW, String::format('Created content type %type.', array('%type' => $type->id()))); diff --git a/core/modules/system/lib/Drupal/system/Tests/Menu/MenuRouterRebuildTest.php b/core/modules/system/lib/Drupal/system/Tests/Menu/MenuRouterRebuildTest.php index 418c451430beb09322264737062f4ebc8352e914..93bb4466c6f71d332b460b2bcf6454a65a03700a 100644 --- a/core/modules/system/lib/Drupal/system/Tests/Menu/MenuRouterRebuildTest.php +++ b/core/modules/system/lib/Drupal/system/Tests/Menu/MenuRouterRebuildTest.php @@ -49,7 +49,7 @@ function setUp() { public function testMenuRouterRebuildContext() { // Enter a language context before rebuilding the menu router tables. \Drupal::configFactory()->setLanguage(language_load('nl')); - menu_router_rebuild(); + \Drupal::service('router.builder')->rebuild(); // Check that the language context was not used for building the menu item. $menu_items = \Drupal::entityManager()->getStorageController('menu_link')->loadByProperties(array('route_name' => 'menu_test.context')); 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 f631d6fbbaf4fb2ac44562888523a7fc2b4ea373..72fe06af24bb96d3fa2dc4247c4d5f9f5736de41 100644 --- a/core/modules/system/lib/Drupal/system/Tests/Menu/MenuRouterTest.php +++ b/core/modules/system/lib/Drupal/system/Tests/Menu/MenuRouterTest.php @@ -10,7 +10,7 @@ use Drupal\simpletest\WebTestBase; /** - * Tests menu router and hook_menu() functionality. + * Tests menu router and hook_menu_link_defaults() functionality. */ class MenuRouterTest extends WebTestBase { @@ -45,7 +45,7 @@ class MenuRouterTest extends WebTestBase { public static function getInfo() { return array( 'name' => 'Menu router', - 'description' => 'Tests menu router and hook_menu() functionality.', + 'description' => 'Tests menu router and hook_menu_link_defaults() functionality.', 'group' => 'Menu', ); } @@ -69,7 +69,6 @@ public function testMenuIntegration() { $this->doTestMenuLinkMaintain(); $this->doTestMenuLinkOptions(); $this->doTestMenuItemHooks(); - $this->doTestDescriptionMenuItems(); $this->doTestHookMenuIntegration(); $this->doTestExoticPath(); } @@ -119,7 +118,6 @@ protected function doTestDescriptionMenuItems() { // Verify that the menu router item title is output as page title. $this->drupalGet('menu_callback_description'); $this->assertText(t('Menu item description text')); - $this->assertRaw(check_plain('<strong>Menu item description arguments</strong>')); } /** @@ -169,7 +167,7 @@ protected function doTestMenuLinkMaintain() { } /** - * Tests for menu_name parameter for hook_menu(). + * Tests for menu_name parameter for hook_menu_link_defaults(). */ protected function doTestMenuName() { $admin_user = $this->drupalCreateUser(array('administer site configuration')); diff --git a/core/modules/system/lib/Drupal/system/Tests/Menu/RebuildTest.php b/core/modules/system/lib/Drupal/system/Tests/Menu/RebuildTest.php deleted file mode 100644 index e02c9c4f23d45b5e6412d295dd6d819ebfdc9f1f..0000000000000000000000000000000000000000 --- a/core/modules/system/lib/Drupal/system/Tests/Menu/RebuildTest.php +++ /dev/null @@ -1,49 +0,0 @@ -<?php - -/** - * @file - * Definition of Drupal\system\Tests\Menu\RebuildTest. - */ - -namespace Drupal\system\Tests\Menu; - -use Drupal\Core\Routing\RouteBuilderInterface; -use Drupal\simpletest\WebTestBase; - -/** - * Tests rebuilding the router. - */ -class RebuildTest extends WebTestBase { - public static function getInfo() { - return array( - 'name' => 'Menu rebuild test', - 'description' => 'Test rebuilding of menu.', - 'group' => 'Menu', - ); - } - - /** - * Tests that set a router rebuild needed works. - */ - function testMenuRebuild() { - // Check if 'admin' path exists. - $admin_exists = db_query('SELECT path from {menu_router} WHERE path = :path', array(':path' => 'admin'))->fetchField(); - $this->assertEqual($admin_exists, 'admin', "The path 'admin/' exists prior to deleting."); - - // Delete the path item 'admin', and test that the path doesn't exist in the database. - db_delete('menu_router') - ->condition('path', 'admin') - ->execute(); - $admin_exists = db_query('SELECT path from {menu_router} WHERE path = :path', array(':path' => 'admin'))->fetchField(); - $this->assertFalse($admin_exists, "The path 'admin/' has been deleted and doesn't exist in the database."); - - // Now we set the router to be rebuilt. After the rebuild 'admin' should exist. - \Drupal::service('router.builder')->setRebuildNeeded(); - - // The request should trigger the rebuild. - $this->drupalGet('<front>'); - $admin_exists = db_query('SELECT path from {menu_router} WHERE path = :path', array(':path' => 'admin'))->fetchField(); - $this->assertEqual($admin_exists, 'admin', "The menu has been rebuilt, the path 'admin' now exists again."); - } - -} diff --git a/core/modules/system/lib/Drupal/system/Tests/Menu/TreeAccessTest.php b/core/modules/system/lib/Drupal/system/Tests/Menu/TreeAccessTest.php index df10877630d34b3154db851ff6fb14c12e45a33b..974208f5d0dcc103c578a3468113f45d43a7f504 100644 --- a/core/modules/system/lib/Drupal/system/Tests/Menu/TreeAccessTest.php +++ b/core/modules/system/lib/Drupal/system/Tests/Menu/TreeAccessTest.php @@ -14,7 +14,7 @@ use Symfony\Component\Routing\RouteCollection; /** - * Tests the access check for menu tree using both hook_menu() and route items. + * Tests the access check for menu tree using both menu links and route items. */ class TreeAccessTest extends DrupalUnitTestBase { @@ -43,7 +43,7 @@ class TreeAccessTest extends DrupalUnitTestBase { public static function getInfo() { return array( 'name' => 'Menu tree access', - 'description' => 'Tests the access check for menu tree using both hook_menu() and route items.', + 'description' => 'Tests the access check for menu tree using both menu links and route items.', 'group' => 'Menu', ); } 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 d6927181657c947ada248afd3ef218c36a0998f8..bc80cb584f244d479758274416859d86ca3d2d92 100644 --- a/core/modules/system/lib/Drupal/system/Tests/Menu/TreeOutputTest.php +++ b/core/modules/system/lib/Drupal/system/Tests/Menu/TreeOutputTest.php @@ -32,7 +32,7 @@ public static function getInfo() { function setUp() { parent::setUp(); - $this->installSchema('system', array('router', 'menu_router')); + $this->installSchema('system', array('router')); } /** diff --git a/core/modules/system/lib/Drupal/system/Tests/Routing/RouterPermissionTest.php b/core/modules/system/lib/Drupal/system/Tests/Routing/RouterPermissionTest.php index 060303a525006ef582aa4d356b1d39f22d888887..e33156d917c4c5b650c6c8f7a15f1f8062998e05 100644 --- a/core/modules/system/lib/Drupal/system/Tests/Routing/RouterPermissionTest.php +++ b/core/modules/system/lib/Drupal/system/Tests/Routing/RouterPermissionTest.php @@ -7,6 +7,7 @@ namespace Drupal\system\Tests\Routing; +use Drupal\Core\Routing\RequestHelper; use Drupal\simpletest\WebTestBase; use Symfony\Component\Routing\Exception\ResourceNotFoundException; @@ -37,17 +38,6 @@ public function testPermissionAccess() { $path = 'router_test/test7'; $this->drupalGet($path); $this->assertResponse(403, "Access denied for a route where we don't have a permission"); - // An invalid path should throw an exception. - $map = array(); - $route = \Drupal::service('router.route_provider')->getRouteByName('router_test.7'); - try { - menu_item_route_access($route, $path . 'invalid', $map); - $exception = FALSE; - } - catch (ResourceNotFoundException $e) { - $exception = TRUE; - } - $this->assertTrue($exception, 'A ResourceNotFoundException was thrown while checking access for an invalid route.'); $this->drupalGet('router_test/test8'); $this->assertResponse(403, 'Access denied by default if no access specified'); diff --git a/core/modules/system/lib/Drupal/system/Tests/System/AdminTest.php b/core/modules/system/lib/Drupal/system/Tests/System/AdminTest.php index 900a4fa5334294098f1180136506994f2a613f5d..44cccb2ca7ea5a3a50db5d6037505bc2cacad556 100644 --- a/core/modules/system/lib/Drupal/system/Tests/System/AdminTest.php +++ b/core/modules/system/lib/Drupal/system/Tests/System/AdminTest.php @@ -53,12 +53,10 @@ function testAdminPages() { // Verify that all visible, top-level administration links are listed on // the main administration page. - foreach (menu_get_router() as $path => $item) { - if (strpos($path, 'admin/') === 0 && ($item['type'] & MENU_VISIBLE_IN_TREE) && $item['_number_parts'] == 2) { - $this->assertLink($item['title']); - $this->assertLinkByHref($path); - $this->assertText($item['description']); - } + foreach ($this->getTopLevelMenuLinks() as $item) { + $this->assertLink($item['title']); + $this->assertLinkByHref($item['link_path']); + $this->assertText($item['localized_options']['attributes']['title']); } // For each administrative listing page on which the Locale module appears, @@ -110,6 +108,31 @@ function testAdminPages() { } } + /** + * Returns all top level menu links. + * + * @return \Drupal\menu_link\MenuLinkInterface[] + */ + protected function getTopLevelMenuLinks() { + $route_provider = \Drupal::service('router.route_provider'); + $routes = array(); + foreach ($route_provider->getAllRoutes() as $key => $value) { + $path = $value->getPath(); + if (strpos($path, '/admin/') === 0 && count(explode('/', $path)) == 3) { + $routes[$key] = $key; + } + } + $menu_link_ids = \Drupal::entityQuery('menu_link') + ->condition('route_name', $routes) + ->execute(); + + $menu_items = \Drupal::entityManager()->getStorageController('menu_link')->loadMultiple($menu_link_ids); + foreach ($menu_items as &$menu_item) { + _menu_link_translate($menu_item); + } + return $menu_items; + } + /** * Test compact mode. */ diff --git a/core/modules/system/system.admin.inc b/core/modules/system/system.admin.inc index ebcf07cc0f00082d3ddfd697fc3a1283cfe69523..37a30e4c71d7035ecab9e377745db4bdfb3ddc03 100644 --- a/core/modules/system/system.admin.inc +++ b/core/modules/system/system.admin.inc @@ -30,12 +30,6 @@ function system_theme_default() { ->set('default', $theme) ->save(); - // Rebuild the menu. This duplicates the menu_router_rebuild() in - // theme_enable(). However, modules must know the current default theme in - // order to use this information in hook_menu() or hook_menu_alter() - // implementations, and saving the configuration before the theme_enable() - // could result in a race condition where the theme is default but not - // enabled. \Drupal::service('router.builder')->setRebuildNeeded(); // The status message depends on whether an admin theme is currently in use: diff --git a/core/modules/system/system.api.php b/core/modules/system/system.api.php index 63a848e885b8126a47ef93bd8d6a87d43a6dca68..b830cdee1e2fb4d800f218f95c11c87f1974c9b1 100644 --- a/core/modules/system/system.api.php +++ b/core/modules/system/system.api.php @@ -499,94 +499,6 @@ function hook_menu_link_defaults_alter(&$links) { $links['user.logout']['link_title'] = t('Logout'); } -/** - * Define links for menus. - * - * @section sec_menu_link Creating Menu Items - * Menu item example of type MENU_NORMAL_ITEM: - * @code - * // Make "Foo settings" appear on the admin Config page - * $items['admin/config/system/foo'] = array( - * 'title' => 'Foo settings', - * 'type' => MENU_NORMAL_ITEM, - * 'route_name' => 'foo.settings' - * ); - * @endcode - * - * @todo The section that used to be here about path argument substitution has - * been removed, but is still referred to in the return section. It needs to - * be added back in, or a corrected version of it. - * - * @return - * An array of menu items. Each menu item has a key corresponding to the - * Drupal path being registered. The corresponding array value is an - * associative array that may contain the following key-value pairs: - * - "title": Required. The untranslated title of the menu item. - * - "title callback": Function to generate the title; defaults to t(). - * If you require only the raw string to be output, set this to FALSE. - * - "title arguments": Arguments to send to t() or your custom callback, - * with path component substitution as described above. - * - "description": The untranslated description of the menu item. - * - description callback: Function to generate the description; defaults to - * t(). If you require only the raw string to be output, set this to FALSE. - * - description arguments: Arguments to send to t() or your custom callback, - * with path component substitution as described above. - * - "weight": 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. Set this to a custom menu if you don't want your - * item to be placed in 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. - * - "position": Position of the block ('left' or 'right') on the system - * administration page for this item. - * - "type": A bitmask of flags describing properties of the menu item. - * Many shortcut 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": An array of options to be passed to l() when generating a link - * from this menu item. - * - * For a detailed usage example, see page_example.module. - * For comprehensive documentation on the menu system, see - * http://drupal.org/node/102338. - * - * @see menu - */ -function hook_menu() { - $items['example'] = array( - 'title' => 'Example Page', - 'route_name' => 'example.page', - ); - $items['example/feed'] = array( - 'title' => 'Example RSS feed', - 'route_name' => 'example.feed', - ); - - return $items; -} - -/** - * Alter the data being saved to the {menu_router} table after hook_menu is invoked. - * - * This hook is invoked by menu_router_build(). The menu definitions are passed - * in by reference. Each element of the $items array is one item returned - * by a module from hook_menu. Additional items may be added, or existing items - * altered. - * - * @param $items - * Associative array of menu router definitions returned from hook_menu(). - */ -function hook_menu_alter(&$items) { - // Example - disable the page at node/add - $items['node/add']['access callback'] = FALSE; -} - /** * Alter tabs and actions displayed on the page before they are rendered. * @@ -1524,11 +1436,6 @@ function hook_cache_flush() { * system is known to return current information, so your module can safely rely * on all available data to rebuild its own. * - * The menu router is the only exception regarding rebuilt data; it is only - * rebuilt after all hook_rebuild() implementations have been invoked. That - * ensures that hook_menu() implementations and the final router rebuild can - * rely on all data being returned by all modules. - * * @see hook_cache_flush() * @see drupal_flush_all_caches() */ diff --git a/core/modules/system/system.install b/core/modules/system/system.install index 2918e9d3784b8be4cd31495b13bba768c89f52ee..7a7208e1ead1c1b4428af0efcfc6bb7f8952e424 100644 --- a/core/modules/system/system.install +++ b/core/modules/system/system.install @@ -729,161 +729,6 @@ function system_schema() { ), ); - $schema['menu_router'] = array( - 'description' => 'Maps paths to various callbacks (access, page and title)', - 'fields' => array( - 'path' => array( - 'description' => 'Primary Key: the Drupal path this entry describes', - 'type' => 'varchar', - 'length' => 255, - 'not null' => TRUE, - 'default' => '', - ), - 'load_functions' => array( - 'description' => 'A serialized array of function names (like node_load) to be called to load an object corresponding to a part of the current path.', - 'type' => 'blob', - 'not null' => TRUE, - ), - 'to_arg_functions' => array( - 'description' => 'A serialized array of function names (like user_uid_optional_to_arg) to be called to replace a part of the router path with another string.', - 'type' => 'blob', - 'not null' => TRUE, - ), - 'access_callback' => array( - 'description' => 'The callback which determines the access to this router path. Defaults to user_access.', - 'type' => 'varchar', - 'length' => 255, - 'not null' => TRUE, - 'default' => '', - ), - 'access_arguments' => array( - 'description' => 'A serialized array of arguments for the access callback.', - 'type' => 'blob', - 'not null' => FALSE, - ), - 'page_callback' => array( - 'description' => 'The name of the function that renders the page.', - 'type' => 'varchar', - 'length' => 255, - 'not null' => TRUE, - 'default' => '', - ), - 'page_arguments' => array( - 'description' => 'A serialized array of arguments for the page callback.', - 'type' => 'blob', - 'not null' => FALSE, - ), - 'fit' => array( - 'description' => 'A numeric representation of how specific the path is.', - 'type' => 'int', - 'not null' => TRUE, - 'default' => 0, - ), - 'number_parts' => array( - 'description' => 'Number of parts in this router path.', - 'type' => 'int', - 'not null' => TRUE, - 'default' => 0, - 'size' => 'small', - ), - 'context' => array( - 'description' => 'Only for local tasks (tabs) - the context of a local task to control its placement.', - 'type' => 'int', - 'not null' => TRUE, - 'default' => 0, - ), - 'tab_parent' => array( - 'description' => 'Only for local tasks (tabs) - the router path of the parent page (which may also be a local task).', - 'type' => 'varchar', - 'length' => 255, - 'not null' => TRUE, - 'default' => '', - ), - 'tab_root' => array( - 'description' => 'Router path of the closest non-tab parent page. For pages that are not local tasks, this will be the same as the path.', - 'type' => 'varchar', - 'length' => 255, - 'not null' => TRUE, - 'default' => '', - ), - 'title' => array( - 'description' => 'The title for the current page, or the title for the tab if this is a local task.', - 'type' => 'varchar', - 'length' => 255, - 'not null' => TRUE, - 'default' => '', - ), - 'title_callback' => array( - 'description' => 'A function which will alter the title. Defaults to t()', - 'type' => 'varchar', - 'length' => 255, - 'not null' => TRUE, - 'default' => '', - ), - 'title_arguments' => array( - 'description' => 'A serialized array of arguments for the title callback. If empty, the title will be used as the sole argument for the title callback.', - 'type' => 'varchar', - 'length' => 255, - 'not null' => TRUE, - 'default' => '', - ), - 'type' => array( - 'description' => 'Numeric representation of the type of the menu item, like MENU_LOCAL_TASK.', - 'type' => 'int', - 'not null' => TRUE, - 'default' => 0, - ), - 'description' => array( - 'description' => 'A description of this item.', - 'type' => 'text', - 'not null' => TRUE, - ), - 'description_callback' => array( - 'description' => 'A function which will alter the description. Defaults to t().', - 'type' => 'varchar', - 'length' => 255, - 'not null' => TRUE, - 'default' => '', - ), - 'description_arguments' => array( - 'description' => 'A serialized array of arguments for the description callback. If empty, the description will be used as the sole argument for the description callback.', - 'type' => 'varchar', - 'length' => 255, - 'not null' => TRUE, - 'default' => '', - ), - 'position' => array( - 'description' => 'The position of the block (left or right) on the system administration page for this item.', - 'type' => 'varchar', - 'length' => 255, - 'not null' => TRUE, - 'default' => '', - ), - 'weight' => array( - 'description' => 'Weight of the element. Lighter weights are higher up, heavier weights go down.', - 'type' => 'int', - 'not null' => TRUE, - 'default' => 0, - ), - 'include_file' => array( - 'description' => 'The file to include for this element, usually the page callback function lives in this file.', - 'type' => 'text', - 'size' => 'medium', - ), - 'route_name' => array( - 'description' => 'The machine name of a defined Symfony Route this menu item represents.', - 'type' => 'varchar', - 'length' => 255, - ), - ), - 'indexes' => array( - 'fit' => array('fit'), - 'tab_parent' => array(array('tab_parent', 64), 'weight', 'title'), - 'tab_root_weight_title' => array(array('tab_root', 64), 'weight', 'title'), - ), - 'primary key' => array('path'), - ); - $schema['queue'] = array( 'description' => 'Stores items in queues.', 'fields' => array( diff --git a/core/modules/system/system.module b/core/modules/system/system.module index d36b68f3a3a49fee1c656eece6abd290823df3ec..34883922b42b16380196c6875fd52e9ac46ff7c5 100644 --- a/core/modules/system/system.module +++ b/core/modules/system/system.module @@ -626,206 +626,6 @@ function system_element_info() { return $types; } -/** - * Implements hook_menu(). - */ -function system_menu() { - $items['admin'] = array( - 'title' => 'Administration', - 'route_name' => 'system.admin', - 'weight' => 9, - 'menu_name' => 'admin', - ); - - // Menu items that are basically just menu blocks. - $items['admin/structure'] = array( - 'title' => 'Structure', - 'description' => 'Administer blocks, content types, menus, etc.', - 'position' => 'right', - 'weight' => -8, - 'route_name' => 'system.admin_structure', - ); - // Appearance. - $items['admin/appearance'] = array( - 'title' => 'Appearance', - 'description' => 'Select and configure your themes.', - 'route_name' => 'system.themes_page', - 'position' => 'left', - 'weight' => -6, - ); - - // Modules. - $items['admin/modules'] = array( - 'title' => 'Extend', - 'description' => 'Add and enable modules to extend site functionality.', - 'route_name' => 'system.modules_list', - 'weight' => -2, - ); - - // Configuration. - $items['admin/config'] = array( - 'title' => 'Configuration', - 'description' => 'Administer settings.', - 'route_name' => 'system.admin_config', - ); - - // Media settings. - $items['admin/config/media'] = array( - 'title' => 'Media', - 'description' => 'Media tools.', - 'position' => 'left', - 'weight' => -10, - 'route_name' => 'system.admin_config_media', - ); - $items['admin/config/media/file-system'] = array( - 'title' => 'File system', - 'description' => 'Tell Drupal where to store uploaded files and how they are accessed.', - 'route_name' => 'system.file_system_settings', - 'weight' => -10, - ); - $items['admin/config/media/image-toolkit'] = array( - 'title' => 'Image toolkit', - 'description' => 'Choose which image toolkit to use if you have installed optional toolkits.', - 'route_name' => 'system.image_toolkit_settings', - 'weight' => 20, - ); - - // Service settings. - $items['admin/config/services'] = array( - 'title' => 'Web services', - 'description' => 'Tools related to web services.', - 'position' => 'right', - 'weight' => 0, - 'route_name' => 'system.admin_config_services', - ); - $items['admin/config/services/rss-publishing'] = array( - 'title' => 'RSS publishing', - '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['admin/config/development'] = array( - 'title' => 'Development', - 'description' => 'Development tools.', - 'position' => 'right', - 'weight' => -10, - 'route_name' => 'system.admin_config_development', - ); - $items['admin/config/development/maintenance'] = array( - 'title' => 'Maintenance mode', - 'description' => 'Take the site offline for maintenance or bring it back online.', - 'route_name' => 'system.site_maintenance_mode', - 'weight' => -10, - ); - $items['admin/config/development/performance'] = array( - 'title' => 'Performance', - '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['admin/config/development/logging'] = array( - 'title' => 'Logging and errors', - '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['admin/config/regional'] = array( - 'title' => 'Regional and language', - 'description' => 'Regional settings, localization and translation.', - 'position' => 'left', - 'weight' => -5, - 'route_name' => 'system.admin_config_regional', - ); - $items['admin/config/regional/settings'] = array( - 'title' => 'Regional settings', - 'description' => "Settings for the site's default time zone and country.", - 'route_name' => 'system.regional_settings', - 'weight' => -20, - ); - $items['admin/config/regional/date-time'] = array( - 'title' => 'Date and time formats', - 'description' => 'Configure display format strings for date and time.', - 'route_name' => 'system.date_format_list', - 'weight' => -5, - ); - $items['admin/config/regional/date-time/formats/manage/%'] = array( - 'title' => 'Edit date format', - 'description' => 'Allow users to edit a configured date format.', - 'route_name' => 'system.date_format_edit', - ); - - // Search settings. - $items['admin/config/search'] = array( - 'title' => 'Search and metadata', - 'description' => 'Local site search, metadata and SEO.', - 'position' => 'left', - 'weight' => -10, - 'route_name' => 'system.admin_config_search', - ); - - // System settings. - $items['admin/config/system'] = array( - 'title' => 'System', - 'description' => 'General system related configuration.', - 'position' => 'right', - 'weight' => -20, - 'route_name' => 'system.admin_config_system', - ); - $items['admin/config/system/site-information'] = array( - 'title' => 'Site information', - 'description' => 'Change site name, e-mail address, slogan, default front page and error pages.', - 'route_name' => 'system.site_information_settings', - 'weight' => -20, - ); - $items['admin/config/system/cron'] = array( - 'title' => 'Cron', - 'description' => 'Manage automatic site maintenance tasks.', - 'route_name' => 'system.cron_settings', - 'weight' => 20, - ); - // Additional categories - $items['admin/config/user-interface'] = array( - 'title' => 'User interface', - 'description' => 'Tools that enhance the user interface.', - 'position' => 'right', - 'route_name' => 'system.admin_config_ui', - 'weight' => -15, - ); - $items['admin/config/workflow'] = array( - 'title' => 'Workflow', - 'description' => 'Content workflow, editorial workflow tools.', - 'position' => 'right', - 'weight' => 5, - 'route_name' => 'system.admin_config_workflow', - ); - $items['admin/config/content'] = array( - 'title' => 'Content authoring', - 'description' => 'Settings related to formatting and authoring content.', - 'position' => 'left', - 'weight' => -15, - 'route_name' => 'system.admin_config_content', - ); - - // Reports. - $items['admin/reports'] = array( - 'title' => 'Reports', - 'description' => 'View reports, updates, and errors.', - 'route_name' => 'system.admin_reports', - 'weight' => 5, - 'position' => 'left', - ); - $items['admin/reports/status'] = array( - 'title' => 'Status report', - 'description' => "Get a status report about your site's operation and any detected problems.", - 'route_name' => 'system.status', - ); - - return $items; -} - /** * Implements hook_menu_link_defaults(). */ @@ -849,12 +649,14 @@ function system_menu_link_defaults() { $items['system.admin.appearance'] = array( 'route_name' => 'system.themes_page', 'link_title' => 'Appearance', + 'description' => 'Select and configure your themes.', 'parent' => 'system.admin', 'weight' => -6, ); // Modules. $items['system.admin.modules'] = array( 'link_title' => 'Extend', + 'description' => 'Add and enable modules to extend site functionality.', 'parent' => 'system.admin', 'route_name' => 'system.modules_list', 'weight' => -2, diff --git a/core/modules/system/tests/modules/batch_test/batch_test.module b/core/modules/system/tests/modules/batch_test/batch_test.module index ba8b273a576ffbb4b2b735d50e6d449cf1bce67a..b97f96655daaca3170a17dec79b5bd73712f246a 100644 --- a/core/modules/system/tests/modules/batch_test/batch_test.module +++ b/core/modules/system/tests/modules/batch_test/batch_test.module @@ -5,20 +5,6 @@ * Helper module for the Batch API tests. */ -/** - * Implements hook_menu(). - */ -function batch_test_menu() { - $items = array(); - - $items['batch-test'] = array( - 'title' => 'Batch test', - 'route_name' => 'batch_test.test_form', - ); - - return $items; -} - /** * Form constructor for a batch selection form. * diff --git a/core/modules/system/tests/modules/entity_test/entity_test.module b/core/modules/system/tests/modules/entity_test/entity_test.module index 9620ef50b572e351852f46009761c88c3330b823..9bcc69f46662f3a60e1ad6c010f5dc1a139ce318 100644 --- a/core/modules/system/tests/modules/entity_test/entity_test.module +++ b/core/modules/system/tests/modules/entity_test/entity_test.module @@ -239,30 +239,6 @@ function entity_test_permission() { return $permissions; } -/** - * Implements hook_menu(). - */ -function entity_test_menu() { - $items = array(); - $types = entity_test_entity_types(); - - foreach($types as $entity_type) { - $items[$entity_type . '/add'] = array( - 'title' => 'Add an @type', - 'title arguments' => array('@type' => $entity_type), - 'route_name' => "entity_test.add_$entity_type", - ); - - $items[$entity_type . '/manage/%' . $entity_type] = array( - 'title' => 'Edit @type', - 'title arguments' => array('@type' => $entity_type), - 'route_name' => "entity_test.edit_$entity_type", - ); - } - - return $items; -} - /** * Implements hook_form_BASE_FORM_ID_alter(). */ 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 30dffdc37af505b95c6cd4e63a873ee56548eb47..08e6382522413bb21433d1871cdc697a4d1d4480 100644 --- a/core/modules/system/tests/modules/menu_test/menu_test.module +++ b/core/modules/system/tests/modules/menu_test/menu_test.module @@ -7,147 +7,6 @@ use Drupal\menu_link\Entity\MenuLink; -/** - * Implements hook_menu(). - */ -function menu_test_menu() { - // The name of the menu changes during the course of the test. Using a GET. - $items['menu_name_test'] = array( - '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_callback_description'] = array( - 'title' => 'Menu item title', - 'description' => 'Menu item description parent', - 'route_name' => 'menu_test.callback_description', - ); - // This item tests the description key. - $items['menu_callback_description/description-plain'] = array( - 'title' => 'Menu item with a regular description', - 'description' => 'Menu item description text', - 'route_name' => 'menu_test.callback_description_plain', - ); - // This item tests using a description callback. - $items['menu_callback_description/description-callback'] = array( - 'title' => 'Menu item with a description set with a callback', - 'description callback' => 'check_plain', - 'description arguments' => array('<strong>Menu item description arguments</strong>'), - 'route_name' => 'menu_test.callback_description_callback', - ); - // Use FALSE as 'title callback' to bypass t(). - $items['menu_no_title_callback'] = array( - 'title' => 'A title with @placeholder', - 'title callback' => FALSE, - 'title arguments' => array('@placeholder' => 'some other text'), - 'route_name' => 'menu_test.menu_no_title_callback', - ); - - // Hidden link for menu_link_maintain tests - $items['menu_test_maintain/%'] = array( - 'title' => 'Menu maintain test', - 'route_name' => 'menu_test.menu_test_maintain', - ); - // Hierarchical tests. - $items['menu-test/hierarchy/parent'] = array( - 'title' => 'Parent menu router', - 'route_name' => 'menu_test.hierarchy_parent', - ); - $items['menu-test/hierarchy/parent/child'] = array( - 'title' => 'Child menu router', - 'route_name' => 'menu_test.hierarchy_parent_child', - ); - $items['menu-test/hierarchy/parent/child2/child'] = array( - 'title' => 'Unattached subchild router', - 'route_name' => 'menu_test.hierarchy_parent_child2', - ); - // Theme callback tests. - $items['menu-test/theme-callback/%/inheritance'] = array( - 'title' => 'Page that tests theme negotiation inheritance.', - 'route_name' => 'menu_test.theme_callback_inheritance', - ); - $items['menu-test/no-theme-callback'] = array( - 'title' => 'Page that displays different themes without using a theme negotiation.', - 'route_name' => 'menu_test.no_theme_callback', - ); - // Path containing "exotic" characters. - $path = "menu-test/ -._~!$'\"()*@[]?&+%#,;=:" . // "Special" ASCII characters. - "%23%25%26%2B%2F%3F" . // Characters that look like a percent-escaped string. - "éøïвβä¸åœ‹æ›¸Ûž"; // Characters from various non-ASCII alphabets. - $items[$path] = array( - 'title' => '"Exotic" path', - 'route_name' => 'menu_test.exotic_path', - ); - - // 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( - 'title' => 'Menu test root', - 'route_name' => 'menu_test.menu_test', - ); - - // Menu trail tests. - // @see MenuTrailTestCase - $items['menu-test/menu-trail'] = array( - 'title' => 'Menu trail - Case 1', - 'route_name' => 'menu_test.menu_trail', - ); - $items['admin/config/development/menu-trail'] = array( - 'title' => 'Menu trail - Case 2', - 'description' => 'Tests menu_tree_set_path()', - 'route_name' => 'menu_test.menu_trail_admin', - ); - $items['menu-test/custom-403-page'] = array( - 'title' => 'Custom 403 page', - 'route_name' => 'menu_test.custom_403', - ); - $items['menu-test/custom-404-page'] = array( - 'title' => 'Custom 404 page', - 'route_name' => 'menu_test.custom_404', - ); - - // Test the access key. - $items['menu-title-test/case1'] = array( - 'title' => 'Example title - Case 1', - 'route_name' => 'menu_test.title_test_case1', - ); - $items['menu-title-test/case2'] = array( - 'title' => 'Example title', - 'title callback' => 'menu_test_title_callback', - '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', - 'route_name' => 'menu_test.title_test_case3', - ); - - $items['menu-test-local-action'] = array( - 'title' => 'Local action parent', - 'route_name' => 'menu_test.local_action1', - ); - - $items['menu-local-task-test/tasks'] = array( - 'title' => 'Local tasks', - 'route_name' => 'menu_test.local_task_test_tasks', - ); - $items['menu-test/optional'] = array( - 'title' => 'Test optional placeholder', - 'route_name' => 'menu_test.optional_placeholder', - 'type' => MENU_LOCAL_TASK, - ); - - $items['menu-test/context'] = array( - 'title' => \Drupal::config('menu_test.menu_item')->get('title'), - 'route_name' => 'menu_test.context', - ); - - return $items; -} - /** * Implements hook_menu_link_defaults(). */ @@ -172,12 +31,6 @@ function menu_test_menu_link_defaults() { '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', @@ -337,36 +190,6 @@ function menu_test_menu_local_tasks_alter(&$data, $route_name) { } } -/** - * Argument callback: Loads an argument using a function for hook_menu(). - * - * @param string $arg1 - * A parameter passed in via the URL. - * - * @return false - * Always return NULL. - * - * @see menu_test_menu(); - */ -function menu_test_argument_load($arg1) { - return NULL; -} - -/** - * Argument callback: Loads an argument using a function for hook_menu(). - * - * @param string $arg1 - * A parameter passed in via the URL. - * - * @return false - * Always return NULL. - * - * @see menu_test_menu(); - */ -function menu_test_other_argument_load($arg1) { - return NULL; -} - /** * Page callback: Provides a dummy function which can be used as a placeholder. * 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 637be3c1ade2ed487374c6aba7284c3470996372..34d5dadc45482cec80c56dd6fe12eb944c61545a 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 @@ -36,14 +36,6 @@ menu_test.callback_description_plain: requirements: _access: 'TRUE' -menu_test.callback_description_callback: - path: '/menu_callback_description/description-callback' - defaults: - _title: 'Menu item with a description set with a callback' - _content: '\Drupal\menu_test\Controller\MenuTestController::menuTestCallback' - requirements: - _access: 'TRUE' - menu_test.menu_no_title_callback: path: '/menu_no_title_callback' defaults: diff --git a/core/modules/user/lib/Drupal/user/Access/RegisterAccessCheck.php b/core/modules/user/lib/Drupal/user/Access/RegisterAccessCheck.php index e234afbf59f71275e2437a7d33c3b8b8f3eec02a..eff984ba07153d13a83b284afe325f38225a6d88 100644 --- a/core/modules/user/lib/Drupal/user/Access/RegisterAccessCheck.php +++ b/core/modules/user/lib/Drupal/user/Access/RegisterAccessCheck.php @@ -21,6 +21,6 @@ class RegisterAccessCheck implements AccessInterface { * Implements AccessCheckInterface::access(). */ public function access(Route $route, Request $request, AccountInterface $account) { - return ($account->isAnonymous() && (\Drupal::config('user.settings')->get('register') != USER_REGISTER_ADMINISTRATORS_ONLY)) ? static::ALLOW : static::DENY; + return ($request->attributes->get('_menu_admin') || $account->isAnonymous()) && (\Drupal::config('user.settings')->get('register') != USER_REGISTER_ADMINISTRATORS_ONLY) ? static::ALLOW : static::DENY; } } diff --git a/core/modules/user/lib/Drupal/user/EventSubscriber/MaintenanceModeSubscriber.php b/core/modules/user/lib/Drupal/user/EventSubscriber/MaintenanceModeSubscriber.php index 0a42c917be0fdc36d37c0ca7cdb6175c253d9bea..3c478f7b6075cdc1c5a7941f217b71c37cb02dc4 100644 --- a/core/modules/user/lib/Drupal/user/EventSubscriber/MaintenanceModeSubscriber.php +++ b/core/modules/user/lib/Drupal/user/EventSubscriber/MaintenanceModeSubscriber.php @@ -37,7 +37,7 @@ public function onKernelRequestMaintenance(GetResponseEvent $event) { return; } - if (user_is_anonymous()) { + if ($user->isAnonymous()) { switch ($path) { case 'user': // Forward anonymous user to login page. diff --git a/core/modules/user/tests/modules/user_form_test/user_form_test.module b/core/modules/user/tests/modules/user_form_test/user_form_test.module index 134804f45948d23fbb74da3afaeb6d81d77f95e9..aefc9d3538f64f8f5a1636b9bd1c59d8fe7463e9 100644 --- a/core/modules/user/tests/modules/user_form_test/user_form_test.module +++ b/core/modules/user/tests/modules/user_form_test/user_form_test.module @@ -4,18 +4,3 @@ * @file * Dummy module implementing a form to test user password validation */ - -/** - * Implements hook_menu(). - * - * Sets up a form that allows a user to validate password. - */ -function user_form_test_menu() { - $items = array(); - $items['user_form_test_current_password/%user'] = array( - 'title' => 'User form test for current password validation', - 'route_name' => 'user_form_test.current_password', - 'type' => MENU_SUGGESTED_ITEM, - ); - return $items; -} diff --git a/core/modules/user/user.module b/core/modules/user/user.module index 9b2194b32cce042136cbbc4dce4ace435baf82e9..c8b51b7d013797df13a554110c8316044827eef6 100644 --- a/core/modules/user/user.module +++ b/core/modules/user/user.module @@ -685,40 +685,6 @@ function theme_username($variables) { return $output; } -/** - * Determines if the current user is anonymous. - * - * @return bool - * TRUE if the user is anonymous, FALSE if the user is authenticated. - */ -function user_is_anonymous() { - // Menu administrators can see items for anonymous when administering. - return $GLOBALS['user']->isAnonymous() || !empty($GLOBALS['menu_admin']); -} - -/** - * Determines if the current user is logged in. - * - * @return bool - * TRUE if the user is logged in, FALSE if the user is anonymous. - * - * @deprecated in Drupal 8.x-dev, will be removed before Drupal 8.0. - * Use \Drupal\Core\Session\UserSession::isAuthenticated(). - */ -function user_is_logged_in() { - return $GLOBALS['user']->isAuthenticated(); -} - -/** - * Determines if the current user has access to the user registration page. - * - * @return bool - * TRUE if the user is not already logged in and can register for an account. - */ -function user_register_access() { - return user_is_anonymous() && (\Drupal::config('user.settings')->get('register') != USER_REGISTER_ADMINISTRATORS_ONLY); -} - /** * Implements hook_menu_link_defaults(). */ @@ -816,81 +782,6 @@ function user_admin_paths() { return $paths; } -/** - * Returns $arg or the user ID of the current user if $arg is '%' or empty. - * - * Deprecated. Use %user_uid_optional instead. - * - * @todo D8: Remove. - */ -function user_uid_only_optional_to_arg($arg) { - return user_uid_optional_to_arg($arg); -} - -/** - * Load either a specified or the current user account. - * - * @param $uid - * An optional user ID of the user to load. If not provided, the current - * user's ID will be used. - * @return - * A fully-loaded $user object upon successful user load, NULL if user - * cannot be loaded. - * - * @see user_load() - * @todo rethink the naming of this in Drupal 8. - */ -function user_uid_optional_load($uid = NULL) { - if (!isset($uid)) { - $uid = $GLOBALS['user']->id(); - } - return user_load($uid); -} - -/** - * Returns $arg or the user ID of the current user if $arg is '%' or empty. - * - * @todo rethink the naming of this in Drupal 8. - */ -function user_uid_optional_to_arg($arg) { - // Give back the current user uid when called from eg. tracker, aka. - // with an empty arg. Also use the current user uid when called from - // the menu with a % for the current account link. - return empty($arg) || $arg == '%' ? $GLOBALS['user']->id() : $arg; -} - -/** - * Menu item title callback for the 'user' path. - * - * Anonymous users should see a title based on the requested page, but - * authenticated users are expected to see "My account". - */ -function user_menu_title() { - if ($GLOBALS['user']->isAnonymous()) { - switch (current_path()) { - case 'user' : - case 'user/login' : - return t('Log in'); - case 'user/register' : - return t('Create new account'); - case 'user/password' : - return t('Request new password'); - default : - return t('User account'); - } - } - else { - return t('My account'); - } -} - -/** - * Menu item title callback - use the user name. - */ -function user_page_title(UserInterface $account = NULL) { - return $account ? $account->getUsername() : ''; -} - /** * Try to validate the user's login credentials locally. * 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 7b22ce9584373a8d1e6433ce4f24ae88cf188888..ac2f70695b14bdd92329fc15f4e8fea80344388c 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 @@ -327,121 +327,6 @@ public function executeHookMenuLinkDefaults(array &$existing_links) { return $links; } - /** - * Overrides \Drupal\views\Plugin\views\display\DisplayPluginBase::executeHookMenu(). - */ - public function executeHookMenu($callbacks) { - $items = 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; - - $path = implode('/', $bits); - - $view_route_names = $this->state->get('views.view_route_names') ?: 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']}"; - $items[$path] = 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') { - $items[$path]['title'] = $menu['title']; - $items[$path]['description'] = $menu['description']; - } - - if (isset($menu['weight'])) { - $items[$path]['weight'] = intval($menu['weight']); - } - - switch ($menu['type']) { - case 'none': - default: - $items[$path]['type'] = MENU_CALLBACK; - break; - case 'normal': - $items[$path]['type'] = MENU_NORMAL_ITEM; - // Insert item into the proper menu. - $items[$path]['menu_name'] = $menu['name']; - break; - case 'tab': - $items[$path]['type'] = MENU_CALLBACK; - break; - case 'default tab': - $items[$path]['type'] = MENU_CALLBACK; - break; - } - - // Add context for contextual links. - if (in_array($menu['type'], array('tab', 'default tab'))) { - // @todo Remove once contextual links are ported to a new plugin based - // system. - if (!empty($menu['context'])) { - $items[$path]['context'] = TRUE; - } - } - - // If this is a 'default' tab, check to see if we have to create the - // parent menu item. - if ($this->isDefaultTabPath()) { - $tab_options = $this->getOption('tab_options'); - - $bits = explode('/', $path); - // Remove the last piece. - $bit = array_pop($bits); - - // Default tabs are handled by the local task plugins. - if ($tab_options['type'] == 'tab') { - return $items; - } - - // we can't do this if they tried to make the last path bit variable. - // @todo: We can validate this. - if (!empty($bits)) { - // Assign the route name to the parent route, not the default tab. - $default_route_name = $items[$path]['route_name']; - unset($items[$path]['route_name']); - - $default_path = implode('/', $bits); - $items[$default_path] = array( - // Default views page entry. - // Identify URL embedded arguments and correlate them to a - // handler. - 'load arguments' => array($this->view->storage->id(), $this->display['id'], '%index'), - 'title' => $tab_options['title'], - 'description' => $tab_options['description'], - 'menu_name' => $tab_options['name'], - 'route_name' => $default_route_name, - ); - switch ($tab_options['type']) { - default: - case 'normal': - $items[$default_path]['type'] = MENU_NORMAL_ITEM; - break; - } - if (isset($tab_options['weight'])) { - $items[$default_path]['weight'] = intval($tab_options['weight']); - } - } - } - } - - return $items; - } - /** * Overrides \Drupal\views\Plugin\views\display\DisplayPluginBase::execute(). */ diff --git a/core/modules/views/lib/Drupal/views/Tests/Handler/FilterBooleanOperatorStringTest.php b/core/modules/views/lib/Drupal/views/Tests/Handler/FilterBooleanOperatorStringTest.php index 75c7b65db161c3dce346bff48d23b8f5762910ee..079e0031a14b3861d105526c68dd2307f1d0fd7b 100644 --- a/core/modules/views/lib/Drupal/views/Tests/Handler/FilterBooleanOperatorStringTest.php +++ b/core/modules/views/lib/Drupal/views/Tests/Handler/FilterBooleanOperatorStringTest.php @@ -49,7 +49,7 @@ public static function getInfo() { protected function setUp() { parent::setUp(); - $this->installSchema('system', array('menu_router', 'key_value_expire')); + $this->installSchema('system', array('key_value_expire')); } diff --git a/core/modules/views/lib/Drupal/views/Tests/Handler/FilterBooleanOperatorTest.php b/core/modules/views/lib/Drupal/views/Tests/Handler/FilterBooleanOperatorTest.php index 1ef7ca860e9338bb375da24c60b6f1645c1a6e3c..a9ff2cf89df2b25cd2664337e1013e3e193e995a 100644 --- a/core/modules/views/lib/Drupal/views/Tests/Handler/FilterBooleanOperatorTest.php +++ b/core/modules/views/lib/Drupal/views/Tests/Handler/FilterBooleanOperatorTest.php @@ -45,7 +45,7 @@ public static function getInfo() { protected function setUp() { parent::setUp(); - $this->installSchema('system', array('menu_router', 'key_value_expire')); + $this->installSchema('system', array('key_value_expire')); } /** diff --git a/core/modules/views/lib/Drupal/views/Tests/Handler/FilterEqualityTest.php b/core/modules/views/lib/Drupal/views/Tests/Handler/FilterEqualityTest.php index 0c0c5179f675c00776592cc462df79212475a7cd..f2397739b158436ab69ebb72feee933e15f87ba3 100644 --- a/core/modules/views/lib/Drupal/views/Tests/Handler/FilterEqualityTest.php +++ b/core/modules/views/lib/Drupal/views/Tests/Handler/FilterEqualityTest.php @@ -38,7 +38,7 @@ public static function getInfo() { protected function setUp() { parent::setUp(); - $this->installSchema('system', array('menu_router', 'key_value_expire')); + $this->installSchema('system', array('key_value_expire')); } function viewsData() { diff --git a/core/modules/views/lib/Drupal/views/Tests/Handler/FilterInOperatorTest.php b/core/modules/views/lib/Drupal/views/Tests/Handler/FilterInOperatorTest.php index bd024e2ace3bd75b4c2107c6115334162b03ef12..7c710e32c6ca82738aaad873d5d267e113e67f46 100644 --- a/core/modules/views/lib/Drupal/views/Tests/Handler/FilterInOperatorTest.php +++ b/core/modules/views/lib/Drupal/views/Tests/Handler/FilterInOperatorTest.php @@ -39,7 +39,7 @@ public static function getInfo() { protected function setUp() { parent::setUp(); - $this->installSchema('system', array('menu_router', 'key_value_expire')); + $this->installSchema('system', array('key_value_expire')); } function viewsData() { diff --git a/core/modules/views/lib/Drupal/views/Tests/Handler/FilterNumericTest.php b/core/modules/views/lib/Drupal/views/Tests/Handler/FilterNumericTest.php index ad0a627465443a6065b0c45ec037d17fe83943c4..ae187500057cad74e16a5691b34093778b076522 100644 --- a/core/modules/views/lib/Drupal/views/Tests/Handler/FilterNumericTest.php +++ b/core/modules/views/lib/Drupal/views/Tests/Handler/FilterNumericTest.php @@ -39,7 +39,7 @@ public static function getInfo() { protected function setUp() { parent::setUp(); - $this->installSchema('system', array('menu_router', 'key_value_expire')); + $this->installSchema('system', array('key_value_expire')); } function viewsData() { diff --git a/core/modules/views/lib/Drupal/views/Tests/Handler/FilterStringTest.php b/core/modules/views/lib/Drupal/views/Tests/Handler/FilterStringTest.php index 5a62bed44f5c580a2f6c577f1e6dd6c0cb785c72..8d7e1f587a0ec6124eb1d7c966a2af5d59a679a6 100644 --- a/core/modules/views/lib/Drupal/views/Tests/Handler/FilterStringTest.php +++ b/core/modules/views/lib/Drupal/views/Tests/Handler/FilterStringTest.php @@ -38,7 +38,7 @@ public static function getInfo() { protected function setUp() { parent::setUp(); - $this->installSchema('system', array('menu_router', 'key_value_expire')); + $this->installSchema('system', array('key_value_expire')); } function viewsData() { diff --git a/core/modules/views/lib/Drupal/views/Tests/Plugin/DisplayPageTest.php b/core/modules/views/lib/Drupal/views/Tests/Plugin/DisplayPageTest.php index 5867c982376467349983bb4f3742e899360fcc7c..48ad3f2ebeaebb1c7321b93c6203130ab1b77c04 100644 --- a/core/modules/views/lib/Drupal/views/Tests/Plugin/DisplayPageTest.php +++ b/core/modules/views/lib/Drupal/views/Tests/Plugin/DisplayPageTest.php @@ -54,7 +54,7 @@ protected function setUp() { parent::setUp(); // Setup the needed tables in order to make the drupal router working. - $this->installSchema('system', array('menu_router', 'url_alias')); + $this->installSchema('system', array('url_alias')); $this->installSchema('menu_link', 'menu_links'); } diff --git a/core/modules/views/lib/Drupal/views/Tests/Plugin/RowEntityTest.php b/core/modules/views/lib/Drupal/views/Tests/Plugin/RowEntityTest.php index 807880a651fd3c89ddc48759ee94433bcb171872..5efa290225265b05d8809fd9ba7d27ac4e5560ee 100644 --- a/core/modules/views/lib/Drupal/views/Tests/Plugin/RowEntityTest.php +++ b/core/modules/views/lib/Drupal/views/Tests/Plugin/RowEntityTest.php @@ -51,7 +51,6 @@ public static function getInfo() { protected function setUp() { parent::setUp(); - $this->installSchema('system', array('menu_router')); $this->installSchema('taxonomy', array('taxonomy_term_data', 'taxonomy_term_hierarchy')); $this->installConfig(array('taxonomy')); \Drupal::service('router.builder')->rebuild(); diff --git a/core/modules/views/lib/Drupal/views/ViewExecutable.php b/core/modules/views/lib/Drupal/views/ViewExecutable.php index 6fa98d271a0ff078f619b580cbb17031b38a714e..17131c4568b2c5e6986c1016323562cf5cb1236e 100644 --- a/core/modules/views/lib/Drupal/views/ViewExecutable.php +++ b/core/modules/views/lib/Drupal/views/ViewExecutable.php @@ -1511,28 +1511,6 @@ public function attachDisplays() { $this->is_attachment = FALSE; } - /** - * Called to get hook_menu() information from the view and the named display handler. - * - * @param $display_id - * A display id. - * @param $callbacks - * A menu callback array passed from views_menu_alter(). - */ - public function executeHookMenu($display_id = NULL, &$callbacks = 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 view - if (isset($this->display_handler)) { - return $this->display_handler->executeHookMenu($callbacks); - } - } - /** * Returns default menu links from the view and the named display handler. *