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