diff --git a/core/lib/Drupal/Core/Menu/ContextualLinkManager.php b/core/lib/Drupal/Core/Menu/ContextualLinkManager.php index e19052d..3335cec 100644 --- a/core/lib/Drupal/Core/Menu/ContextualLinkManager.php +++ b/core/lib/Drupal/Core/Menu/ContextualLinkManager.php @@ -136,6 +136,8 @@ public function getContextualLinkPluginsByGroup($group_name) { * The incoming route parameters. The route parameters need to have the same * name on all contextual link routes, e.g. you cannot use node and entity * in parallel. + * @param array $metadata + * Additional metadata of contextual links, like the position (optional). * * @return array * A list of links as array, keyed by the plugin ID. Each entry is an @@ -146,9 +148,8 @@ public function getContextualLinkPluginsByGroup($group_name) { * - weight: The weight of the contextual link. * - localized_options: The options of the link, which will be passed * to the link generator. - * */ - public function getContextualLinksArrayByGroup($group_name, array $route_parameters) { + public function getContextualLinksArrayByGroup($group_name, array $route_parameters, array $metadata = array()) { $links = array(); foreach ($this->getContextualLinkPluginsByGroup($group_name) as $plugin_id => $plugin_definition) { /** @var $plugin \Drupal\Core\Menu\ContextualLinkInterface */ @@ -166,6 +167,7 @@ public function getContextualLinksArrayByGroup($group_name, array $route_paramet 'title' => $plugin->getTitle(), 'weight' => $plugin->getWeight(), 'localized_options' => $plugin->getOptions(), + 'metadata' => $metadata, ); } diff --git a/core/modules/block/block.module b/core/modules/block/block.module index fc460d8..e337a13 100644 --- a/core/modules/block/block.module +++ b/core/modules/block/block.module @@ -303,7 +303,9 @@ function _block_get_renderable_region($list = array()) { // to perform contextual actions on the help block, and the links needlessly // draw attention on it. if (isset($build[$key]) && !in_array($block->get('plugin'), array('system_help_block', 'system_main_block'))) { - $build[$key]['#contextual_links']['block'] = array('block', array('block' => $key)); + $build[$key]['#contextual_links']['block.block'] = array( + 'route_parameters' => array('block' => $key), + ); // If there are any nested contextual links, move them to the top level. if (isset($build[$key]['content']['#contextual_links'])) { diff --git a/core/modules/block/custom_block/lib/Drupal/custom_block/CustomBlockRenderController.php b/core/modules/block/custom_block/lib/Drupal/custom_block/CustomBlockRenderController.php index c162a64..5c17396 100644 --- a/core/modules/block/custom_block/lib/Drupal/custom_block/CustomBlockRenderController.php +++ b/core/modules/block/custom_block/lib/Drupal/custom_block/CustomBlockRenderController.php @@ -23,7 +23,9 @@ protected function alterBuild(array &$build, EntityInterface $entity, EntityDisp parent::alterBuild($build, $entity, $display, $view_mode, $langcode); // Add contextual links for this custom block. if (!empty($entity->id->value) && $view_mode == 'full') { - $build['#contextual_links']['custom_block'] = array('custom_block', array('custom_block' => $entity->id())); + $build['#contextual_links']['custom_block.custom_block'] = array( + 'route_parameters' => array('custom_block' => $entity->id()), + ); } } diff --git a/core/modules/content_translation/content_translation.module b/core/modules/content_translation/content_translation.module index 20d72ed..0c91ab4 100644 --- a/core/modules/content_translation/content_translation.module +++ b/core/modules/content_translation/content_translation.module @@ -152,7 +152,7 @@ function content_translation_menu() { 'title' => 'Translate', 'route_name' => "content_translation.translation_overview_$entity_type", 'type' => MENU_LOCAL_TASK, - 'context' => MENU_CONTEXT_PAGE | MENU_CONTEXT_INLINE, + 'context' => MENU_CONTEXT_PAGE, 'weight' => 2, ) + $item; diff --git a/core/modules/contextual/contextual.module b/core/modules/contextual/contextual.module index 14e7249..c196e5a 100644 --- a/core/modules/contextual/contextual.module +++ b/core/modules/contextual/contextual.module @@ -1,4 +1,5 @@ array( - * 'block' => array('block', array('block' => 'system.menu-tools')), - * 'menu' => array('menu', array('menu' => 'tools')), + * 'block.block' => array( + * 'route_parameters' => array('block' => 'system.menu-tools'), + * ), + * 'menu.menu' => array( + * 'route_parameters' => array('menu' => 'tools'), + * ), * )) * @endcode * @@ -257,18 +260,29 @@ function contextual_pre_render_links($element) { // Retrieve contextual menu links. $items = array(); + /** @var $contextual_links_manager \Drupal\Core\Menu\ContextualLinkManager */ $contextual_links_manager = \Drupal::service('plugin.manager.menu.contextual_link'); - foreach ($element['#contextual_links'] as $module => $args) { - $contextual_links = $contextual_links_manager->getContextualLinksArrayByGroup($args[0], $args[1]); + foreach ($element['#contextual_links'] as $module_group => $args) { + list($module, $group) = explode('.', $module_group); + $args += array( + 'route_parameters' => array(), + 'metadata' => array(), + ); + $contextual_links = $contextual_links_manager->getContextualLinksArrayByGroup($group, $args['route_parameters'], $args['metadata']); if (!empty($contextual_links)) { - unset($element['#contextual_links'][$module]); + unset($element['#contextual_links'][$module_group]); } $items += $contextual_links; } // @todo Remove once all contextual links are converted. - foreach ($element['#contextual_links'] as $module => $args) { - $items += menu_contextual_links($module, $args[0], $args[1]); + foreach ($element['#contextual_links'] as $module_group => $args) { + list($module, $group) = explode('.', $module_group); + $args += array( + 'route_parameters' => array(), + ); + + $items += menu_contextual_links($module, $group, array_values($args['route_parameters'])); } // Transform contextual links into parameters suitable for theme_links(). @@ -305,7 +319,7 @@ function contextual_pre_render_links($element) { */ function contextual_contextual_links_view_alter(&$element, $items) { if (isset($element['#contextual_links']['contextual'])) { - $encoded_links = $element['#contextual_links']['contextual'][2]['contextual-views-field-links']; + $encoded_links = $element['#contextual_links']['contextual']['metadata']['contextual-views-field-links']; $element['#links'] = drupal_json_decode(rawurldecode($encoded_links)); } } @@ -332,10 +346,10 @@ function contextual_contextual_links_view_alter(&$element, $items) { */ function _contextual_links_to_id($contextual_links) { $ids = array(); - foreach ($contextual_links as $module => $args) { - $group = $args[0]; - $route_parameters = drupal_http_build_query($args[1]); - $metadata = drupal_http_build_query((isset($args[2])) ? $args[2] : array()); + foreach ($contextual_links as $module_group => $args) { + list($module, $group) = explode('.', $module_group); + $route_parameters = Url::buildQuery($args['route_parameters']); + $metadata = Url::buildQuery((isset($args['metadata'])) ? $args['metadata'] : array()); $ids[] = "{$module}:{$group}:{$route_parameters}:{$metadata}"; } return implode('|', $ids); @@ -360,7 +374,10 @@ function _contextual_id_to_links($id) { parse_str($route_parameters_raw, $route_parameters); $metadata = array(); parse_str($metadata_raw, $metadata); - $contextual_links[$module] = array($group, $route_parameters, $metadata); + $contextual_links["$module.$group"] = array( + 'route_parameters' => $route_parameters, + 'metadata' => $metadata + ); } return $contextual_links; } diff --git a/core/modules/menu/menu.module b/core/modules/menu/menu.module index 2256c66..7de6eb7 100644 --- a/core/modules/menu/menu.module +++ b/core/modules/menu/menu.module @@ -338,7 +338,9 @@ function menu_block_view_system_menu_block_alter(array &$build, BlockPluginInter list(, $menu_name) = explode(':', $block->getPluginId()); if (isset($menus[$menu_name]) && isset($build['content'])) { foreach (element_children($build['content']) as $key) { - $build['content']['#contextual_links']['menu'] = array('menu', array('menu' => $build['content'][$key]['#original_link']['menu_name'])); + $build['content']['#contextual_links']['menu.menu'] = array( + 'route_parameters' => array('menu' => $build['content'][$key]['#original_link']['menu_name']), + ); } } } diff --git a/core/modules/node/lib/Drupal/node/NodeRenderController.php b/core/modules/node/lib/Drupal/node/NodeRenderController.php index 4d6e409..a37c5ff 100644 --- a/core/modules/node/lib/Drupal/node/NodeRenderController.php +++ b/core/modules/node/lib/Drupal/node/NodeRenderController.php @@ -83,7 +83,9 @@ public function buildContent(array $entities, array $displays, $view_mode, $lang protected function alterBuild(array &$build, EntityInterface $entity, EntityDisplay $display, $view_mode, $langcode = NULL) { parent::alterBuild($build, $entity, $display, $view_mode, $langcode); if ($entity->id()) { - $build['#contextual_links']['node'] = array('node', array('node' => $entity->id())); + $build['#contextual_links']['node.node'] = array( + 'route_parameters' =>array('node' => $entity->id()), + ); } // The node 'submitted' info is not rendered in a standard way (renderable diff --git a/core/modules/taxonomy/lib/Drupal/taxonomy/TermRenderController.php b/core/modules/taxonomy/lib/Drupal/taxonomy/TermRenderController.php index f4a852b..c23391b 100644 --- a/core/modules/taxonomy/lib/Drupal/taxonomy/TermRenderController.php +++ b/core/modules/taxonomy/lib/Drupal/taxonomy/TermRenderController.php @@ -54,9 +54,9 @@ protected function getBuildDefaults(EntityInterface $entity, $view_mode, $langco protected function alterBuild(array &$build, EntityInterface $entity, EntityDisplay $display, $view_mode, $langcode = NULL) { parent::alterBuild($build, $entity, $display, $view_mode, $langcode); $build['#attached']['css'][] = drupal_get_path('module', 'taxonomy') . '/css/taxonomy.module.css'; - $build['#contextual_links']['taxonomy'] = array('taxonomy_term', array( - 'taxonomy_term' => $entity->id(), - )); + $build['#contextual_links']['taxonomy.taxonomy_term'] = array( + 'route_parameters' => array('taxonomy_term' => $entity->id()), + ); } } diff --git a/core/modules/views/lib/Drupal/views/Annotation/ViewsDisplay.php b/core/modules/views/lib/Drupal/views/Annotation/ViewsDisplay.php index fc6652e..5c4b09a 100644 --- a/core/modules/views/lib/Drupal/views/Annotation/ViewsDisplay.php +++ b/core/modules/views/lib/Drupal/views/Annotation/ViewsDisplay.php @@ -86,7 +86,7 @@ class ViewsDisplay extends ViewsPluginAnnotationBase { public $uses_hook_block; /** - * A list of places where contextual links should be added. + * A list of groups where contextual links should be added. * For example: * @code * array( diff --git a/core/modules/views/views.module b/core/modules/views/views.module index f8f9ff5..118f146 100644 --- a/core/modules/views/views.module +++ b/core/modules/views/views.module @@ -603,11 +603,13 @@ function views_add_contextual_links(&$render_element, $location, ViewExecutable $plugin['contextual_links_locations'][] = 'exposed_filter'; $has_links = !empty($plugin['contextual links']) && !empty($plugin['contextual_links_locations']); if ($has_links && in_array($location, $plugin['contextual_links_locations'])) { - foreach ($plugin['contextual links'] as $module => $link) { + foreach ($plugin['contextual links'] as $module_group => $link) { + list($module, $group) = explode('.', $module_group); + $args = array(); $valid = TRUE; - if (!empty($link['argument properties'])) { - foreach ($link['argument properties'] as $property) { + if (!empty($link['route_parameters_names'])) { + foreach ($link['route_parameters_names'] as $parameter_name => $property) { // If the plugin is trying to create an invalid contextual link // (for example, "path/to/{$view->storage->property}", where // $view->storage->{property} does not exist), we cannot construct @@ -617,7 +619,7 @@ function views_add_contextual_links(&$render_element, $location, ViewExecutable break; } else { - $args[] = $view->storage->{$property}; + $args[$parameter_name] = $view->storage->{$property}; } } } @@ -625,14 +627,13 @@ function views_add_contextual_links(&$render_element, $location, ViewExecutable // array. if ($valid) { $render_element['#views_contextual_links'] = TRUE; - $render_element['#contextual_links'][$module] = array( - $link['parent path'], - $args, - array( + $render_element['#contextual_links'][$module_group] = array( + 'route_parameters' => $args, + 'metadata' => array( 'location' => $location, 'name' => $view->storage->id(), 'display_id' => $display_id, - ) + ), ); } } diff --git a/core/modules/views_ui/views_ui.module b/core/modules/views_ui/views_ui.module index 6da5339..c6525ad 100644 --- a/core/modules/views_ui/views_ui.module +++ b/core/modules/views_ui/views_ui.module @@ -47,11 +47,11 @@ function views_ui_menu() { $items['admin/structure/views/view/%/edit'] = array( 'title' => 'Edit view', 'type' => MENU_DEFAULT_LOCAL_TASK, - 'context' => MENU_CONTEXT_PAGE | MENU_CONTEXT_INLINE, + 'context' => MENU_CONTEXT_PAGE, ); $items['admin/structure/views/view/%/preview/%'] = array( 'route_name' => 'views_ui.preview', - 'context' => MENU_CONTEXT_PAGE | MENU_CONTEXT_INLINE, + 'context' => MENU_CONTEXT_PAGE, 'type' => MENU_VISIBLE_IN_BREADCRUMB, ); @@ -317,9 +317,9 @@ function views_ui_views_plugins_display_alter(&$plugins) { // paths underneath "admin/structure/views/view/{$view->id()}" (i.e., paths // for editing and performing other contextual actions on the view). foreach ($plugins as &$display) { - $display['contextual links']['views_ui'] = array( - 'parent path' => 'admin/structure/views/view', - 'argument properties' => array('id'), + $display['contextual links']['views_ui.views_ui_edit'] = array( + 'route_name' => 'views_ui.edit', + 'route_parameters_names' => array('view' => 'id'), ); } } @@ -336,9 +336,10 @@ function views_ui_contextual_links_view_alter(&$element, $items) { // Append the display ID to the Views UI edit links, so that clicking on the // contextual link takes you directly to the correct display tab on the edit // screen. - elseif (!empty($element['#links']['views-ui-edit'])) { - $display_id = $element['#contextual_links']['views_ui'][2]['display_id']; - $element['#links']['views-ui-edit']['href'] .= '/edit/' . $display_id; + elseif (!empty($element['#links']['views-uiedit'])) { + $display_id = $items['views_ui.edit']['metadata']['display_id']; + $element['#links']['views-uiedit']['route_parameters']['display_id'] = $display_id; + $element['#links']['views-uiedit']['route_name'] = 'views_ui.edit_display'; } }