Issue #2114069 by dawehner, Gábor Hojtsy, ursula: Fixed Routing / tabs / actions lack way to attach context to UI strings.

8.0.x
Alex Pott 2013-10-28 15:45:33 -07:00
parent 4361e6795b
commit b376379368
9 changed files with 308 additions and 9 deletions

View File

@ -57,8 +57,12 @@ class TitleResolver implements TitleResolverInterface {
$route_title = call_user_func_array($callable, $arguments);
}
elseif ($title = $route->getDefault('_title')) {
$options = array();
if ($context = $route->getDefault('_title_context')) {
$options['context'] = $context;
}
// Fall back to a static string from the route.
$route_title = $this->translationManager->translate($title);
$route_title = $this->translationManager->translate($title, array(), $options);
}
return $route_title;
}

View File

@ -27,6 +27,11 @@ use Drupal\Core\ContentNegotiation;
*/
class ViewSubscriber implements EventSubscriberInterface {
/**
* The content negotiation.
*
* @var \Drupal\Core\ContentNegotiation
*/
protected $negotiation;
/**
@ -91,8 +96,8 @@ class ViewSubscriber implements EventSubscriberInterface {
}
// If no title was returned fall back to one defined in the route.
if (!isset($page_result['#title']) && $request->attributes->has('_title')) {
$page_result['#title'] = $request->attributes->get('_title');
if (!isset($page_result['#title'])) {
$page_result['#title'] = $this->titleResolver->getTitle($request, $request->attributes->get(RouteObjectInterface::ROUTE_OBJECT));
}
$event->setResponse(new Response(drupal_render_page($page_result)));
@ -109,8 +114,8 @@ class ViewSubscriber implements EventSubscriberInterface {
}
// If no title was returned fall back to one defined in the route.
if (!isset($page_result['#title']) && $request->attributes->has('_title')) {
$page_result['#title'] = $request->attributes->get('_title');
if (!isset($page_result['#title'])) {
$page_result['#title'] = $this->titleResolver->getTitle($request, $request->attributes->get(RouteObjectInterface::ROUTE_OBJECT));
}
$event->setResponse(new Response(drupal_render($page_result)));

View File

@ -67,7 +67,11 @@ class LocalActionDefault extends PluginBase implements LocalActionInterface, Con
*/
public function getTitle() {
// Subclasses may pull in the request or specific attributes as parameters.
return $this->t($this->pluginDefinition['title']);
$options = array();
if (!empty($this->pluginDefinition['title_context'])) {
$options['context'] = $this->pluginDefinition['title_context'];
}
return $this->t($this->pluginDefinition['title'], array(), $options);
}
/**

View File

@ -75,7 +75,11 @@ class LocalTaskDefault extends PluginBase implements LocalTaskInterface {
*/
public function getTitle() {
// Subclasses may pull in the request or specific attributes as parameters.
return $this->t($this->pluginDefinition['title']);
$options = array();
if (!empty($this->pluginDefinition['title_context'])) {
$options['context'] = $this->pluginDefinition['title_context'];
}
return $this->t($this->pluginDefinition['title'], array(), $options);
}
/**

View File

@ -115,6 +115,9 @@ class CommentFormController extends ContentEntityFormController {
'%title' => $comment->subject->value,
));
}
else {
$form['#title'] = $this->t('Preview comment');
}
}
else {
if ($this->currentUser->isAuthenticated()) {

View File

@ -239,6 +239,8 @@ system.date_format_localize_reset:
system.modules_list:
path: '/admin/modules'
defaults:
_title: 'Extend'
_title_context: 'With components'
_form: 'Drupal\system\Form\ModulesListForm'
requirements:
_permission: 'administer modules'

View File

@ -0,0 +1,135 @@
<?php
/**
* @file
* Contains \Drupal\Tests\Core\Controller\TitleResolverTest.
*/
namespace Drupal\Tests\Core\Controller;
use Drupal\Component\Utility\String;
use Drupal\Core\Controller\TitleResolver;
use Drupal\Tests\UnitTestCase;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Route;
/**
* Tests the title resolver.
*
* @see \Drupal\Core\Controller\TitleResolver
*/
class TitleResolverTest extends UnitTestCase {
/**
* The mocked controller resolver.
*
* @var \Drupal\Core\Controller\ControllerResolverInterface|\PHPUnit_Framework_MockObject_MockObject
*/
protected $controllerResolver;
/**
* The mocked translation manager.
*
* @var \Drupal\Core\StringTranslation\TranslationInterface|\PHPUnit_Framework_MockObject_MockObject
*/
protected $translationManager;
/**
* The actual tested title resolver.
*
* @var \Drupal\Core\Controller\TitleResolver
*/
protected $titleResolver;
public static function getInfo() {
return array(
'name' => 'Title resolver',
'description' => 'Tests the title resolver.',
'group' => 'Routing',
);
}
protected function setUp() {
$this->controllerResolver = $this->getMock('\Drupal\Core\Controller\ControllerResolverInterface');
$this->translationManager = $this->getMock('\Drupal\Core\StringTranslation\TranslationInterface');
$this->titleResolver = new TitleResolver($this->controllerResolver, $this->translationManager);
}
/**
* Tests a static title without a context.
*
* @see \Drupal\Core\Controller\TitleResolver::getTitle()
*/
public function testStaticTitle() {
$request = new Request();
$route = new Route('/test-route', array('_title' => 'static title'));
$this->translationManager->expects($this->once())
->method('translate')
->with('static title', array(), array())
->will($this->returnValue('translated title'));
$this->assertEquals('translated title', $this->titleResolver->getTitle($request, $route));
}
/**
* Tests a static title with a context.
*
* @see \Drupal\Core\Controller\TitleResolver::getTitle()
*/
public function testStaticTitleWithContext() {
$request = new Request();
$route = new Route('/test-route', array('_title' => 'static title', '_title_context' => 'context'));
$this->translationManager->expects($this->once())
->method('translate')
->with('static title', array(), array('context' => 'context'))
->will($this->returnValue('translated title with context'));
$this->assertEquals('translated title with context', $this->titleResolver->getTitle($request, $route));
}
/**
* Tests a dynamic title.
*
* @see \Drupal\Core\Controller\TitleResolver::getTitle()
*/
public function testDynamicTitle() {
$request = new Request();
$route = new Route('/test-route', array('_title' => 'static title', '_title_callback' => 'Drupal\Tests\Core\Controller\TitleCallback::example'));
$callable = array(new TitleCallback(), 'example');
$this->controllerResolver->expects($this->once())
->method('getControllerFromDefinition')
->with('Drupal\Tests\Core\Controller\TitleCallback::example')
->will($this->returnValue($callable));
$this->controllerResolver->expects($this->once())
->method('getArguments')
->with($request, $callable)
->will($this->returnValue(array('example')));
$this->assertEquals('test example', $this->titleResolver->getTitle($request, $route));
}
}
/**
* Provides an example title callback for the testDynamicTitle method above.
*/
class TitleCallback {
/**
* Gets the example string.
*
* @param string $value
* The dynamic value.
*
* @return string
* Returns the example string.
*/
public function example($value) {
return String::format('test @value', array('@value' => $value));
}
}

View File

@ -0,0 +1,124 @@
<?php
/**
* @file
* Contains \Drupal\Tests\Core\Menu\LocalActionDefaultTest.
*/
namespace Drupal\Tests\Core\Menu;
use Drupal\Core\DependencyInjection\ContainerBuilder;
use Drupal\Core\Menu\LocalActionDefault;
use Drupal\Tests\UnitTestCase;
/**
* Tests the local action default class.
*
* @see \Drupal\Core\Menu\LocalActionDefault
*/
class LocalActionDefaultTest extends UnitTestCase {
/**
* The tested local action default plugin.
*
* @var \Drupal\Core\Menu\LocalActionDefault
*/
protected $localActionDefault;
/**
* The used plugin configuration.
*
* @var array
*/
protected $config = array();
/**
* The used plugin ID.
*
* @var string
*/
protected $pluginId = 'local_action_default';
/**
* The used plugin definition.
*
* @var array
*/
protected $pluginDefinition = array(
'id' => 'local_action_default',
);
/**
* The mocked translator.
*
* @var \Drupal\Core\StringTranslation\TranslationInterface|\PHPUnit_Framework_MockObject_MockObject
*/
protected $stringTranslation;
/**
* The mocked route provider.
*
* @var \Drupal\Core\Routing\RouteProviderInterface|\PHPUnit_Framework_MockObject_MockObject
*/
protected $routeProvider;
public static function getInfo() {
return array(
'name' => 'Local actions default plugin.',
'description' => 'Tests the local action default class.',
'group' => 'Menu',
);
}
protected function setUp() {
parent::setUp();
$this->stringTranslation = $this->getMock('Drupal\Core\StringTranslation\TranslationInterface');
$this->routeProvider = $this->getMock('Drupal\Core\Routing\RouteProviderInterface');
}
/**
* Setups the local action default.
*/
protected function setupLocalActionDefault() {
$container = new ContainerBuilder();
$container->set('string_translation', $this->stringTranslation);
\Drupal::setContainer($container);
$this->localActionDefault = new LocalActionDefault($this->config, $this->pluginId, $this->pluginDefinition, $this->routeProvider);
}
/**
* Tests the getTitle method without a translation context.
*
* @see \Drupal\Core\Menu\LocalTaskDefault::getTitle()
*/
public function testGetTitle() {
$this->pluginDefinition['title'] = 'Example';
$this->stringTranslation->expects($this->once())
->method('translate')
->with($this->pluginDefinition['title'], array(), array())
->will($this->returnValue('Example translated'));
$this->setupLocalActionDefault();
$this->assertEquals('Example translated', $this->localActionDefault->getTitle());
}
/**
* Tests the getTitle method with a translation context.
*
* @see \Drupal\Core\Menu\LocalTaskDefault::getTitle()
*/
public function testGetTitleWithContext() {
$this->pluginDefinition['title'] = 'Example';
$this->pluginDefinition['title_context'] = 'context';
$this->stringTranslation->expects($this->once())
->method('translate')
->with($this->pluginDefinition['title'], array(), array('context' => 'context'))
->will($this->returnValue('Example translated with context'));
$this->setupLocalActionDefault();
$this->assertEquals('Example translated with context', $this->localActionDefault->getTitle());
}
}

View File

@ -253,20 +253,38 @@ class LocalTaskDefaultTest extends UnitTestCase {
}
/**
* Tests the getTitle method.
* Tests the getTitle method without a translation context.
*
* @see \Drupal\Core\Menu\LocalTaskDefault::getTitle()
*/
public function testGetTitle() {
$this->pluginDefinition['title'] = 'Example';
$this->stringTranslation->expects($this->once())
->method('translate', $this->pluginDefinition['title'])
->method('translate')
->with($this->pluginDefinition['title'], array(), array())
->will($this->returnValue('Example translated'));
$this->setupLocalTaskDefault();
$this->assertEquals('Example translated', $this->localTaskBase->getTitle());
}
/**
* Tests the getTitle method with a translation context.
*
* @see \Drupal\Core\Menu\LocalTaskDefault::getTitle()
*/
public function testGetTitleWithContext() {
$this->pluginDefinition['title'] = 'Example';
$this->pluginDefinition['title_context'] = 'context';
$this->stringTranslation->expects($this->once())
->method('translate')
->with($this->pluginDefinition['title'], array(), array('context' => 'context'))
->will($this->returnValue('Example translated with context'));
$this->setupLocalTaskDefault();
$this->assertEquals('Example translated with context', $this->localTaskBase->getTitle());
}
/**
* Tests the getOption method.
*