diff --git a/core/includes/form.inc b/core/includes/form.inc index 6a747b6..9c035b2 100644 --- a/core/includes/form.inc +++ b/core/includes/form.inc @@ -1343,7 +1343,11 @@ function _form_validate(&$elements, &$form_state, $form_id = NULL) { $elements['#value'] = NULL; form_set_value($elements, NULL, $form_state); } - elseif (!isset($options[$elements['#value']])) { + // Throw an error if the submitted #value is not contained in #options, + // but only if there actually is a value. A #type 'radios' may not have + // a value if it has no #default_value and when it is optional (or only + // conditionally required via #limit_validation_errors). + elseif (!isset($options[$elements['#value']]) && $elements['#value'] !== '') { form_error($elements, $t('An illegal choice has been detected. Please contact the site administrator.')); watchdog('form', 'Illegal choice %choice in %name element.', array('%choice' => $elements['#value'], '%name' => empty($elements['#title']) ? $elements['#parents'][0] : $elements['#title']), WATCHDOG_ERROR); } @@ -2809,7 +2813,7 @@ function theme_radio($variables) { $element['#attributes']['type'] = 'radio'; element_set_attributes($element, array('id', 'name', '#return_value' => 'value')); - if (isset($element['#return_value']) && $element['#value'] !== FALSE && $element['#value'] == $element['#return_value']) { + if (isset($element['#return_value']) && $element['#value'] !== FALSE && $element['#value'] === $element['#return_value']) { $element['#attributes']['checked'] = 'checked'; } _form_set_class($element, array('form-radio')); diff --git a/core/modules/system/lib/Drupal/system/Tests/Form/ElementTest.php b/core/modules/system/lib/Drupal/system/Tests/Form/ElementTest.php index cac8d2c..5bae111 100644 --- a/core/modules/system/lib/Drupal/system/Tests/Form/ElementTest.php +++ b/core/modules/system/lib/Drupal/system/Tests/Form/ElementTest.php @@ -62,6 +62,10 @@ class ElementTest extends WebTestBase { $expected = array_shift($expected_values); $this->assertIdentical((string) $element['value'], $expected); } + // Additionally verify that there is only one option checked. + $elements = $this->xpath('//input[@type=:type and @checked="checked"]', array(':type' => $type)); + $this->assertEqual(count($elements), 1); + $this->assertIdentical((string) $elements[0]['value'], '0'); } // Enable customized option sub-elements. diff --git a/core/modules/system/tests/modules/form_test/form_test.module b/core/modules/system/tests/modules/form_test/form_test.module index b89426c..67f1d5d 100644 --- a/core/modules/system/tests/modules/form_test/form_test.module +++ b/core/modules/system/tests/modules/form_test/form_test.module @@ -1455,6 +1455,7 @@ function form_test_checkboxes_radios($form, &$form_state, $customize = FALSE) { $form['checkboxes'] = array( '#type' => 'checkboxes', '#title' => 'Checkboxes', + '#default_value' => array(0), '#options' => array( 0 => 'Zero', 'foo' => 'Foo', @@ -1479,6 +1480,7 @@ function form_test_checkboxes_radios($form, &$form_state, $customize = FALSE) { $form['radios'] = array( '#type' => 'radios', '#title' => 'Radios', + '#default_value' => 0, '#options' => array( 0 => 'Zero', 'foo' => 'Foo',