diff --git a/core/includes/theme.inc b/core/includes/theme.inc index 47c99d9..838524a 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,46 @@ 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']); + } + if (isset($heading['id'])) { + $attributes['id'] = $heading['id']; + unset($heading['id']); + } } - // 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 .= ''; + // 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 +1796,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 +1804,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; } /** @@ -3155,6 +3156,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..0ec3e84 --- /dev/null +++ b/core/modules/system/templates/links.html.twig @@ -0,0 +1,65 @@ +{# +/** + * @file + * Default theme implementation for a set of links. + * + * Available variables: + * - attributes: Attributes for the UL containing the list of links. + * - links: Links to be output. + * Each link will have 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. If 'href' is supplied, the entire link is passed + * to l() as its $options parameter. + * - html: (optional) Whether or not 'title' is HTML. If set, the title will + * not be passed through check_plain(). + * - attributes: (optional) HTML attributes for the anchor, or for the + * tag if no 'href' is supplied. + * - heading: (optional) A heading to precede the links. May be an associative + * array or a string. + * If the heading is 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. + * If the heading is 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/1842034 is resolved. +#} +{% spaceless %} +{% if links %} + {% if heading %} + {% if heading.level %} + <{{ heading.level }}{{ heading.attributes }}>{{ heading.text }} + {% 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 %}