diff --git a/core/includes/form.inc b/core/includes/form.inc index c94bc62..2caba0e 100644 --- a/core/includes/form.inc +++ b/core/includes/form.inc @@ -4376,31 +4376,60 @@ function theme_form_element($variables) { } $output = '' . "\n"; + // Composite elements consist of more than one HTML form control. These must + // be grouped by a fieldset. + $composite = FALSE; + if (isset($element['#composite']) && $element['#composite'] === TRUE) { + $composite = TRUE; + } + + if ($composite) { + $output .= '
'; + } + // 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'] . '' : ''; + $children = ' ' . $prefix . $element['#children'] . $suffix; + + // Generate the title, either a legend or a label, only if the title will be + // used. + if (!in_array($element['#title_display'], array('none', 'attribute'))) { + if ($composite) { + $attributes = array(); + if ($element['#title_display'] === 'invisible') { + $attributes['class'] = 'element-invisible'; + } + $title = '' . $element['#title']; + if (!empty($element['#required'])) { + $title .= theme('form_required_marker', array('element' => $element)); + } + $title .= ''; + } else { + $title = ' ' . theme('form_element_label', $variables); + } + } switch ($element['#title_display']) { case 'before': case 'invisible': - $output .= ' ' . theme('form_element_label', $variables); - $output .= ' ' . $prefix . $element['#children'] . $suffix . "\n"; + $output .= $title . $children; break; case 'after': - $output .= ' ' . $prefix . $element['#children'] . $suffix; - $output .= ' ' . theme('form_element_label', $variables) . "\n"; + $output .= $children . $title; break; case 'none': case 'attribute': // Output no label and no required marker, only the children. - $output .= ' ' . $prefix . $element['#children'] . $suffix . "\n"; + $output .= $children; break; } + $output .= "\n"; if (!empty($element['#description'])) { $attributes = array('class' => 'description'); @@ -4410,6 +4439,10 @@ function theme_form_element($variables) { $output .= '' . $element['#description'] . "\n"; } + if ($composite) { + $output .= '
'; + } + $output .= "\n"; return $output; diff --git a/core/modules/system/lib/Drupal/system/Tests/Form/FormTest.php b/core/modules/system/lib/Drupal/system/Tests/Form/FormTest.php index 20d1f56..f5e260f 100644 --- a/core/modules/system/lib/Drupal/system/Tests/Form/FormTest.php +++ b/core/modules/system/lib/Drupal/system/Tests/Form/FormTest.php @@ -88,7 +88,7 @@ class FormTest extends WebTestBase { $elements['file']['empty_values'] = $empty_strings; // Regular expression to find the expected marker on required elements. - $required_marker_preg = '@\*@'; + $required_marker_preg = '@<(label|legend).*\*@'; // Go through all the elements and all the empty values for them. foreach ($elements as $type => $data) { diff --git a/core/modules/system/system.module b/core/modules/system/system.module index 73236f7..d10a1de 100644 --- a/core/modules/system/system.module +++ b/core/modules/system/system.module @@ -455,6 +455,7 @@ function system_element_info() { '#theme_wrappers' => array('form_element'), ); $types['radios'] = array( + '#composite' => TRUE, '#input' => TRUE, '#process' => array('form_process_radios'), '#theme_wrappers' => array('radios'), @@ -469,6 +470,7 @@ function system_element_info() { '#title_display' => 'after', ); $types['checkboxes'] = array( + '#composite' => TRUE, '#input' => TRUE, '#process' => array('form_process_checkboxes'), '#theme_wrappers' => array('checkboxes'), @@ -496,6 +498,7 @@ function system_element_info() { '#process' => array('form_process_weight', 'ajax_process_form'), ); $types['date'] = array( + '#composite' => TRUE, '#input' => TRUE, '#element_validate' => array('date_validate'), '#process' => array('form_process_date'),