diff --git a/core/modules/views/lib/Drupal/views/Plugin/Derivative/ViewsLocalTask.php b/core/modules/views/lib/Drupal/views/Plugin/Derivative/ViewsLocalTask.php index f92c183..3a24b14 100644 --- a/core/modules/views/lib/Drupal/views/Plugin/Derivative/ViewsLocalTask.php +++ b/core/modules/views/lib/Drupal/views/Plugin/Derivative/ViewsLocalTask.php @@ -8,11 +8,15 @@ namespace Drupal\views\Plugin\Derivative; use Drupal\Component\Plugin\Derivative\DerivativeBase; +use Drupal\Core\KeyValueStore\KeyValueStoreInterface; +use Drupal\Core\Plugin\Discovery\ContainerDerivativeInterface; +use Drupal\Core\Routing\RouteProviderInterface; +use Symfony\Component\DependencyInjection\ContainerInterface; /** * Provides local task definitions for all views configured as local tasks. */ -class ViewsLocalTask extends DerivativeBase { +class ViewsLocalTask extends DerivativeBase implements ContainerDerivativeInterface { /** * The route provider. @@ -22,12 +26,34 @@ class ViewsLocalTask extends DerivativeBase { protected $routeProvider; /** + * The state key value store. + * + * @var \Drupal\Core\KeyValueStore\KeyValueStoreInterface + */ + protected $state; + + /** * Constructs a \Drupal\views\Plugin\Derivative\ViewsLocalTask instance. + * + * @param \Drupal\Core\Routing\RouteProviderInterface $route_provider + * The route provider. + * @param \Drupal\Core\KeyValueStore\KeyValueStoreInterface $state + * The state key value store. */ - public function __construct() { - $this->routeProvider = \Drupal::service('router.route_provider'); + public function __construct(RouteProviderInterface $route_provider, KeyValueStoreInterface $state) { + $this->routeProvider = $route_provider; + $this->state = $state; } + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container, $base_plugin_id) { + return new static( + $container->get('router.route_provider'), + $container->get('state') + ); + } /** * {@inheritdoc} @@ -41,12 +67,37 @@ public function getDerivativeDefinitions(array $base_plugin_definition) { $executable->setDisplay($display_id); $menu = $executable->display_handler->getOption('menu'); if (in_array($menu['type'], array('tab', 'default tab'))) { - $route_name = $plugin_id = 'view.' . $executable->storage->id() . '.' . $display_id; + $plugin_id = 'view.' . $executable->storage->id() . '.' . $display_id; + $route_name = $this->state[$executable->storage->id() . '.' . $display_id]; $this->derivatives[$plugin_id] = array( 'route_name' => $route_name, 'class' => 'Drupal\views\Plugin\Menu\LocalTask\ViewsLocalTask', 'weight' => $menu['weight'] ); + } + } + return $this->derivatives; + } + + /** + * Alters tab_root_id and tab_parent_id into the views local tasks. + */ + public function alterLocalTasks(&$local_tasks) { + foreach (views_get_applicable_views('uses_hook_menu') as $pair) { + /** @var $executable \Drupal\views\ViewExecutable */ + list($executable, $display_id) = $pair; + + $executable->setDisplay($display_id); + $menu = $executable->display_handler->getOption('menu'); + if (in_array($menu['type'], array('tab', 'default tab'))) { + $plugin_id = 'view.' . $executable->storage->id() . '.' . $display_id; + $view_route_name = $this->state[$executable->storage->id() . '.' . $display_id]; + + // Don't add a local task for views which override existing routes. + if ($view_route_name != $plugin_id) { + unset($local_tasks[$plugin_id]); + continue; + } // Find out the parent route. // @todo Find out how to find both the root and parent tab. @@ -57,16 +108,40 @@ public function getDerivativeDefinitions(array $base_plugin_definition) { $pattern = '/' . str_replace('%', '{}', $path); if ($routes = $this->routeProvider->getRoutesByPattern($pattern)) { foreach ($routes->all() as $name => $route) { - // @TODO So good so far, from the route name we would get the parent - // local ask, which might be defined by views or by other plugins. - $this->derivatives[$plugin_id]['tab_root_id'] = $name; + if ($parent_task = $this->getTaskFromRoute($name, $local_tasks)) { + $this->derivatives[$plugin_id]['tab_root_id'] = $parent_task; + } // Skip after the first found route. break; } } } } - return $this->derivatives; + + $foo = 123; + } + + /** + * Find the local task ID of the parent route given the route name. + * + * @param string $route_name + * The route name of the parent local task. + * @param array $local_tasks + * An array of all local task definitions. + * + * @return bool|string + * Returns the local task ID of the parent task, otherwise return FALSE. + */ + protected function getTaskFromRoute($route_name, &$local_tasks) { + $local_task = FALSE; + foreach ($local_tasks as $plugin_id => $local_task) { + if ($local_task['route_name'] == $route_name) { + $local_task = $plugin_id; + break; + } + } + + return $local_task; } } diff --git a/core/modules/views/lib/Drupal/views/Plugin/Menu/LocalTask/ViewsLocalTask.php b/core/modules/views/lib/Drupal/views/Plugin/Menu/LocalTask/ViewsLocalTask.php index 9c43e5f..417de72 100644 --- a/core/modules/views/lib/Drupal/views/Plugin/Menu/LocalTask/ViewsLocalTask.php +++ b/core/modules/views/lib/Drupal/views/Plugin/Menu/LocalTask/ViewsLocalTask.php @@ -9,6 +9,7 @@ use Drupal\Core\Annotation\Menu\LocalTask; use Drupal\Core\Menu\LocalTaskBase; +use Drupal\Core\Menu\LocalTaskDefault; /** * Defines a local task for views with configured local tasks. @@ -18,5 +19,5 @@ * derivative = "Drupal\views\Plugin\Derivative\ViewsLocalTask" * ) */ -class ViewsLocalTask extends LocalTaskBase { +class ViewsLocalTask extends LocalTaskDefault { } diff --git a/core/modules/views/views.module b/core/modules/views/views.module index f8f9ff5..d25ae54 100644 --- a/core/modules/views/views.module +++ b/core/modules/views/views.module @@ -12,6 +12,7 @@ use Drupal\Core\Cache\Cache; use Drupal\Core\Database\Query\AlterableInterface; use Drupal\Core\Language\Language; +use Drupal\views\Plugin\Derivative\ViewsLocalTask; use Drupal\views\ViewExecutable; use Drupal\Component\Plugin\Exception\PluginException; use Drupal\views\Entity\View; @@ -1729,3 +1730,11 @@ function views_cache_get($cid, $use_language = FALSE) { return cache('views_info')->get($cid); } +/** + * Implements hook_local_tasks_alter(). + */ +function views_local_tasks_alter(&$local_tasks) { + $container = \Drupal::getContainer(); + $local_task = ViewsLocalTask::create($container, 'views_view'); + $local_task->alterLocalTasks($local_tasks); +}