diff --git a/core/includes/common.inc b/core/includes/common.inc index 540f42b..c10ef6f 100644 --- a/core/includes/common.inc +++ b/core/includes/common.inc @@ -2314,12 +2314,10 @@ function drupal_http_header_attributes(array $attributes = array()) { * * @see url() */ -function l($text, $path, array $options = array()) { - static $use_theme = NULL; +function l($content, $path, $options = array(), $attributes = array()) { // Merge in defaults. $options += array( - 'attributes' => array(), 'query' => array(), 'html' => FALSE, ); @@ -2334,47 +2332,23 @@ function l($text, $path, array $options = array()) { $is_active = $is_active && (empty($options['language']) || $options['language']->langcode == language(LANGUAGE_TYPE_URL)->langcode); $is_active = $is_active && (drupal_container()->get('request')->query->all() == $options['query']); if ($is_active) { - $options['attributes']['class'][] = 'active'; + $attributes['class'][] = 'active'; } // Remove all HTML and PHP tags from a tooltip. For best performance, we act only // if a quick strpos() pre-check gave a suspicion (because strip_tags() is expensive). - if (isset($options['attributes']['title']) && strpos($options['attributes']['title'], '<') !== FALSE) { - $options['attributes']['title'] = strip_tags($options['attributes']['title']); - } - - // Determine if rendering of the link is to be done with a theme function - // or the inline default. Inline is faster, but if the theme system has been - // loaded and a module or theme implements a preprocess or process function - // or overrides the theme_link() function, then invoke theme(). Preliminary - // benchmarks indicate that invoking theme() can slow down the l() function - // by 20% or more, and that some of the link-heavy Drupal pages spend more - // than 10% of the total page request time in the l() function. - if (!isset($use_theme) && function_exists('theme')) { - // Allow edge cases to prevent theme initialization and force inline link - // rendering. - if (variable_get('theme_link', TRUE)) { - drupal_theme_initialize(); - $registry = theme_get_registry(FALSE); - // We don't want to duplicate functionality that's in theme(), so any - // hint of a module or theme doing anything at all special with the 'link' - // theme hook should simply result in theme() being called. This includes - // the overriding of theme_link() with an alternate function or template, - // the presence of preprocess or process functions, or the presence of - // include files. - $use_theme = !isset($registry['link']['function']) || ($registry['link']['function'] != 'theme_link'); - $use_theme = $use_theme || !empty($registry['link']['preprocess functions']) || !empty($registry['link']['process functions']) || !empty($registry['link']['includes']); - } - else { - $use_theme = FALSE; - } - } - if ($use_theme) { - return theme('link', array('text' => $text, 'path' => $path, 'options' => $options)); + if (isset($attributes['title']) && strpos($attributes['title'], '<') !== FALSE) { + $attributes['title'] = strip_tags($attributes['title']); } + + $attributes = new Attribute($attributes); + // The result of url() is a plain-text URL. Because we are using it here // in an HTML argument context, we need to encode it properly. - return '' . ($options['html'] ? $text : check_plain($text)) . ''; + $href = check_plain(url($path, $options)); + $content = $options['html'] ? $content : check_plain($content); + + return '' . $content . ''; } /** @@ -5357,31 +5331,32 @@ function drupal_pre_render_conditional_comments($elements) { */ function drupal_pre_render_link($element) { // By default, link options to pass to l() are normally set in #options. - $element += array('#options' => array()); - // However, within the scope of renderable elements, #attributes is a valid - // way to specify attributes, too. Take them into account, but do not override - // attributes from #options. - if (isset($element['#attributes'])) { - $element['#options'] += array('attributes' => array()); - $element['#options']['attributes'] += $element['#attributes']; + $element += array( + '#content' => '', + '#path' => '', + '#options' => array(), + '#attributes' => array() + ); + + if (!isset($element['#content']) || !isset($element['#path'])) { + $oh_shit = TRUE; } // This #pre_render callback can be invoked from inside or outside of a Form // API context, and depending on that, a HTML ID may be already set in // different locations. #options should have precedence over Form API's #id. - // #attributes have been taken over into #options above already. - if (isset($element['#options']['attributes']['id'])) { - $element['#id'] = $element['#options']['attributes']['id']; + if (isset($element['#attributes']['id'])) { + $element['#id'] = $element['#attributes']['id']; } elseif (isset($element['#id'])) { - $element['#options']['attributes']['id'] = $element['#id']; + $element['#attributes']['id'] = $element['#id']; } // Conditionally invoke ajax_pre_render_element(), if #ajax is set. if (isset($element['#ajax']) && !isset($element['#ajax_processed'])) { // If no HTML ID was found above, automatically create one. if (!isset($element['#id'])) { - $element['#id'] = $element['#options']['attributes']['id'] = drupal_html_id('ajax-link'); + $element['#id'] = $element['#attributes']['id'] = drupal_html_id('ajax-link'); } // If #ajax['path] was not specified, use the href as Ajax request URL. if (!isset($element['#ajax']['path'])) { @@ -5391,7 +5366,7 @@ function drupal_pre_render_link($element) { $element = ajax_pre_render_element($element); } - $element['#markup'] = l($element['#title'], $element['#href'], $element['#options']); + $element['#markup'] = l($element['#content'], $element['#path'], $element['#options'], $element['#attributes']); return $element; } diff --git a/core/includes/theme.inc b/core/includes/theme.inc index d2fe902..6f556ac 100644 --- a/core/includes/theme.inc +++ b/core/includes/theme.inc @@ -1620,25 +1620,33 @@ function theme_status_messages($variables) { } /** + * Preprocess variables for link templates. + */ +function template_preprocess_link(&$variables) { + $variables['attributes'] = new Attribute(isset($variables['attributes']) ? $variables['attributes'] : array()); + $variables['content'] = $variables['options']['html'] ? $variables['content'] : check_plain($variables['content']); + $variables['href'] = check_plain(url($variables['path'], $variables['options'])); + // Do not pass 'path' or 'options' to link functions or templates. + unset($variables['path']); + unset($variables['options']); +} + +/** * Returns HTML for a link. * - * All Drupal code that outputs a link should call the l() function. That - * function performs some initial preprocessing, and then, if necessary, calls - * theme('link') for rendering the anchor tag. + * All Drupal code that outputs a link should call the l() function. * - * To optimize performance for sites that don't need custom theming of links, - * the l() function includes an inline copy of this function, and uses that copy - * if none of the enabled modules or the active theme implement any preprocess - * or process functions or override this theme implementation. + * theme('link') should only be used when HTML attributes for the tag + * such as 'class', 'id', etc. are not sufficient for themeing a given link. * * @param $variables - * An associative array containing the keys 'text', 'path', and 'options'. See - * the l() function for information about these variables. + * An associative array containing the keys 'content', 'href', and 'attributes'. + * See the l() function for information about $variables. * * @see l() */ function theme_link($variables) { - return '' . ($variables['options']['html'] ? $variables['text'] : check_plain($variables['text'])) . ''; + return '' . $variables['content'] . ''; } /** @@ -2967,7 +2975,7 @@ function drupal_common_theme() { 'variables' => array('display' => NULL), ), 'link' => array( - 'variables' => array('text' => NULL, 'path' => NULL, 'options' => array()), + 'variables' => array('content' => NULL, 'path' => NULL, 'options' => array(), 'attributes' => array()), ), 'links' => array( 'variables' => array('links' => array(), 'attributes' => array('class' => array('links')), 'heading' => array()), diff --git a/core/modules/overlay/overlay.module b/core/modules/overlay/overlay.module index 8e6e65b..d0fa29c 100644 --- a/core/modules/overlay/overlay.module +++ b/core/modules/overlay/overlay.module @@ -444,9 +444,9 @@ function theme_overlay_disable_message($variables) { // screen-reader users, this message appears in both the parent and child // documents, but only the one in the child document is part of the tab order. foreach (array('profile_link', 'dismiss_message_link') as $key) { - $element[$key]['#options']['attributes']['class'][] = 'element-invisible'; + $element[$key]['#attributes']['class'][] = 'element-invisible'; if (overlay_get_mode() == 'child') { - $element[$key]['#options']['attributes']['class'][] = 'element-focusable'; + $element[$key]['#attributes']['class'][] = 'element-focusable'; } } diff --git a/core/modules/shortcut/shortcut.module b/core/modules/shortcut/shortcut.module index 9bbb12a..4753300 100644 --- a/core/modules/shortcut/shortcut.module +++ b/core/modules/shortcut/shortcut.module @@ -741,9 +741,10 @@ function shortcut_toolbar_pre_render($toolbar) { if (shortcut_set_edit_access($shortcut_set)) { $configure_link = array( '#type' => 'link', - '#title' => t('Edit shortcuts'), - '#href' => 'admin/config/user-interface/shortcut/' . $shortcut_set->set_name, - '#options' => array('attributes' => array('id' => 'edit-shortcuts')), + '#content' => t('Edit shortcuts'), + '#path' => 'admin/config/user-interface/shortcut/' . $shortcut_set->set_name, + '#options' => array(), + '#attributes' => array('id' => 'edit-shortcuts'), ); } diff --git a/core/modules/toolbar/toolbar.module b/core/modules/toolbar/toolbar.module index a54743a..14aab92 100644 --- a/core/modules/toolbar/toolbar.module +++ b/core/modules/toolbar/toolbar.module @@ -77,30 +77,6 @@ function toolbar_toggle_page() { } /** - * Formats an element used to toggle the toolbar drawer's visibility. - * - * @param $variables - * An associative array containing: - * - collapsed: A boolean value representing the toolbar drawer's visibility. - * - attributes: An associative array of HTML attributes. - * - * @return - * An HTML string representing the element for toggling. - * - * @ingroup themable - */ -function theme_toolbar_toggle($variables) { - if ($variables['collapsed']) { - $toggle_text = t('Show shortcuts'); - } - else { - $toggle_text = t('Hide shortcuts'); - $variables['attributes']['class'][] = 'toggle-active'; - } - return l($toggle_text, 'toolbar/toggle', array('query' => drupal_get_destination(), 'attributes' => array('title' => $toggle_text) + $variables['attributes'])); -} - -/** * Determines the current state of the toolbar drawer's visibility. * * @return @@ -250,10 +226,15 @@ function toolbar_view() { ); // Add an anchor to be able to toggle the visibility of the drawer. + $toggle_text = _toolbar_is_collapsed() ? t('Show toolbar') : t('Hide toolbar'); + $toggle_path = 'toolbar/toggle'; + $toggle_options = array('query' => drupal_get_destination()); + $toggle_attributes = array('class' => array('toggle')); + if (_toolbar_is_collapsed()) { + $toggle_attributes['class'][] = 'toggle-active'; + } $build['toolbar_toggle'] = array( - '#theme' => 'toolbar_toggle', - '#collapsed' => _toolbar_is_collapsed(), - '#attributes' => array('class' => array('toggle')), + '#markup' => l($toggle_text, $toggle_path, $toggle_options, $toggle_attributes), ); // Prepare the drawer links CSS classes.