Commit 29110623 authored by catch's avatar catch

Issue #2120235 by dawehner, YesCT: Regression: routing / tabs / actions /...

Issue #2120235 by dawehner, YesCT: Regression: routing / tabs / actions / contextual links lack way to attach replacement arguments to UI strings.
parent 2f959b96
......@@ -216,7 +216,7 @@ services:
arguments: ['@controller_resolver', '@request', '@router.route_provider', '@router.builder', '@module_handler', '@cache.cache', '@language_manager', '@access_manager', '@current_user']
plugin.manager.menu.contextual_link:
class: Drupal\Core\Menu\ContextualLinkManager
arguments: ['@controller_resolver', '@module_handler', '@cache.cache', '@language_manager', '@access_manager', '@current_user']
arguments: ['@controller_resolver', '@module_handler', '@cache.cache', '@language_manager', '@access_manager', '@current_user', '@request_stack']
plugin.cache_clearer:
class: Drupal\Core\Plugin\CachedDiscoveryClearer
request:
......
......@@ -61,8 +61,20 @@ public function getTitle(Request $request, Route $route) {
if ($context = $route->getDefault('_title_context')) {
$options['context'] = $context;
}
$args = array();
if (($raw_parameters = $request->attributes->get('_raw_variables'))) {
foreach ($raw_parameters->all() as $key => $value) {
$args['@' . $key] = $value;
$args['!' . $key] = $value;
$args['%' . $key] = $value;
}
}
if ($title_arguments = $route->getDefault('_title_arguments')) {
$args = array_merge($args, (array) $title_arguments);
}
// Fall back to a static string from the route.
$route_title = $this->translationManager->translate($title, array(), $options);
$route_title = $this->translationManager->translate($title, $args, $options);
}
return $route_title;
}
......
......@@ -8,6 +8,7 @@
namespace Drupal\Core\Menu;
use Drupal\Core\Plugin\PluginBase;
use Symfony\Component\HttpFoundation\Request;
/**
* Provides a common base implementation of a contextual link.
......@@ -16,13 +17,21 @@ class ContextualLinkDefault extends PluginBase implements ContextualLinkInterfac
/**
* {@inheritdoc}
*
* @todo: It might be helpful at some point to move this getTitle logic into
* a trait.
*/
public function getTitle() {
public function getTitle(Request $request = NULL) {
$options = array();
if (!empty($this->pluginDefinition['title_context'])) {
$options['context'] = $this->pluginDefinition['title_context'];
}
return $this->t($this->pluginDefinition['title'], array(), $options);
$args = array();
if (isset($this->pluginDefinition['title_arguments']) && $title_arguments = $this->pluginDefinition['title_arguments']) {
$args = (array) $title_arguments;
}
return $this->t($this->pluginDefinition['title'], $args, $options);
}
/**
......
......@@ -18,6 +18,7 @@
use Drupal\Core\Plugin\Discovery\YamlDiscovery;
use Drupal\Core\Plugin\Factory\ContainerFactory;
use Drupal\Core\Session\AccountInterface;
use Symfony\Component\HttpFoundation\RequestStack;
/**
* Defines a contextual link plugin manager to deal with contextual links.
......@@ -69,6 +70,13 @@ class ContextualLinkManager extends DefaultPluginManager implements ContextualLi
*/
protected $account;
/**
* The request stack.
*
* @var \Symfony\Component\HttpFoundation\RequestStack
*/
protected $requestStack;
/**
* A static cache of all the contextual link plugins by group name.
*
......@@ -91,8 +99,10 @@ class ContextualLinkManager extends DefaultPluginManager implements ContextualLi
* The access manager.
* @param \Drupal\Core\Session\AccountInterface $account
* The current user.
* @param \Symfony\Component\HttpFoundation\RequestStack $request_stack
* The request stack.
*/
public function __construct(ControllerResolverInterface $controller_resolver, ModuleHandlerInterface $module_handler, CacheBackendInterface $cache_backend, LanguageManager $language_manager, AccessManager $access_manager, AccountInterface $account) {
public function __construct(ControllerResolverInterface $controller_resolver, ModuleHandlerInterface $module_handler, CacheBackendInterface $cache_backend, LanguageManager $language_manager, AccessManager $access_manager, AccountInterface $account, RequestStack $request_stack) {
$this->discovery = new YamlDiscovery('contextual_links', $module_handler->getModuleDirectories());
$this->discovery = new ContainerDerivativeDiscoveryDecorator($this->discovery);
$this->factory = new ContainerFactory($this);
......@@ -101,6 +111,7 @@ public function __construct(ControllerResolverInterface $controller_resolver, Mo
$this->accessManager = $access_manager;
$this->account = $account;
$this->moduleHandler = $module_handler;
$this->requestStack = $request_stack;
$this->alterInfo('contextual_links_plugins');
$this->setCacheBackend($cache_backend, $language_manager, 'contextual_links_plugins');
}
......@@ -150,6 +161,7 @@ public function getContextualLinkPluginsByGroup($group_name) {
*/
public function getContextualLinksArrayByGroup($group_name, array $route_parameters, array $metadata = array()) {
$links = array();
$request = $this->requestStack->getCurrentRequest();
foreach ($this->getContextualLinkPluginsByGroup($group_name) as $plugin_id => $plugin_definition) {
/** @var $plugin \Drupal\Core\Menu\ContextualLinkInterface */
$plugin = $this->createInstance($plugin_id);
......@@ -163,7 +175,7 @@ public function getContextualLinksArrayByGroup($group_name, array $route_paramet
$links[$plugin_id] = array(
'route_name' => $route_name,
'route_parameters' => $route_parameters,
'title' => $plugin->getTitle(),
'title' => $plugin->getTitle($request),
'weight' => $plugin->getWeight(),
'localized_options' => $plugin->getOptions(),
'metadata' => $metadata,
......
......@@ -65,13 +65,17 @@ public function getRouteName() {
/**
* {@inheritdoc}
*/
public function getTitle() {
public function getTitle(Request $request = NULL) {
// Subclasses may pull in the request or specific attributes as parameters.
$options = array();
if (!empty($this->pluginDefinition['title_context'])) {
$options['context'] = $this->pluginDefinition['title_context'];
}
return $this->t($this->pluginDefinition['title'], array(), $options);
$args = array();
if (isset($this->pluginDefinition['title_arguments']) && $title_arguments = $this->pluginDefinition['title_arguments']) {
$args = (array) $title_arguments;
}
return $this->t($this->pluginDefinition['title'], $args, $options);
}
/**
......
......@@ -73,13 +73,17 @@ public function getRouteParameters(Request $request) {
/**
* {@inheritdoc}
*/
public function getTitle() {
public function getTitle(Request $request = NULL) {
// Subclasses may pull in the request or specific attributes as parameters.
$options = array();
if (!empty($this->pluginDefinition['title_context'])) {
$options['context'] = $this->pluginDefinition['title_context'];
}
return $this->t($this->pluginDefinition['title'], array(), $options);
$args = array();
if (isset($this->pluginDefinition['title_arguments']) && $title_arguments = $this->pluginDefinition['title_arguments']) {
$args = (array) $title_arguments;
}
return $this->t($this->pluginDefinition['title'], $args, $options);
}
/**
......
......@@ -10,6 +10,7 @@
use Drupal\Component\Utility\String;
use Drupal\Core\Controller\TitleResolver;
use Drupal\Tests\UnitTestCase;
use Symfony\Component\HttpFoundation\ParameterBag;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Route;
......@@ -90,6 +91,36 @@ public function testStaticTitleWithContext() {
$this->assertEquals('translated title with context', $this->titleResolver->getTitle($request, $route));
}
/**
* Tests a static title with a parameter.
*
* @see \Drupal\Core\Controller\TitleResolver::getTitle()
*
* @dataProvider providerTestStaticTitleWithParameter
*/
public function testStaticTitleWithParameter($title, $expected_title) {
$raw_variables = new ParameterBag(array('test' => 'value', 'test2' => 'value2'));
$request = new Request();
$request->attributes->set('_raw_variables', $raw_variables);
$route = new Route('/test-route', array('_title' => $title));
$this->translationManager->expects($this->once())
->method('translate')
->with($title, $this->logicalOr($this->arrayHasKey('@test'), $this->arrayHasKey('%test'), $this->arrayHasKey('!test')), array())
->will($this->returnValue('static title value'));
$this->assertEquals($expected_title, $this->titleResolver->getTitle($request, $route));
}
public function providerTestStaticTitleWithParameter() {
return array(
array('static title @test', 'static title value'),
array('static title !test', 'static title value'),
array('static title %test', 'static title value'),
);
}
/**
* Tests a dynamic title.
*
......
......@@ -9,6 +9,8 @@
use Drupal\Core\Menu\ContextualLinkDefault;
use Drupal\Tests\UnitTestCase;
use Symfony\Component\HttpFoundation\ParameterBag;
use Symfony\Component\HttpFoundation\Request;
/**
* Tests the contextual link default class.
......@@ -107,6 +109,22 @@ public function testGetTitleWithContext() {
$this->assertEquals('Example translated with context', $this->contextualLinkDefault->getTitle());
}
/**
* Tests the getTitle method with title arguments.
*/
public function testGetTitleWithTitleArguments() {
$this->pluginDefinition['title'] = 'Example @test';
$this->pluginDefinition['title_arguments'] = array('@test' => 'value');
$this->stringTranslation->expects($this->once())
->method('translate')
->with($this->pluginDefinition['title'], $this->arrayHasKey('@test'), array())
->will($this->returnValue('Example value'));
$this->setupContextualLinkDefault();
$request = new Request();
$this->assertEquals('Example value', $this->contextualLinkDefault->getTitle($request));
}
/**
* Tests the getRouteName() method.
*
......
......@@ -9,6 +9,7 @@
use Drupal\Core\Language\Language;
use Drupal\Tests\UnitTestCase;
use Symfony\Component\HttpFoundation\RequestStack;
/**
* Tests the contextual links manager.
......@@ -123,6 +124,11 @@ protected function setUp() {
->method('getCurrentLanguage')
->will($this->returnValue(new Language(array('id' => 'en'))));
$request_stack = new RequestStack();
$property = new \ReflectionProperty('Drupal\Core\Menu\ContextualLinkManager', 'requestStack');
$property->setAccessible(TRUE);
$property->setValue($this->contextualLinkManager, $request_stack);
$method = new \ReflectionMethod('Drupal\Core\Menu\ContextualLinkManager', 'alterInfo');
$method->setAccessible(TRUE);
$method->invoke($this->contextualLinkManager, 'contextual_links_plugins');
......
......@@ -9,6 +9,8 @@
use Drupal\Core\Menu\LocalActionDefault;
use Drupal\Tests\UnitTestCase;
use Symfony\Component\HttpFoundation\ParameterBag;
use Symfony\Component\HttpFoundation\Request;
/**
* Tests the local action default class.
......@@ -117,4 +119,20 @@ public function testGetTitleWithContext() {
$this->assertEquals('Example translated with context', $this->localActionDefault->getTitle());
}
/**
* Tests the getTitle method with title arguments.
*/
public function testGetTitleWithTitleArguments() {
$this->pluginDefinition['title'] = 'Example @test';
$this->pluginDefinition['title_arguments'] = array('@test' => 'value');
$this->stringTranslation->expects($this->once())
->method('translate')
->with($this->pluginDefinition['title'], $this->arrayHasKey('@test'), array())
->will($this->returnValue('Example value'));
$this->setupLocalActionDefault();
$request = new Request();
$this->assertEquals('Example value', $this->localActionDefault->getTitle($request));
}
}
......@@ -288,6 +288,22 @@ public function testGetTitleWithContext() {
$this->assertEquals('Example translated with context', $this->localTaskBase->getTitle());
}
/**
* Tests the getTitle method with title arguments.
*/
public function testGetTitleWithTitleArguments() {
$this->pluginDefinition['title'] = 'Example @test';
$this->pluginDefinition['title_arguments'] = array('@test' => 'value');
$this->stringTranslation->expects($this->once())
->method('translate')
->with($this->pluginDefinition['title'], $this->arrayHasKey('@test'), array())
->will($this->returnValue('Example value'));
$this->setupLocalTaskDefault();
$request = new Request();
$this->assertEquals('Example value', $this->localTaskBase->getTitle($request));
}
/**
* Tests the getOption method.
*
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment