diff --git a/core/lib/Drupal/Core/Utility/LinkGenerator.php b/core/lib/Drupal/Core/Utility/LinkGenerator.php index 0ec5280..ed022a6 100644 --- a/core/lib/Drupal/Core/Utility/LinkGenerator.php +++ b/core/lib/Drupal/Core/Utility/LinkGenerator.php @@ -76,6 +76,11 @@ public function generateFromLink(Link $link) { * @see system_page_attachments() */ public function generate($text, Url $url) { + // The link generator should not modify the original url object, this + // ensures consistent rendering. + // @see https://www.drupal.org/node/2842399 + $url = clone $url; + // Performance: avoid Url::toString() needing to retrieve the URL generator // service from the container. $url->setUrlGenerator($this->urlGenerator); diff --git a/core/modules/system/src/Tests/Theme/EngineTwigTest.php b/core/modules/system/src/Tests/Theme/EngineTwigTest.php index 51d092d..58661d1 100644 --- a/core/modules/system/src/Tests/Theme/EngineTwigTest.php +++ b/core/modules/system/src/Tests/Theme/EngineTwigTest.php @@ -86,6 +86,7 @@ public function testTwigLinkGenerator() { 'link via the linkgenerator: ' . $link_generator->generate('register', new Url('user.register', [], ['attributes' => ['class' => ['llama', 'kitten', 'panda']]])), 'link via the linkgenerator: ' . $link_generator->generate(Markup::create('register'), new Url('user.register', [], ['absolute' => TRUE])), 'link via the linkgenerator: register', + 'link via the linkgenerator: ' . $link_generator->generate('register', new Url('user.register', [], ['attributes' => ['foo' => 'bar']])) . ' ' . $link_generator->generate('register', new Url('user.register', [], ['attributes' => ['foo' => 'bar']])), ]; // Verify that link() has the ability to bubble cacheability metadata: diff --git a/core/modules/system/tests/modules/twig_theme_test/templates/twig_theme_test.link_generator.html.twig b/core/modules/system/tests/modules/twig_theme_test/templates/twig_theme_test.link_generator.html.twig index a836aec..1b20b46 100644 --- a/core/modules/system/tests/modules/twig_theme_test/templates/twig_theme_test.link_generator.html.twig +++ b/core/modules/system/tests/modules/twig_theme_test/templates/twig_theme_test.link_generator.html.twig @@ -7,3 +7,4 @@
link via the linkgenerator: {{ link(title, test_url) }}
{% set title %}register{% endset %}
link via the linkgenerator: {{ link(title, test_url) }}
+
link via the linkgenerator: {{ link('register', test_url_attribute) }} {{ link('register', test_url_attribute) }}
diff --git a/core/tests/Drupal/Tests/Core/Utility/LinkGeneratorTest.php b/core/tests/Drupal/Tests/Core/Utility/LinkGeneratorTest.php index f4dc2df..c3af2db 100644 --- a/core/tests/Drupal/Tests/Core/Utility/LinkGeneratorTest.php +++ b/core/tests/Drupal/Tests/Core/Utility/LinkGeneratorTest.php @@ -538,6 +538,25 @@ public function testGenerateWithAlterHook() { } /** + * Tests whether rendering the same link twice works. + * + * This is a regression test for https://www.drupal.org/node/2842399. + */ + public function testGenerateTwice() { + $this->urlGenerator->expects($this->any()) + ->method('generateFromRoute') + ->will($this->returnValue((new GeneratedUrl())->setGeneratedUrl('/'))); + + $url = Url::fromRoute('', [], ['attributes' => ['class' => ['foo', 'bar']]]); + $url->setUrlGenerator($this->urlGenerator); + + $link = Link::fromTextAndUrl('text', $url); + $link->setLinkGenerator($this->linkGenerator); + $output = $link->toString() . $link->toString(); + $this->assertEquals('texttext', $output); + } + + /** * Checks that a link with certain properties exists in a given HTML snippet. * * @param array $properties