annotate core/lib/Drupal/Core/Menu/MenuActiveTrail.php @ 19:fa3358dc1485 tip

Add ndrum files
author Chris Cannam
date Wed, 28 Aug 2019 13:14:47 +0100
parents 4c8ae668cc8c
children
rev   line source
Chris@0 1 <?php
Chris@0 2
Chris@0 3 namespace Drupal\Core\Menu;
Chris@0 4
Chris@0 5 use Drupal\Core\Cache\CacheBackendInterface;
Chris@0 6 use Drupal\Core\Cache\CacheCollector;
Chris@0 7 use Drupal\Core\Lock\LockBackendInterface;
Chris@0 8 use Drupal\Core\Routing\RouteMatchInterface;
Chris@0 9
Chris@0 10 /**
Chris@0 11 * Provides the default implementation of the active menu trail service.
Chris@0 12 *
Chris@0 13 * It uses the current route name and route parameters to compare with the ones
Chris@0 14 * of the menu links.
Chris@0 15 */
Chris@0 16 class MenuActiveTrail extends CacheCollector implements MenuActiveTrailInterface {
Chris@0 17
Chris@0 18 /**
Chris@0 19 * The menu link plugin manager.
Chris@0 20 *
Chris@0 21 * @var \Drupal\Core\Menu\MenuLinkManagerInterface
Chris@0 22 */
Chris@0 23 protected $menuLinkManager;
Chris@0 24
Chris@0 25 /**
Chris@0 26 * The route match object for the current page.
Chris@0 27 *
Chris@0 28 * @var \Drupal\Core\Routing\RouteMatchInterface
Chris@0 29 */
Chris@0 30 protected $routeMatch;
Chris@0 31
Chris@0 32 /**
Chris@0 33 * Constructs a \Drupal\Core\Menu\MenuActiveTrail object.
Chris@0 34 *
Chris@0 35 * @param \Drupal\Core\Menu\MenuLinkManagerInterface $menu_link_manager
Chris@0 36 * The menu link plugin manager.
Chris@0 37 * @param \Drupal\Core\Routing\RouteMatchInterface $route_match
Chris@0 38 * A route match object for finding the active link.
Chris@0 39 * @param \Drupal\Core\Cache\CacheBackendInterface $cache
Chris@0 40 * The cache backend.
Chris@0 41 * @param \Drupal\Core\Lock\LockBackendInterface $lock
Chris@0 42 * The lock backend.
Chris@0 43 */
Chris@0 44 public function __construct(MenuLinkManagerInterface $menu_link_manager, RouteMatchInterface $route_match, CacheBackendInterface $cache, LockBackendInterface $lock) {
Chris@0 45 parent::__construct(NULL, $cache, $lock);
Chris@0 46 $this->menuLinkManager = $menu_link_manager;
Chris@0 47 $this->routeMatch = $route_match;
Chris@0 48 }
Chris@0 49
Chris@0 50 /**
Chris@0 51 * {@inheritdoc}
Chris@0 52 *
Chris@0 53 * @see ::getActiveTrailIds()
Chris@0 54 */
Chris@0 55 protected function getCid() {
Chris@0 56 if (!isset($this->cid)) {
Chris@0 57 $route_parameters = $this->routeMatch->getRawParameters()->all();
Chris@0 58 ksort($route_parameters);
Chris@0 59 return 'active-trail:route:' . $this->routeMatch->getRouteName() . ':route_parameters:' . serialize($route_parameters);
Chris@0 60 }
Chris@0 61
Chris@0 62 return $this->cid;
Chris@0 63 }
Chris@0 64
Chris@0 65 /**
Chris@0 66 * {@inheritdoc}
Chris@0 67 *
Chris@0 68 * @see ::getActiveTrailIds()
Chris@0 69 */
Chris@0 70 protected function resolveCacheMiss($menu_name) {
Chris@0 71 $this->storage[$menu_name] = $this->doGetActiveTrailIds($menu_name);
Chris@0 72 $this->tags[] = 'config:system.menu.' . $menu_name;
Chris@0 73 $this->persist($menu_name);
Chris@0 74
Chris@0 75 return $this->storage[$menu_name];
Chris@0 76 }
Chris@0 77
Chris@0 78 /**
Chris@0 79 * {@inheritdoc}
Chris@0 80 *
Chris@0 81 * This implementation caches all active trail IDs per route match for *all*
Chris@0 82 * menus whose active trails are calculated on that page. This ensures 1 cache
Chris@0 83 * get for all active trails per page load, rather than N.
Chris@0 84 *
Chris@0 85 * It uses the cache collector pattern to do this.
Chris@0 86 *
Chris@0 87 * @see ::get()
Chris@0 88 * @see \Drupal\Core\Cache\CacheCollectorInterface
Chris@0 89 * @see \Drupal\Core\Cache\CacheCollector
Chris@0 90 */
Chris@0 91 public function getActiveTrailIds($menu_name) {
Chris@0 92 return $this->get($menu_name);
Chris@0 93 }
Chris@0 94
Chris@0 95 /**
Chris@0 96 * Helper method for ::getActiveTrailIds().
Chris@0 97 */
Chris@0 98 protected function doGetActiveTrailIds($menu_name) {
Chris@0 99 // Parent ids; used both as key and value to ensure uniqueness.
Chris@0 100 // We always want all the top-level links with parent == ''.
Chris@0 101 $active_trail = ['' => ''];
Chris@0 102
Chris@0 103 // If a link in the given menu indeed matches the route, then use it to
Chris@0 104 // complete the active trail.
Chris@0 105 if ($active_link = $this->getActiveLink($menu_name)) {
Chris@0 106 if ($parents = $this->menuLinkManager->getParentIds($active_link->getPluginId())) {
Chris@0 107 $active_trail = $parents + $active_trail;
Chris@0 108 }
Chris@0 109 }
Chris@0 110
Chris@0 111 return $active_trail;
Chris@0 112 }
Chris@0 113
Chris@0 114 /**
Chris@0 115 * {@inheritdoc}
Chris@0 116 */
Chris@0 117 public function getActiveLink($menu_name = NULL) {
Chris@0 118 // Note: this is a very simple implementation. If you need more control
Chris@0 119 // over the return value, such as matching a prioritized list of menu names,
Chris@0 120 // you should substitute your own implementation for the 'menu.active_trail'
Chris@0 121 // service in the container.
Chris@0 122 // The menu links coming from the storage are already sorted by depth,
Chris@0 123 // weight and ID.
Chris@0 124 $found = NULL;
Chris@0 125
Chris@0 126 $route_name = $this->routeMatch->getRouteName();
Chris@0 127 // On a default (not custom) 403 page the route name is NULL. On a custom
Chris@0 128 // 403 page we will get the route name for that page, so we can consider
Chris@0 129 // it a feature that a relevant menu tree may be displayed.
Chris@0 130 if ($route_name) {
Chris@0 131 $route_parameters = $this->routeMatch->getRawParameters()->all();
Chris@0 132
Chris@0 133 // Load links matching this route.
Chris@0 134 $links = $this->menuLinkManager->loadLinksByRoute($route_name, $route_parameters, $menu_name);
Chris@0 135 // Select the first matching link.
Chris@0 136 if ($links) {
Chris@0 137 $found = reset($links);
Chris@0 138 }
Chris@0 139 }
Chris@0 140 return $found;
Chris@0 141 }
Chris@0 142
Chris@0 143 }