' . "\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 .= '';
+ }
+
$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).*\*\1>@';
// 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'),