diff --git a/core/includes/form.inc b/core/includes/form.inc index 8aee8f0..9e8551c 100644 --- a/core/includes/form.inc +++ b/core/includes/form.inc @@ -2692,7 +2692,7 @@ function _form_options_flatten($array) { } /** - * Processes a select list form element. + * Processes a select list element. * * This process callback is mandatory for select fields, since all user agents * automatically preselect the first available option of single (non-multiple) @@ -2760,26 +2760,27 @@ function form_process_select($element) { } /** - * Returns HTML for a select form element. + * Prepares variables for select element templates. + * + * Default template: select.html.twig. * * It is possible to group options together; to do this, change the format of * $options to an associative array in which the keys are group labels, and the * values are associative arrays in the normal $options format. * - * @param $variables + * @param array $variables * An associative array containing: * - element: An associative array containing the properties of the element. * Properties used: #title, #value, #options, #description, #extra, * #multiple, #required, #name, #attributes, #size. - * - * @ingroup themeable */ -function theme_select($variables) { +function template_preprocess_select(&$variables) { $element = $variables['element']; element_set_attributes($element, array('id', 'name', 'size')); _form_set_attributes($element, array('form-select')); - return '' . form_select_options($element) . ''; + $variables['options'] = form_select_options($element); + $variables['attributes'] = $element['#attributes']; } /** @@ -2881,94 +2882,79 @@ function form_get_options($element, $key) { } /** - * Returns HTML for a fieldset form element and its children. + * Prepares variables for fieldset element templates. * - * @param $variables + * Default template: fieldset.html.twig. + * + * @param array $variables * An associative array containing: * - element: An associative array containing the properties of the element. * Properties used: #attributes, #children, #collapsed, #description, #id, * #title, #value. - * - * @ingroup themeable */ -function theme_fieldset($variables) { +function template_preprocess_fieldset(&$variables) { $element = $variables['element']; element_set_attributes($element, array('id')); _form_set_attributes($element, array('form-wrapper')); - if (!empty($element['#description'])) { - $description_id = $element['#attributes']['id'] . '--description'; - $element['#attributes']['aria-describedby'] = $description_id; - } - - $legend_attributes = array(); - if (isset($element['#title_display']) && $element['#title_display'] == 'invisible') { - $legend_attributes['class'][] = 'visually-hidden'; - } + $variables['attributes'] = $element['#attributes']; - $output = ''; if (!empty($element['#title'])) { - // Always wrap fieldset legends in a SPAN for CSS positioning. - $output .= '' . $element['#title'] . ''; + $variables['title'] = $element['#title']; + if (isset($element['#title_display']) && $element['#title_display'] == 'invisible') { + $variables['title_attributes']['class'] = array('visually-hidden'); + } } - $output .= '
'; - if (!empty($element['#description'])) { - $attributes = array('class' => 'fieldset-description', 'id' => $description_id); - $output .= '' . $element['#description'] . '
'; + if (!empty($element['#description'])) { + $variables['description'] = $element['#description']; + $description_id = $element['#attributes']['id'] . '--description'; + $variables['description_attributes'] = new Attribute(array( + 'id' => $description_id, + 'class' => array('fieldset-description'), + 'aria-describedby' => $description_id, + )); } - $output .= $element['#children']; - if (isset($element['#value'])) { - $output .= $element['#value']; - } - $output .= ''; - $output .= "\n"; - return $output; + + $variables['children'] = $element['#children']; + $variables['value'] = (isset($element['#value'])) ? $element['#value'] : NULL; } /** - * Returns HTML for a details form element and its children. + * Prepares variables for details element templates. * - * @param $variables + * Default template: details.html.twig. + * + * @param array $variables * An associative array containing: * - element: An associative array containing the properties of the element. - * Properties used: #attributes, #children, #collapsed, #description, #id, - * #title, #value. + * Properties used: #attributes, #children, #collapsed, #collapsible, + * #description, #id, #title, #value. * * @ingroup themeable */ -function theme_details($variables) { +function template_preprocess_details(&$variables) { $element = $variables['element']; - element_set_attributes($element, array('id')); - _form_set_attributes($element, array('form-wrapper')); - $output = ''; + $variables['attributes'] = $element['#attributes']; + $variables['summary_attributes'] = new Attribute(array()); if (!empty($element['#title'])) { - $summary_attributes = new Attribute(array( - 'role' => 'button', - )); + $variables['summary_attributes']['role'] = 'button'; if (!empty($element['#attributes']['id'])) { - $summary_attributes['aria-controls'] = $element['#attributes']['id']; + $variables['summary_attributes']['aria-controls'] = $element['#attributes']['id']; } - $summary_attributes['aria-expanded'] = empty($element['#attributes']['open']) ? FALSE : TRUE; - $summary_attributes['aria-pressed'] = $summary_attributes['aria-expanded']; - $output .= '' . $element['#title'] . ''; - } - $output .= '
'; - if (!empty($element['#description'])) { - $output .= '
' . $element['#description'] . '
'; - } - $output .= $element['#children']; - if (isset($element['#value'])) { - $output .= $element['#value']; + $variables['summary_attributes']['aria-expanded'] = empty($element['#attributes']['open']) ? FALSE : TRUE; + $variables['summary_attributes']['aria-pressed'] = $variables['summary_attributes']['aria-expanded']; } - $output .= '
'; - $output .= "\n"; - return $output; + + $variables['title'] = (!empty($element['#title'])) ? $element['#title'] : ''; + $variables['description'] = (!empty($element['#description'])) ? $element['#description'] : ''; + $variables['children'] = (isset($element['#children'])) ? $element['#children'] : ''; + $variables['value'] = (isset($element['#value'])) ? $element['#value'] : ''; } /** - * Prepares a #type 'radio' render element for theme_input(). + * Adds form-specific attributes to a 'radio' #type element. * * @param array $element * An associative array containing the properties of the element. @@ -2980,7 +2966,7 @@ function theme_details($variables) { * all the attributes. * * @return array - * The $element with prepared variables ready for theme_input(). + * The $element with variables prepared for #theme 'input__radio'. */ function form_pre_render_radio($element) { $element['#attributes']['type'] = 'radio'; @@ -2995,34 +2981,34 @@ function form_pre_render_radio($element) { } /** - * Returns HTML for a set of radio button form elements. + * Prepares variables for radios templates. * - * @param $variables + * Default template: radios.html.twig. + * + * @param array $variables * An associative array containing: * - element: An associative array containing the properties of the element. - * Properties used: #title, #value, #options, #description, #required, - * #attributes, #children. - * - * @ingroup themeable + * Properties used: #attributes, #id, #children. */ -function theme_radios($variables) { +function template_preprocess_radios(&$variables) { $element = $variables['element']; - $attributes = array(); if (isset($element['#id'])) { - $attributes['id'] = $element['#id']; - } - $attributes['class'] = 'form-radios'; - if (!empty($element['#attributes']['class'])) { - $attributes['class'] .= ' ' . implode(' ', $element['#attributes']['class']); + $variables['attributes']['id'] = $element['#id']; } + $variables['attributes']['class'] = (!empty($element['#attributes']['class'])) ? $element['#attributes']['class'] : array(); + $variables['attributes']['class'][] = 'form-radios'; if (isset($element['#attributes']['title'])) { - $attributes['title'] = $element['#attributes']['title']; + $variables['attributes']['title'] = $element['#attributes']['title']; } - return '' . (!empty($element['#children']) ? $element['#children'] : '') . ''; + + $variables['children'] = !empty($element['#children']) ? $element['#children'] : ''; + + // Remove the disabled attribute on the wrapper. + unset($variables['attributes']['disabled']); } /** - * Expand a password_confirm field into two text boxes. + * Expands a password_confirm field into two text boxes. */ function form_process_password_confirm($element) { $element['pass1'] = array( @@ -3075,29 +3061,30 @@ function password_confirm_validate($element, &$element_state) { } /** - * Returns HTML for an #date form element. + * Adds form-specific attributes to a 'date' #type element. * * Supports HTML5 types of 'date', 'datetime', 'datetime-local', and 'time'. * Falls back to a plain textfield. Used as a sub-element by the datetime * element type. * - * @param array $variables - * An associative array containing: - * - element: An associative array containing the properties of the element. - * Properties used: #title, #value, #options, #description, #required, - * #attributes, #id, #name, #type, #min, #max, #step, #value, #size. + * @param array $element + * An associative array containing the properties of the element. + * Properties used: #title, #value, #options, #description, #required, + * #attributes, #id, #name, #type, #min, #max, #step, #value, #size. * - * @ingroup themeable + * Note: The input "name" attribute needs to be sanitized before output, which + * is currently done by initializing Drupal\Core\Template\Attribute with + * all the attributes. + * + * @return array + * The $element with prepared variables ready for #theme 'input__date'. */ -function theme_date($variables) { - $element = $variables['element']; - if (empty($element['attribute']['type'])) { - $element['attribute']['type'] = 'date'; - } - element_set_attributes($element, array('id', 'name', 'type', 'min', 'max', 'step', 'value', 'size')); - _form_set_attributes($element, array('form-' . $element['attribute']['type'])); +function form_pre_render_date($element) { + $element['#attributes']['type'] = 'date'; + element_set_attributes($element, array('id', 'name', 'min', 'max', 'step', 'value', 'size')); + _form_set_attributes($element, array('form-date')); - return ''; + return $element; } /** @@ -3113,7 +3100,7 @@ function weight_value(&$form) { } /** - * Expands a radios element into individual radio elements. + * Expands a #type 'radios' element into individual radio elements. */ function form_process_radios($element) { if (count($element['#options']) > 0) { @@ -3149,7 +3136,7 @@ function form_process_radios($element) { } /** - * Prepares a #type 'checkbox' render element for theme_input(). + * Adds form-specific attributes to a 'checkbox' #type element. * * @param array $element * An associative array containing the properties of the element. @@ -3157,7 +3144,7 @@ function form_process_radios($element) { * #attributes, #checked. * * @return array - * The $element with prepared variables ready for theme_input(). + * The $element with variables prepared for #theme 'input__checkbox'. */ function form_pre_render_checkbox($element) { $element['#attributes']['type'] = 'checkbox'; @@ -3173,33 +3160,44 @@ function form_pre_render_checkbox($element) { } /** - * Returns HTML for a set of checkbox form elements. + * Prepares variables for checkboxes templates. * - * @param $variables + * Default template: checkboxes.html.twig. + * + * @param array $variables * An associative array containing: * - element: An associative array containing the properties of the element. * Properties used: #children, #attributes. - * - * @ingroup themeable */ -function theme_checkboxes($variables) { +function template_preprocess_checkboxes(&$variables) { $element = $variables['element']; - $attributes = array(); + if (isset($element['#id'])) { - $attributes['id'] = $element['#id']; + $variables['attributes']['id'] = $element['#id']; } - $attributes['class'][] = 'form-checkboxes'; + $variables['attributes']['class'] = array(); + $variables['attributes']['class'][] = 'form-checkboxes'; if (!empty($element['#attributes']['class'])) { - $attributes['class'] = array_merge($attributes['class'], $element['#attributes']['class']); + if (is_array($element['#attributes']['class'])) { + foreach ($element['#attributes']['class'] as $class) { + $variables['attributes']['class'][] = $class; + } + } + else { + $variables['attributes']['class'][] = $element['#attributes']['class']; + } } if (isset($element['#attributes']['title'])) { - $attributes['title'] = $element['#attributes']['title']; + $variables['attributes']['title'] = $element['#attributes']['title']; } - return '' . (!empty($element['#children']) ? $element['#children'] : '') . ''; + $variables['children'] = (!empty($element['#children'])) ? $element['#children'] : ''; + + // Remove the disabled attribute on the wrapper. + unset($variables['attributes']['disabled']); } /** - * Adds form element theming to an element if its title or description is set. + * Adds form element themeing to an element if its title or description is set. * * This is used as a pre render function for checkboxes and radios. */ @@ -3432,7 +3430,9 @@ function form_process_container($element, &$form_state) { } /** - * Returns HTML for a table with radio buttons or checkboxes. + * Prepares a 'tableselect' #type element for rendering. + * + * Adds a column of radio buttons or checkboxes for each row of a table. * * @param $variables * An associative array containing: @@ -3470,11 +3470,8 @@ function form_process_container($element, &$form_state) { * '#empty' => t('No content available.'), * ); * @endcode - * - * @ingroup themeable */ -function theme_tableselect($variables) { - $element = $variables['element']; +function form_pre_render_tableselect(array $element) { $rows = array(); $header = $element['#header']; if (!empty($element['#options'])) { @@ -3514,7 +3511,7 @@ function theme_tableselect($variables) { // checkboxes/radios in the first table column. if ($element['#js_select']) { // Add a "Select all" checkbox. - drupal_add_library('system', 'drupal.tableselect'); + $element['#attached']['library'][] = array('system', 'drupal.tableselect'); array_unshift($header, array('class' => array('select-all'))); } else { @@ -3523,7 +3520,10 @@ function theme_tableselect($variables) { array_unshift($header, ''); } } - return theme('table', array('header' => $header, 'rows' => $rows, 'empty' => $element['#empty'], 'attributes' => $element['#attributes'])); + $element['#header'] = $header; + $element['#rows'] = $rows; + + return $element; } /** @@ -3908,7 +3908,7 @@ function form_process_group(&$element, &$form_state) { } /** - * Adds form element theming to details. + * Adds form-specific attributes to a 'details' #type element. * * @param $element * An associative array containing the properties and children of the @@ -3918,11 +3918,13 @@ function form_process_group(&$element, &$form_state) { * The modified element. */ function form_pre_render_details($element) { - // The .form-wrapper class is required for #states to treat details like - // containers. + element_set_attributes($element, array('id')); if (!isset($element['#attributes']['class'])) { $element['#attributes']['class'] = array(); } + // The .form-wrapper class is required for #states to treat details like + // containers. + _form_set_attributes($element, array('form-wrapper')); // Collapsible details. $element['#attached']['library'][] = array('system', 'drupal.collapse'); @@ -4056,18 +4058,20 @@ function form_pre_render_vertical_tabs($element) { } /** - * Returns HTML for an element's children details as vertical tabs. + * Preapres an element's children details for vertical tabs templates. * - * @param $variables + * Default template: vertical-tabs.html.twig. + * + * @param array $variables * An associative array containing: * - element: An associative array containing the properties and children of * the details element. Properties used: #children. - * - * @ingroup themeable */ -function theme_vertical_tabs($variables) { - $element = $variables['element']; - return '
' . $element['#children'] . '
'; +function template_preprocess_vertical_tabs(&$variables) { + $variables['attributes'] = array( + 'class' => 'vertical-tabs-panes', + ); + $variables['children'] = $variables['element']['#children']; } /** @@ -4135,37 +4139,20 @@ function form_process_autocomplete($element, &$form_state) { } /** - * Preprocesses variables for theme_input(). - * - * @param array $variables - * An associative array containing: - * - element: An associative array containing the properties of the element. + * Prepares variables for input templates. * - * @ingroup themeable - */ -function template_preprocess_input(&$variables) { - $element = $variables['element']; - $variables['attributes'] = new Attribute($element['#attributes']); -} - -/** - * Returns HTML for an input form element. + * Default template: input.html.twig. * * @param array $variables * An associative array containing: * - element: An associative array containing the properties of the element. - * Properties used: #attributes. - * - * @ingroup themeable */ -function theme_input($variables) { - $element = $variables['element']; - $attributes = $variables['attributes']; - return '' . drupal_render_children($element); +function template_preprocess_input(&$variables) { + $variables['attributes'] = $variables['element']['#attributes']; } /** - * Prepares a #type 'button' render element for theme_input(). + * Adds form-specific attributes to a 'button' #type element. * * @param array $element * An associative array containing the properties of the element. @@ -4175,7 +4162,7 @@ function theme_input($variables) { * styles the following button_types appropriately: 'primary', 'danger'. * * @return array - * The $element with prepared variables ready for theme_input(). + * The $element with variables prepared for #theme 'input__button'. */ function form_pre_render_button($element) { $element['#attributes']['type'] = 'submit'; @@ -4196,7 +4183,7 @@ function form_pre_render_button($element) { } /** - * Prepares a #type 'image_button' render element for theme_input(). + * Adds form-specific attributes to an 'image_button' #type element. * * @param array $element * An associative array containing the properties of the element. @@ -4206,7 +4193,7 @@ function form_pre_render_button($element) { * styles the following button_types appropriately: 'primary', 'danger'. * * @return array - * The $element with prepared variables ready for theme_input(). + * The $element with variables prepared for #theme 'input__image_button'. */ function form_pre_render_image_button($element) { $element['#attributes']['type'] = 'image'; @@ -4233,14 +4220,14 @@ function form_pre_render_image_button($element) { } /** - * Prepares a #type 'hidden' render element for theme_input(). + * Adds form-specific attributes to a 'hidden' #type element. * * @param array $element * An associative array containing the properties of the element. * Properties used: #name, #value, #attributes. * * @return array - * The $element with prepared variables ready for theme_input(). + * The $element with variables prepared for #theme 'input__hidden'. */ function form_pre_render_hidden($element) { $element['#attributes']['type'] = 'hidden'; @@ -4250,7 +4237,7 @@ function form_pre_render_hidden($element) { } /** - * Prepares a #type 'textfield' render element for theme_input(). + * Adds form-specific attributes to a 'textfield' #type element. * * @param array $element * An associative array containing the properties of the element. @@ -4258,7 +4245,7 @@ function form_pre_render_hidden($element) { * #placeholder, #required, #attributes. * * @return array - * The $element with prepared variables ready for theme_input(). + * The $element with variables prepared for #theme 'input__textfield'. */ function form_pre_render_textfield($element) { $element['#attributes']['type'] = 'text'; @@ -4269,7 +4256,7 @@ function form_pre_render_textfield($element) { } /** - * Prepares a #type 'email' render element for theme_input(). + * Adds form-specific attributes to an 'email' #type element. * * @param array $element * An associative array containing the properties of the element. @@ -4277,7 +4264,7 @@ function form_pre_render_textfield($element) { * #placeholder, #required, #attributes. * * @return array - * The $element with prepared variables ready for theme_input(). + * The $element with variables prepared for #theme 'input__email'. */ function form_pre_render_email($element) { $element['#attributes']['type'] = 'email'; @@ -4302,7 +4289,7 @@ function form_validate_email(&$element, &$form_state) { } /** - * Prepares a #type 'tel' render element for theme_input(). + * Adds form-specific attributes to a 'tel' #type element. * * @param array $element * An associative array containing the properties of the element. @@ -4310,7 +4297,7 @@ function form_validate_email(&$element, &$form_state) { * #placeholder, #required, #attributes. * * @return array - * The $element with prepared variables ready for theme_input(). + * The $element with variables prepared for #theme 'input__tel'. */ function form_pre_render_tel($element) { $element['#attributes']['type'] = 'tel'; @@ -4321,7 +4308,7 @@ function form_pre_render_tel($element) { } /** - * Prepares a #type 'number' render element for theme_input(). + * Adds form-specific attributes to a 'number' #type element. * * @param array $element * An associative array containing the properties of the element. @@ -4329,7 +4316,7 @@ function form_pre_render_tel($element) { * #required, #attributes, #step, #size. * * @return array - * The $element with prepared variables ready for theme_input(). + * The $element with variables prepared for #theme 'input__number'. */ function form_pre_render_number($element) { $element['#attributes']['type'] = 'number'; @@ -4340,7 +4327,7 @@ function form_pre_render_number($element) { } /** - * Prepares a #type 'range' render element for theme_input(). + * Adds form-specific attributes to a 'range' #type element. * * @param array $element * An associative array containing the properties of the element. @@ -4348,7 +4335,7 @@ function form_pre_render_number($element) { * #step. * * @return array - * The $element with prepared variables ready for theme_input(). + * The $element with variables prepared for #theme 'input__range'. */ function form_pre_render_range($element) { $element['#attributes']['type'] = 'range'; @@ -4429,7 +4416,7 @@ function form_type_range_value($element, $input = FALSE) { } /** - * Prepares a #type 'url' render element for theme_input(). + * Adds form-specific attributes to a 'url' #type element. * * @param array $element * An associative array containing the properties of the element. @@ -4437,7 +4424,7 @@ function form_type_range_value($element, $input = FALSE) { * #placeholder, #required, #attributes. * * @return array - * The $element with prepared variables ready for theme_input(). + * The $element with variables prepared for #theme 'input__url'. */ function form_pre_render_url($element) { $element['#attributes']['type'] = 'url'; @@ -4448,7 +4435,7 @@ function form_pre_render_url($element) { } /** - * Prepares a #type 'search' render element for theme_input(). + * Adds form-specific attributes to a 'search' #type element. * * @param array $element * An associative array containing the properties of the element. @@ -4456,7 +4443,7 @@ function form_pre_render_url($element) { * #placeholder, #required, #attributes. * * @return array - * The $element with prepared variables ready for theme_input(). + * The $element with variables prepared for #theme 'input__search'. */ function form_pre_render_search($element) { $element['#attributes']['type'] = 'search'; @@ -4503,14 +4490,14 @@ function form_validate_color(&$element, &$form_state) { } /** - * Prepares a #type 'color' render element for theme_input(). + * Adds form-specific attriutes to a 'color' #type element. * * @param array $element * An associative array containing the properties of the element. * Properties used: #title, #value, #description, #attributes. * * @return array - * The $element with prepared variables ready for theme_input(). + * The $element with variables prepared for #theme 'input__color'. */ function form_pre_render_color($element) { $element['#attributes']['type'] = 'color'; @@ -4521,61 +4508,61 @@ function form_pre_render_color($element) { } /** - * Returns HTML for a form. + * Prepares variables for form templates. * - * @param $variables + * Default template: form.html.twig. + * + * @param array $variables * An associative array containing: * - element: An associative array containing the properties of the element. * Properties used: #action, #method, #attributes, #children * * @ingroup themeable */ -function theme_form($variables) { +function template_preprocess_form(&$variables) { $element = $variables['element']; + element_set_attributes($element, array('method', 'id')); if (isset($element['#action'])) { $element['#attributes']['action'] = drupal_strip_dangerous_protocols($element['#action']); } - element_set_attributes($element, array('method', 'id')); if (empty($element['#attributes']['accept-charset'])) { $element['#attributes']['accept-charset'] = "UTF-8"; } - // Anonymous DIV to satisfy XHTML compliance. - return '
' . $element['#children'] . '
'; + $variables['attributes'] = $element['#attributes']; + $variables['children'] = $element['#children']; } /** - * Returns HTML for a textarea form element. + * Prepares variables for textarea form element templates. * - * @param $variables + * Default template: textarea.html.twig. + * + * @param array $variables * An associative array containing: * - element: An associative array containing the properties of the element. * Properties used: #title, #value, #description, #rows, #cols, * #placeholder, #required, #attributes, #resizable - * - * @ingroup themeable */ -function theme_textarea($variables) { +function template_preprocess_textarea(&$variables) { $element = $variables['element']; element_set_attributes($element, array('id', 'name', 'rows', 'cols', 'placeholder')); _form_set_attributes($element, array('form-textarea')); - $wrapper_attributes = array( + $variables['wrapper_attributes'] = new Attribute(array( 'class' => array('form-textarea-wrapper'), - ); + )); // Add resizable behavior. if (!empty($element['#resizable'])) { $element['#attributes']['class'][] = 'resize-' . $element['#resizable']; } - $output = ''; - $output .= '' . check_plain($element['#value']) . ''; - $output .= ''; - return $output; + $variables['attributes'] = $element['#attributes']; + $variables['value'] = check_plain($element['#value']); } /** - * Prepares a #type 'password' render element for theme_input(). + * Adds form-specific attributes to a 'password' #type element. * * @param array $element * An associative array containing the properties of the element. @@ -4583,7 +4570,7 @@ function theme_textarea($variables) { * #placeholder, #required, #attributes. * * @return array - * The $element with prepared variables ready for theme_input(). + * The $element with variables prepared for #theme 'input__password'. */ function form_pre_render_password($element) { $element['#attributes']['type'] = 'password'; @@ -4621,7 +4608,7 @@ function form_process_weight($element) { } /** - * Prepares a #type 'file' render element for theme_input(). + * Adds form-specific attributes to a 'file' #type element. * * For assistance with handling the uploaded file correctly, see the API * provided by file.inc. @@ -4632,7 +4619,7 @@ function form_process_weight($element) { * #attributes. * * @return array - * The $element with prepared variables ready for theme_input(). + * The $element with variables prepared for #theme 'input__file'. */ function form_pre_render_file($element) { $element['#attributes']['type'] = 'file'; @@ -4691,105 +4678,80 @@ function form_process_file($element) { * but the parent element should have neither. Use this carefully because a * field without an associated label can cause accessibility challenges. * - * @param $variables + * @param array $variables * An associative array containing: * - element: An associative array containing the properties of the element. * Properties used: #title, #title_display, #description, #id, #required, * #children, #type, #name. - * - * @ingroup themeable */ -function theme_form_element($variables) { - $element = &$variables['element']; +function template_preprocess_form_element(&$variables) { + $element = $variables['element']; // This function is invoked as theme wrapper, but the rendered form element // may not necessarily have been processed by form_builder(). $element += array( '#title_display' => 'before', ); - + // If #title is not set, we don't display any label or required marker. + if (!isset($element['#title'])) { + $element['#title_display'] = 'none'; + } + // We call it a label, though. + $variables['label_display'] = $element['#title_display']; + // Label returns empty string in some cases. + $variables['label'] = array('#theme' => 'form_element_label', '#element' => $element); // Take over any #wrapper_attributes defined by the element. // @todo Temporary hack for #type 'item'. // @see http://drupal.org/node/1829202 - if (isset($element['#wrapper_attributes'])) { - $attributes = $element['#wrapper_attributes']; - } - // Add element #id for #type 'item'. - if (isset($element['#markup']) && !empty($element['#id'])) { - $attributes['id'] = $element['#id']; - } + $variables['attributes'] = (isset($element['#wrapper_attributes']) ? $element['#wrapper_attributes'] : array('class' => array())); // Add element's #type and #name as class to aid with JS/CSS selectors. - $attributes['class'][] = 'form-item'; + $variables['attributes']['class'][] = 'form-item'; if (!empty($element['#type'])) { - $attributes['class'][] = 'form-type-' . strtr($element['#type'], '_', '-'); + $variables['attributes']['class'][] = 'form-type-' . strtr($element['#type'], '_', '-'); } if (!empty($element['#name'])) { - $attributes['class'][] = 'form-item-' . strtr($element['#name'], array(' ' => '-', '_' => '-', '[' => '-', ']' => '')); + $variables['attributes']['class'][] = 'form-item-' . strtr($element['#name'], array(' ' => '-', '_' => '-', '[' => '-', ']' => '')); } // Add a class for disabled elements to facilitate cross-browser styling. if (!empty($element['#attributes']['disabled'])) { - $attributes['class'][] = 'form-disabled'; + $variables['attributes']['class'][] = 'form-disabled'; } - $output = '' . "\n"; - - // If #title is not set, we don't display any label or required marker. - if (!isset($element['#title'])) { - $element['#title_display'] = 'none'; - } - $prefix = isset($element['#field_prefix']) ? '' . $element['#field_prefix'] . ' ' : ''; - $suffix = isset($element['#field_suffix']) ? ' ' . $element['#field_suffix'] . '' : ''; - - switch ($element['#title_display']) { - case 'before': - case 'invisible': - $output .= ' ' . theme('form_element_label', $variables); - $output .= ' ' . $prefix . $element['#children'] . $suffix . "\n"; - break; - - case 'after': - $output .= ' ' . $prefix . $element['#children'] . $suffix; - $output .= ' ' . theme('form_element_label', $variables) . "\n"; - break; - - case 'none': - case 'attribute': - // Output no label and no required marker, only the children. - $output .= ' ' . $prefix . $element['#children'] . $suffix . "\n"; - break; - } - - if (!empty($element['#description'])) { - $attributes = array('class' => 'description'); + // Add element #id for #type 'item'. + if (isset($element['#markup']) && !empty($element['#id'])) { + $variables['attributes']['id'] = $element['#id']; + } + $variables['prefix'] = isset($element['#field_prefix']) ? $element['#field_prefix'] : ''; + $variables['suffix'] = isset($element['#field_suffix']) ? $element['#field_suffix'] : ''; + $variables['children'] = isset($element['#children']) ? $element['#children'] : NULL; + $variables['description'] = !empty($element['#description']) ? $element['#description'] : ''; + if ($variables['description']) { + $variables['description_attributes'] = new Attribute(array('class' => 'description')); if (!empty($element['#id'])) { - $attributes['id'] = $element['#id'] . '--description'; + $variables['description_attributes']['id'] = $element['#id'] . '--description'; } - $output .= '' . $element['#description'] . "\n"; } - - $output .= "\n"; - - return $output; } /** - * Returns HTML for a marker for required form elements. + * Prepares variables for form element required marker templates. * - * @param $variables + * Default template: form-element-required.html.twig. + * + * @param array $variables * An associative array containing: * - element: An associative array containing the properties of the element. - * - * @ingroup themeable */ -function theme_form_required_marker($variables) { - $attributes = array( +function template_preprocess_form_required_marker(&$variables) { + $variables['attributes'] = array( 'class' => 'form-required', 'title' => t('This field is required.'), ); - return '*'; } /** - * Returns HTML for a form element label and required marker. + * Prepares variables for form element label templates. + * + * Default template: form-element-label.html.twig. * * Form element labels include the #title and a #required marker. The label is * associated with the element itself by the element #id. Labels may appear @@ -4801,44 +4763,72 @@ function theme_form_required_marker($variables) { * this function will output no label (''). For required elements that have an * empty #title, this will output the required marker alone within the label. * The label will use the #id to associate the marker with the field that is - * required. That is especially important for screenreader users to know - * which field is required. + * required. That is especially important for screenreader users to know which + * field is required. * - * @param $variables + * @param array $variables * An associative array containing: * - element: An associative array containing the properties of the element. * Properties used: #required, #title, #id, #value, #description. - * - * @ingroup themeable */ -function theme_form_element_label($variables) { - $element = $variables['element']; - - // If title and required marker are both empty, output no label. - if ((!isset($element['#title']) || $element['#title'] === '') && empty($element['#required'])) { - return ''; - } +function template_preprocess_form_element_label(&$variables) { + // @todo: Figure out how to do this differently (calling from form_element). + $element = $variables['element']['#element']; - // If the element is required, a required marker is appended to the label. - $required = !empty($element['#required']) ? theme('form_required_marker', array('element' => $element)) : ''; - - $title = filter_xss_admin($element['#title']); - - $attributes = array(); - // Style the label as class option to display inline with the element. - if ($element['#title_display'] == 'after') { - $attributes['class'] = 'option'; + // If title and required marker are both empty, prepare no label. + if (empty($element['#required']) && (!isset($element['#title']) || $element['#title'] === '')) { + $variables['label'] = $variables['required'] = $variables['attributes'] = NULL; } - // Show label only to screen readers to avoid disruption in visual flows. - elseif ($element['#title_display'] == 'invisible') { - $attributes['class'] = 'visually-hidden'; + else { + // If the element is required, a required marker is appended to the label. + $variables['label'] = (isset($element['#title'])) ? filter_xss_admin($element['#title']) : NULL; + $variables['required'] = (!empty($element['#required'])) ? array('#theme' => 'form_required_marker', '#element' => $element) : ''; + // Associate the label with the field it is for. + if (!empty($element['#id'])) { + $variables['attributes']['for'] = $element['#id']; + } + // Add label positioning classes. + if (!empty($element['#title_display'])) { + $variables['attributes']['class'] = array(); + // Style the label as class 'option' to display inline with the element. + // @todo: Use a more semantic class name like 'layout-inline-after'? + if ($element['#title_display'] == 'after') { + $variables['attributes']['class'][] = 'option'; + } + // Show label only to screen readers to avoid disruption in visual flows. + elseif ($element['#title_display'] == 'invisible') { + $variables['attributes']['class'][] = 'visually-hidden'; + } + } } +} - if (!empty($element['#id'])) { - $attributes['for'] = $element['#id']; +/** + * Prepares variables for exposed filters templates. + * + * Default template: exposed-filters.html.twig. + * + * @param array $variables + * An associative array containing: + * - form: An associative array containing the structure of the form. + */ +function template_preprocess_exposed_filters(&$variables) { + $form = $variables['form']; + + $variables['items'] = array(); + if (isset($form['current'])) { + $items = array(); + foreach (element_children($form['current']) as $key) { + $items[] = $form['current'][$key]; + } + $variables['items'][] = array( + '#theme' => 'item_list', + '#items' => $items, + '#attributes' => array( + 'class' => array('clearfix', 'current-filters'), + ), + ); } - - return '' . t('!title!required', array('!title' => $title, '!required' => $required)) . ''; } /** diff --git a/core/includes/install.core.inc b/core/includes/install.core.inc index 8e4b66e..3af87fa 100644 --- a/core/includes/install.core.inc +++ b/core/includes/install.core.inc @@ -13,6 +13,7 @@ use Drupal\Core\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Reference; +use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; diff --git a/core/includes/theme.inc b/core/includes/theme.inc index 330c448..9d96809 100644 --- a/core/includes/theme.inc +++ b/core/includes/theme.inc @@ -2338,20 +2338,18 @@ function theme_indentation($variables) { } /** - * Returns HTML to wrap child elements in a container. + * Prepares variables for container templates. * - * Used for grouped form items. Can also be used as a #theme_wrapper for any - * renderable element, to surround it with a
and add attributes such as - * classes or an HTML id. + * Default template: container.html.twig. * - * @param $variables + * @param array $variables * An associative array containing: * - element: An associative array containing the properties of the element. * Properties used: #id, #attributes, #children. * * @ingroup themeable */ -function theme_container($variables) { +function template_preprocess_container(&$variables) { $element = $variables['element']; // Ensure #attributes is set. $element += array('#attributes' => array()); @@ -2366,7 +2364,8 @@ function theme_container($variables) { $element['#attributes']['class'][] = 'form-wrapper'; } - return '' . $element['#children'] . '
'; + $variables['children'] = $element['#children']; + $variables['attributes'] = $element['#attributes']; } /** @@ -3117,51 +3116,59 @@ function drupal_common_theme() { // From form.inc. 'input' => array( 'render element' => 'element', + 'template' => 'input', ), 'select' => array( 'render element' => 'element', + 'template' => 'select', ), 'fieldset' => array( 'render element' => 'element', + 'template' => 'fieldset', ), 'details' => array( 'render element' => 'element', + 'template' => 'details', ), 'radios' => array( 'render element' => 'element', - ), - 'date' => array( - 'render element' => 'element', + 'template' => 'radios', ), 'exposed_filters' => array( 'render element' => 'form', + 'template' => 'exposed-filters', ), 'checkboxes' => array( 'render element' => 'element', + 'template' => 'checkboxes', ), 'form' => array( 'render element' => 'element', + 'template' => 'form', ), 'textarea' => array( 'render element' => 'element', - ), - 'tableselect' => array( - 'render element' => 'element', + 'template' => 'textarea', ), 'form_element' => array( 'render element' => 'element', + 'template' => 'form-element', ), 'form_required_marker' => array( 'render element' => 'element', + 'template' => 'form-required-marker', ), 'form_element_label' => array( 'render element' => 'element', + 'template' => 'form-element-label', ), 'vertical_tabs' => array( 'render element' => 'element', + 'template' => 'vertical-tabs', ), 'container' => array( 'render element' => 'element', + 'template' => 'container', ), ); } diff --git a/core/modules/system/system.module b/core/modules/system/system.module index 94fbd21..facb639 100644 --- a/core/modules/system/system.module +++ b/core/modules/system/system.module @@ -295,7 +295,7 @@ function system_element_info() { '#limit_validation_errors' => FALSE, '#process' => array('form_process_button', 'ajax_process_form'), '#pre_render' => array('form_pre_render_button'), - '#theme_wrappers' => array('input__submit'), + '#theme' => 'input__submit', ); $types['button'] = array( '#input' => TRUE, @@ -305,7 +305,7 @@ function system_element_info() { '#limit_validation_errors' => FALSE, '#process' => array('form_process_button', 'ajax_process_form'), '#pre_render' => array('form_pre_render_button'), - '#theme_wrappers' => array('input__button'), + '#theme' => 'input__button', ); $types['image_button'] = array( '#input' => TRUE, @@ -317,7 +317,7 @@ function system_element_info() { '#has_garbage_value' => TRUE, '#src' => NULL, '#pre_render' => array('form_pre_render_image_button'), - '#theme_wrappers' => array('input__image_button'), + '#theme' => 'input__image_button', ); $types['textfield'] = array( '#input' => TRUE, @@ -486,7 +486,8 @@ function system_element_info() { ); $types['date'] = array( '#input' => TRUE, - '#theme' => 'date', + '#theme' => 'input__date', + '#pre_render' => array('form_pre_render_date'), '#theme_wrappers' => array('form_element'), ); $types['file'] = array( @@ -502,10 +503,11 @@ function system_element_info() { '#input' => TRUE, '#js_select' => TRUE, '#multiple' => TRUE, + '#pre_render' => array('form_pre_render_tableselect'), '#process' => array('form_process_tableselect'), '#options' => array(), '#empty' => '', - '#theme' => 'tableselect', + '#theme' => 'table__tableselect', ); // Form structure. @@ -3254,35 +3256,6 @@ function theme_system_config_form($variables) { } /** - * Returns HTML for an exposed filter form. - * - * @param $variables - * An associative array containing: - * - form: An associative array containing the structure of the form. - * - * @return - * A string containing an HTML-formatted form. - * - * @ingroup themeable - */ -function theme_exposed_filters($variables) { - $form = $variables['form']; - $output = ''; - - if (isset($form['current'])) { - $items = array(); - foreach (element_children($form['current']) as $key) { - $items[] = $form['current'][$key]; - } - $output .= theme('item_list', array('items' => $items, 'attributes' => array('class' => array('clearfix', 'current-filters')))); - } - - $output .= drupal_render_children($form); - - return '
' . $output . '
'; -} - -/** * Implements hook_admin_paths(). */ function system_admin_paths() { diff --git a/core/modules/system/templates/checkboxes.html.twig b/core/modules/system/templates/checkboxes.html.twig new file mode 100644 index 0000000..00384d3 --- /dev/null +++ b/core/modules/system/templates/checkboxes.html.twig @@ -0,0 +1,17 @@ +{# +/** + * @file + * Default theme implementation for a 'checkboxes' #type form element. + * + * Available variables + * - attributes: A list of HTML attributes for the wrapper element. + * - children: The rendered checkboxes. + * + * @see template_preprocess_checkboxes() + * + * @ingroup themeable + */ + @todo: remove this file once http://drupal.org/node/1819284 is resolved. + This is identical to core/modules/system/templates/container.html.twig +#} +{{ children }} diff --git a/core/modules/system/templates/container.html.twig b/core/modules/system/templates/container.html.twig new file mode 100644 index 0000000..10b9426 --- /dev/null +++ b/core/modules/system/templates/container.html.twig @@ -0,0 +1,15 @@ +{# +/** + * @file + * Default theme implementation of a container used to wrap child elements. + * + * Available variables: + * - attributes: HTML attributes for the containing element. + * - children: The rendered child elements of the container. + * + * @see template_preprocess_container() + * + * @ingroup themeable + */ +#} +{{ children }}{# Comment removes trailing newline #} diff --git a/core/modules/system/templates/datetime.html.twig b/core/modules/system/templates/datetime.html.twig index 25ef788..0af45c3 100644 --- a/core/modules/system/templates/datetime.html.twig +++ b/core/modules/system/templates/datetime.html.twig @@ -7,19 +7,20 @@ * - timestamp: (optional) A UNIX timestamp for the datetime attribute. If the * datetime cannot be represented as a UNIX timestamp, use a valid datetime * attribute value in attributes.datetime. - * - text: (optional) The content to display within the