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 }
|