diff --git a/core/core.services.yml b/core/core.services.yml
index 4fab422..f4a26a7 100644
--- a/core/core.services.yml
+++ b/core/core.services.yml
@@ -174,7 +174,7 @@ services:
arguments: ['@container.namespaces']
plugin.manager.menu.local_action:
class: Drupal\Core\Menu\LocalActionManager
- arguments: ['@container.namespaces', '@controller_resolver', '@request', '@module_handler', '@cache.cache', '@language_manager']
+ arguments: ['@controller_resolver', '@request', '@router.route_provider', '@module_handler', '@cache.cache', '@language_manager', '@access_manager']
plugin.manager.menu.local_task:
class: Drupal\Core\Menu\LocalTaskManager
arguments: ['@controller_resolver', '@request', '@router.route_provider', '@module_handler', '@cache.cache', '@language_manager']
diff --git a/core/includes/menu.inc b/core/includes/menu.inc
index f289cbb..1cb0495 100644
--- a/core/includes/menu.inc
+++ b/core/includes/menu.inc
@@ -1737,12 +1737,21 @@ function theme_menu_local_action($variables) {
$link += array(
'href' => '',
'localized_options' => array(),
+ 'route_parameters' => array(),
);
$link['localized_options']['attributes']['class'][] = 'button';
$link['localized_options']['attributes']['class'][] = 'button-action';
$output = '
';
- $output .= l($link['title'], $link['href'], $link['localized_options']);
+ // @todo Remove this check and the call to l() when all pages are converted to
+ // routes.
+ // @todo Figure out how to support local actions without a href properly.
+ if ($link['href'] === '' && !empty($link['route_name'])) {
+ $output .= Drupal::l($link['title'], $link['route_name'], $link['route_parameters'], $link['localized_options']);
+ }
+ else {
+ $output .= l($link['title'], $link['href'], $link['localized_options']);
+ }
$output .= "";
return $output;
@@ -2308,21 +2317,9 @@ function menu_secondary_local_tasks() {
*/
function menu_get_local_actions() {
$links = menu_local_tasks();
- $router_item = menu_get_item();
+ $route_name = Drupal::request()->attributes->get(RouteObjectInterface::ROUTE_NAME);
$manager = \Drupal::service('plugin.manager.menu.local_action');
- $local_actions = $manager->getActionsForRoute($router_item['route_name']);
- foreach ($local_actions as $plugin) {
- $route_path = $manager->getPath($plugin);
- $action_router_item = menu_get_item($route_path);
- $links['actions'][$route_path] = array(
- '#theme' => 'menu_local_action',
- '#link' => array(
- 'title' => $manager->getTitle($plugin),
- 'href' => $route_path,
- ),
- '#access' => $action_router_item['access'],
- );
- }
+ $links['actions'] += $manager->getActionsForRoute($route_name);
return $links['actions'];
}
diff --git a/core/lib/Drupal/Core/Annotation/Menu/LocalAction.php b/core/lib/Drupal/Core/Annotation/Menu/LocalAction.php
deleted file mode 100644
index 3c4cdb3..0000000
--- a/core/lib/Drupal/Core/Annotation/Menu/LocalAction.php
+++ /dev/null
@@ -1,49 +0,0 @@
-generator = $generator;
- // This is available for subclasses that need to translate a dynamic title.
- $this->t = $string_translation;
- }
-
- /**
- * {@inheritdoc}
- */
- public static function create(ContainerInterface $container, array $configuration, $plugin_id, array $plugin_definition) {
- return new static(
- $container->get('string_translation'),
- $container->get('url_generator'),
- $configuration,
- $plugin_id,
- $plugin_definition
- );
- }
-
- /**
- * {@inheritdoc}
- */
- public function getRouteName() {
- return $this->pluginDefinition['route_name'];
- }
-
- /**
- * {@inheritdoc}
- */
- public function getTitle() {
- // Subclasses may pull in the request or specific attributes as parameters.
- return $this->pluginDefinition['title'];
- }
-
- /**
- * {@inheritdoc}
- */
- public function getPath() {
- // Subclasses may set a request into the generator or use any desired method
- // to generate the path.
- // @todo - use the new method from https://drupal.org/node/2031353
- $path = $this->generator->generate($this->getRouteName());
- // In order to get the Drupal path the base URL has to be stripped off.
- $base_url = $this->generator->getContext()->getBaseUrl();
- if (!empty($base_url) && strpos($path, $base_url) === 0) {
- $path = substr($path, strlen($base_url));
- }
- return trim($path, '/');
- }
-
-}
diff --git a/core/lib/Drupal/Core/Menu/LocalActionDefault.php b/core/lib/Drupal/Core/Menu/LocalActionDefault.php
new file mode 100644
index 0000000..03dbbef
--- /dev/null
+++ b/core/lib/Drupal/Core/Menu/LocalActionDefault.php
@@ -0,0 +1,137 @@
+routeProvider = $route_provider;
+ // This is available for subclasses that need to translate a dynamic title.
+ $this->stringTranslation = $string_translation;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public static function create(ContainerInterface $container, array $configuration, $plugin_id, array $plugin_definition) {
+ return new static(
+ $configuration,
+ $plugin_id,
+ $plugin_definition,
+ $container->get('string_translation'),
+ $container->get('router.route_provider')
+ );
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getRouteName() {
+ return $this->pluginDefinition['route_name'];
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getTitle() {
+ // Subclasses may pull in the request or specific attributes as parameters.
+ return $this->t($this->pluginDefinition['title']);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getRouteParameters(Request $request) {
+ $parameters = isset($this->pluginDefinition['route_parameters']) ? $this->pluginDefinition['route_parameters'] : array();
+ $route = $this->routeProvider->getRouteByName($this->getRouteName());
+ $variables = $route->compile()->getVariables();
+
+ // Noramlly the \Drupal\Core\ParamConverter\ParamConverterManager has
+ // processed the Request attributes, and in that case the _raw_variables
+ // attribute holds the original path strings keyed to the corresponding
+ // slugs in the path patterns. For example, if the route's path pattern is
+ // /filter/tips/{filter_format} and the path is /filter/tips/plain_text then
+ // $raw_variables->get('filter_format') == 'plain_text'.
+
+ $raw_variables = $request->attributes->get('_raw_variables');
+
+ foreach ($variables as $name) {
+ if (isset($parameters[$name])) {
+ continue;
+ }
+
+ if ($raw_variables && $raw_variables->has($name)) {
+ $parameters[$name] = $raw_variables->get($name);
+ }
+ elseif ($request->attributes->has($name)) {
+ $parameters[$name] = $request->attributes->get($name);
+ }
+ }
+ // The UrlGenerator will throw an exception if expected parameters are
+ // missing. This method should be overridden if that is possible.
+ return $parameters;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getOptions(Request $request) {
+ return (array) $this->pluginDefinition['options'];
+ }
+
+ /**
+ * Translates a string to the current language or to a given language.
+ *
+ * See the t() documentation for details.
+ */
+ protected function t($string, array $args = array(), array $options = array()) {
+ return $this->stringTranslation->translate($string, $args, $options);
+ }
+}
diff --git a/core/lib/Drupal/Core/Menu/LocalActionInterface.php b/core/lib/Drupal/Core/Menu/LocalActionInterface.php
index 65287b6..4151160 100644
--- a/core/lib/Drupal/Core/Menu/LocalActionInterface.php
+++ b/core/lib/Drupal/Core/Menu/LocalActionInterface.php
@@ -7,6 +7,8 @@
namespace Drupal\Core\Menu;
+use Symfony\Component\HttpFoundation\Request;
+
/**
* Defines an interface for menu local actions.
*/
@@ -21,6 +23,37 @@
public function getRouteName();
/**
+ * Returns the route parameters needed to render a link for the local task.
+ *
+ * @param \Symfony\Component\HttpFoundation\Request $request
+ * The HttpRequest object representing the current request.
+ *
+ * @return array
+ * An array of parameter names and values.
+ *
+ * @see \Drupal\Core\Utility\LinkGeneratorInterface::generate()
+ */
+ public function getRouteParameters(Request $request);
+
+ /**
+ * Returns the weight of the local task.
+@@ -51,14 +55,17 @@ public function getPath();
+ public function getWeight();
+
+ /**
+ * Returns options for rendering a link to the local task.
+ *
+ * @param \Symfony\Component\HttpFoundation\Request $request
+ * The HttpRequest object representing the current request.
+ *
+ * @return array
+ * An associative array of options.
+ *
+ * @see \Drupal\Core\Utility\LinkGeneratorInterface::generate()
+ */
+ public function getOptions(Request $request);
+
+ /**
* Returns the localized title to be shown for this action.
*
* Subclasses may add optional arguments like NodeInterface $node = NULL that
@@ -33,17 +66,6 @@ public function getRouteName();
*/
public function getTitle();
- /**
- * Return an internal Drupal path to use when linking to the action.
- *
- * Subclasses may add arguments for request attributes which will then be
- * automatically supplied by the controller resolver.
- *
- * @return string
- * The path to use when linking to the action.
- *
- * @see \Drupal\Core\Menu\LocalActionManager::getPath()
- */
- public function getPath();
+
}
diff --git a/core/lib/Drupal/Core/Menu/LocalActionManager.php b/core/lib/Drupal/Core/Menu/LocalActionManager.php
index 39ea454..eeb73d3 100644
--- a/core/lib/Drupal/Core/Menu/LocalActionManager.php
+++ b/core/lib/Drupal/Core/Menu/LocalActionManager.php
@@ -7,11 +7,17 @@
namespace Drupal\Core\Menu;
+use Drupal\Core\Access\AccessManager;
use Drupal\Core\Cache\CacheBackendInterface;
use Drupal\Core\Extension\ModuleHandlerInterface;
use Drupal\Core\Language\LanguageManager;
use Drupal\Core\Menu\LocalActionInterface;
use Drupal\Core\Plugin\DefaultPluginManager;
+use Drupal\Component\Plugin\Discovery\ProcessDecorator;
+use Drupal\Core\Plugin\Discovery\ContainerDerivativeDiscoveryDecorator;
+use Drupal\Core\Plugin\Discovery\YamlDiscovery;
+use Drupal\Core\Plugin\Factory\ContainerFactory;
+use Drupal\Core\Routing\RouteProviderInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Controller\ControllerResolverInterface;
@@ -26,6 +32,28 @@
class LocalActionManager extends DefaultPluginManager {
/**
+ * Provides some default values for all local action plugin.s
+ *
+ * @var array
+ */
+ protected $defaults = array(
+ // The plugin id. Set by the plugin system based on the top-level YAML key.
+ 'id' => '',
+ // The static title for the local action.
+ 'title' => '',
+ // (Required) the route name used to generate a link.
+ 'route_name' => '',
+ // Default route parameters for generating links.
+ 'route_parameters' => array(),
+ // Associative array of link options.
+ 'options' => array(),
+ // The route names where this local action appears.
+ 'appears_on' => array(),
+ // Default class for local action implementations.
+ 'class' => 'Drupal\Core\Menu\LocalActionBase',
+ );
+
+ /**
* A controller resolver object.
*
* @var \Symfony\Component\HttpKernel\Controller\ControllerResolverInterface
@@ -40,6 +68,20 @@ class LocalActionManager extends DefaultPluginManager {
protected $request;
/**
+ * The route provider to load routes by name.
+ *
+ * @var \Drupal\Core\Routing\RouteProviderInterface
+ */
+ protected $routeProvider;
+
+ /**
+ * The access manager.
+ *
+ * @var \Drupal\Core\Access\AccessManager
+ */
+ protected $accessManager;
+
+/**
* The plugin instances.
*
* @var array
@@ -49,28 +91,34 @@ class LocalActionManager extends DefaultPluginManager {
/**
* Constructs a LocalActionManager object.
*
- * @param \Traversable $namespaces
- * An object that implements \Traversable which contains the root paths
- * keyed by the corresponding namespace to look for plugin implementations.
* @param \Symfony\Component\HttpKernel\Controller\ControllerResolverInterface $controller_resolver
* An object to use in introspecting route methods.
* @param \Symfony\Component\HttpFoundation\Request $request
* The request object to use for building titles and paths for plugin
* instances.
+ * @param \Drupal\Core\Routing\RouteProviderInterface $route_provider
+ * The route provider.
* @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
* The module handler.
* @param \Drupal\Core\Cache\CacheBackendInterface $cache_backend
* Cache backend instance to use.
* @param \Drupal\Core\Language\LanguageManager $language_manager
* The language manager.
+ * @param \Drupal\Core\Access\AccessManager $access_manager
+ * The access manager.
*/
- public function __construct(\Traversable $namespaces, ControllerResolverInterface $controller_resolver, Request $request, ModuleHandlerInterface $module_handler, CacheBackendInterface $cache_backend, LanguageManager $language_manager) {
- parent::__construct('Plugin/Menu/LocalAction', $namespaces, 'Drupal\Core\Annotation\Menu\LocalAction');
-
+ public function __construct(ControllerResolverInterface $controller_resolver, Request $request, RouteProviderInterface $route_provider, ModuleHandlerInterface $module_handler, CacheBackendInterface $cache_backend, LanguageManager $language_manager, AccessManager $access_manager) {
+ // Skip calling the parent constructor, since that assumes annontation-based discovery
+ $this->discovery = new YamlDiscovery('local_actions', $module_handler->getModuleDirectories());
+ $this->discovery = new ContainerDerivativeDiscoveryDecorator($this->discovery);
+ $this->factory = new ContainerFactory($this);
+ $this->routeProvider = $route_provider;
+ $this->accessManager = $access_manager;
$this->controllerResolver = $controller_resolver;
$this->request = $request;
$this->alterInfo($module_handler, 'menu_local_actions');
- $this->setCacheBackend($cache_backend, $language_manager, 'local_action_plugins');
+ $this->setCacheBackend($cache_backend, $language_manager, 'local_action_plugins', array('local_action' => TRUE));
+
}
/**
@@ -92,44 +140,46 @@ public function getTitle(LocalActionInterface $local_action) {
}
/**
- * Gets the Drupal path for a local action.
- *
- * @param \Drupal\Core\Menu\LocalActionInterface $local_action
- * An object to get the path from.
- *
- * @return string
- * The path.
- *
- * @throws \BadMethodCallException
- * If the plugin does not implement the getPath() method.
- */
- public function getPath(LocalActionInterface $local_action) {
- $controller = array($local_action, 'getPath');
- $arguments = $this->controllerResolver->getArguments($this->request, $controller);
- return call_user_func_array($controller, $arguments);
- }
-
- /**
* Finds all local actions that appear on a named route.
*
- * @param string $route_name
- * The route for which to find local actions.
+ * @param string $route_appears
+ * The route name for which to find local actions.
*
- * @return \Drupal\Core\Menu\LocalActionInterface[]
- * An array of LocalActionInterface objects that appear on the route path.
+ * @return array
+ * An array of link render arrays.
*/
- public function getActionsForRoute($route_name) {
- if (!isset($this->instances[$route_name])) {
- $this->instances[$route_name] = array();
+ public function getActionsForRoute($route_appears) {
+ if (!isset($this->instances[$route_appears])) {
+ $route_names = array();
+ $this->instances[$route_appears] = array();
// @todo - optimize this lookup by compiling or caching.
foreach ($this->getDefinitions() as $plugin_id => $action_info) {
- if (in_array($route_name, $action_info['appears_on'])) {
+ if (in_array($route_appears, $action_info['appears_on'])) {
$plugin = $this->createInstance($plugin_id);
- $this->instances[$route_name][$plugin_id] = $plugin;
+ $route_names[] = $plugin->getRouteName();
+ $this->instances[$route_appears][$plugin_id] = $plugin;
}
}
+ // Pre-fetch all the action route objects. This reduces the number of SQL
+ // queries that would otherwise be triggered by the access manager.
+ $route_names ? $this->routeProvider->getRoutesByNames($route_names) : array();
+ }
+ $links = array();
+ foreach ($this->instances[$route_appears] as $plugin) {
+ $route_name = $plugin->getRouteName();
+ $route_parameters = $plugin->getRouteParameters($this->request);
+ $links[$route_name] = array(
+ '#theme' => 'menu_local_action',
+ '#link' => array(
+ 'title' => $this->getTitle($plugin),
+ 'route_name' => $route_name,
+ 'route_parameters' => $route_parameters,
+ 'localized_options' => $plugin->getOptions($this->request),
+ ),
+ '#access' => $this->accessManager->checkNamedRoute($route_name, $route_parameters),
+ );
}
- return $this->instances[$route_name];
+ return $links;
}
}
diff --git a/core/lib/Drupal/Core/Menu/Plugin/Derivative/StaticLocalActionDeriver.php b/core/lib/Drupal/Core/Menu/Plugin/Derivative/StaticLocalActionDeriver.php
deleted file mode 100644
index e9ef0ee..0000000
--- a/core/lib/Drupal/Core/Menu/Plugin/Derivative/StaticLocalActionDeriver.php
+++ /dev/null
@@ -1,124 +0,0 @@
-get('module_handler'),
- $container->get('string_translation')
- );
- }
-
- /**
- * Constructs a StaticLocalActionDeriver object.
- *
- * @param string $base_plugin_id
- * The base plugin ID.
- * @param\Drupal\Core\Extension\ModuleHandlerInterface $module_handler
- * The module handler.
- * @param \Drupal\Core\StringTranslation\TranslationInterface translation_manager
- * The translation manager.
- */
- public function __construct($base_plugin_id, ModuleHandlerInterface $module_handler, TranslationInterface $translation_manager) {
- $this->basePluginId = $base_plugin_id;
- $this->moduleHandler = $module_handler;
- $this->translationManager = $translation_manager;
- }
-
- /**
- * {@inheritdoc}
- */
- public function getDerivativeDefinition($derivative_id, array $base_plugin_definition) {
- if (!empty($this->derivatives) && !empty($this->derivatives[$derivative_id])) {
- return $this->derivatives[$derivative_id];
- }
- $this->getDerivativeDefinitions($base_plugin_definition);
- return $this->derivatives[$derivative_id];
- }
-
- /**
- * {@inheritdoc}
- */
- public function getDerivativeDefinitions(array $base_plugin_definition) {
- $yaml_discovery = new YamlDiscovery('local_actions', $this->moduleHandler->getModuleDirectories());
- $required_keys = array('title' => 1, 'route_name' => 1, 'appears_on' => 1);
-
- foreach ($yaml_discovery->findAll() as $module => $local_actions) {
- if (!empty($local_actions)) {
- foreach ($local_actions as $name => $info) {
- if ($missing_keys = array_diff_key($required_keys, array_intersect_key($info, $required_keys))) {
- throw new PluginException(String::format('Static local action @name is missing @keys', array('@name' => $name, '@keys' => implode(', ', array_keys($missing_keys)))));
- }
-
- $info += array('provider' => $module);
- // Make sure 'appears_on' is an array.
- $info['appears_on'] = (array) $info['appears_on'];
- $info['title'] = $this->t($info['title']);
- $this->derivatives[$name] = $info + $base_plugin_definition;
- }
- }
- }
-
- return $this->derivatives;
- }
-
- /**
- * Translates a string to the current language or to a given language.
- *
- * See the t() documentation for details.
- */
- protected function t($string, array $args = array(), array $options = array()) {
- return $this->translationManager->translate($string, $args, $options);
- }
-
-}
diff --git a/core/lib/Drupal/Core/Menu/Plugin/Menu/LocalAction/StaticLocalAction.php b/core/lib/Drupal/Core/Menu/Plugin/Menu/LocalAction/StaticLocalAction.php
deleted file mode 100644
index b0e0e9d..0000000
--- a/core/lib/Drupal/Core/Menu/Plugin/Menu/LocalAction/StaticLocalAction.php
+++ /dev/null
@@ -1,21 +0,0 @@
- 'Test configuration',
'route_name' => 'config_test.list_page',
);
- $items['admin/structure/config_test/add'] = array(
- 'title' => 'Add test configuration',
- 'route_name' => 'config_test.entity_add',
- 'type' => MENU_SIBLING_LOCAL_TASK,
- );
$items['admin/structure/config_test/manage/%config_test'] = array(
'route_name' => 'config_test.entity',
);
diff --git a/core/modules/config/tests/config_test/lib/Drupal/config_test/Plugin/Menu/LocalAction/AddConfigTestEntityLocalAction.php b/core/modules/config/tests/config_test/lib/Drupal/config_test/Plugin/Menu/LocalAction/AddConfigTestEntityLocalAction.php
index 1f31d46..ec5760f 100644
--- a/core/modules/config/tests/config_test/lib/Drupal/config_test/Plugin/Menu/LocalAction/AddConfigTestEntityLocalAction.php
+++ b/core/modules/config/tests/config_test/lib/Drupal/config_test/Plugin/Menu/LocalAction/AddConfigTestEntityLocalAction.php
@@ -8,7 +8,7 @@
namespace Drupal\config_test\Plugin\Menu\LocalAction;
use Drupal\Core\Annotation\Translation;
-use Drupal\Core\Menu\LocalActionBase;
+use Drupal\Core\Menu\LocalActionDefault;
use Drupal\Core\Annotation\Menu\LocalAction;
/**
@@ -19,6 +19,6 @@
* appears_on = {"config_test.list_page"}
* )
*/
-class AddConfigTestEntityLocalAction extends LocalActionBase {
+class AddConfigTestEntityLocalAction extends LocalActionDefault {
}
diff --git a/core/modules/filter/filter.local_actions.yml b/core/modules/filter/filter.local_actions.yml
new file mode 100644
index 0000000..f5f3fe8
--- /dev/null
+++ b/core/modules/filter/filter.local_actions.yml
@@ -0,0 +1,5 @@
+filter_format_add_local_action:
+ route_name: filter_format_add
+ title: 'Add text format'
+ appears_on:
+ - filter_admin_overview
diff --git a/core/modules/filter/filter.module b/core/modules/filter/filter.module
index 2cdc275..585535e 100644
--- a/core/modules/filter/filter.module
+++ b/core/modules/filter/filter.module
@@ -140,10 +140,6 @@ function filter_menu() {
'title' => 'List',
'type' => MENU_DEFAULT_LOCAL_TASK,
);
- $items['admin/config/content/formats/add'] = array(
- 'route_name' => 'filter.format_add',
- 'type' => MENU_SIBLING_LOCAL_TASK,
- );
$items['admin/config/content/formats/manage/%'] = array(
'title callback' => 'entity_page_label',
'title arguments' => array(5),
diff --git a/core/modules/filter/lib/Drupal/filter/Plugin/Menu/LocalAction/AddFilterFormatLocalAction.php b/core/modules/filter/lib/Drupal/filter/Plugin/Menu/LocalAction/AddFilterFormatLocalAction.php
index b75c102..da45c05 100644
--- a/core/modules/filter/lib/Drupal/filter/Plugin/Menu/LocalAction/AddFilterFormatLocalAction.php
+++ b/core/modules/filter/lib/Drupal/filter/Plugin/Menu/LocalAction/AddFilterFormatLocalAction.php
@@ -8,7 +8,7 @@
namespace Drupal\filter\Plugin\Menu\LocalAction;
use Drupal\Core\Annotation\Translation;
-use Drupal\Core\Menu\LocalActionBase;
+use Drupal\Core\Menu\LocalActionDefault;
use Drupal\Core\Annotation\Menu\LocalAction;
/**
@@ -19,6 +19,6 @@
* appears_on = {"filter.admin_overview"}
* )
*/
-class AddFilterFormatLocalAction extends LocalActionBase {
+class AddFilterFormatLocalAction extends LocalActionDefault {
}
diff --git a/core/modules/image/image.local_actions.yml b/core/modules/image/image.local_actions.yml
new file mode 100644
index 0000000..134f3a8
--- /dev/null
+++ b/core/modules/image/image.local_actions.yml
@@ -0,0 +1,5 @@
+image_style_add_action:
+ route_name: image.style_add
+ title: 'Add image style'
+ appears_on:
+ - image.style_list
diff --git a/core/modules/image/image.module b/core/modules/image/image.module
index e3d1497..e0d4810 100644
--- a/core/modules/image/image.module
+++ b/core/modules/image/image.module
@@ -102,11 +102,6 @@ function image_menu() {
'description' => 'List the current image styles on the site.',
'type' => MENU_DEFAULT_LOCAL_TASK,
);
- $items['admin/config/media/image-styles/add'] = array(
- 'route_name' => 'image.style_add',
- 'type' => MENU_SIBLING_LOCAL_TASK,
- 'weight' => 1,
- );
$items['admin/config/media/image-styles/manage/%image_style'] = array(
'title' => 'Edit style',
'description' => 'Configure an image style.',
diff --git a/core/modules/image/lib/Drupal/image/Plugin/Menu/LocalAction/ImageStyleAddLocalAction.php b/core/modules/image/lib/Drupal/image/Plugin/Menu/LocalAction/ImageStyleAddLocalAction.php
deleted file mode 100644
index eb13813..0000000
--- a/core/modules/image/lib/Drupal/image/Plugin/Menu/LocalAction/ImageStyleAddLocalAction.php
+++ /dev/null
@@ -1,24 +0,0 @@
- 'entity_page_label',
'title arguments' => array(4),
);
- $items['admin/structure/menu/manage/%menu/add'] = array(
- 'title' => 'Add link',
- 'route_name' => 'menu.link_add',
- 'type' => MENU_LOCAL_ACTION,
- );
$items['admin/structure/menu/manage/%menu/edit'] = array(
'title' => 'Edit menu',
'type' => MENU_DEFAULT_LOCAL_TASK,
diff --git a/core/modules/shortcut/lib/Drupal/shortcut/Plugin/Menu/LocalAction/AddShortcutSetLocalAction.php b/core/modules/shortcut/lib/Drupal/shortcut/Plugin/Menu/LocalAction/AddShortcutSetLocalAction.php
index 8a01f7b..499ff3b 100644
--- a/core/modules/shortcut/lib/Drupal/shortcut/Plugin/Menu/LocalAction/AddShortcutSetLocalAction.php
+++ b/core/modules/shortcut/lib/Drupal/shortcut/Plugin/Menu/LocalAction/AddShortcutSetLocalAction.php
@@ -9,7 +9,7 @@
use Drupal\Core\Annotation\Translation;
use Drupal\Core\Annotation\Menu\LocalAction;
-use Drupal\Core\Menu\LocalActionBase;
+use Drupal\Core\Menu\LocalActionDefault;
/**
* @LocalAction(
@@ -19,6 +19,6 @@
* appears_on = {"shortcut.set_admin"}
* )
*/
-class AddShortcutSetLocalAction extends LocalActionBase {
+class AddShortcutSetLocalAction extends LocalActionDefault {
}
diff --git a/core/modules/shortcut/shortcut.local_actions.yml b/core/modules/shortcut/shortcut.local_actions.yml
new file mode 100644
index 0000000..2067f7d
--- /dev/null
+++ b/core/modules/shortcut/shortcut.local_actions.yml
@@ -0,0 +1,5 @@
+shortcut_set_add_local_action:
+ route_name: shortcut.set_add
+ title: 'Add shortcut set'
+ appears_on:
+ - shortcut.set_admin
diff --git a/core/modules/shortcut/shortcut.module b/core/modules/shortcut/shortcut.module
index e47b5ed..35bbb2b 100644
--- a/core/modules/shortcut/shortcut.module
+++ b/core/modules/shortcut/shortcut.module
@@ -90,11 +90,6 @@ function shortcut_menu() {
'description' => 'Add and modify shortcut sets.',
'route_name' => 'shortcut.set_admin',
);
- $items['admin/config/user-interface/shortcut/add-set'] = array(
- 'title' => 'Add shortcut set',
- 'route_name' => 'shortcut.set_add',
- 'type' => MENU_SIBLING_LOCAL_TASK,
- );
$items['admin/config/user-interface/shortcut/manage/%shortcut_set'] = array(
'title' => 'Edit shortcuts',
'route_name' => 'shortcut.set_customize',
diff --git a/core/modules/system/tests/modules/menu_test/lib/Drupal/menu_test/Plugin/Menu/LocalAction/MenuTestLocalAction.php b/core/modules/system/tests/modules/menu_test/lib/Drupal/menu_test/Plugin/Menu/LocalAction/MenuTestLocalAction.php
deleted file mode 100644
index fb33b7e..0000000
--- a/core/modules/system/tests/modules/menu_test/lib/Drupal/menu_test/Plugin/Menu/LocalAction/MenuTestLocalAction.php
+++ /dev/null
@@ -1,24 +0,0 @@
- 'views_ui.list',
);
- $items['admin/structure/views/add'] = array(
- 'route_name' => 'views_ui.add',
- 'type' => MENU_SIBLING_LOCAL_TASK,
- );
-
// @todo - remove all items of type MENU_VISIBLE_IN_BREADCRUMB
// when there is a route-aware breadcrumb builder.
$items['admin/structure/views/settings'] = array(