diff --git a/core/includes/menu.inc b/core/includes/menu.inc
index fe65d0a..987d9d0 100644
--- a/core/includes/menu.inc
+++ b/core/includes/menu.inc
@@ -322,594 +322,6 @@ function _menu_link_translate(&$item) {
}
/**
- * Renders a menu tree based on the current path.
- *
- * @param $menu_name
- * The name of the menu.
- *
- * @return
- * A structured array representing the specified menu on the current page, to
- * be rendered by drupal_render().
- */
-function menu_tree($menu_name) {
- $menu_output = &drupal_static(__FUNCTION__, array());
-
- if (!isset($menu_output[$menu_name])) {
- $tree = menu_tree_page_data($menu_name);
- $menu_output[$menu_name] = menu_tree_output($tree);
- }
- return $menu_output[$menu_name];
-}
-
-/**
- * Returns an output structure for rendering a menu tree.
- *
- * The menu item's LI element is given one of the following classes:
- * - expanded: The menu item is showing its submenu.
- * - collapsed: The menu item has a submenu which is not shown.
- * - leaf: The menu item has no submenu.
- *
- * @param $tree
- * A data structure representing the tree as returned from menu_tree_data.
- *
- * @return
- * A structured array to be rendered by drupal_render().
- */
-function menu_tree_output($tree) {
- $build = array();
- $items = array();
-
- // Pull out just the menu links we are going to render so that we
- // get an accurate count for the first/last classes.
- foreach ($tree as $data) {
- if ($data['link']['access'] && !$data['link']['hidden']) {
- $items[] = $data;
- }
- }
-
- foreach ($items as $data) {
- $class = array();
- // Set a class for the
-tag. Since $data['below'] may contain local
- // tasks, only set 'expanded' class if the link also has children within
- // the current menu.
- if ($data['link']['has_children'] && $data['below']) {
- $class[] = 'expanded';
- }
- elseif ($data['link']['has_children']) {
- $class[] = 'collapsed';
- }
- else {
- $class[] = 'leaf';
- }
- // Set a class if the link is in the active trail.
- if ($data['link']['in_active_trail']) {
- $class[] = 'active-trail';
- $data['link']['localized_options']['attributes']['class'][] = 'active-trail';
- }
-
- // Allow menu-specific theme overrides.
- $element['#theme'] = 'menu_link__' . strtr($data['link']['menu_name'], '-', '_');
- $element['#attributes']['class'] = $class;
- $element['#title'] = $data['link']['title'];
- // @todo Use route name and parameters to generate the link path, unless
- // it is external.
- $element['#href'] = $data['link']['link_path'];
- $element['#localized_options'] = !empty($data['link']['localized_options']) ? $data['link']['localized_options'] : array();
- $element['#below'] = $data['below'] ? menu_tree_output($data['below']) : $data['below'];
- $element['#original_link'] = $data['link'];
- // Index using the link's unique mlid.
- $build[$data['link']['mlid']] = $element;
- }
- if ($build) {
- // Make sure drupal_render() does not re-order the links.
- $build['#sorted'] = TRUE;
- // Add the theme wrapper for outer markup.
- // Allow menu-specific theme overrides.
- $build['#theme_wrappers'][] = 'menu_tree__' . strtr($data['link']['menu_name'], '-', '_');
- // Set cache tag.
- $menu_name = $data['link']['menu_name'];
- $build['#cache']['tags']['menu'][$menu_name] = $menu_name;
- }
-
- return $build;
-}
-
-/**
- * Gets the data structure representing a named menu tree.
- *
- * Since this can be the full tree including hidden items, the data returned
- * may be used for generating an an admin interface or a select.
- *
- * @param $menu_name
- * The named menu links to return
- * @param $link
- * A fully loaded menu link, or NULL. If a link is supplied, only the
- * path to root will be included in the returned tree - as if this link
- * represented the current page in a visible menu.
- * @param $max_depth
- * Optional maximum depth of links to retrieve. Typically useful if only one
- * or two levels of a sub tree are needed in conjunction with a non-NULL
- * $link, in which case $max_depth should be greater than $link['depth'].
- *
- * @return
- * An tree of menu links in an array, in the order they should be rendered.
- */
-function menu_tree_all_data($menu_name, $link = NULL, $max_depth = NULL) {
- $tree = &drupal_static(__FUNCTION__, array());
- $language_interface = \Drupal::languageManager()->getCurrentLanguage();
-
- // Use $mlid as a flag for whether the data being loaded is for the whole tree.
- $mlid = isset($link['mlid']) ? $link['mlid'] : 0;
- // Generate a cache ID (cid) specific for this $menu_name, $link, $language, and depth.
- $cid = 'links:' . $menu_name . ':all:' . $mlid . ':' . $language_interface->id . ':' . (int) $max_depth;
-
- if (!isset($tree[$cid])) {
- // If the static variable doesn't have the data, check {cache_data}.
- $cache = \Drupal::cache('data')->get($cid);
- if ($cache && isset($cache->data)) {
- // If the cache entry exists, it contains the parameters for
- // menu_build_tree().
- $tree_parameters = $cache->data;
- }
- // If the tree data was not in the cache, build $tree_parameters.
- if (!isset($tree_parameters)) {
- $tree_parameters = array(
- 'min_depth' => 1,
- 'max_depth' => $max_depth,
- );
- if ($mlid) {
- // The tree is for a single item, so we need to match the values in its
- // p columns and 0 (the top level) with the plid values of other links.
- $parents = array(0);
- for ($i = 1; $i < MENU_MAX_DEPTH; $i++) {
- if (!empty($link["p$i"])) {
- $parents[] = $link["p$i"];
- }
- }
- $tree_parameters['expanded'] = $parents;
- $tree_parameters['active_trail'] = $parents;
- $tree_parameters['active_trail'][] = $mlid;
- }
-
- // Cache the tree building parameters using the page-specific cid.
- \Drupal::cache('data')->set($cid, $tree_parameters, Cache::PERMANENT, array('menu' => $menu_name));
- }
-
- // Build the tree using the parameters; the resulting tree will be cached
- // by _menu_build_tree()).
- $tree[$cid] = menu_build_tree($menu_name, $tree_parameters);
- }
-
- return $tree[$cid];
-}
-
-/**
- * Sets the path for determining the active trail of the specified menu tree.
- *
- * This path will also affect the breadcrumbs under some circumstances.
- * Breadcrumbs are built using the preferred link returned by
- * menu_link_get_preferred(). If the preferred link is inside one of the menus
- * specified in calls to menu_tree_set_path(), the preferred link will be
- * overridden by the corresponding path returned by menu_tree_get_path().
- *
- * Setting this path does not affect the main content; for that use
- * menu_set_active_item() instead.
- *
- * @param $menu_name
- * The name of the affected menu tree.
- * @param $path
- * The path to use when finding the active trail.
- */
-function menu_tree_set_path($menu_name, $path = NULL) {
- $paths = &drupal_static(__FUNCTION__);
- if (isset($path)) {
- $paths[$menu_name] = $path;
- }
- return isset($paths[$menu_name]) ? $paths[$menu_name] : NULL;
-}
-
-/**
- * Gets the path for determining the active trail of the specified menu tree.
- *
- * @param $menu_name
- * The menu name of the requested tree.
- *
- * @return
- * A string containing the path. If no path has been specified with
- * menu_tree_set_path(), NULL is returned.
- */
-function menu_tree_get_path($menu_name) {
- return menu_tree_set_path($menu_name);
-}
-
-/**
- * Gets the data structure for a named menu tree, based on the current page.
- *
- * The tree order is maintained by storing each parent in an individual
- * field, see http://drupal.org/node/141866 for more.
- *
- * @param $menu_name
- * The named menu links to return.
- * @param $max_depth
- * (optional) The maximum depth of links to retrieve.
- * @param $only_active_trail
- * (optional) Whether to only return the links in the active trail (TRUE)
- * instead of all links on every level of the menu link tree (FALSE). Defaults
- * to FALSE.
- *
- * @return
- * An array of menu links, in the order they should be rendered. The array
- * is a list of associative arrays -- these have two keys, link and below.
- * link is a menu item, ready for theming as a link. Below represents the
- * submenu below the link if there is one, and it is a subtree that has the
- * same structure described for the top-level array.
- */
-function menu_tree_page_data($menu_name, $max_depth = NULL, $only_active_trail = FALSE) {
- $tree = &drupal_static(__FUNCTION__, array());
-
- $language_interface = \Drupal::languageManager()->getCurrentLanguage();
-
- // Check if the active trail has been overridden for this menu tree.
- $active_path = menu_tree_get_path($menu_name);
- // Load the request corresponding to the current page.
- $request = \Drupal::request();
- $system_path = NULL;
- if ($route_name = $request->attributes->get(RouteObjectInterface::ROUTE_NAME)) {
- // @todo https://drupal.org/node/2068471 is adding support so we can tell
- // if this is called on a 404/403 page.
- $system_path = $request->attributes->get('_system_path');
- $page_not_403 = 1;
- }
- if (isset($system_path)) {
- if (isset($max_depth)) {
- $max_depth = min($max_depth, MENU_MAX_DEPTH);
- }
- // Generate a cache ID (cid) specific for this page.
- $cid = 'links:' . $menu_name . ':page:' . $system_path . ':' . $language_interface->id . ':' . $page_not_403 . ':' . (int) $max_depth;
- // If we are asked for the active trail only, and $menu_name has not been
- // built and cached for this page yet, then this likely means that it
- // won't be built anymore, as this function is invoked from
- // template_preprocess_page(). So in order to not build a giant menu tree
- // that needs to be checked for access on all levels, we simply check
- // whether we have the menu already in cache, or otherwise, build a minimum
- // tree containing the active trail only.
- // @see menu_set_active_trail()
- if (!isset($tree[$cid]) && $only_active_trail) {
- $cid .= ':trail';
- }
-
- if (!isset($tree[$cid])) {
- // If the static variable doesn't have the data, check {cache_data}.
- $cache = \Drupal::cache('data')->get($cid);
- if ($cache && isset($cache->data)) {
- // If the cache entry exists, it contains the parameters for
- // menu_build_tree().
- $tree_parameters = $cache->data;
- }
- // If the tree data was not in the cache, build $tree_parameters.
- if (!isset($tree_parameters)) {
- $tree_parameters = array(
- 'min_depth' => 1,
- 'max_depth' => $max_depth,
- );
- // Parent mlids; used both as key and value to ensure uniqueness.
- // We always want all the top-level links with plid == 0.
- $active_trail = array(0 => 0);
-
- // If this page is accessible to the current user, build the tree
- // parameters accordingly.
- if ($page_not_403) {
- // Find a menu link corresponding to the current path. If $active_path
- // is NULL, let menu_link_get_preferred() determine the path.
- if ($active_link = menu_link_get_preferred($active_path, $menu_name)) {
- // The active link may only be taken into account to build the
- // active trail, if it resides in the requested menu. Otherwise,
- // we'd needlessly re-run _menu_build_tree() queries for every menu
- // on every page.
- if ($active_link['menu_name'] == $menu_name) {
- // Use all the coordinates, except the last one because there
- // can be no child beyond the last column.
- for ($i = 1; $i < MENU_MAX_DEPTH; $i++) {
- if ($active_link['p' . $i]) {
- $active_trail[$active_link['p' . $i]] = $active_link['p' . $i];
- }
- }
- // If we are asked to build links for the active trail only, skip
- // the entire 'expanded' handling.
- if ($only_active_trail) {
- $tree_parameters['only_active_trail'] = TRUE;
- }
- }
- }
- $parents = $active_trail;
-
- $expanded = \Drupal::state()->get('menu_expanded');
- // Check whether the current menu has any links set to be expanded.
- if (!$only_active_trail && $expanded && in_array($menu_name, $expanded)) {
- // Collect all the links set to be expanded, and then add all of
- // their children to the list as well.
- do {
- $query = \Drupal::entityQuery('menu_link')
- ->condition('menu_name', $menu_name)
- ->condition('expanded', 1)
- ->condition('has_children', 1)
- ->condition('plid', $parents, 'IN')
- ->condition('mlid', $parents, 'NOT IN');
- $result = $query->execute();
- $parents += $result;
- } while (!empty($result));
- }
- $tree_parameters['expanded'] = $parents;
- $tree_parameters['active_trail'] = $active_trail;
- }
- // If access is denied, we only show top-level links in menus.
- else {
- $tree_parameters['expanded'] = $active_trail;
- $tree_parameters['active_trail'] = $active_trail;
- }
- // Cache the tree building parameters using the page-specific cid.
- \Drupal::cache('data')->set($cid, $tree_parameters, Cache::PERMANENT, array('menu' => $menu_name));
- }
-
- // Build the tree using the parameters; the resulting tree will be cached
- // by _menu_build_tree().
- $tree[$cid] = menu_build_tree($menu_name, $tree_parameters);
- }
- return $tree[$cid];
- }
-
- return array();
-}
-
-/**
- * Builds a menu tree, translates links, and checks access.
- *
- * @param $menu_name
- * The name of the menu.
- * @param $parameters
- * (optional) An associative array of build parameters. Possible keys:
- * - expanded: An array of parent link ids to return only menu links that are
- * children of one of the plids in this list. If empty, the whole menu tree
- * is built, unless 'only_active_trail' is TRUE.
- * - active_trail: An array of mlids, representing the coordinates of the
- * currently active menu link.
- * - only_active_trail: Whether to only return links that are in the active
- * trail. This option is ignored, if 'expanded' is non-empty.
- * - min_depth: The minimum depth of menu links in the resulting tree.
- * Defaults to 1, which is the default to build a whole tree for a menu
- * (excluding menu container itself).
- * - max_depth: The maximum depth of menu links in the resulting tree.
- * - conditions: An associative array of custom database select query
- * condition key/value pairs; see _menu_build_tree() for the actual query.
- *
- * @return
- * A fully built menu tree.
- */
-function menu_build_tree($menu_name, array $parameters = array()) {
- // Build the menu tree.
- $data = _menu_build_tree($menu_name, $parameters);
- // Check access for the current user to each item in the tree.
- menu_tree_check_access($data['tree'], $data['node_links']);
- return $data['tree'];
-}
-
-/**
- * Builds a menu tree.
- *
- * This function may be used build the data for a menu tree only, for example
- * to further massage the data manually before further processing happens.
- * menu_tree_check_access() needs to be invoked afterwards.
- *
- * @see menu_build_tree()
- */
-function _menu_build_tree($menu_name, array $parameters = array()) {
- // Static cache of already built menu trees.
- $trees = &drupal_static(__FUNCTION__, array());
- $language_interface = \Drupal::languageManager()->getCurrentLanguage();
-
- // Build the cache id; sort parents to prevent duplicate storage and remove
- // default parameter values.
- if (isset($parameters['expanded'])) {
- sort($parameters['expanded']);
- }
- $tree_cid = 'links:' . $menu_name . ':tree-data:' . $language_interface->id . ':' . hash('sha256', serialize($parameters));
-
- // If we do not have this tree in the static cache, check {cache_data}.
- if (!isset($trees[$tree_cid])) {
- $cache = \Drupal::cache('data')->get($tree_cid);
- if ($cache && isset($cache->data)) {
- $trees[$tree_cid] = $cache->data;
- }
- }
-
- if (!isset($trees[$tree_cid])) {
- $query = \Drupal::entityQuery('menu_link');
- for ($i = 1; $i <= MENU_MAX_DEPTH; $i++) {
- $query->sort('p' . $i, 'ASC');
- }
- $query->condition('menu_name', $menu_name);
- if (!empty($parameters['expanded'])) {
- $query->condition('plid', $parameters['expanded'], 'IN');
- }
- elseif (!empty($parameters['only_active_trail'])) {
- $query->condition('mlid', $parameters['active_trail'], 'IN');
- }
- $min_depth = (isset($parameters['min_depth']) ? $parameters['min_depth'] : 1);
- if ($min_depth != 1) {
- $query->condition('depth', $min_depth, '>=');
- }
- if (isset($parameters['max_depth'])) {
- $query->condition('depth', $parameters['max_depth'], '<=');
- }
- // Add custom query conditions, if any were passed.
- if (isset($parameters['conditions'])) {
- foreach ($parameters['conditions'] as $column => $value) {
- $query->condition($column, $value);
- }
- }
-
- // Build an ordered array of links using the query result object.
- $links = array();
- if ($result = $query->execute()) {
- $links = menu_link_load_multiple($result);
- }
- $active_trail = (isset($parameters['active_trail']) ? $parameters['active_trail'] : array());
- $data['tree'] = menu_tree_data($links, $active_trail, $min_depth);
- $data['node_links'] = array();
- menu_tree_collect_node_links($data['tree'], $data['node_links']);
-
- // Cache the data, if it is not already in the cache.
- \Drupal::cache('data')->set($tree_cid, $data, Cache::PERMANENT, array('menu' => $menu_name));
- $trees[$tree_cid] = $data;
- }
-
- return $trees[$tree_cid];
-}
-
-/**
- * Collects node links from a given menu tree recursively.
- *
- * @param $tree
- * The menu tree you wish to collect node links from.
- * @param $node_links
- * An array in which to store the collected node links.
- */
-function menu_tree_collect_node_links(&$tree, &$node_links) {
- foreach ($tree as $key => $v) {
- if ($tree[$key]['link']['router_path'] == 'node/%') {
- $nid = substr($tree[$key]['link']['link_path'], 5);
- if (is_numeric($nid)) {
- $node_links[$nid][$tree[$key]['link']['mlid']] = &$tree[$key]['link'];
- $tree[$key]['link']['access'] = FALSE;
- }
- }
- if ($tree[$key]['below']) {
- menu_tree_collect_node_links($tree[$key]['below'], $node_links);
- }
- }
-}
-
-/**
- * Checks access and performs dynamic operations for each link in the tree.
- *
- * @param $tree
- * The menu tree you wish to operate on.
- * @param $node_links
- * A collection of node link references generated from $tree by
- * menu_tree_collect_node_links().
- */
-function menu_tree_check_access(&$tree, $node_links = array()) {
- if ($node_links) {
- $nids = array_keys($node_links);
- $select = db_select('node_field_data', 'n');
- $select->addField('n', 'nid');
- // @todo This should be actually filtering on the desired node status field
- // language and just fall back to the default language.
- $select->condition('n.status', 1);
-
- $select->condition('n.nid', $nids, 'IN');
- $select->addTag('node_access');
- $nids = $select->execute()->fetchCol();
- foreach ($nids as $nid) {
- foreach ($node_links[$nid] as $mlid => $link) {
- $node_links[$nid][$mlid]['access'] = TRUE;
- }
- }
- }
- _menu_tree_check_access($tree);
-}
-
-/**
- * Sorts the menu tree and recursively checks access for each item.
- */
-function _menu_tree_check_access(&$tree) {
- $new_tree = array();
- foreach ($tree as $key => $v) {
- $item = &$tree[$key]['link'];
- _menu_link_translate($item);
- if ($item['access'] || ($item['in_active_trail'] && strpos($item['href'], '%') !== FALSE)) {
- if ($tree[$key]['below']) {
- _menu_tree_check_access($tree[$key]['below']);
- }
- // The weights are made a uniform 5 digits by adding 50000 as an offset.
- // After _menu_link_translate(), $item['title'] has the localized link title.
- // Adding the mlid to the end of the index insures that it is unique.
- $new_tree[(50000 + $item['weight']) . ' ' . $item['title'] . ' ' . $item['mlid']] = $tree[$key];
- }
- }
- // Sort siblings in the tree based on the weights and localized titles.
- ksort($new_tree);
- $tree = $new_tree;
-}
-
-/**
- * Sorts and returns the built data representing a menu tree.
- *
- * @param $links
- * A flat array of menu links that are part of the menu. Each array element
- * is an associative array of information about the menu link, containing the
- * fields from the {menu_links} table, and optionally additional information
- * from the {menu_router} table, if the menu item appears in both tables.
- * This array must be ordered depth-first. See _menu_build_tree() for a sample
- * query.
- * @param $parents
- * An array of the menu link ID values that are in the path from the current
- * page to the root of the menu tree.
- * @param $depth
- * The minimum depth to include in the returned menu tree.
- *
- * @return
- * An array of menu links in the form of a tree. Each item in the tree is an
- * associative array containing:
- * - link: The menu link item from $links, with additional element
- * 'in_active_trail' (TRUE if the link ID was in $parents).
- * - below: An array containing the sub-tree of this item, where each element
- * is a tree item array with 'link' and 'below' elements. This array will be
- * empty if the menu item has no items in its sub-tree having a depth
- * greater than or equal to $depth.
- */
-function menu_tree_data(array $links, array $parents = array(), $depth = 1) {
- // Reverse the array so we can use the more efficient array_pop() function.
- $links = array_reverse($links);
- return _menu_tree_data($links, $parents, $depth);
-}
-
-/**
- * Builds the data representing a menu tree.
- *
- * The function is a bit complex because the rendering of a link depends on
- * the next menu link.
- */
-function _menu_tree_data(&$links, $parents, $depth) {
- $tree = array();
- while ($item = array_pop($links)) {
- // We need to determine if we're on the path to root so we can later build
- // the correct active trail.
- $item['in_active_trail'] = in_array($item['mlid'], $parents);
- // Add the current link to the tree.
- $tree[$item['mlid']] = array(
- 'link' => $item,
- 'below' => array(),
- );
- // Look ahead to the next link, but leave it on the array so it's available
- // to other recursive function calls if we return or build a sub-tree.
- $next = end($links);
- // Check whether the next link is the first in a new sub-tree.
- if ($next && $next['depth'] > $depth) {
- // Recursively call _menu_tree_data to build the sub-tree.
- $tree[$item['mlid']]['below'] = _menu_tree_data($links, $parents, $next['depth']);
- // Fetch next link after filling the sub-tree.
- $next = end($links);
- }
- // Determine if we should exit the loop and return.
- if (!$next || $next['depth'] < $depth) {
- break;
- }
- }
- return $tree;
-}
-
-/**
* Implements template_preprocess_HOOK() for theme_menu_tree().
*/
function template_preprocess_menu_tree(&$variables) {
diff --git a/core/modules/menu_link/menu_link.services.yml b/core/modules/menu_link/menu_link.services.yml
index 8a2c5b2..5793fa0 100644
--- a/core/modules/menu_link/menu_link.services.yml
+++ b/core/modules/menu_link/menu_link.services.yml
@@ -1,4 +1,4 @@
services:
menu_link.tree:
class: Drupal\menu_link\MenuTree
- arguments: ['@database', '@cache.menu', '@language_manager', '@request_stack', '@entity.manager', '@entity.query', '@state']
+ arguments: ['@database', '@cache.data', '@language_manager', '@request_stack', '@entity.manager', '@entity.query', '@state']