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\Cache;
|
Chris@0
|
8 use Drupal\Core\Cache\CacheableMetadata;
|
Chris@0
|
9 use Drupal\Core\Cache\CacheBackendInterface;
|
Chris@0
|
10 use Drupal\Core\Cache\RefinableCacheableDependencyInterface;
|
Chris@0
|
11 use Drupal\Core\Controller\ControllerResolverInterface;
|
Chris@0
|
12 use Drupal\Core\Extension\ModuleHandlerInterface;
|
Chris@0
|
13 use Drupal\Core\Language\LanguageManagerInterface;
|
Chris@0
|
14 use Drupal\Core\Plugin\DefaultPluginManager;
|
Chris@0
|
15 use Drupal\Core\Plugin\Discovery\ContainerDerivativeDiscoveryDecorator;
|
Chris@0
|
16 use Drupal\Core\Plugin\Discovery\YamlDiscovery;
|
Chris@0
|
17 use Drupal\Core\Plugin\Factory\ContainerFactory;
|
Chris@0
|
18 use Drupal\Core\Routing\RouteMatchInterface;
|
Chris@0
|
19 use Drupal\Core\Routing\RouteProviderInterface;
|
Chris@0
|
20 use Drupal\Core\Session\AccountInterface;
|
Chris@0
|
21 use Drupal\Core\Url;
|
Chris@0
|
22 use Symfony\Component\HttpFoundation\RequestStack;
|
Chris@17
|
23 use Symfony\Component\HttpKernel\Controller\ArgumentResolverInterface;
|
Chris@0
|
24
|
Chris@0
|
25 /**
|
Chris@0
|
26 * Provides the default local task manager using YML as primary definition.
|
Chris@0
|
27 */
|
Chris@0
|
28 class LocalTaskManager extends DefaultPluginManager implements LocalTaskManagerInterface {
|
Chris@0
|
29
|
Chris@0
|
30 /**
|
Chris@0
|
31 * {@inheritdoc}
|
Chris@0
|
32 */
|
Chris@0
|
33 protected $defaults = [
|
Chris@0
|
34 // (required) The name of the route this task links to.
|
Chris@0
|
35 'route_name' => '',
|
Chris@0
|
36 // Parameters for route variables when generating a link.
|
Chris@0
|
37 'route_parameters' => [],
|
Chris@0
|
38 // The static title for the local task.
|
Chris@0
|
39 'title' => '',
|
Chris@0
|
40 // The route name where the root tab appears.
|
Chris@0
|
41 'base_route' => '',
|
Chris@0
|
42 // The plugin ID of the parent tab (or NULL for the top-level tab).
|
Chris@0
|
43 'parent_id' => NULL,
|
Chris@0
|
44 // The weight of the tab.
|
Chris@0
|
45 'weight' => NULL,
|
Chris@0
|
46 // The default link options.
|
Chris@0
|
47 'options' => [],
|
Chris@0
|
48 // Default class for local task implementations.
|
Chris@0
|
49 'class' => 'Drupal\Core\Menu\LocalTaskDefault',
|
Chris@0
|
50 // The plugin id. Set by the plugin system based on the top-level YAML key.
|
Chris@0
|
51 'id' => '',
|
Chris@0
|
52 ];
|
Chris@0
|
53
|
Chris@0
|
54 /**
|
Chris@17
|
55 * An argument resolver object.
|
Chris@17
|
56 *
|
Chris@17
|
57 * @var \Symfony\Component\HttpKernel\Controller\ArgumentResolverInterface
|
Chris@17
|
58 */
|
Chris@17
|
59 protected $argumentResolver;
|
Chris@17
|
60
|
Chris@17
|
61 /**
|
Chris@0
|
62 * A controller resolver object.
|
Chris@0
|
63 *
|
Chris@17
|
64 * @var \Symfony\Component\HttpKernel\Controller\ControllerResolverInterface
|
Chris@17
|
65 *
|
Chris@17
|
66 * @deprecated
|
Chris@17
|
67 * Using the 'controller_resolver' service as the first argument is
|
Chris@17
|
68 * deprecated, use the 'http_kernel.controller.argument_resolver' instead.
|
Chris@17
|
69 * If your subclass requires the 'controller_resolver' service add it as an
|
Chris@17
|
70 * additional argument.
|
Chris@17
|
71 *
|
Chris@17
|
72 * @see https://www.drupal.org/node/2959408
|
Chris@0
|
73 */
|
Chris@0
|
74 protected $controllerResolver;
|
Chris@0
|
75
|
Chris@0
|
76 /**
|
Chris@0
|
77 * The request stack.
|
Chris@0
|
78 *
|
Chris@0
|
79 * @var \Symfony\Component\HttpFoundation\RequestStack
|
Chris@0
|
80 */
|
Chris@0
|
81 protected $requestStack;
|
Chris@0
|
82
|
Chris@0
|
83 /**
|
Chris@0
|
84 * The current route match.
|
Chris@0
|
85 *
|
Chris@0
|
86 * @var \Drupal\Core\Routing\RouteMatchInterface
|
Chris@0
|
87 */
|
Chris@0
|
88 protected $routeMatch;
|
Chris@0
|
89
|
Chris@0
|
90 /**
|
Chris@0
|
91 * The plugin instances.
|
Chris@0
|
92 *
|
Chris@0
|
93 * @var array
|
Chris@0
|
94 */
|
Chris@0
|
95 protected $instances = [];
|
Chris@0
|
96
|
Chris@0
|
97 /**
|
Chris@0
|
98 * The local task render arrays for the current route.
|
Chris@0
|
99 *
|
Chris@0
|
100 * @var array
|
Chris@0
|
101 */
|
Chris@0
|
102 protected $taskData;
|
Chris@0
|
103
|
Chris@0
|
104 /**
|
Chris@0
|
105 * The route provider to load routes by name.
|
Chris@0
|
106 *
|
Chris@0
|
107 * @var \Drupal\Core\Routing\RouteProviderInterface
|
Chris@0
|
108 */
|
Chris@0
|
109 protected $routeProvider;
|
Chris@0
|
110
|
Chris@0
|
111 /**
|
Chris@0
|
112 * The access manager.
|
Chris@0
|
113 *
|
Chris@0
|
114 * @var \Drupal\Core\Access\AccessManagerInterface
|
Chris@0
|
115 */
|
Chris@0
|
116 protected $accessManager;
|
Chris@0
|
117
|
Chris@0
|
118 /**
|
Chris@0
|
119 * The current user.
|
Chris@0
|
120 *
|
Chris@0
|
121 * @var \Drupal\Core\Session\AccountInterface
|
Chris@0
|
122 */
|
Chris@0
|
123 protected $account;
|
Chris@0
|
124
|
Chris@0
|
125 /**
|
Chris@0
|
126 * Constructs a \Drupal\Core\Menu\LocalTaskManager object.
|
Chris@0
|
127 *
|
Chris@17
|
128 * @param \Symfony\Component\HttpKernel\Controller\ArgumentResolverInterface $argument_resolver
|
Chris@17
|
129 * An object to use in resolving route arguments.
|
Chris@0
|
130 * @param \Symfony\Component\HttpFoundation\RequestStack $request_stack
|
Chris@0
|
131 * The request object to use for building titles and paths for plugin instances.
|
Chris@0
|
132 * @param \Drupal\Core\Routing\RouteMatchInterface $route_match
|
Chris@0
|
133 * The current route match.
|
Chris@0
|
134 * @param \Drupal\Core\Routing\RouteProviderInterface $route_provider
|
Chris@0
|
135 * The route provider to load routes by name.
|
Chris@0
|
136 * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
|
Chris@0
|
137 * The module handler.
|
Chris@0
|
138 * @param \Drupal\Core\Cache\CacheBackendInterface $cache
|
Chris@0
|
139 * The cache backend.
|
Chris@0
|
140 * @param \Drupal\Core\Language\LanguageManagerInterface $language_manager
|
Chris@0
|
141 * The language manager.
|
Chris@0
|
142 * @param \Drupal\Core\Access\AccessManagerInterface $access_manager
|
Chris@0
|
143 * The access manager.
|
Chris@0
|
144 * @param \Drupal\Core\Session\AccountInterface $account
|
Chris@0
|
145 * The current user.
|
Chris@0
|
146 */
|
Chris@17
|
147 public function __construct(ArgumentResolverInterface $argument_resolver, RequestStack $request_stack, RouteMatchInterface $route_match, RouteProviderInterface $route_provider, ModuleHandlerInterface $module_handler, CacheBackendInterface $cache, LanguageManagerInterface $language_manager, AccessManagerInterface $access_manager, AccountInterface $account) {
|
Chris@0
|
148 $this->factory = new ContainerFactory($this, '\Drupal\Core\Menu\LocalTaskInterface');
|
Chris@17
|
149 $this->argumentResolver = $argument_resolver;
|
Chris@17
|
150 if ($argument_resolver instanceof ControllerResolverInterface) {
|
Chris@17
|
151 @trigger_error("Using the 'controller_resolver' service as the first argument is deprecated, use the 'http_kernel.controller.argument_resolver' instead. If your subclass requires the 'controller_resolver' service add it as an additional argument. See https://www.drupal.org/node/2959408.", E_USER_DEPRECATED);
|
Chris@17
|
152 $this->controllerResolver = $argument_resolver;
|
Chris@17
|
153 }
|
Chris@0
|
154 $this->requestStack = $request_stack;
|
Chris@0
|
155 $this->routeMatch = $route_match;
|
Chris@0
|
156 $this->routeProvider = $route_provider;
|
Chris@0
|
157 $this->accessManager = $access_manager;
|
Chris@0
|
158 $this->account = $account;
|
Chris@0
|
159 $this->moduleHandler = $module_handler;
|
Chris@0
|
160 $this->alterInfo('local_tasks');
|
Chris@0
|
161 $this->setCacheBackend($cache, 'local_task_plugins:' . $language_manager->getCurrentLanguage()->getId(), ['local_task']);
|
Chris@0
|
162 }
|
Chris@0
|
163
|
Chris@0
|
164 /**
|
Chris@0
|
165 * {@inheritdoc}
|
Chris@0
|
166 */
|
Chris@0
|
167 protected function getDiscovery() {
|
Chris@0
|
168 if (!isset($this->discovery)) {
|
Chris@0
|
169 $yaml_discovery = new YamlDiscovery('links.task', $this->moduleHandler->getModuleDirectories());
|
Chris@0
|
170 $yaml_discovery->addTranslatableProperty('title', 'title_context');
|
Chris@0
|
171 $this->discovery = new ContainerDerivativeDiscoveryDecorator($yaml_discovery);
|
Chris@0
|
172 }
|
Chris@0
|
173 return $this->discovery;
|
Chris@0
|
174 }
|
Chris@0
|
175
|
Chris@0
|
176 /**
|
Chris@0
|
177 * {@inheritdoc}
|
Chris@0
|
178 */
|
Chris@0
|
179 public function processDefinition(&$definition, $plugin_id) {
|
Chris@0
|
180 parent::processDefinition($definition, $plugin_id);
|
Chris@0
|
181 // If there is no route name, this is a broken definition.
|
Chris@0
|
182 if (empty($definition['route_name'])) {
|
Chris@0
|
183 throw new PluginException(sprintf('Plugin (%s) definition must include "route_name"', $plugin_id));
|
Chris@0
|
184 }
|
Chris@0
|
185 }
|
Chris@0
|
186
|
Chris@0
|
187 /**
|
Chris@0
|
188 * {@inheritdoc}
|
Chris@0
|
189 */
|
Chris@0
|
190 public function getTitle(LocalTaskInterface $local_task) {
|
Chris@0
|
191 $controller = [$local_task, 'getTitle'];
|
Chris@0
|
192 $request = $this->requestStack->getCurrentRequest();
|
Chris@17
|
193 $arguments = $this->argumentResolver->getArguments($request, $controller);
|
Chris@0
|
194 return call_user_func_array($controller, $arguments);
|
Chris@0
|
195 }
|
Chris@0
|
196
|
Chris@0
|
197 /**
|
Chris@0
|
198 * {@inheritdoc}
|
Chris@0
|
199 */
|
Chris@0
|
200 public function getDefinitions() {
|
Chris@0
|
201 $definitions = parent::getDefinitions();
|
Chris@0
|
202
|
Chris@0
|
203 $count = 0;
|
Chris@0
|
204 foreach ($definitions as &$definition) {
|
Chris@0
|
205 if (isset($definition['weight'])) {
|
Chris@0
|
206 // Add some micro weight.
|
Chris@0
|
207 $definition['weight'] += ($count++) * 1e-6;
|
Chris@0
|
208 }
|
Chris@0
|
209 }
|
Chris@0
|
210
|
Chris@0
|
211 return $definitions;
|
Chris@0
|
212 }
|
Chris@0
|
213
|
Chris@0
|
214 /**
|
Chris@0
|
215 * {@inheritdoc}
|
Chris@0
|
216 */
|
Chris@0
|
217 public function getLocalTasksForRoute($route_name) {
|
Chris@0
|
218 if (!isset($this->instances[$route_name])) {
|
Chris@0
|
219 $this->instances[$route_name] = [];
|
Chris@0
|
220 if ($cache = $this->cacheBackend->get($this->cacheKey . ':' . $route_name)) {
|
Chris@0
|
221 $base_routes = $cache->data['base_routes'];
|
Chris@0
|
222 $parents = $cache->data['parents'];
|
Chris@0
|
223 $children = $cache->data['children'];
|
Chris@0
|
224 }
|
Chris@0
|
225 else {
|
Chris@0
|
226 $definitions = $this->getDefinitions();
|
Chris@0
|
227 // We build the hierarchy by finding all tabs that should
|
Chris@0
|
228 // appear on the current route.
|
Chris@0
|
229 $base_routes = [];
|
Chris@0
|
230 $parents = [];
|
Chris@0
|
231 $children = [];
|
Chris@0
|
232 foreach ($definitions as $plugin_id => $task_info) {
|
Chris@0
|
233 // Fill in the base_route from the parent to insure consistency.
|
Chris@0
|
234 if (!empty($task_info['parent_id']) && !empty($definitions[$task_info['parent_id']])) {
|
Chris@0
|
235 $task_info['base_route'] = $definitions[$task_info['parent_id']]['base_route'];
|
Chris@0
|
236 // Populate the definitions we use in the next loop. Using a
|
Chris@0
|
237 // reference like &$task_info causes bugs.
|
Chris@0
|
238 $definitions[$plugin_id]['base_route'] = $definitions[$task_info['parent_id']]['base_route'];
|
Chris@0
|
239 }
|
Chris@0
|
240 if ($route_name == $task_info['route_name']) {
|
Chris@0
|
241 if (!empty($task_info['base_route'])) {
|
Chris@0
|
242 $base_routes[$task_info['base_route']] = $task_info['base_route'];
|
Chris@0
|
243 }
|
Chris@0
|
244 // Tabs that link to the current route are viable parents
|
Chris@0
|
245 // and their parent and children should be visible also.
|
Chris@0
|
246 // @todo - this only works for 2 levels of tabs.
|
Chris@0
|
247 // instead need to iterate up.
|
Chris@0
|
248 $parents[$plugin_id] = TRUE;
|
Chris@0
|
249 if (!empty($task_info['parent_id'])) {
|
Chris@0
|
250 $parents[$task_info['parent_id']] = TRUE;
|
Chris@0
|
251 }
|
Chris@0
|
252 }
|
Chris@0
|
253 }
|
Chris@0
|
254 if ($base_routes) {
|
Chris@0
|
255 // Find all the plugins with the same root and that are at the top
|
Chris@0
|
256 // level or that have a visible parent.
|
Chris@0
|
257 foreach ($definitions as $plugin_id => $task_info) {
|
Chris@0
|
258 if (!empty($base_routes[$task_info['base_route']]) && (empty($task_info['parent_id']) || !empty($parents[$task_info['parent_id']]))) {
|
Chris@0
|
259 // Concat '> ' with root ID for the parent of top-level tabs.
|
Chris@0
|
260 $parent = empty($task_info['parent_id']) ? '> ' . $task_info['base_route'] : $task_info['parent_id'];
|
Chris@0
|
261 $children[$parent][$plugin_id] = $task_info;
|
Chris@0
|
262 }
|
Chris@0
|
263 }
|
Chris@0
|
264 }
|
Chris@0
|
265 $data = [
|
Chris@0
|
266 'base_routes' => $base_routes,
|
Chris@0
|
267 'parents' => $parents,
|
Chris@0
|
268 'children' => $children,
|
Chris@0
|
269 ];
|
Chris@0
|
270 $this->cacheBackend->set($this->cacheKey . ':' . $route_name, $data, Cache::PERMANENT, $this->cacheTags);
|
Chris@0
|
271 }
|
Chris@0
|
272 // Create a plugin instance for each element of the hierarchy.
|
Chris@0
|
273 foreach ($base_routes as $base_route) {
|
Chris@0
|
274 // Convert the tree keyed by plugin IDs into a simple one with
|
Chris@0
|
275 // integer depth. Create instances for each plugin along the way.
|
Chris@0
|
276 $level = 0;
|
Chris@0
|
277 // We used this above as the top-level parent array key.
|
Chris@0
|
278 $next_parent = '> ' . $base_route;
|
Chris@0
|
279 do {
|
Chris@0
|
280 $parent = $next_parent;
|
Chris@0
|
281 $next_parent = FALSE;
|
Chris@0
|
282 foreach ($children[$parent] as $plugin_id => $task_info) {
|
Chris@0
|
283 $plugin = $this->createInstance($plugin_id);
|
Chris@0
|
284 $this->instances[$route_name][$level][$plugin_id] = $plugin;
|
Chris@0
|
285 // Normally, the link generator compares the href of every link with
|
Chris@0
|
286 // the current path and sets the active class accordingly. But the
|
Chris@0
|
287 // parents of the current local task may be on a different route in
|
Chris@0
|
288 // which case we have to set the class manually by flagging it
|
Chris@0
|
289 // active.
|
Chris@0
|
290 if (!empty($parents[$plugin_id]) && $route_name != $task_info['route_name']) {
|
Chris@0
|
291 $plugin->setActive();
|
Chris@0
|
292 }
|
Chris@0
|
293 if (isset($children[$plugin_id])) {
|
Chris@0
|
294 // This tab has visible children.
|
Chris@0
|
295 $next_parent = $plugin_id;
|
Chris@0
|
296 }
|
Chris@0
|
297 }
|
Chris@0
|
298 $level++;
|
Chris@0
|
299 } while ($next_parent);
|
Chris@0
|
300 }
|
Chris@0
|
301
|
Chris@0
|
302 }
|
Chris@0
|
303 return $this->instances[$route_name];
|
Chris@0
|
304 }
|
Chris@0
|
305
|
Chris@0
|
306 /**
|
Chris@0
|
307 * {@inheritdoc}
|
Chris@0
|
308 */
|
Chris@0
|
309 public function getTasksBuild($current_route_name, RefinableCacheableDependencyInterface &$cacheability) {
|
Chris@0
|
310 $tree = $this->getLocalTasksForRoute($current_route_name);
|
Chris@0
|
311 $build = [];
|
Chris@0
|
312
|
Chris@0
|
313 // Collect all route names.
|
Chris@0
|
314 $route_names = [];
|
Chris@0
|
315 foreach ($tree as $instances) {
|
Chris@0
|
316 foreach ($instances as $child) {
|
Chris@0
|
317 $route_names[] = $child->getRouteName();
|
Chris@0
|
318 }
|
Chris@0
|
319 }
|
Chris@0
|
320 // Pre-fetch all routes involved in the tree. This reduces the number
|
Chris@0
|
321 // of SQL queries that would otherwise be triggered by the access manager.
|
Chris@0
|
322 if ($route_names) {
|
Chris@0
|
323 $this->routeProvider->getRoutesByNames($route_names);
|
Chris@0
|
324 }
|
Chris@0
|
325
|
Chris@0
|
326 foreach ($tree as $level => $instances) {
|
Chris@0
|
327 /** @var $instances \Drupal\Core\Menu\LocalTaskInterface[] */
|
Chris@0
|
328 foreach ($instances as $plugin_id => $child) {
|
Chris@0
|
329 $route_name = $child->getRouteName();
|
Chris@0
|
330 $route_parameters = $child->getRouteParameters($this->routeMatch);
|
Chris@0
|
331
|
Chris@0
|
332 // Given that the active flag depends on the route we have to add the
|
Chris@0
|
333 // route cache context.
|
Chris@0
|
334 $cacheability->addCacheContexts(['route']);
|
Chris@0
|
335 $active = $this->isRouteActive($current_route_name, $route_name, $route_parameters);
|
Chris@0
|
336
|
Chris@0
|
337 // The plugin may have been set active in getLocalTasksForRoute() if
|
Chris@0
|
338 // one of its child tabs is the active tab.
|
Chris@0
|
339 $active = $active || $child->getActive();
|
Chris@0
|
340 // @todo It might make sense to use link render elements instead.
|
Chris@0
|
341
|
Chris@0
|
342 $link = [
|
Chris@0
|
343 'title' => $this->getTitle($child),
|
Chris@0
|
344 'url' => Url::fromRoute($route_name, $route_parameters),
|
Chris@0
|
345 'localized_options' => $child->getOptions($this->routeMatch),
|
Chris@0
|
346 ];
|
Chris@0
|
347 $access = $this->accessManager->checkNamedRoute($route_name, $route_parameters, $this->account, TRUE);
|
Chris@0
|
348 $build[$level][$plugin_id] = [
|
Chris@0
|
349 '#theme' => 'menu_local_task',
|
Chris@0
|
350 '#link' => $link,
|
Chris@0
|
351 '#active' => $active,
|
Chris@0
|
352 '#weight' => $child->getWeight(),
|
Chris@0
|
353 '#access' => $access,
|
Chris@0
|
354 ];
|
Chris@0
|
355 $cacheability->addCacheableDependency($access)->addCacheableDependency($child);
|
Chris@0
|
356 }
|
Chris@0
|
357 }
|
Chris@0
|
358
|
Chris@0
|
359 return $build;
|
Chris@0
|
360 }
|
Chris@0
|
361
|
Chris@0
|
362 /**
|
Chris@0
|
363 * {@inheritdoc}
|
Chris@0
|
364 */
|
Chris@0
|
365 public function getLocalTasks($route_name, $level = 0) {
|
Chris@0
|
366 if (!isset($this->taskData[$route_name])) {
|
Chris@0
|
367 $cacheability = new CacheableMetadata();
|
Chris@0
|
368 $cacheability->addCacheContexts(['route']);
|
Chris@0
|
369 // Look for route-based tabs.
|
Chris@0
|
370 $this->taskData[$route_name] = [
|
Chris@0
|
371 'tabs' => [],
|
Chris@0
|
372 'cacheability' => $cacheability,
|
Chris@0
|
373 ];
|
Chris@0
|
374
|
Chris@0
|
375 if (!$this->requestStack->getCurrentRequest()->attributes->has('exception')) {
|
Chris@0
|
376 // Safe to build tasks only when no exceptions raised.
|
Chris@0
|
377 $data = [];
|
Chris@0
|
378 $local_tasks = $this->getTasksBuild($route_name, $cacheability);
|
Chris@0
|
379 foreach ($local_tasks as $tab_level => $items) {
|
Chris@0
|
380 $data[$tab_level] = empty($data[$tab_level]) ? $items : array_merge($data[$tab_level], $items);
|
Chris@0
|
381 }
|
Chris@0
|
382 $this->taskData[$route_name]['tabs'] = $data;
|
Chris@0
|
383 // Allow modules to alter local tasks.
|
Chris@0
|
384 $this->moduleHandler->alter('menu_local_tasks', $this->taskData[$route_name], $route_name, $cacheability);
|
Chris@0
|
385 $this->taskData[$route_name]['cacheability'] = $cacheability;
|
Chris@0
|
386 }
|
Chris@0
|
387 }
|
Chris@0
|
388
|
Chris@0
|
389 if (isset($this->taskData[$route_name]['tabs'][$level])) {
|
Chris@0
|
390 return [
|
Chris@0
|
391 'tabs' => $this->taskData[$route_name]['tabs'][$level],
|
Chris@0
|
392 'route_name' => $route_name,
|
Chris@0
|
393 'cacheability' => $this->taskData[$route_name]['cacheability'],
|
Chris@0
|
394 ];
|
Chris@0
|
395 }
|
Chris@0
|
396
|
Chris@0
|
397 return [
|
Chris@0
|
398 'tabs' => [],
|
Chris@0
|
399 'route_name' => $route_name,
|
Chris@0
|
400 'cacheability' => $this->taskData[$route_name]['cacheability'],
|
Chris@0
|
401 ];
|
Chris@0
|
402 }
|
Chris@0
|
403
|
Chris@0
|
404 /**
|
Chris@0
|
405 * Determines whether the route of a certain local task is currently active.
|
Chris@0
|
406 *
|
Chris@0
|
407 * @param string $current_route_name
|
Chris@0
|
408 * The route name of the current main request.
|
Chris@0
|
409 * @param string $route_name
|
Chris@0
|
410 * The route name of the local task to determine the active status.
|
Chris@0
|
411 * @param array $route_parameters
|
Chris@0
|
412 *
|
Chris@0
|
413 * @return bool
|
Chris@0
|
414 * Returns TRUE if the passed route_name and route_parameters is considered
|
Chris@0
|
415 * as the same as the one from the request, otherwise FALSE.
|
Chris@0
|
416 */
|
Chris@0
|
417 protected function isRouteActive($current_route_name, $route_name, $route_parameters) {
|
Chris@0
|
418 // Flag the list element as active if this tab's route and parameters match
|
Chris@0
|
419 // the current request's route and route variables.
|
Chris@0
|
420 $active = $current_route_name == $route_name;
|
Chris@0
|
421 if ($active) {
|
Chris@0
|
422 // The request is injected, so we need to verify that we have the expected
|
Chris@0
|
423 // _raw_variables attribute.
|
Chris@0
|
424 $raw_variables_bag = $this->routeMatch->getRawParameters();
|
Chris@0
|
425 // If we don't have _raw_variables, we assume the attributes are still the
|
Chris@0
|
426 // original values.
|
Chris@0
|
427 $raw_variables = $raw_variables_bag ? $raw_variables_bag->all() : $this->routeMatch->getParameters()->all();
|
Chris@0
|
428 $active = array_intersect_assoc($route_parameters, $raw_variables) == $route_parameters;
|
Chris@0
|
429 }
|
Chris@0
|
430 return $active;
|
Chris@0
|
431 }
|
Chris@0
|
432
|
Chris@0
|
433 }
|