diff --git a/core/modules/system/src/Tests/Theme/FunctionsTest.php b/core/modules/system/src/Tests/Theme/FunctionsTest.php
index 5e31422..e64f10e 100644
--- a/core/modules/system/src/Tests/Theme/FunctionsTest.php
+++ b/core/modules/system/src/Tests/Theme/FunctionsTest.php
@@ -290,6 +290,127 @@ function testLinks() {
}
/**
+ * Tests links.html.twig.
+ */
+ function testIndexedKeyedLinks() {
+ // Turn off the query for the
+ // \Drupal\Core\Utility\LinkGeneratorInterface::generate() method to compare
+ // the active link correctly.
+ $original_query = \Drupal::request()->query->all();
+ \Drupal::request()->query->replace([]);
+ // Verify that empty variables produce no output.
+ $variables = [];
+ $expected = '';
+ $this->assertThemeOutput('links', $variables, $expected, 'Empty %callback generates no output.');
+
+ $variables = [];
+ $variables['heading'] = 'Some title';
+ $expected = '';
+ $this->assertThemeOutput('links', $variables, $expected, 'Empty %callback with heading generates no output.');
+
+ // Verify that a list of links is properly rendered.
+ $variables = [];
+ $variables['attributes'] = ['id' => 'somelinks'];
+ $variables['links'] = array(
+ array(
+ 'title' => 'A ',
+ 'url' => Url::fromUri('base:a/link'),
+ ),
+ array(
+ 'title' => 'Plain "text"',
+ ),
+ array(
+ 'title' => SafeMarkup::format('@text', array('@text' => 'potentially unsafe text that be escaped')),
+ ),
+ array(
+ 'title' => 'Front page',
+ 'url' => Url::fromRoute(''),
+ ),
+ array(
+ 'title' => 'Test route',
+ 'url' => Url::fromRoute('router_test.1'),
+ ),
+ array(
+ 'title' => 'Query test route',
+ 'url' => Url::fromRoute('router_test.1'),
+ 'query' => array(
+ 'key' => 'value',
+ )
+ ),
+ );
+
+ $expected_links = '';
+ $expected_links .= '';
+
+ // Verify that passing a string as heading works.
+ $variables['heading'] = 'Links heading';
+ $expected_heading = 'Links heading
';
+ $expected = $expected_heading . $expected_links;
+ $this->assertThemeOutput('links', $variables, $expected);
+
+ // Restore the original request's query.
+ \Drupal::request()->query->replace($original_query);
+
+ // Verify that passing an array as heading works (core support).
+ $variables['heading'] = [
+ 'text' => 'Links heading',
+ 'level' => 'h3',
+ 'attributes' => ['class' => ['heading']],
+ ];
+ $expected_heading = 'Links heading
';
+ $expected = $expected_heading . $expected_links;
+ $this->assertThemeOutput('links', $variables, $expected);
+
+ // Verify that passing attributes for the heading works.
+ $variables['heading'] = ['text' => 'Links heading', 'level' => 'h3', 'attributes' => ['id' => 'heading']];
+ $expected_heading = 'Links heading
';
+ $expected = $expected_heading . $expected_links;
+ $this->assertThemeOutput('links', $variables, $expected);
+
+ // Verify that passing attributes for the links work.
+ $variables['links'][1]['attributes'] = [
+ 'class' => ['a/class'],
+ ];
+ $expected_links = '';
+ $expected_links .= '';
+ $expected = $expected_heading . $expected_links;
+ $this->assertThemeOutput('links', $variables, $expected);
+
+ // Verify the data- attributes for setting the "active" class on links.
+ \Drupal::currentUser()->setAccount(new UserSession(array('uid' => 1)));
+ $variables['set_active_class'] = TRUE;
+ $expected_links = '';
+ $expected_links .= '';
+ $expected = $expected_heading . $expected_links;
+ $this->assertThemeOutput('links', $variables, $expected);
+ }
+
+ /**
* Test the use of drupal_pre_render_links() on a nested array of links.
*/
function testDrupalPreRenderLinks() {
diff --git a/core/themes/stable/stable.theme b/core/themes/stable/stable.theme
index dac7d7c..aafe570 100644
--- a/core/themes/stable/stable.theme
+++ b/core/themes/stable/stable.theme
@@ -1,13 +1,17 @@
$value) {
if (!is_numeric($key)) {
- $variables['links'][$key]['attributes']['class'][] = $key;
+ $class = Html::getClass($key);
+ $variables['links'][$key]['attributes']->addClass($class);
}
}
}