diff --git a/core/includes/theme.inc b/core/includes/theme.inc
index 88ab65d..a2dfc4b 100644
--- a/core/includes/theme.inc
+++ b/core/includes/theme.inc
@@ -1703,9 +1703,11 @@ function theme_link($variables) {
}
/**
- * Returns HTML for a set of links.
+ * Prepares variables for links templates.
*
- * @param $variables
+ * Default template: links.html.twig.
+ *
+ * @param array $variables
* An associative array containing:
* - links: An associative array of links to be themed. The key for each link
* is used as its CSS class. Each link should be itself an array, with the
@@ -1738,38 +1740,42 @@ function theme_link($variables) {
* http://juicystudio.com/article/screen-readers-display-none.php and
* http://www.w3.org/TR/WCAG-TECHS/H42.html for more information.
*/
-function theme_links($variables) {
+function template_preprocess_links(&$variables) {
$language_url = language(LANGUAGE_TYPE_URL);
$links = $variables['links'];
- $attributes = $variables['attributes'];
- $heading = $variables['heading'];
- $output = '';
+ $heading = &$variables['heading'];
+
+ // Remove 'links' from the attributes array. This is added through
+ // template_preprocess() but we do not need it.
+ // @todo Remove after http://drupal.org/node/1938430 is resolved.
+ if (isset($variables['attributes']['class'][0]) && $variables['attributes']['class'][0] == 'links') {
+ unset($variables['attributes']['class'][0]);
+ if (empty($variables['attributes']['class'])) {
+ unset($variables['attributes']['class']);
+ }
+ }
+ $variables['attributes'] = new Attribute($variables['attributes']);
if (!empty($links)) {
// Prepend the heading to the list, if any.
if (!empty($heading)) {
+ $attributes = array();
// Convert a string heading into an array, using a H2 tag by default.
if (is_string($heading)) {
$heading = array('text' => $heading);
+ } else {
+ // @todo Remove backwards compatibility for $heading['class'].
+ if (isset($heading['class'])) {
+ $attributes['class'] = $heading['class'];
+ unset($heading['class']);
+ }
}
- // Merge in default array properties into $heading.
- $heading += array(
- 'level' => 'h2',
- 'attributes' => array(),
- );
- // @todo Remove backwards compatibility for $heading['class'].
- if (isset($heading['class'])) {
- $heading['attributes']['class'] = $heading['class'];
- }
-
- $output .= '<' . $heading['level'] . new Attribute($heading['attributes']) . '>';
- $output .= check_plain($heading['text']);
- $output .= '' . $heading['level'] . '>';
+ // Convert the attributes array into an attributes object.
+ $heading['attributes'] = new Attribute($attributes);
+ $heading['text'] = check_plain($heading['text']);
}
- $output .= '
';
-
$num_links = count($links);
$i = 0;
foreach ($links as $key => $link) {
@@ -1786,7 +1792,6 @@ function theme_links($variables) {
if ($i == $num_links) {
$class[] = 'last';
}
-
// Handle links.
if (isset($link['href'])) {
$is_current_path = ($link['href'] == current_path() || ($link['href'] == '' && drupal_is_front_page()));
@@ -1795,45 +1800,37 @@ function theme_links($variables) {
$class[] = 'active';
}
// @todo Reconcile Views usage of 'ajax' as a boolean with the rest of
- // core's usage of it as an array.
+ // core's usage of it as an array.
+ $item = array(
+ '#type' => 'link',
+ '#title' => $link['title'],
+ '#href' => $link['href'],
+ );
if (isset($link['ajax']) && is_array($link['ajax'])) {
- // To attach Ajax behavior, render a link element, rather than just
- // call l().
- $link_element = array(
- '#type' => 'link',
- '#title' => $link['title'],
- '#href' => $link['href'],
+ $item += array(
'#ajax' => $link['ajax'],
'#options' => array_diff_key($link, drupal_map_assoc(array('title', 'href', 'ajax'))),
);
- $item = drupal_render($link_element);
}
else {
- // Pass in $link as $options, they share the same keys.
- $item = l($link['title'], $link['href'], $link);
+ $item += array(
+ '#options' => array_diff_key($link, drupal_map_assoc(array('title', 'href'))),
+ );
}
+ $variables['links'][$key]['link'] = $item;
}
- // Handle title-only text items.
- else {
- // Merge in default array properties into $link.
- $link += array(
- 'html' => FALSE,
- );
- $item = ($link['html'] ? $link['title'] : check_plain($link['title']));
- if (isset($link['attributes'])) {
- $item = '' . $item . '';
- }
+
+ // Handle text.
+ $text = (!empty($link['html']) ? $link['title'] : check_plain($link['title']));
+ $variables['links'][$key]['text'] = $text;
+ if (isset($link['attributes'])) {
+ $variables['links'][$key]['text_attributes'] = new Attribute($link['attributes']);
}
- $output .= '- $class)) . '>';
- $output .= $item;
- $output .= '
';
+ // Handle list item attributes.
+ $variables['links'][$key]['attributes'] = new Attribute(array('class' => $class));
}
-
- $output .= '
';
}
-
- return $output;
}
/**
@@ -3147,6 +3144,7 @@ function drupal_common_theme() {
),
'links' => array(
'variables' => array('links' => array(), 'attributes' => array('class' => array('links')), 'heading' => array()),
+ 'template' => 'links',
),
'dropbutton_wrapper' => array(
'render element' => 'element',
diff --git a/core/modules/system/templates/links.html.twig b/core/modules/system/templates/links.html.twig
new file mode 100644
index 0000000..472fb82
--- /dev/null
+++ b/core/modules/system/templates/links.html.twig
@@ -0,0 +1,70 @@
+{#
+/**
+ * @file
+ * Default theme implementation for a set of links.
+ *
+ * Available variables:
+ * - links: An associative array of links to be themed. The key for each link
+ * is used as its CSS class. Each link should be itself an array, with the
+ * following elements:
+ * - title: The link text.
+ * - href: The link URL. If omitted, the 'title' is shown as a plain text
+ * item in the links list.
+ * - html: (optional) Whether or not 'title' is HTML. If set, the title
+ * will not be passed through check_plain().
+ * - attributes: (optional) Attributes for the anchor, or for the tag
+ * used in its place if no 'href' is supplied. If element 'class' is
+ * included, it must be an array of one or more class names.
+ * If the 'href' element is supplied, the entire link array is passed to l()
+ * as its $options parameter.
+ * - attributes: attributes for the UL containing the
+ * list of links.
+ * - heading: (optional) A heading to precede the links. May be an associative
+ * array or a string. If it's an array, it can have the following elements:
+ * - text: The heading text.
+ * - level: The heading level (e.g. 'h2', 'h3').
+ * - attributes: (optional) A keyed array of attributes for the heading.
+ * - class: (optional) An array of classes for the heading element.
+ * When using a string it will be used as the text of the heading and the
+ * level will default to 'h2'. Headings should be used on navigation menus
+ * and any list of links that consistently appears on multiple pages. To
+ * make the heading invisible use the 'element-invisible' CSS class. Do not
+ * use 'display:none', which removes it from screen-readers and assistive
+ * technology. Headings allow screen-reader and keyboard only users to
+ * navigate to or skip the links. See
+ * http://juicystudio.com/article/screen-readers-display-none.php and
+ * http://www.w3.org/TR/WCAG-TECHS/H42.html for more information.
+ *
+ * @see template_preprocess()
+ * @see template_preprocess_links()
+ *
+ * @ingroup themeable
+ */
+ @todo revisit once http://drupal.org/node/1842024 is resolved.
+ @todo revisit once http://drupal.org/node/1842034 is resolved.
+ @todo remove include once http://drupal.org/node/1842160 is resolved.
+#}
+{% spaceless %}
+{% if links %}
+ {% if heading %}
+ {% if heading.level %}
+ <{{ heading.level }}{{ heading.attributes }}>{{ heading.text }}{{ heading.level }}>
+ {% else %}
+ {{ heading.text }}
+ {% endif %}
+ {% endif %}
+
+ {% for item in links %}
+ -
+ {% if item.link %}
+ {{ item.link }}
+ {% elseif item.text_attributes %}
+ {{ item.text }}
+ {% else %}
+ {{ item.text }}
+ {% endif %}
+
+ {% endfor %}
+
+ {% endif %}
+{% endspaceless %}