From 2ebbc8a1bfc579dd38f711d44b65d88e6e76435f Mon Sep 17 00:00:00 2001 From: Alex Pott Date: Mon, 20 Nov 2023 09:42:11 +0000 Subject: [PATCH] Issue #3351458 by dburiak, Mingsong, Mahima_Mathur23, sthomen, smustgrave, catch, alexpott: [regression] Language switcher block returns links to node on the frontpage (cherry picked from commit 9e7ff4623af4a04ebc23758e75c71e7812dcb0b1) --- .../src/Plugin/Block/LanguageBlock.php | 11 ++- .../src/Functional/LanguageSwitchingTest.php | 96 ++++++++++++++++++- 2 files changed, 105 insertions(+), 2 deletions(-) diff --git a/core/modules/language/src/Plugin/Block/LanguageBlock.php b/core/modules/language/src/Plugin/Block/LanguageBlock.php index e672ce6583d..d516b259f1e 100644 --- a/core/modules/language/src/Plugin/Block/LanguageBlock.php +++ b/core/modules/language/src/Plugin/Block/LanguageBlock.php @@ -89,7 +89,16 @@ class LanguageBlock extends BlockBase implements ContainerFactoryPluginInterface $route_match = \Drupal::routeMatch(); // If there is no route match, for example when creating blocks on 404 pages // for logged-in users with big_pipe enabled using the front page instead. - $url = $route_match->getRouteObject() ? Url::fromRouteMatch($route_match) : Url::fromRoute(''); + if ($this->pathMatcher->isFrontPage() || !$route_match->getRouteObject()) { + // We are skipping the route match on both 404 and front page. + // Example: If on front page, there is no route match like when creating + // blocks on 404 pages for logged-in users with big_pipe enabled, use the + // front page. + $url = Url::fromRoute(''); + } + else { + $url = Url::fromRouteMatch($route_match); + } $links = $this->languageManager->getLanguageSwitchLinks($type, $url); if (isset($links->links)) { diff --git a/core/modules/language/tests/src/Functional/LanguageSwitchingTest.php b/core/modules/language/tests/src/Functional/LanguageSwitchingTest.php index 9918190e8b0..e3760e1d2d9 100644 --- a/core/modules/language/tests/src/Functional/LanguageSwitchingTest.php +++ b/core/modules/language/tests/src/Functional/LanguageSwitchingTest.php @@ -7,6 +7,7 @@ use Drupal\language\Plugin\LanguageNegotiation\LanguageNegotiationUrl; use Drupal\menu_link_content\Entity\MenuLinkContent; use Drupal\Core\Language\LanguageInterface; use Drupal\Tests\BrowserTestBase; +use Drupal\Core\Url; // cspell:ignore publi publié @@ -29,6 +30,7 @@ class LanguageSwitchingTest extends BrowserTestBase { 'block', 'language_test', 'menu_ui', + 'node', ]; /** @@ -48,6 +50,7 @@ class LanguageSwitchingTest extends BrowserTestBase { $admin_user = $this->drupalCreateUser([ 'administer blocks', 'administer languages', + 'administer site configuration', 'access administration pages', 'access content', ]); @@ -81,6 +84,7 @@ class LanguageSwitchingTest extends BrowserTestBase { ]); $this->doTestLanguageBlockAuthenticated($block->label()); + $this->doTestHomePageLinks($block->label()); $this->doTestLanguageBlockAnonymous($block->label()); $this->doTestLanguageBlock404($block->label(), 'system/404'); @@ -96,6 +100,68 @@ class LanguageSwitchingTest extends BrowserTestBase { $this->doTestLanguageBlock404($block->label(), ''); } + /** + * The home page link should be "/" or "/{language_prefix}". + * + * @param string $block_label + * The label of the language switching block. + * + * @see self::testLanguageBlock() + */ + protected function doTestHomePageLinks($block_label) { + // Create a node and set as home page. + $this->createHomePage(); + // Go to home page. + $this->DrupalGet(''); + // The language switcher block should display. + $this->assertSession()->pageTextContains($block_label); + // Assert that each list item and anchor element has the appropriate data- + // attributes. + $language_switchers = $this->xpath('//div[@id=:id]/ul/li', [':id' => 'block-test-language-block']); + $list_items = []; + $anchors = []; + $labels = []; + foreach ($language_switchers as $list_item) { + $list_items[] = [ + 'hreflang' => $list_item->getAttribute('hreflang'), + 'data-drupal-link-system-path' => $list_item->getAttribute('data-drupal-link-system-path'), + ]; + + $link = $list_item->find('xpath', 'a'); + $anchors[] = [ + 'hreflang' => $link->getAttribute('hreflang'), + 'data-drupal-link-system-path' => $link->getAttribute('data-drupal-link-system-path'), + 'href' => $link->getAttribute('href'), + ]; + $labels[] = $link->getText(); + } + $expected_list_items = [ + 0 => [ + 'hreflang' => 'en', + 'data-drupal-link-system-path' => '', + ], + 1 => [ + 'hreflang' => 'fr', + 'data-drupal-link-system-path' => '', + ], + ]; + $this->assertSame($expected_list_items, $list_items, 'The list items have the correct attributes that will contain the correct home page links.'); + $expected_anchors = [ + 0 => [ + 'hreflang' => 'en', + 'data-drupal-link-system-path' => '', + 'href' => Url::fromRoute('')->toString(), + ], + 1 => [ + 'hreflang' => 'fr', + 'data-drupal-link-system-path' => '', + 'href' => Url::fromRoute('')->toString() . 'fr', + ], + ]; + $this->assertSame($expected_anchors, $anchors, 'The anchors have the correct attributes that will link to the correct home page in that language.'); + $this->assertSame(['English', 'français'], $labels, 'The language links labels are in their own language on the language switcher block.'); + } + /** * For authenticated users, the "active" class is set by JavaScript. * @@ -504,7 +570,6 @@ class LanguageSwitchingTest extends BrowserTestBase { * Test that the language switching block does not expose restricted paths. */ public function testRestrictedPaths(): void { - \Drupal::service('module_installer')->install(['node']); $entity_type_manager = \Drupal::entityTypeManager(); // Add the French language. @@ -633,4 +698,33 @@ class LanguageSwitchingTest extends BrowserTestBase { ->getOverride($langcode, 'language.entity.' . $langcode)->set('label', $label)->save(); } + /** + * Create a node and set it as the home pages. + */ + protected function createHomePage() { + $entity_type_manager = \Drupal::entityTypeManager(); + + // Create a node type and make it translatable. + $entity_type_manager->getStorage('node_type') + ->create([ + 'type' => 'page', + 'name' => 'Page', + ]) + ->save(); + + // Create a published node. + $node = $entity_type_manager->getStorage('node') + ->create([ + 'type' => 'page', + 'title' => $this->randomMachineName(), + 'status' => 1, + ]); + $node->save(); + + // Change the front page to /node/1. + $edit = ['site_frontpage' => '/node/1']; + $this->drupalGet('admin/config/system/site-information'); + $this->submitForm($edit, 'Save configuration'); + } + }