From 4f37cf02556c374ea4db81433d492d4dd2e3aa5d Mon Sep 17 00:00:00 2001 From: catch <catch@35733.no-reply.drupal.org> Date: Tue, 4 Sep 2012 14:32:47 +0100 Subject: [PATCH] Issue #1700382 by Albert Volkman, cam8001: Replace remaining references to drupal_attributes() with new Attributes(). --- core/includes/common.inc | 61 ++++-------------- core/includes/form.inc | 64 ++++++++++--------- core/includes/menu.inc | 4 +- core/includes/pager.inc | 4 +- core/includes/theme.inc | 39 +++++------ core/lib/Drupal/Core/Template/Attribute.php | 5 -- core/modules/book/book.module | 3 +- core/modules/field/field.module | 17 ++--- core/modules/file/file.module | 3 +- core/modules/filter/filter.module | 3 +- core/modules/node/node.module | 3 +- core/modules/rdf/rdf.module | 18 +++--- .../Tests/Common/AttributesUnitTest.php | 17 ++--- core/modules/user/user.module | 7 +- 14 files changed, 111 insertions(+), 137 deletions(-) diff --git a/core/includes/common.inc b/core/includes/common.inc index dece53967abc..39a30d2686ec 100644 --- a/core/includes/common.inc +++ b/core/includes/common.inc @@ -1246,8 +1246,9 @@ function flood_is_allowed($name, $threshold, $window = 3600, $identifier = NULL) * to being output to an HTML attribute value. It is often called as part of * check_url() or filter_xss(), but those functions return an HTML-encoded * string, so this function can be called independently when the output needs to - * be a plain-text string for passing to t(), l(), drupal_attributes(), or - * another function that will call check_plain() separately. + * be a plain-text string for passing to t(), l(), + * Drupal\Core\Template\Attribute, or another function that will call + * check_plain() separately. * * @param $uri * A plain-text URI that might contain dangerous protocols. @@ -1300,10 +1301,11 @@ function drupal_strip_dangerous_protocols($uri) { * @return * A URI stripped of dangerous protocols and encoded for output to an HTML * attribute value. Because it is already encoded, it should not be set as a - * value within a $attributes array passed to drupal_attributes(), because - * drupal_attributes() expects those values to be plain-text strings. To pass - * a filtered URI to drupal_attributes(), call - * drupal_strip_dangerous_protocols() instead. + * value within a $attributes array passed to Drupal\Core\Template\Attribute, + * because Drupal\Core\Template\Attribute expects those values to be + * plain-text strings. To pass a filtered URI to + * Drupal\Core\Template\Attribute, call drupal_strip_dangerous_protocols() + * instead. * * @see drupal_strip_dangerous_protocols() */ @@ -1661,7 +1663,7 @@ function format_xml_elements($array) { if ($value['key']) { $output .= ' <' . $value['key']; if (isset($value['attributes']) && is_array($value['attributes'])) { - $output .= drupal_attributes($value['attributes']); + $output .= new Attribute($value['attributes']); } if (isset($value['value']) && $value['value'] != '') { @@ -2242,46 +2244,6 @@ function drupal_http_header_attributes(array $attributes = array()) { return $attributes ? ' ' . implode('; ', $attributes) : ''; } -/** - * Converts an associative array to an XML/HTML tag attribute string. - * - * Each array key and its value will be formatted into an attribute string. - * If a value is itself an array, then its elements are concatenated to a single - * space-delimited string (for example, a class attribute with multiple values). - * - * Attribute values are sanitized by running them through check_plain(). - * Attribute names are not automatically sanitized. When using user-supplied - * attribute names, it is strongly recommended to allow only white-listed names, - * since certain attributes carry security risks and can be abused. - * - * Examples of security aspects when using drupal_attributes: - * @code - * // By running the value in the following statement through check_plain, - * // the malicious script is neutralized. - * drupal_attributes(array('title' => t('<script>steal_cookie();</script>'))); - * - * // The statement below demonstrates dangerous use of drupal_attributes, and - * // will return an onmouseout attribute with JavaScript code that, when used - * // as attribute in a tag, will cause users to be redirected to another site. - * // - * // In this case, the 'onmouseout' attribute should not be whitelisted -- - * // you don't want users to have the ability to add this attribute or others - * // that take JavaScript commands. - * drupal_attributes(array('onmouseout' => 'window.location="http://malicious.com/";'))); - * @endcode - * - * @param $attributes - * An associative array of key-value pairs to be converted to attributes. - * - * @return - * A string ready for insertion in a tag (starts with a space). - * - * @ingroup sanitization - */ -function drupal_attributes(array $attributes = array()) { - return new Attribute($attributes); -} - /** * Formats an internal or external URL link as an HTML anchor tag. * @@ -2303,7 +2265,8 @@ function drupal_attributes(array $attributes = array()) { * - 'attributes': An associative array of HTML attributes to apply to the * anchor tag. If element 'class' is included, it must be an array; 'title' * must be a string; other elements are more flexible, as they just need - * to work in a call to drupal_attributes($options['attributes']). + * to work as an argument for the constructor of the class + * Drupal\Core\Template\Attribute($options['attributes']). * - 'html' (default FALSE): Whether $text is HTML or just plain-text. For * example, to make an image tag into a link, this must be set to TRUE, or * you will see the escaped HTML image tag. $text is not sanitized if @@ -2370,7 +2333,7 @@ function l($text, $path, array $options = array()) { } // 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 '<a href="' . check_plain(url($path, $options)) . '"' . drupal_attributes($options['attributes']) . '>' . ($options['html'] ? $text : check_plain($text)) . '</a>'; + return '<a href="' . check_plain(url($path, $options)) . '"' . new Attribute($options['attributes']) . '>' . ($options['html'] ? $text : check_plain($text)) . '</a>'; } /** diff --git a/core/includes/form.inc b/core/includes/form.inc index e2003453274f..29bce0019be8 100644 --- a/core/includes/form.inc +++ b/core/includes/form.inc @@ -6,6 +6,7 @@ */ use Drupal\Core\Utility\Color; +use Drupal\Core\Template\Attribute; /** * @defgroup forms Form builder functions @@ -2670,7 +2671,7 @@ function theme_select($variables) { element_set_attributes($element, array('id', 'name', 'size')); _form_set_class($element, array('form-select')); - return '<select' . drupal_attributes($element['#attributes']) . '>' . form_select_options($element) . '</select>'; + return '<select' . new Attribute($element['#attributes']) . '>' . form_select_options($element) . '</select>'; } /** @@ -2784,7 +2785,7 @@ function theme_fieldset($variables) { element_set_attributes($element, array('id')); _form_set_class($element, array('form-wrapper')); - $output = '<fieldset' . drupal_attributes($element['#attributes']) . '>'; + $output = '<fieldset' . new Attribute($element['#attributes']) . '>'; if (!empty($element['#title'])) { // Always wrap fieldset legends in a SPAN for CSS positioning. $output .= '<legend><span class="fieldset-legend">' . $element['#title'] . '</span></legend>'; @@ -2806,7 +2807,8 @@ function theme_fieldset($variables) { * Returns HTML for a radio button form element. * * Note: The input "name" attribute needs to be sanitized before output, which - * is currently done by passing all attributes to drupal_attributes(). + * is currently done by initializing Drupal\Core\Template\Attribute with + * all the attributes. * * @param $variables * An associative array containing: @@ -2826,7 +2828,7 @@ function theme_radio($variables) { } _form_set_class($element, array('form-radio')); - return '<input' . drupal_attributes($element['#attributes']) . ' />'; + return '<input' . new Attribute($element['#attributes']) . ' />'; } /** @@ -2853,7 +2855,7 @@ function theme_radios($variables) { if (isset($element['#attributes']['title'])) { $attributes['title'] = $element['#attributes']['title']; } - return '<div' . drupal_attributes($attributes) . '>' . (!empty($element['#children']) ? $element['#children'] : '') . '</div>'; + return '<div' . new Attribute($attributes) . '>' . (!empty($element['#children']) ? $element['#children'] : '') . '</div>'; } /** @@ -2932,7 +2934,7 @@ function theme_date($variables) { } $attributes['class'][] = 'container-inline'; - return '<div' . drupal_attributes($attributes) . '>' . drupal_render_children($element) . '</div>'; + return '<div' . new Attribute($attributes) . '>' . drupal_render_children($element) . '</div>'; } /** @@ -3054,8 +3056,8 @@ function form_process_radios($element) { $element[$key] += array( '#type' => 'radio', '#title' => $choice, - // The key is sanitized in drupal_attributes() during output from the - // theme function. + // The key is sanitized in Drupal\Core\Template\Attribute during output + // from the theme function. '#return_value' => $key, // Use default or FALSE. A value of FALSE means that the radio button is // not 'checked'. @@ -3094,7 +3096,7 @@ function theme_checkbox($variables) { } _form_set_class($element, array('form-checkbox')); - return '<input' . drupal_attributes($element['#attributes']) . ' />'; + return '<input' . new Attribute($element['#attributes']) . ' />'; } /** @@ -3120,7 +3122,7 @@ function theme_checkboxes($variables) { if (isset($element['#attributes']['title'])) { $attributes['title'] = $element['#attributes']['title']; } - return '<div' . drupal_attributes($attributes) . '>' . (!empty($element['#children']) ? $element['#children'] : '') . '</div>'; + return '<div' . new Attribute($attributes) . '>' . (!empty($element['#children']) ? $element['#children'] : '') . '</div>'; } /** @@ -3338,7 +3340,7 @@ function theme_container($variables) { $element['#attributes']['class'][] = 'form-wrapper'; } - return '<div' . drupal_attributes($element['#attributes']) . '>' . $element['#children'] . '</div>'; + return '<div' . new Attribute($element['#attributes']) . '>' . $element['#children'] . '</div>'; } /** @@ -3914,7 +3916,7 @@ function theme_button($variables) { $element['#attributes']['class'][] = 'form-button-disabled'; } - return '<input' . drupal_attributes($element['#attributes']) . ' />'; + return '<input' . new Attribute($element['#attributes']) . ' />'; } /** @@ -3943,7 +3945,7 @@ function theme_image_button($variables) { $element['#attributes']['class'][] = 'form-button-disabled'; } - return '<input' . drupal_attributes($element['#attributes']) . ' />'; + return '<input' . new Attribute($element['#attributes']) . ' />'; } /** @@ -3960,7 +3962,7 @@ function theme_hidden($variables) { $element = $variables['element']; $element['#attributes']['type'] = 'hidden'; element_set_attributes($element, array('name', 'value')); - return '<input' . drupal_attributes($element['#attributes']) . " />\n"; + return '<input' . new Attribute($element['#attributes']) . " />\n"; } /** @@ -3980,7 +3982,7 @@ function theme_textfield($variables) { element_set_attributes($element, array('id', 'name', 'value', 'size', 'maxlength', 'placeholder')); _form_set_class($element, array('form-text')); - return '<input' . drupal_attributes($element['#attributes']) . ' />' . drupal_render_children($element); + return '<input' . new Attribute($element['#attributes']) . ' />' . drupal_render_children($element); } /** @@ -4000,7 +4002,7 @@ function theme_email($variables) { element_set_attributes($element, array('id', 'name', 'value', 'size', 'maxlength', 'placeholder')); _form_set_class($element, array('form-email')); - return '<input' . drupal_attributes($element['#attributes']) . ' />' . drupal_render_children($element); + return '<input' . new Attribute($element['#attributes']) . ' />' . drupal_render_children($element); } /** @@ -4034,7 +4036,7 @@ function theme_tel($variables) { element_set_attributes($element, array('id', 'name', 'value', 'size', 'maxlength', 'placeholder')); _form_set_class($element, array('form-tel')); - return '<input' . drupal_attributes($element['#attributes']) . ' />' . drupal_render_children($element); + return '<input' . new Attribute($element['#attributes']) . ' />' . drupal_render_children($element); } /** @@ -4055,7 +4057,7 @@ function theme_number($variables) { element_set_attributes($element, array('id', 'name', 'value', 'step', 'min', 'max', 'placeholder')); _form_set_class($element, array('form-number')); - $output = '<input' . drupal_attributes($element['#attributes']) . ' />'; + $output = '<input' . new Attribute($element['#attributes']) . ' />'; return $output; } @@ -4078,7 +4080,7 @@ function theme_range($variables) { element_set_attributes($element, array('id', 'name', 'value', 'step', 'min', 'max')); _form_set_class($element, array('form-range')); - $output = '<input' . drupal_attributes($element['#attributes']) . ' />'; + $output = '<input' . new Attribute($element['#attributes']) . ' />'; return $output; } @@ -4170,7 +4172,7 @@ function theme_url($variables) { element_set_attributes($element, array('id', 'name', 'value', 'size', 'maxlength', 'placeholder')); _form_set_class($element, array('form-url')); - return '<input' . drupal_attributes($element['#attributes']) . ' />' . drupal_render_children($element); + return '<input' . new Attribute($element['#attributes']) . ' />' . drupal_render_children($element); } /** @@ -4190,7 +4192,7 @@ function theme_search($variables) { element_set_attributes($element, array('id', 'name', 'value', 'size', 'maxlength', 'placeholder')); _form_set_class($element, array('form-search')); - return '<input' . drupal_attributes($element['#attributes']) . ' />' . drupal_render_children($element); + return '<input' . new Attribute($element['#attributes']) . ' />' . drupal_render_children($element); } /** @@ -4245,7 +4247,7 @@ function theme_color($variables) { element_set_attributes($element, array('id', 'name', 'value')); _form_set_class($element, array('form-color')); - return '<input' . drupal_attributes($element['#attributes']) . ' />' . drupal_render_children($element); + return '<input' . new Attribute($element['#attributes']) . ' />' . drupal_render_children($element); } /** @@ -4268,7 +4270,7 @@ function theme_form($variables) { $element['#attributes']['accept-charset'] = "UTF-8"; } // Anonymous DIV to satisfy XHTML compliance. - return '<form' . drupal_attributes($element['#attributes']) . '><div>' . $element['#children'] . '</div></form>'; + return '<form' . new Attribute($element['#attributes']) . '><div>' . $element['#children'] . '</div></form>'; } /** @@ -4296,8 +4298,8 @@ function theme_textarea($variables) { $element['#attributes']['class'][] = 'resize-' . $element['#resizable']; } - $output = '<div' . drupal_attributes($wrapper_attributes) . '>'; - $output .= '<textarea' . drupal_attributes($element['#attributes']) . '>' . check_plain($element['#value']) . '</textarea>'; + $output = '<div' . new Attribute($wrapper_attributes) . '>'; + $output .= '<textarea' . new Attribute($element['#attributes']) . '>' . check_plain($element['#value']) . '</textarea>'; $output .= '</div>'; return $output; } @@ -4319,7 +4321,7 @@ function theme_password($variables) { element_set_attributes($element, array('id', 'name', 'size', 'maxlength', 'placeholder')); _form_set_class($element, array('form-text')); - return '<input' . drupal_attributes($element['#attributes']) . ' />'; + return '<input' . new Attribute($element['#attributes']) . ' />'; } /** @@ -4369,7 +4371,7 @@ function theme_file($variables) { element_set_attributes($element, array('id', 'name', 'size')); _form_set_class($element, array('form-file')); - return '<input' . drupal_attributes($element['#attributes']) . ' />'; + return '<input' . new Attribute($element['#attributes']) . ' />'; } /** @@ -4445,7 +4447,7 @@ function theme_form_element($variables) { if (!empty($element['#attributes']['disabled'])) { $attributes['class'][] = 'form-disabled'; } - $output = '<div' . drupal_attributes($attributes) . '>' . "\n"; + $output = '<div' . new Attribute($attributes) . '>' . "\n"; // If #title is not set, we don't display any label or required marker. if (!isset($element['#title'])) { @@ -4478,7 +4480,7 @@ function theme_form_element($variables) { if (!empty($element['#id'])) { $attributes['id'] = $element['#id'] . '--description'; } - $output .= '<div' . drupal_attributes($attributes) . '>' . $element['#description'] . "</div>\n"; + $output .= '<div' . new Attribute($attributes) . '>' . $element['#description'] . "</div>\n"; } $output .= "</div>\n"; @@ -4502,7 +4504,7 @@ function theme_form_required_marker($variables) { 'class' => 'form-required', 'title' => $t('This field is required.'), ); - return '<abbr' . drupal_attributes($attributes) . '>*</abbr>'; + return '<abbr' . new Attribute($attributes) . '>*</abbr>'; } /** @@ -4558,7 +4560,7 @@ function theme_form_element_label($variables) { } // The leading whitespace helps visually separate fields from inline labels. - return ' <label' . drupal_attributes($attributes) . '>' . $t('!title !required', array('!title' => $title, '!required' => $required)) . "</label>\n"; + return ' <label' . new Attribute($attributes) . '>' . $t('!title !required', array('!title' => $title, '!required' => $required)) . "</label>\n"; } /** diff --git a/core/includes/menu.inc b/core/includes/menu.inc index 420b09273627..8574dbe0180b 100644 --- a/core/includes/menu.inc +++ b/core/includes/menu.inc @@ -5,6 +5,8 @@ * API for the Drupal menu system. */ +use Drupal\Core\Template\Attribute; + /** * @defgroup menu Menu system * @{ @@ -1602,7 +1604,7 @@ function theme_menu_link(array $variables) { $sub_menu = drupal_render($element['#below']); } $output = l($element['#title'], $element['#href'], $element['#localized_options']); - return '<li' . drupal_attributes($element['#attributes']) . '>' . $output . $sub_menu . "</li>\n"; + return '<li' . new Attribute($element['#attributes']) . '>' . $output . $sub_menu . "</li>\n"; } /** diff --git a/core/includes/pager.inc b/core/includes/pager.inc index 40d9c01078fc..75dcf824c9b9 100644 --- a/core/includes/pager.inc +++ b/core/includes/pager.inc @@ -5,6 +5,8 @@ * Functions to aid in presenting database results as a set of pages. */ +use Drupal\Core\Template\Attribute; + /** * Returns the current page being requested for display within a pager. * @@ -476,7 +478,7 @@ function theme_pager_link($variables) { // possible to use l() here. // @see http://drupal.org/node/1410574 $attributes['href'] = url(current_path(), array('query' => $query)); - return '<a' . drupal_attributes($attributes) . '>' . check_plain($text) . '</a>'; + return '<a' . new Attribute($attributes) . '>' . check_plain($text) . '</a>'; } /** diff --git a/core/includes/theme.inc b/core/includes/theme.inc index 30457bff18a0..2d1d375e05c2 100644 --- a/core/includes/theme.inc +++ b/core/includes/theme.inc @@ -9,6 +9,7 @@ */ use Drupal\Core\Utility\ThemeRegistry; +use Drupal\Core\Template\Attribute; /** * @defgroup content_flags Content markers @@ -1503,7 +1504,7 @@ function template_preprocess_datetime(&$variables) { * @see http://www.w3.org/TR/html5-author/the-time-element.html#attr-time-datetime */ function theme_datetime($variables) { - $output = '<time' . drupal_attributes($variables['attributes']) . '>'; + $output = '<time' . new Attribute($variables['attributes']) . '>'; $output .= !empty($variables['html']) ? $variables['text'] : check_plain($variables['text']); $output .= '</time>'; return $output; @@ -1569,7 +1570,7 @@ function theme_status_messages($variables) { * @see l() */ function theme_link($variables) { - return '<a href="' . check_plain(url($variables['path'], $variables['options'])) . '"' . drupal_attributes($variables['options']['attributes']) . '>' . ($variables['options']['html'] ? $variables['text'] : check_plain($variables['text'])) . '</a>'; + return '<a href="' . check_plain(url($variables['path'], $variables['options'])) . '"' . new Attribute($variables['options']['attributes']) . '>' . ($variables['options']['html'] ? $variables['text'] : check_plain($variables['text'])) . '</a>'; } /** @@ -1632,12 +1633,12 @@ function theme_links($variables) { $heading['attributes']['class'] = $heading['class']; } - $output .= '<' . $heading['level'] . drupal_attributes($heading['attributes']) . '>'; + $output .= '<' . $heading['level'] . new Attribute($heading['attributes']) . '>'; $output .= check_plain($heading['text']); $output .= '</' . $heading['level'] . '>'; } - $output .= '<ul' . drupal_attributes($attributes) . '>'; + $output .= '<ul' . new Attribute($attributes) . '>'; $num_links = count($links); $i = 0; @@ -1673,12 +1674,12 @@ function theme_links($variables) { 'html' => FALSE, 'attributes' => array(), ); - $item = '<span' . drupal_attributes($link['attributes']) . '>'; + $item = '<span' . new Attribute($link['attributes']) . '>'; $item .= ($link['html'] ? $link['title'] : check_plain($link['title'])); $item .= '</span>'; } - $output .= '<li' . drupal_attributes(array('class' => $class)) . '>'; + $output .= '<li' . new Attribute(array('class' => $class)) . '>'; $output .= $item; $output .= '</li>'; } @@ -1722,7 +1723,7 @@ function theme_image($variables) { } } - return '<img' . drupal_attributes($attributes) . ' />'; + return '<img' . new Attribute($attributes) . ' />'; } /** @@ -1838,7 +1839,7 @@ function theme_table($variables) { $attributes['class'][] = 'sticky-enabled'; } - $output = '<table' . drupal_attributes($attributes) . ">\n"; + $output = '<table' . new Attribute($attributes) . ">\n"; if (isset($caption)) { $output .= '<caption>' . $caption . "</caption>\n"; @@ -1866,15 +1867,15 @@ function theme_table($variables) { // Build colgroup if (is_array($cols) && count($cols)) { - $output .= ' <colgroup' . drupal_attributes($attributes) . '>'; + $output .= ' <colgroup' . new Attribute($attributes) . '>'; $i = 0; foreach ($cols as $col) { - $output .= ' <col' . drupal_attributes($col) . ' />'; + $output .= ' <col' . new Attribute($col) . ' />'; } $output .= " </colgroup>\n"; } else { - $output .= ' <colgroup' . drupal_attributes($attributes) . " />\n"; + $output .= ' <colgroup' . new Attribute($attributes) . " />\n"; } } } @@ -1940,7 +1941,7 @@ function theme_table($variables) { } // Build row - $output .= ' <tr' . drupal_attributes($attributes) . '>'; + $output .= ' <tr' . new Attribute($attributes) . '>'; $i = 0; foreach ($cells as $cell) { $cell = tablesort_cell($cell, $header, $ts, $i++); @@ -2018,7 +2019,7 @@ function theme_item_list($variables) { $output = ''; if ($items) { - $output .= '<' . $type . drupal_attributes($list_attributes) . '>'; + $output .= '<' . $type . new Attribute($list_attributes) . '>'; $num_items = count($items); $i = 0; @@ -2064,7 +2065,7 @@ function theme_item_list($variables) { $attributes['class'][] = 'last'; } - $output .= '<li' . drupal_attributes($attributes) . '>' . $value . '</li>'; + $output .= '<li' . new Attribute($attributes) . '>' . $value . '</li>'; } $output .= "</$type>"; } @@ -2129,7 +2130,7 @@ function theme_feed_icon($variables) { */ function theme_html_tag($variables) { $element = $variables['element']; - $attributes = isset($element['#attributes']) ? drupal_attributes($element['#attributes']) : ''; + $attributes = isset($element['#attributes']) ? new Attribute($element['#attributes']) : ''; if (!isset($element['#value'])) { return '<' . $element['#tag'] . $attributes . " />\n"; } @@ -2211,7 +2212,7 @@ function theme_meter($variables) { } } - $output = '<div' . drupal_attributes($attributes) . '>'; + $output = '<div' . new Attribute($attributes) . '>'; $output .= ' <div style="width: '. $variables['percentage'] .'%;" class="foreground"></div>'; $output .= "</div>\n"; @@ -2266,7 +2267,7 @@ function _theme_table_cell($cell, $header = FALSE) { $header |= isset($cell['header']); unset($cell['data']); unset($cell['header']); - $attributes = drupal_attributes($cell); + $attributes = new Attribute($cell); } else { $data = $cell; @@ -2322,7 +2323,7 @@ function template_preprocess(&$variables, $hook) { $default_variables = _template_preprocess_default_variables(); } if (!isset($default_attributes)) { - $default_attributes = drupal_attributes(array('class' => array())); + $default_attributes = new Attribute(array('class' => array())); } $variables += $default_variables + array( 'attributes' => clone $default_attributes, @@ -2422,7 +2423,7 @@ function template_preprocess_html(&$variables) { } // Initializes attributes which are specific to the html and body elements. - $variables['html_attributes'] = drupal_attributes(); + $variables['html_attributes'] = new Attribute; // HTML element attributes. $variables['html_attributes']['lang'] = $language_interface->langcode; diff --git a/core/lib/Drupal/Core/Template/Attribute.php b/core/lib/Drupal/Core/Template/Attribute.php index 3004c71a8101..b2196245fa17 100644 --- a/core/lib/Drupal/Core/Template/Attribute.php +++ b/core/lib/Drupal/Core/Template/Attribute.php @@ -31,11 +31,6 @@ * echo '<cat class="cat ' . $attributes['class'] . '" ' . $attributes . '>'; * // Produces <cat class="cat black-cat white-cat black-white-cat" id="socks"> * @endcode - * - * Most of the time this object is not created directly, but - * instantiated by drupal_attributes(). - * - * @see drupal_attributes() */ class Attribute implements ArrayAccess, IteratorAggregate { diff --git a/core/modules/book/book.module b/core/modules/book/book.module index 7e7ca52c4f7a..fd4fac9f2c22 100644 --- a/core/modules/book/book.module +++ b/core/modules/book/book.module @@ -6,6 +6,7 @@ */ use Drupal\node\Node; +use Drupal\Core\Template\Attribute; /** * Implements hook_help(). @@ -1245,7 +1246,7 @@ function template_preprocess_book_export_html(&$variables) { */ function template_process_book_export_html(&$variables) { // Flatten out html_attributes - $variables['html_attributes'] = drupal_attributes($variables['html_attributes']); + $variables['html_attributes'] = new Attribute($variables['html_attributes']); } /** diff --git a/core/modules/field/field.module b/core/modules/field/field.module index 8157971683cc..e75111e86cea 100644 --- a/core/modules/field/field.module +++ b/core/modules/field/field.module @@ -5,6 +5,7 @@ */ use Drupal\entity\EntityFieldQuery; +use Drupal\Core\Template\Attribute; /* * Load all public Field API functions. Drupal currently has no @@ -1107,17 +1108,17 @@ function template_process_field(&$variables, $hook) { static $default_attributes; // The default theme implementation is a function, so template_process() does // not automatically run, so we need to flatten the classes and attributes - // here. For best performance, only call drupal_attributes() when needed, and - // note that template_preprocess_field() does not initialize the - // *_attributes variables. + // here. For best performance, only instantiate Drupal\Core\Template\Attribute + // when needed, and note that template_preprocess_field() does not initialize + // the *_attributes variables. if (!isset($default_attributes)) { - $default_attributes = drupal_attributes(); + $default_attributes = new Attribute; } - $variables['attributes'] = isset($variables['attributes']) ? drupal_attributes($variables['attributes']) : clone $default_attributes; - $variables['title_attributes'] = isset($variables['title_attributes']) ? drupal_attributes($variables['title_attributes']) : clone($default_attributes); - $variables['content_attributes'] = isset($variables['content_attributes']) ? drupal_attributes($variables['content_attributes']) : clone($default_attributes); + $variables['attributes'] = isset($variables['attributes']) ? new Attribute($variables['attributes']) : clone $default_attributes; + $variables['title_attributes'] = isset($variables['title_attributes']) ? new Attribute($variables['title_attributes']) : clone($default_attributes); + $variables['content_attributes'] = isset($variables['content_attributes']) ? new Attribute($variables['content_attributes']) : clone($default_attributes); foreach ($variables['items'] as $delta => $item) { - $variables['item_attributes'][$delta] = isset($variables['item_attributes'][$delta]) ? drupal_attributes($variables['item_attributes'][$delta]) : clone($default_attributes); + $variables['item_attributes'][$delta] = isset($variables['item_attributes'][$delta]) ? new Attribute($variables['item_attributes'][$delta]) : clone($default_attributes); } } diff --git a/core/modules/file/file.module b/core/modules/file/file.module index 3763ea00e8cd..60448639d156 100644 --- a/core/modules/file/file.module +++ b/core/modules/file/file.module @@ -7,6 +7,7 @@ use Drupal\entity\EntityFieldQuery; use Drupal\file\File; +use Drupal\Core\Template\Attribute; use Symfony\Component\HttpFoundation\JsonResponse; // Load all Field module hooks for File. @@ -1352,7 +1353,7 @@ function theme_file_managed_file($variables) { // This wrapper is required to apply JS behaviors and CSS styling. $output = ''; - $output .= '<div' . drupal_attributes($attributes) . '>'; + $output .= '<div' . new Attribute($attributes) . '>'; $output .= drupal_render_children($element); $output .= '</div>'; return $output; diff --git a/core/modules/filter/filter.module b/core/modules/filter/filter.module index 1bafc6a35b49..6c54faebefd0 100644 --- a/core/modules/filter/filter.module +++ b/core/modules/filter/filter.module @@ -4,6 +4,7 @@ * @file * Framework for handling the filtering of content. */ +use Drupal\Core\Template\Attribute; /** * Implements hook_cache_flush(). @@ -1201,7 +1202,7 @@ function theme_filter_guidelines($variables) { $format = $variables['format']; $attributes['class'][] = 'filter-guidelines-item'; $attributes['class'][] = 'filter-guidelines-' . $format->format; - $output = '<div' . drupal_attributes($attributes) . '>'; + $output = '<div' . new Attribute($attributes) . '>'; $output .= '<h3>' . check_plain($format->name) . '</h3>'; $output .= theme('filter_tips', array('tips' => _filter_tips($format->format, FALSE))); $output .= '</div>'; diff --git a/core/modules/node/node.module b/core/modules/node/node.module index 7ebb1dcee508..7d84b9dd1aac 100644 --- a/core/modules/node/node.module +++ b/core/modules/node/node.module @@ -13,6 +13,7 @@ use Drupal\Core\Database\Query\AlterableInterface; use Drupal\Core\Database\Query\SelectExtender; use Drupal\Core\Database\Query\SelectInterface; +use Drupal\Core\Template\Attribute; use Drupal\node\Node; use Drupal\file\File; use Drupal\entity\EntityInterface; @@ -2465,7 +2466,7 @@ function node_feed($nids = FALSE, $channel = array()) { $channel = array_merge($channel_defaults, $channel); $output = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"; - $output .= "<rss version=\"" . $channel["version"] . "\" xml:base=\"" . $base_url . "\" " . drupal_attributes($namespaces) . ">\n"; + $output .= "<rss version=\"" . $channel["version"] . "\" xml:base=\"" . $base_url . "\" " . new Attribute($namespaces) . ">\n"; $output .= format_rss_channel($channel['title'], $channel['link'], $channel['description'], $items, $channel['language'], $channel_extras); $output .= "</rss>\n"; diff --git a/core/modules/rdf/rdf.module b/core/modules/rdf/rdf.module index a61760c1b3ff..fda5d5796d62 100644 --- a/core/modules/rdf/rdf.module +++ b/core/modules/rdf/rdf.module @@ -5,6 +5,8 @@ * Enables semantically enriched output for Drupal sites in the form of RDFa. */ +use Drupal\Core\Template\Attribute; + /** * Implements hook_help(). */ @@ -268,10 +270,10 @@ function rdf_mapping_delete($type, $bundle) { /** * Builds an array of RDFa attributes for a given mapping. * - * This array will typically be passed through drupal_attributes() to create - * the attributes variables that are available to template files. These include - * $attributes, $title_attributes, $content_attributes and the field-specific - * $item_attributes variables. + * This array will typically be passed through Drupal\Core\Template\Attribute + * to create the attributes variables that are available to template files. + * These include $attributes, $title_attributes, $content_attributes and the + * field-specific $item_attributes variables. * * @param $mapping * An array containing a mandatory 'predicates' key and optional 'datatype', @@ -289,7 +291,7 @@ function rdf_mapping_delete($type, $bundle) { * function. * * @return - * RDFa attributes suitable for drupal_attributes(). + * RDFa attributes suitable for Drupal\Core\Template\Attribute. * * @see theme_rdf_template_variable_wrapper() */ @@ -815,7 +817,7 @@ function rdf_preprocess_image(&$variables) { * an extra wrapper element, you can override this function to not wrap that * variable and instead print the following inside your template file: * @code - * drupal_attributes($rdf_template_variable_attributes[$variable_name]) + * new Drupal\Core\Template\Attribute($rdf_template_variable_attributes[$variable_name]) * @endcode * * @param $variables @@ -853,7 +855,7 @@ function rdf_preprocess_image(&$variables) { function theme_rdf_template_variable_wrapper($variables) { $output = $variables['content']; if (!empty($output) && !empty($variables['attributes'])) { - $attributes = drupal_attributes($variables['attributes']); + $attributes = new Attribute($variables['attributes']); $output = $variables['inline'] ? "<span$attributes>$output</span>" : "<div$attributes>$output</div>"; } return $output; @@ -889,7 +891,7 @@ function theme_rdf_metadata($variables) { // be used, but for maximum browser compatibility, W3C recommends the // former when serving pages using the text/html media type, see // http://www.w3.org/TR/xhtml1/#C_3. - $output .= '<span' . drupal_attributes($attributes) . '></span>'; + $output .= '<span' . new Attribute($attributes) . '></span>'; } return $output; } diff --git a/core/modules/system/lib/Drupal/system/Tests/Common/AttributesUnitTest.php b/core/modules/system/lib/Drupal/system/Tests/Common/AttributesUnitTest.php index 30316252ace4..22ae4edeb16a 100644 --- a/core/modules/system/lib/Drupal/system/Tests/Common/AttributesUnitTest.php +++ b/core/modules/system/lib/Drupal/system/Tests/Common/AttributesUnitTest.php @@ -7,16 +7,17 @@ namespace Drupal\system\Tests\Common; +use Drupal\Core\Template\Attribute; use Drupal\simpletest\UnitTestBase; /** - * Tests the drupal_attributes() functionality. + * Tests the Drupal\Core\Template\Attribute functionality. */ class AttributesUnitTest extends UnitTestBase { public static function getInfo() { return array( 'name' => 'HTML Attributes', - 'description' => 'Tests the drupal_attributes() functionality.', + 'description' => 'Tests the Drupal\Core\Template\Attribute functionality.', 'group' => 'Common', ); } @@ -26,15 +27,15 @@ public static function getInfo() { */ function testDrupalAttributes() { // Verify that special characters are HTML encoded. - $this->assertIdentical((string) drupal_attributes(array('title' => '&"\'<>')), ' title="&"'<>"', t('HTML encode attribute values.')); + $this->assertIdentical((string) new Attribute(array('title' => '&"\'<>')), ' title="&"'<>"', t('HTML encode attribute values.')); // Verify multi-value attributes are concatenated with spaces. $attributes = array('class' => array('first', 'last')); - $this->assertIdentical((string) drupal_attributes(array('class' => array('first', 'last'))), ' class="first last"', t('Concatenate multi-value attributes.')); + $this->assertIdentical((string) new Attribute(array('class' => array('first', 'last'))), ' class="first last"', t('Concatenate multi-value attributes.')); // Verify empty attribute values are rendered. - $this->assertIdentical((string) drupal_attributes(array('alt' => '')), ' alt=""', t('Empty attribute value #1.')); - $this->assertIdentical((string) drupal_attributes(array('alt' => NULL)), ' alt=""', t('Empty attribute value #2.')); + $this->assertIdentical((string) new Attribute(array('alt' => '')), ' alt=""', t('Empty attribute value #1.')); + $this->assertIdentical((string) new Attribute(array('alt' => NULL)), ' alt=""', t('Empty attribute value #2.')); // Verify multiple attributes are rendered. $attributes = array( @@ -42,9 +43,9 @@ function testDrupalAttributes() { 'class' => array('first', 'last'), 'alt' => 'Alternate', ); - $this->assertIdentical((string) drupal_attributes($attributes), ' id="id-test" class="first last" alt="Alternate"', t('Multiple attributes.')); + $this->assertIdentical((string) new Attribute($attributes), ' id="id-test" class="first last" alt="Alternate"', t('Multiple attributes.')); // Verify empty attributes array is rendered. - $this->assertIdentical((string) drupal_attributes(array()), '', t('Empty attributes array.')); + $this->assertIdentical((string) new Attribute(array()), '', t('Empty attributes array.')); } } diff --git a/core/modules/user/user.module b/core/modules/user/user.module index a526b20c3470..9dd47da3c531 100644 --- a/core/modules/user/user.module +++ b/core/modules/user/user.module @@ -3,6 +3,7 @@ use Drupal\Core\Database\Query\SelectInterface; use Drupal\entity\EntityInterface; use Drupal\file\File; +use Drupal\Core\Template\Attribute; use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; /** @@ -1059,8 +1060,8 @@ function template_process_username(&$variables) { * other desired page to link to for more information about the user. * - link_options: An array of options to pass to the l() function's $options * parameter if linking the user's name to the user's page. - * - attributes: An array of attributes to pass to the - * drupal_attributes() function if not linking to the user's page. + * - attributes: An array of attributes to instantiate the + * Drupal\Core\Template\Attribute class if not linking to the user's page. * * @see template_preprocess_username() * @see template_process_username() @@ -1076,7 +1077,7 @@ function theme_username($variables) { // Modules may have added important attributes so they must be included // in the output. Additional classes may be added as array elements like // $variables['attributes']['class'][] = 'myclass'; - $output = '<span' . drupal_attributes($variables['attributes']) . '>' . $variables['name'] . $variables['extra'] . '</span>'; + $output = '<span' . new Attribute($variables['attributes']) . '>' . $variables['name'] . $variables['extra'] . '</span>'; } return $output; } -- GitLab