Chris@0
|
1 <?php
|
Chris@0
|
2
|
Chris@0
|
3 namespace Drupal\Core\Menu;
|
Chris@0
|
4
|
Chris@0
|
5 use Drupal\Component\Plugin\Exception\PluginException;
|
Chris@0
|
6 use Drupal\Core\Access\AccessManagerInterface;
|
Chris@0
|
7 use Drupal\Core\Cache\CacheBackendInterface;
|
Chris@0
|
8 use Drupal\Core\Controller\ControllerResolverInterface;
|
Chris@0
|
9 use Drupal\Core\Extension\ModuleHandlerInterface;
|
Chris@0
|
10 use Drupal\Core\Language\LanguageManagerInterface;
|
Chris@0
|
11 use Drupal\Core\Plugin\DefaultPluginManager;
|
Chris@0
|
12 use Drupal\Core\Plugin\Discovery\ContainerDerivativeDiscoveryDecorator;
|
Chris@0
|
13 use Drupal\Core\Plugin\Discovery\YamlDiscovery;
|
Chris@0
|
14 use Drupal\Core\Plugin\Factory\ContainerFactory;
|
Chris@0
|
15 use Drupal\Core\Session\AccountInterface;
|
Chris@0
|
16 use Symfony\Component\HttpFoundation\RequestStack;
|
Chris@0
|
17
|
Chris@0
|
18 /**
|
Chris@0
|
19 * Defines a contextual link plugin manager to deal with contextual links.
|
Chris@0
|
20 *
|
Chris@0
|
21 * @see \Drupal\Core\Menu\ContextualLinkInterface
|
Chris@0
|
22 */
|
Chris@0
|
23 class ContextualLinkManager extends DefaultPluginManager implements ContextualLinkManagerInterface {
|
Chris@0
|
24
|
Chris@0
|
25 /**
|
Chris@0
|
26 * Provides default values for a contextual link definition.
|
Chris@0
|
27 *
|
Chris@0
|
28 * @var array
|
Chris@0
|
29 */
|
Chris@0
|
30 protected $defaults = [
|
Chris@0
|
31 // (required) The name of the route to link to.
|
Chris@0
|
32 'route_name' => '',
|
Chris@0
|
33 // (required) The contextual links group.
|
Chris@0
|
34 'group' => '',
|
Chris@0
|
35 // The static title text for the link.
|
Chris@0
|
36 'title' => '',
|
Chris@0
|
37 // The default link options.
|
Chris@0
|
38 'options' => [],
|
Chris@0
|
39 // The weight of the link.
|
Chris@0
|
40 'weight' => NULL,
|
Chris@0
|
41 // Default class for contextual link implementations.
|
Chris@0
|
42 'class' => '\Drupal\Core\Menu\ContextualLinkDefault',
|
Chris@0
|
43 // The plugin id. Set by the plugin system based on the top-level YAML key.
|
Chris@0
|
44 'id' => '',
|
Chris@0
|
45 ];
|
Chris@0
|
46
|
Chris@0
|
47 /**
|
Chris@0
|
48 * A controller resolver object.
|
Chris@0
|
49 *
|
Chris@0
|
50 * @var \Symfony\Component\HttpKernel\Controller\ControllerResolverInterface
|
Chris@0
|
51 */
|
Chris@0
|
52 protected $controllerResolver;
|
Chris@0
|
53
|
Chris@0
|
54 /**
|
Chris@0
|
55 * The access manager.
|
Chris@0
|
56 *
|
Chris@0
|
57 * @var \Drupal\Core\Access\AccessManagerInterface
|
Chris@0
|
58 */
|
Chris@0
|
59 protected $accessManager;
|
Chris@0
|
60
|
Chris@0
|
61 /**
|
Chris@0
|
62 * The current user.
|
Chris@0
|
63 *
|
Chris@0
|
64 * @var \Drupal\Core\Session\AccountInterface
|
Chris@0
|
65 */
|
Chris@0
|
66 protected $account;
|
Chris@0
|
67
|
Chris@0
|
68 /**
|
Chris@0
|
69 * The request stack.
|
Chris@0
|
70 *
|
Chris@0
|
71 * @var \Symfony\Component\HttpFoundation\RequestStack
|
Chris@0
|
72 */
|
Chris@0
|
73 protected $requestStack;
|
Chris@0
|
74
|
Chris@0
|
75 /**
|
Chris@0
|
76 * A static cache of all the contextual link plugins by group name.
|
Chris@0
|
77 *
|
Chris@0
|
78 * @var array
|
Chris@0
|
79 */
|
Chris@0
|
80 protected $pluginsByGroup;
|
Chris@0
|
81
|
Chris@0
|
82 /**
|
Chris@0
|
83 * Constructs a new ContextualLinkManager instance.
|
Chris@0
|
84 *
|
Chris@0
|
85 * @param \Drupal\Core\Controller\ControllerResolverInterface $controller_resolver
|
Chris@0
|
86 * The controller resolver.
|
Chris@0
|
87 * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
|
Chris@0
|
88 * The module handler.
|
Chris@0
|
89 * @param \Drupal\Core\Cache\CacheBackendInterface $cache_backend
|
Chris@0
|
90 * The cache backend.
|
Chris@0
|
91 * @param \Drupal\Core\Language\LanguageManagerInterface $language_manager
|
Chris@0
|
92 * The language manager.
|
Chris@0
|
93 * @param \Drupal\Core\Access\AccessManagerInterface $access_manager
|
Chris@0
|
94 * The access manager.
|
Chris@0
|
95 * @param \Drupal\Core\Session\AccountInterface $account
|
Chris@0
|
96 * The current user.
|
Chris@0
|
97 * @param \Symfony\Component\HttpFoundation\RequestStack $request_stack
|
Chris@0
|
98 * The request stack.
|
Chris@0
|
99 */
|
Chris@0
|
100 public function __construct(ControllerResolverInterface $controller_resolver, ModuleHandlerInterface $module_handler, CacheBackendInterface $cache_backend, LanguageManagerInterface $language_manager, AccessManagerInterface $access_manager, AccountInterface $account, RequestStack $request_stack) {
|
Chris@0
|
101 $this->factory = new ContainerFactory($this, '\Drupal\Core\Menu\ContextualLinkInterface');
|
Chris@0
|
102 $this->controllerResolver = $controller_resolver;
|
Chris@0
|
103 $this->accessManager = $access_manager;
|
Chris@0
|
104 $this->account = $account;
|
Chris@0
|
105 $this->moduleHandler = $module_handler;
|
Chris@0
|
106 $this->requestStack = $request_stack;
|
Chris@0
|
107 $this->alterInfo('contextual_links_plugins');
|
Chris@0
|
108 $this->setCacheBackend($cache_backend, 'contextual_links_plugins:' . $language_manager->getCurrentLanguage()->getId(), ['contextual_links_plugins']);
|
Chris@0
|
109 }
|
Chris@0
|
110
|
Chris@0
|
111 /**
|
Chris@0
|
112 * {@inheritdoc}
|
Chris@0
|
113 */
|
Chris@0
|
114 protected function getDiscovery() {
|
Chris@0
|
115 if (!isset($this->discovery)) {
|
Chris@0
|
116 $yaml_discovery = new YamlDiscovery('links.contextual', $this->moduleHandler->getModuleDirectories());
|
Chris@0
|
117 $yaml_discovery->addTranslatableProperty('title', 'title_context');
|
Chris@0
|
118 $this->discovery = new ContainerDerivativeDiscoveryDecorator($yaml_discovery);
|
Chris@0
|
119 }
|
Chris@0
|
120 return $this->discovery;
|
Chris@0
|
121 }
|
Chris@0
|
122
|
Chris@0
|
123 /**
|
Chris@0
|
124 * {@inheritdoc}
|
Chris@0
|
125 */
|
Chris@0
|
126 public function processDefinition(&$definition, $plugin_id) {
|
Chris@0
|
127 parent::processDefinition($definition, $plugin_id);
|
Chris@0
|
128
|
Chris@0
|
129 // If there is no route name, this is a broken definition.
|
Chris@0
|
130 if (empty($definition['route_name'])) {
|
Chris@0
|
131 throw new PluginException(sprintf('Contextual link plugin (%s) definition must include "route_name".', $plugin_id));
|
Chris@0
|
132 }
|
Chris@0
|
133 // If there is no group name, this is a broken definition.
|
Chris@0
|
134 if (empty($definition['group'])) {
|
Chris@0
|
135 throw new PluginException(sprintf('Contextual link plugin (%s) definition must include "group".', $plugin_id));
|
Chris@0
|
136 }
|
Chris@0
|
137 }
|
Chris@0
|
138
|
Chris@0
|
139 /**
|
Chris@0
|
140 * {@inheritdoc}
|
Chris@0
|
141 */
|
Chris@0
|
142 public function getContextualLinkPluginsByGroup($group_name) {
|
Chris@0
|
143 if (isset($this->pluginsByGroup[$group_name])) {
|
Chris@0
|
144 $contextual_links = $this->pluginsByGroup[$group_name];
|
Chris@0
|
145 }
|
Chris@0
|
146 elseif ($cache = $this->cacheBackend->get($this->cacheKey . ':' . $group_name)) {
|
Chris@0
|
147 $contextual_links = $cache->data;
|
Chris@0
|
148 $this->pluginsByGroup[$group_name] = $contextual_links;
|
Chris@0
|
149 }
|
Chris@0
|
150 else {
|
Chris@0
|
151 $contextual_links = [];
|
Chris@0
|
152 foreach ($this->getDefinitions() as $plugin_id => $plugin_definition) {
|
Chris@0
|
153 if ($plugin_definition['group'] == $group_name) {
|
Chris@0
|
154 $contextual_links[$plugin_id] = $plugin_definition;
|
Chris@0
|
155 }
|
Chris@0
|
156 }
|
Chris@0
|
157 $this->cacheBackend->set($this->cacheKey . ':' . $group_name, $contextual_links);
|
Chris@0
|
158 $this->pluginsByGroup[$group_name] = $contextual_links;
|
Chris@0
|
159 }
|
Chris@0
|
160 return $contextual_links;
|
Chris@0
|
161 }
|
Chris@0
|
162
|
Chris@0
|
163 /**
|
Chris@0
|
164 * {@inheritdoc}
|
Chris@0
|
165 */
|
Chris@0
|
166 public function getContextualLinksArrayByGroup($group_name, array $route_parameters, array $metadata = []) {
|
Chris@0
|
167 $links = [];
|
Chris@0
|
168 $request = $this->requestStack->getCurrentRequest();
|
Chris@0
|
169 foreach ($this->getContextualLinkPluginsByGroup($group_name) as $plugin_id => $plugin_definition) {
|
Chris@0
|
170 /** @var $plugin \Drupal\Core\Menu\ContextualLinkInterface */
|
Chris@0
|
171 $plugin = $this->createInstance($plugin_id);
|
Chris@0
|
172 $route_name = $plugin->getRouteName();
|
Chris@0
|
173
|
Chris@0
|
174 // Check access.
|
Chris@0
|
175 if (!$this->accessManager->checkNamedRoute($route_name, $route_parameters, $this->account)) {
|
Chris@0
|
176 continue;
|
Chris@0
|
177 }
|
Chris@0
|
178
|
Chris@0
|
179 $links[$plugin_id] = [
|
Chris@0
|
180 'route_name' => $route_name,
|
Chris@0
|
181 'route_parameters' => $route_parameters,
|
Chris@0
|
182 'title' => $plugin->getTitle($request),
|
Chris@0
|
183 'weight' => $plugin->getWeight(),
|
Chris@0
|
184 'localized_options' => $plugin->getOptions(),
|
Chris@0
|
185 'metadata' => $metadata,
|
Chris@0
|
186 ];
|
Chris@0
|
187 }
|
Chris@0
|
188
|
Chris@0
|
189 $this->moduleHandler->alter('contextual_links', $links, $group_name, $route_parameters);
|
Chris@0
|
190
|
Chris@0
|
191 return $links;
|
Chris@0
|
192 }
|
Chris@0
|
193
|
Chris@0
|
194 }
|