function LocalTaskManager::getLocalTasksForRoute

Same name and namespace in other branches
  1. 11.x core/lib/Drupal/Core/Menu/LocalTaskManager.php \Drupal\Core\Menu\LocalTaskManager::getLocalTasksForRoute()

File

core/lib/Drupal/Core/Menu/LocalTaskManager.php, line 197

Class

LocalTaskManager
Provides the default local task manager using YML as primary definition.

Namespace

Drupal\Core\Menu

Code

public function getLocalTasksForRoute($route_name) {
  if (!isset($this->instances[$route_name])) {
    $this->instances[$route_name] = [];
    if ($cache = $this->cacheBackend
      ->get($this->cacheKey . ':' . $route_name)) {
      $base_routes = $cache->data['base_routes'];
      $parents = $cache->data['parents'];
      $children = $cache->data['children'];
    }
    else {
      $definitions = $this->getDefinitions();
      // We build the hierarchy by finding all tabs that should
      // appear on the current route.
      $base_routes = [];
      $parents = [];
      $children = [];
      foreach ($definitions as $plugin_id => $task_info) {
        // Fill in the base_route from the parent to insure consistency.
        if (!empty($task_info['parent_id']) && !empty($definitions[$task_info['parent_id']])) {
          $task_info['base_route'] = $definitions[$task_info['parent_id']]['base_route'];
          // Populate the definitions we use in the next loop. Using a
          // reference like &$task_info causes bugs.
          $definitions[$plugin_id]['base_route'] = $definitions[$task_info['parent_id']]['base_route'];
        }
        if ($route_name == $task_info['route_name']) {
          if (!empty($task_info['base_route'])) {
            $base_routes[$task_info['base_route']] = $task_info['base_route'];
          }
          // Tabs that link to the current route are viable parents
          // and their parent and children should be visible also.
          // @todo - this only works for 2 levels of tabs.
          // instead need to iterate up.
          $parents[$plugin_id] = TRUE;
          if (!empty($task_info['parent_id'])) {
            $parents[$task_info['parent_id']] = TRUE;
          }
        }
      }
      if ($base_routes) {
        // Find all the plugins with the same root and that are at the top
        // level or that have a visible parent.
        foreach ($definitions as $plugin_id => $task_info) {
          if (!empty($base_routes[$task_info['base_route']]) && (empty($task_info['parent_id']) || !empty($parents[$task_info['parent_id']]))) {
            // Concat '> ' with root ID for the parent of top-level tabs.
            $parent = empty($task_info['parent_id']) ? '> ' . $task_info['base_route'] : $task_info['parent_id'];
            $children[$parent][$plugin_id] = $task_info;
          }
        }
      }
      $data = [
        'base_routes' => $base_routes,
        'parents' => $parents,
        'children' => $children,
      ];
      $this->cacheBackend
        ->set($this->cacheKey . ':' . $route_name, $data, Cache::PERMANENT, $this->cacheTags);
    }
    // Create a plugin instance for each element of the hierarchy.
    foreach ($base_routes as $base_route) {
      // Convert the tree keyed by plugin IDs into a simple one with
      // integer depth.  Create instances for each plugin along the way.
      $level = 0;
      // We used this above as the top-level parent array key.
      $next_parent = '> ' . $base_route;
      do {
        $parent = $next_parent;
        $next_parent = FALSE;
        foreach ($children[$parent] as $plugin_id => $task_info) {
          $plugin = $this->createInstance($plugin_id);
          $this->instances[$route_name][$level][$plugin_id] = $plugin;
          // Normally, the link generator compares the href of every link with
          // the current path and sets the active class accordingly. But the
          // parents of the current local task may be on a different route in
          // which case we have to set the class manually by flagging it
          // active.
          if (!empty($parents[$plugin_id]) && $route_name != $task_info['route_name']) {
            $plugin->setActive();
          }
          if (isset($children[$plugin_id])) {
            // This tab has visible children.
            $next_parent = $plugin_id;
          }
        }
        $level++;
      } while ($next_parent);
    }
  }
  return $this->instances[$route_name];
}

Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.