diff --git a/core/modules/config_translation/src/Tests/ConfigTranslationCacheTest.php b/core/modules/config_translation/src/Tests/ConfigTranslationCacheTest.php new file mode 100644 index 0000000..3d4407c --- /dev/null +++ b/core/modules/config_translation/src/Tests/ConfigTranslationCacheTest.php @@ -0,0 +1,183 @@ +getPermissionName(), + $full_html_format->getPermissionName(), + $filter_test_format->getPermissionName(), + 'access site-wide contact form', + 'access contextual links', + 'administer account settings', + 'administer themes', + 'bypass node access', + 'administer content types', + 'translate interface', + 'administer entity_test fields', + ] + ); + // Create and login user. + $this->translatorUser = $this->drupalCreateUser($translator_permissions); + $this->adminUser = $this->drupalCreateUser($admin_permissions); + + // Add languages. + foreach ($this->langcodes as $langcode) { + ConfigurableLanguage::createFromLangcode($langcode)->save(); + } + $this->drupalPlaceBlock('local_tasks_block'); + $this->drupalPlaceBlock('page_title_block'); + } + + /** + * Tests the translation of field and field storage configuration. + */ + public function testFieldConfigTranslation() { + // Add a test field which has a translatable field setting and a + // translatable field storage setting. + $field_name = strtolower($this->randomMachineName()); + $field_storage = FieldStorageConfig::create([ + 'field_name' => $field_name, + 'entity_type' => 'entity_test', + 'type' => 'test_field', + ]); + + $translatable_storage_setting = $this->randomString(); + $field_storage->setSetting('translatable_storage_setting', $translatable_storage_setting); + $field_storage->save(); + + $bundle = strtolower($this->randomMachineName()); + entity_test_create_bundle($bundle); + $field = FieldConfig::create([ + 'field_name' => $field_name, + 'entity_type' => 'entity_test', + 'bundle' => $bundle, + ]); + + $translatable_field_setting = $this->randomString(); + $field->setSetting('translatable_field_setting', $translatable_field_setting); + $field->save(); + + $this->drupalLogin($this->translatorUser); + + $this->drupalGet("/entity_test/structure/$bundle/fields/entity_test.$bundle.$field_name/translate"); + $this->clickLink('Add'); + + $this->assertText('Translatable field setting'); + $this->assertEscaped($translatable_field_setting); + $this->assertText('Translatable storage setting'); + $this->assertEscaped($translatable_storage_setting); + + // Add translation for label. + $field_label_fr = $this->randomString(); + $edit = array( + "translation[config_names][field.field.entity_test.$bundle.$field_name][label]" => $field_label_fr, + ); + $this->drupalPostForm(NULL, $edit, 'Save translation'); + $this->drupalLogout(); + + // Check if the translated label appear. + $this->drupalLogin($this->adminUser); + $this->drupalGet("/fr/entity_test/structure/$bundle/fields"); + $this->assertEscaped($field_label_fr); + + // Clear cache on French version and check for translated label. + $this->drupalPostForm('/fr/admin/config/development/performance', array(), 'Clear all caches'); + $this->drupalGet("/fr/entity_test/structure/$bundle/fields"); + // Check if the translation still there. + $this->assertEscaped($field_label_fr); + + // Clear cache on default version and check for translated label. + $this->drupalPostForm('/admin/config/development/performance', array(), 'Clear all caches'); + $this->drupalGet("/fr/entity_test/structure/$bundle/fields"); + // Check if the translation still there. + $this->assertEscaped($field_label_fr); + } + +} diff --git a/core/modules/views/src/Plugin/views/display/PathPluginBase.php b/core/modules/views/src/Plugin/views/display/PathPluginBase.php index 966cc1a..53b34a0 100644 --- a/core/modules/views/src/Plugin/views/display/PathPluginBase.php +++ b/core/modules/views/src/Plugin/views/display/PathPluginBase.php @@ -129,7 +129,7 @@ protected function defineOptions() { protected function getRoute($view_id, $display_id) { $defaults = array( '_controller' => 'Drupal\views\Routing\ViewPageController::handle', - '_title' => $this->view->getTitle(), + '_title_callback' => 'Drupal\views\Routing\ViewPageController::getTitle', 'view_id' => $view_id, 'display_id' => $display_id, '_view_display_show_admin_links' => $this->getOption('show_admin_links'), diff --git a/core/modules/views/src/Routing/ViewPageController.php b/core/modules/views/src/Routing/ViewPageController.php index dc9153c..89b1a5b 100644 --- a/core/modules/views/src/Routing/ViewPageController.php +++ b/core/modules/views/src/Routing/ViewPageController.php @@ -2,13 +2,54 @@ namespace Drupal\views\Routing; +use Drupal\Core\DependencyInjection\ContainerInjectionInterface; use Drupal\Core\Routing\RouteMatchInterface; use Drupal\views\Plugin\views\display\Page; +use Drupal\Core\Entity\EntityManagerInterface; +use Drupal\views\ViewExecutableFactory; +use Symfony\Component\DependencyInjection\ContainerInterface; /** * Defines a page controller to execute and render a view. */ -class ViewPageController { +class ViewPageController implements ContainerInjectionInterface { + + /** + * The entity manager. + * + * @var \Drupal\Core\Entity\EntityManagerInterface + */ + protected $entityManager; + + /** + * The view executable factory. + * + * @var \Drupal\views\ViewExecutableFactory + */ + protected $viewExecutableFactory; + + /** + * Constructs a new ViewPageController. + * + * @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager + * The entity manager + * @param \Drupal\views\ViewExecutableFactory $view_executable_factory + * The view executable factory + */ + public function __construct(EntityManagerInterface $entity_manager, ViewExecutableFactory $view_executable_factory) { + $this->entityManager = \Drupal::service('entity.manager'); + $this->viewExecutableFactory = \Drupal::service('views.executable'); + } + + /** + * @return static + */ + public static function create(ContainerInterface $container) { + return new static( + $container->get('entity.manager'), + $container->get('views.executable') + ); + } /** * Handler a response for a given view and display. @@ -61,4 +102,22 @@ public function handle($view_id, $display_id, RouteMatchInterface $route_match) } } + /** + * Title callback. + * + * Using callback as direct call to getTitle(() in route definition causing + * issues with configuration translation system. + * + * @see https://www.drupal.org/node/2650434 + * + * @return false|string + */ + public function getTitle($view_id, $display_id, RouteMatchInterface $route_match) { + $view_entity = $this->entityManager->getStorage('view')->load($view_id); + $view = $this->viewExecutableFactory->get($view_entity); + $view->setDisplay($display_id); + $view->initDisplay(); + return $view->getTitle(); + } + } diff --git a/core/modules/views/tests/src/Unit/Plugin/display/PathPluginBaseTest.php b/core/modules/views/tests/src/Unit/Plugin/display/PathPluginBaseTest.php index 9241a35..0b9d0a8 100644 --- a/core/modules/views/tests/src/Unit/Plugin/display/PathPluginBaseTest.php +++ b/core/modules/views/tests/src/Unit/Plugin/display/PathPluginBaseTest.php @@ -108,7 +108,7 @@ public function testCollectRoutes() { $this->assertEquals('test_id', $route->getDefault('view_id')); $this->assertEquals('page_1', $route->getDefault('display_id')); $this->assertSame(FALSE, $route->getOption('returns_response')); - $this->assertEquals('my views title', $route->getDefault('_title')); + $this->assertEquals('Drupal\views\Routing\ViewPageController::getTitle', $route->getDefault('_title_callback')); } /** @@ -135,7 +135,7 @@ public function testCollectRoutesWithDisplayReturnResponse() { $this->pathPlugin->collectRoutes($collection); $route = $collection->get('view.test_id.page_1'); $this->assertSame(TRUE, $route->getOption('returns_response')); - $this->assertEquals('my views title', $route->getDefault('_title')); + $this->assertEquals('Drupal\views\Routing\ViewPageController::getTitle', $route->getDefault('_title_callback')); } /** @@ -163,7 +163,7 @@ public function testCollectRoutesWithArguments() { $this->assertEquals('test_id', $route->getDefault('view_id')); $this->assertEquals('page_1', $route->getDefault('display_id')); $this->assertEquals(array('arg_0' => 'arg_0'), $route->getOption('_view_argument_map')); - $this->assertEquals('my views title', $route->getDefault('_title')); + $this->assertEquals('Drupal\views\Routing\ViewPageController::getTitle', $route->getDefault('_title_callback')); } /** @@ -194,7 +194,7 @@ public function testCollectRoutesWithArgumentsNotSpecifiedInPath() { $this->assertEquals('test_id', $route->getDefault('view_id')); $this->assertEquals('page_1', $route->getDefault('display_id')); $this->assertEquals(array('arg_0' => 'arg_0'), $route->getOption('_view_argument_map')); - $this->assertEquals('my views title', $route->getDefault('_title')); + $this->assertEquals('Drupal\views\Routing\ViewPageController::getTitle', $route->getDefault('_title_callback')); } /** @@ -220,7 +220,7 @@ public function testCollectRoutesWithSpecialRouteName() { $this->assertTrue($route instanceof Route); $this->assertEquals('test_id', $route->getDefault('view_id')); $this->assertEquals('page_1', $route->getDefault('display_id')); - $this->assertEquals('my views title', $route->getDefault('_title')); + $this->assertEquals('Drupal\views\Routing\ViewPageController::getTitle', $route->getDefault('_title_callback')); } /** @@ -250,7 +250,7 @@ public function testAlterRoute() { $this->assertTrue($route instanceof Route); $this->assertEquals('test_id', $route->getDefault('view_id')); $this->assertEquals('page_1', $route->getDefault('display_id')); - $this->assertEquals('my views title', $route->getDefault('_title')); + $this->assertEquals('Drupal\views\Routing\ViewPageController::getTitle', $route->getDefault('_title_callback')); // Ensure that the test_route_2 is not overridden. $route = $collection->get('test_route_2'); @@ -295,7 +295,7 @@ public function testAlterRestRoute() { $this->assertTrue($route instanceof Route); $this->assertEquals('test_id', $route->getDefault('view_id')); $this->assertEquals('page_1', $route->getDefault('display_id')); - $this->assertEquals('my views title', $route->getDefault('_title')); + $this->assertEquals('Drupal\views\Routing\ViewPageController::getTitle', $route->getDefault('_title_callback')); } /** @@ -326,7 +326,6 @@ public function testAlterRouteWithAlterCallback() { $this->assertEquals('test_id', $route->getDefault('view_id')); $this->assertEquals('\Drupal\Tests\views\Unit\Plugin\display\TestController::testTitle', $route->getDefault('_title_callback')); $this->assertEquals('page_1', $route->getDefault('display_id')); - $this->assertEquals('my views title', $route->getDefault('_title')); // Ensure that the test_route_2 is not overridden. $route = $collection->get('test_route_2'); @@ -367,7 +366,7 @@ public function testCollectRoutesWithNamedParameters() { $this->assertEquals('/test_route/{node}/example', $route->getPath()); $this->assertEquals('test_id', $route->getDefault('view_id')); $this->assertEquals('page_1', $route->getDefault('display_id')); - $this->assertEquals('my views title', $route->getDefault('_title')); + $this->assertEquals('Drupal\views\Routing\ViewPageController::getTitle', $route->getDefault('_title_callback')); $this->assertEquals(array('arg_0' => 'node'), $route->getOption('_view_argument_map')); } @@ -405,7 +404,7 @@ public function testAlterRoutesWithParameters() { // Ensure that the path did not changed and placeholders are respected. $this->assertEquals('/test_route/{parameter}', $route->getPath()); $this->assertEquals(array('arg_0' => 'parameter'), $route->getOption('_view_argument_map')); - $this->assertEquals('my views title', $route->getDefault('_title')); + $this->assertEquals('Drupal\views\Routing\ViewPageController::getTitle', $route->getDefault('_title_callback')); } /** @@ -443,7 +442,7 @@ public function testAlterRoutesWithParametersAndUpcasting() { // Ensure that the path did not changed and placeholders are respected kk. $this->assertEquals('/test_route/{parameter}', $route->getPath()); $this->assertEquals(['arg_0' => 'parameter'], $route->getOption('_view_argument_map')); - $this->assertEquals('my views title', $route->getDefault('_title')); + $this->assertEquals('Drupal\views\Routing\ViewPageController::getTitle', $route->getDefault('_title_callback')); } /** @@ -478,7 +477,7 @@ public function testAlterRoutesWithOptionalParameters() { // Ensure that the path did not changed and placeholders are respected. $this->assertEquals('/test_route/{parameter}/{arg_1}', $route->getPath()); $this->assertEquals(array('arg_0' => 'parameter'), $route->getOption('_view_argument_map')); - $this->assertEquals('my views title', $route->getDefault('_title')); + $this->assertEquals('Drupal\views\Routing\ViewPageController::getTitle', $route->getDefault('_title_callback')); } /** diff --git a/core/modules/views/tests/src/Unit/Routing/ViewPageControllerTest.php b/core/modules/views/tests/src/Unit/Routing/ViewPageControllerTest.php index 971c1c4..13686f6 100644 --- a/core/modules/views/tests/src/Unit/Routing/ViewPageControllerTest.php +++ b/core/modules/views/tests/src/Unit/Routing/ViewPageControllerTest.php @@ -2,6 +2,7 @@ namespace Drupal\Tests\views\Unit\Routing; +use Symfony\Component\DependencyInjection\ContainerBuilder; use Drupal\Core\Routing\RouteMatch; use Drupal\Tests\UnitTestCase; use Drupal\views\Routing\ViewPageController; @@ -36,7 +37,45 @@ class ViewPageControllerTest extends UnitTestCase { ]; protected function setUp() { - $this->pageController = new ViewPageController(); + $entity = $this->getMock('Drupal\views\ViewEntityInterface'); + $entity_storage = $this->getMock('\Drupal\Core\Entity\EntityStorageInterface'); + $entity_storage->expects($this->any()) + ->method('load') + ->will($this->returnValue($entity)); + + $entity_manager = $this->getMock('Drupal\Core\Entity\EntityManagerInterface'); + $entity_manager->expects($this->any()) + ->method('getStorage') + ->with($this->equalTo('view')) + ->will($this->returnValue($entity_storage)); + + + $view = $this->getMockBuilder('Drupal\views\ViewExecutable') + ->disableOriginalConstructor() + ->getMock(); + $view->expects($this->any()) + ->method('setDisplay') + ->will($this->returnValue(FALSE)); + $view->expects($this->any()) + ->method('initDisplay') + ->will($this->returnValue(FALSE)); + $view->expects($this->any()) + ->method('getTitle') + ->will($this->returnValue('View title')); + + $view_executable_factory = $this->getMockBuilder('Drupal\views\ViewExecutableFactory') + ->disableOriginalConstructor() + ->getMock(); + $view_executable_factory->expects($this->any()) + ->method('get') + ->with($entity) + ->will($this->returnValue($view)); + + $container = new ContainerBuilder(); + $container->set('entity.manager', $entity_manager); + $container->set('views.executable', $view_executable_factory); + \Drupal::setContainer($container); + $this->pageController = ViewPageController::create($container); } /** @@ -175,6 +214,15 @@ public function testHandleWithArgumentsOnOverriddenRouteWithUpcasting() { $this->assertEquals($build, $result); } + public function testGetTitle() { + $request = new Request(); + $request->attributes->set('view_id', 'test_page_view'); + $request->attributes->set('display_id', 'page_1'); + $route_match = RouteMatch::createFromRequest($request); + $title = $this->pageController->getTitle($route_match->getParameter('view_id'), $route_match->getParameter('display_id'), $route_match); + $this->assertEquals($title, 'View title'); + } + } // @todo https://www.drupal.org/node/2571679 replace