diff --git a/core/includes/common.inc b/core/includes/common.inc index dfd20fa..c6230ac 100644 --- a/core/includes/common.inc +++ b/core/includes/common.inc @@ -1314,6 +1314,12 @@ function l($text, $path, array $options = array()) { 'language' => NULL, ); + // Add a hreflang attribute if we know the language of this link's url and + // hreflang has not already been set. + if (!empty($variables['options']['language']) && !isset($variables['options']['attributes']['hreflang'])) { + $variables['options']['attributes']['hreflang'] = $variables['options']['language']->id; + } + // Because l() is called very often we statically cache values that require an // extra function call. static $drupal_static_fast; diff --git a/core/modules/system/lib/Drupal/system/Tests/Common/UrlTest.php b/core/modules/system/lib/Drupal/system/Tests/Common/UrlTest.php index 249afd4..d79f9e1 100644 --- a/core/modules/system/lib/Drupal/system/Tests/Common/UrlTest.php +++ b/core/modules/system/lib/Drupal/system/Tests/Common/UrlTest.php @@ -7,6 +7,7 @@ namespace Drupal\system\Tests\Common; +use Drupal\Core\Language\Language; use Drupal\simpletest\WebTestBase; use Symfony\Component\HttpFoundation\Request; @@ -51,9 +52,33 @@ function testLinkXSS() { } /** - * Tests for active class in links produced by l() and #type 'link'. + * Tests that default and custom attributes are handled correctly on links. */ - function testLinkActiveClass() { + function testLinkAttributes() { + // Test that hreflang is added when a link has a known language. + $language = new Language(array('id' => 'fr', 'name' => 'French')); + $hreflang_link = array( + '#type' => 'link', + '#options' => array( + 'language' => $language, + ), + '#href' => 'http://drupal.org', + '#title' => 'bar', + ); + $langcode = $language->id; + + // Test that the default hreflang handling for links does not override a + // hreflang attribute explicitly set in the render array. + $hreflang_override_link = $hreflang_link; + $hreflang_override_link['#options']['attributes']['hreflang'] = 'foo'; + + $rendered = drupal_render($hreflang_link); + $this->assertTrue($this->hasAttribute('hreflang', $rendered, $langcode), format_string('hreflang attribute with value @langcode is present on a rendered link when langcode is provided in the render array.', array('@langcode' => $langcode))); + + $rendered = drupal_render($hreflang_override_link); + $this->assertTrue($this->hasAttribute('hreflang', $rendered, 'foo'), format_string('hreflang attribute with value @hreflang is present on a rendered link when @hreflang is provided in the render array.', array('@hreflang' => 'foo'))); + + // Test the active class in links produced by l() and #type 'link'. $options_no_query = array(); $options_query = array( 'query' => array( @@ -87,16 +112,12 @@ function testLinkActiveClass() { $links = $this->xpath('//a[@href = :href and not(contains(@class, :class))]', array(':href' => url($path, $options_no_query), ':class' => 'active')); $this->assertTrue(isset($links[0]), 'A link generated by l() to the current page without a query string when the current page has a query string is not marked active.'); - } - /** - * Tests for custom class in links produced by l() and #type 'link'. - */ - function testLinkCustomClass() { + // Test adding a custom class in links produced by l() and #type 'link'. // Test l(). $class_l = $this->randomName(); $link_l = l($this->randomName(), current_path(), array('attributes' => array('class' => array($class_l)))); - $this->assertTrue($this->hasClass($link_l, $class_l), format_string('Custom class @class is present on link when requested by l()', array('@class' => $class_l))); + $this->assertTrue($this->hasAttribute('class', $link_l, $class_l), format_string('Custom class @class is present on link when requested by l()', array('@class' => $class_l))); // Test #type. $class_theme = $this->randomName(); @@ -111,7 +132,7 @@ function testLinkCustomClass() { ), ); $link_theme = drupal_render($type_link); - $this->assertTrue($this->hasClass($link_theme, $class_theme), format_string('Custom class @class is present on link when requested by #type', array('@class' => $class_theme))); + $this->assertTrue($this->hasAttribute('class', $link_theme, $class_theme), format_string('Custom class @class is present on link when requested by #type', array('@class' => $class_theme))); } /** @@ -156,8 +177,8 @@ function testLinkRenderArrayText() { * @return bool * TRUE if the class is found, FALSE otherwise. */ - private function hasClass($link, $class) { - return preg_match('|class="([^\"\s]+\s+)*' . $class . '|', $link); + private function hasAttribute($attribute, $link, $class) { + return preg_match('|' . $attribute . '="([^\"\s]+\s+)*' . $class . '|', $link); } /**