diff --git a/core/includes/theme.inc b/core/includes/theme.inc index 515a3ea..3878139 100644 --- a/core/includes/theme.inc +++ b/core/includes/theme.inc @@ -1719,12 +1719,17 @@ function theme_links($variables) { $item = drupal_render($link_element); } else { + // @todo theme_links() should *really* use the same parameters as l(), + // and just take an array of '#type' => 'link' elements. + // Pass in $link as $options, as they share the same keys. if (isset($link['href'])) { - // Pass in $link as $options, as they share the same keys. $item = l($link['title'], $link['href'], $link); } else { - $item = \Drupal::linkGenerator()->generate($link['title'], $link['route_name'], isset($link['route_parameters']) ? $link['route_parameters'] : array(), $link); + if (empty($link['route_parameters'])) { + $link['route_parameters'] = array(); + } + $item = \Drupal::l($link['title'], $link['route_name'], $link['route_parameters'], $link); } } } diff --git a/core/lib/Drupal/Core/Menu/ContextualLinkBase.php b/core/lib/Drupal/Core/Menu/ContextualLinkDefault.php similarity index 73% rename from core/lib/Drupal/Core/Menu/ContextualLinkBase.php rename to core/lib/Drupal/Core/Menu/ContextualLinkDefault.php index 454f7b0..94c46b6 100644 --- a/core/lib/Drupal/Core/Menu/ContextualLinkBase.php +++ b/core/lib/Drupal/Core/Menu/ContextualLinkDefault.php @@ -2,7 +2,7 @@ /** * @file - * Contains \Drupal\Core\Menu\ContextualLinkBase. + * Contains \Drupal\Core\Menu\ContextualLinkDefault. */ namespace Drupal\Core\Menu; @@ -12,13 +12,14 @@ /** * Provides a common base implementation of a contextual link. */ -class ContextualLinkBase extends PluginBase implements ContextualLinkInterface { +class ContextualLinkDefault extends PluginBase implements ContextualLinkInterface { /** * {@inheritdoc} */ public function getTitle() { - return $this->pluginDefinition['title']; + // @todo use $this->t() when https://drupal.org/node/2087231 lands. + return t($this->pluginDefinition['title']); } /** diff --git a/core/lib/Drupal/Core/Menu/ContextualLinkManager.php b/core/lib/Drupal/Core/Menu/ContextualLinkManager.php index 9c81a82..996339d 100644 --- a/core/lib/Drupal/Core/Menu/ContextualLinkManager.php +++ b/core/lib/Drupal/Core/Menu/ContextualLinkManager.php @@ -7,6 +7,7 @@ namespace Drupal\Core\Menu; +use Drupal\Component\Plugin\Exception\PluginException; use Drupal\Core\Cache\CacheBackendInterface; use Drupal\Core\Controller\ControllerResolverInterface; use Drupal\Core\Extension\ModuleHandlerInterface; @@ -25,18 +26,25 @@ class ContextualLinkManager extends DefaultPluginManager { /** - * Provides some default values for contextual links + * Provides default values for a contextual link definition. * * @var array */ protected $defaults = array( - 'class' => '\Drupal\Core\Menu\ContextualLinkBase', - 'group' => '', - 'id' => '', - 'options' => array(), + // (required) The name of the route to link to. 'route_name' => '', + // (required) The contextual links group. + 'group' => '', + // The static title text for the link. 'title' => '', - 'weight' => 0, + // The default link options. + 'options' => array(), + // The weight of the link. + 'weight' => NULL, + // Default class for contextual link implementations. + 'class' => '\Drupal\Core\Menu\ContextualLinkDefault', + // The plugin id. Set by the plugin system based on the top-level YAML key. + 'id' => '', ); /** @@ -62,6 +70,21 @@ public function __construct(ControllerResolverInterface $controller_resolver, Mo } /** + * {@inheritdoc} + */ + public function processDefinition(&$definition, $plugin_id) { + parent::processDefinition($definition, $plugin_id); + // If there is no route name, this is a broken definition. + if (empty($definition['route_name'])) { + throw new PluginException(sprintf('Plugin (%s) definition must include "route_name"', $plugin_id)); + } + // If there is no group name, this is a broken definition. + if (empty($definition['group'])) { + throw new PluginException(sprintf('Plugin (%s) definition must include "group"', $plugin_id)); + } + } + + /** * Gets the contextual link plugins by contextual link group. * * @param string $group_name diff --git a/core/modules/contextual/contextual.module b/core/modules/contextual/contextual.module index cbf8e37..5396504 100644 --- a/core/modules/contextual/contextual.module +++ b/core/modules/contextual/contextual.module @@ -277,7 +277,6 @@ function contextual_pre_render_links($element) { 'route_name' => isset($item['route_name']) ? $item['route_name'] : '', 'route_parameters' => isset($item['route_parameters']) ? $item['route_parameters'] : array(), ); - // @todo theme_links() should *really* use the same parameters as l(). $item['localized_options'] += array('query' => array()); $item['localized_options']['query'] += drupal_get_destination(); $links[$class] += $item['localized_options']; @@ -311,15 +310,14 @@ function contextual_contextual_links_view_alter(&$element, $items) { * Serializes #contextual_links property value array to a string. * * Examples: - * - node:node:1: - * - views_ui:admin/structure/views/view:frontpage:location=page&view_name=frontpage&view_display_id=page_1 - * - menu:admin/structure/menu/manage:tools:|block:admin/structure/block/manage:bartik.tools: + * - node:node:node=1: + * - views_ui:admin/structure/views/view:view=frontpage:location=page&view_name=frontpage&view_display_id=page_1 + * - menu:admin/structure/menu/manage:menu=tools:|block:admin/structure/block/manage:block=bartik.tools: * * So, expressed in a pattern: * ::: * - * The (dynamic) path args are joined with slashes. The options are encoded as a - * query string. + * The path args and options are encoded as query strings. * * @param array $contextual_links * The $element['#contextual_links'] value for some render element. @@ -329,19 +327,14 @@ function contextual_contextual_links_view_alter(&$element, $items) { * use in a data- attribute. */ function _contextual_links_to_id($contextual_links) { - $id = ''; + $ids = array(); foreach ($contextual_links as $module => $args) { $parent_path = $args[0]; - $path_keys = implode('/', array_keys($args[1])); - $path_args = implode('/', $args[1]); + $path_args = drupal_http_build_query($args[1]); $metadata = drupal_http_build_query((isset($args[2])) ? $args[2] : array()); - - if (drupal_strlen($id) > 0) { - $id .= '|'; - } - $id .= $module . ':' . $parent_path . ':' . $path_keys . ':' . $path_args . ':' . $metadata; + $ids[] = "{$module}:{$parent_path}:{$path_args}:{$metadata}"; } - return $id; + return implode('|', $ids); } /** @@ -359,14 +352,9 @@ function _contextual_id_to_links($id) { $contextual_links = array(); $contexts = explode('|', $id); foreach ($contexts as $context) { - list($module, $parent_path, $path_keys, $path_args, $metadata_raw) = explode(':', $context); - $path_keys = explode('/', $path_keys); - $path_args = explode('/', $path_args); - foreach ($path_keys as $counter => $key) { - $arg = $path_args[$counter]; - unset($path_args[$counter]); - $path_args[$key] = $arg; - } + list($module, $parent_path, $raw_args, $metadata_raw) = explode(':', $context); + $path_args = array(); + parse_str($raw_args, $path_args); $metadata = array(); parse_str($metadata_raw, $metadata); $contextual_links[$module] = array($parent_path, $path_args, $metadata); diff --git a/core/modules/contextual/lib/Drupal/contextual/Tests/ContextualDynamicContextTest.php b/core/modules/contextual/lib/Drupal/contextual/Tests/ContextualDynamicContextTest.php index 2ea30dc..955c0e1 100644 --- a/core/modules/contextual/lib/Drupal/contextual/Tests/ContextualDynamicContextTest.php +++ b/core/modules/contextual/lib/Drupal/contextual/Tests/ContextualDynamicContextTest.php @@ -60,10 +60,10 @@ function testDifferentPermissions() { // Now, on the front page, all article nodes should have contextual links // placeholders, as should the view that contains them. $ids = array( - 'node:node:node:' . $node1->id() . ':', - 'node:node:node:' . $node2->id() . ':', - 'node:node:node:' . $node3->id() . ':', - 'views_ui:admin/structure/views/view:0:frontpage:location=page&name=frontpage&display_id=page_1', + 'node:node:node=' . $node1->id() . ':', + 'node:node:node=' . $node2->id() . ':', + 'node:node:node=' . $node3->id() . ':', + 'views_ui:admin/structure/views/view:0=frontpage:location=page&name=frontpage&display_id=page_1', ); // Editor user: can access contextual links and can edit articles. diff --git a/core/modules/contextual/lib/Drupal/contextual/Tests/ContextualUnitTest.php b/core/modules/contextual/lib/Drupal/contextual/Tests/ContextualUnitTest.php index e4c828d..2c93f4c 100644 --- a/core/modules/contextual/lib/Drupal/contextual/Tests/ContextualUnitTest.php +++ b/core/modules/contextual/lib/Drupal/contextual/Tests/ContextualUnitTest.php @@ -39,7 +39,7 @@ function _contextual_links_id_testcases() { array() ), ), - 'id' => 'node:node:node:14031991:', + 'id' => 'node:node:node=14031991:', ); // Test branch conditions: @@ -58,7 +58,7 @@ function _contextual_links_id_testcases() { array() ), ), - 'id' => 'foo:baz/in/ga:0/key/1:bar/baz/qux:', + 'id' => 'foo:baz/in/ga:0=bar&key=baz&1=qux:', ); // Test branch conditions: @@ -76,7 +76,7 @@ function _contextual_links_id_testcases() { ) ), ), - 'id' => 'views_ui:admin/structure/views/view:0:frontpage:location=page&display=page_1', + 'id' => 'views_ui:admin/structure/views/view:0=frontpage:location=page&display=page_1', ); // Test branch conditions: @@ -106,7 +106,7 @@ function _contextual_links_id_testcases() { array() ), ), - 'id' => 'node:node:node:14031991:|foo:baz/in/ga:0/key/1:bar/baz/qux:|edge:edge:0:20011988:', + 'id' => 'node:node:node=14031991:|foo:baz/in/ga:0=bar&key=baz&1=qux:|edge:edge:0=20011988:', ); return $tests;