diff --git a/core/lib/Drupal/Core/Render/Element/Radio.php b/core/lib/Drupal/Core/Render/Element/Radio.php index 8687a9dcfc..efb225062d 100644 --- a/core/lib/Drupal/Core/Render/Element/Radio.php +++ b/core/lib/Drupal/Core/Render/Element/Radio.php @@ -54,7 +54,10 @@ public static function preRenderRadio($element) { $element['#attributes']['type'] = 'radio'; Element::setAttributes($element, ['id', 'name', '#return_value' => 'value']); - if (isset($element['#return_value']) && $element['#value'] !== FALSE && $element['#value'] == $element['#return_value']) { + // To avoid auto-casting during '==' we convert $element['#value'] and + // $element['#return_value'] to strings. It will prevent wrong true-checking + // for both cases: 0 == 'string' and 'string' == 0. + if (isset($element['#return_value']) && $element['#value'] !== FALSE && (string) $element['#value'] === (string) $element['#return_value']) { $element['#attributes']['checked'] = 'checked'; } static::setAttributes($element, ['form-radio']); diff --git a/core/modules/system/src/Tests/Form/ElementTest.php b/core/modules/system/src/Tests/Form/ElementTest.php index 0e1c3ce0cb..dad56ea1d1 100644 --- a/core/modules/system/src/Tests/Form/ElementTest.php +++ b/core/modules/system/src/Tests/Form/ElementTest.php @@ -89,6 +89,38 @@ public function testOptions() { } /** + * Tests correct checked attribute for radios element. + */ + public function testRadiosChecked() { + // Verify that there is only one radio option checked. + $this->drupalGet('form-test/radios-checked'); + $elements = $this->xpath('//input[@name="radios" and @checked]'); + $this->assertEqual(count($elements), 1); + $this->assertIdentical((string) $elements[0]['value'], '0'); + $elements = $this->xpath('//input[@name="radios-string" and @checked]'); + $this->assertEqual(count($elements), 1); + $this->assertIdentical((string) $elements[0]['value'], 'bar'); + $elements = $this->xpath('//input[@name="radios-boolean-true" and @checked]'); + $this->assertEqual(count($elements), 1); + $this->assertIdentical((string) $elements[0]['value'], '1'); + // A default value of FALSE indicates that nothing is set. + $elements = $this->xpath('//input[@name="radios-boolean-false" and @checked]'); + $this->assertEqual(count($elements), 0); + $elements = $this->xpath('//input[@name="radios-boolean-any" and @checked]'); + $this->assertEqual(count($elements), 1); + $this->assertIdentical((string) $elements[0]['value'], 'All'); + $elements = $this->xpath('//input[@name="radios-string-zero" and @checked]'); + $this->assertEqual(count($elements), 1); + $this->assertIdentical((string) $elements[0]['value'], '0'); + $elements = $this->xpath('//input[@name="radios-int-non-zero" and @checked]'); + $this->assertEqual(count($elements), 1); + $this->assertIdentical((string) $elements[0]['value'], '10'); + $elements = $this->xpath('//input[@name="radios-int-non-zero-as-string" and @checked]'); + $this->assertEqual(count($elements), 1); + $this->assertIdentical((string) $elements[0]['value'], '100'); + } + + /** * Tests wrapper ids for checkboxes and radios. */ public function testWrapperIds() { diff --git a/core/modules/system/tests/modules/form_test/form_test.routing.yml b/core/modules/system/tests/modules/form_test/form_test.routing.yml index 2250a0bb2f..0ee125c95a 100644 --- a/core/modules/system/tests/modules/form_test/form_test.routing.yml +++ b/core/modules/system/tests/modules/form_test/form_test.routing.yml @@ -294,6 +294,14 @@ form_test.checkboxes_radios: requirements: _access: 'TRUE' +form_test.radios_checked: + path: '/form-test/radios-checked' + defaults: + _form: '\Drupal\form_test\Form\FormTestRadiosCheckedForm' + _title: 'Radios checked defalt value' + requirements: + _access: 'TRUE' + form_test.email: path: '/form-test/email' defaults: diff --git a/core/modules/system/tests/modules/form_test/src/Form/FormTestRadiosCheckedForm.php b/core/modules/system/tests/modules/form_test/src/Form/FormTestRadiosCheckedForm.php new file mode 100644 index 0000000000..e330700a1f --- /dev/null +++ b/core/modules/system/tests/modules/form_test/src/Form/FormTestRadiosCheckedForm.php @@ -0,0 +1,124 @@ + 'radios', + '#title' => 'Radios', + '#options' => [ + 0 => 'Zero', + 'foo' => 'Foo', + 1 => 'One', + 'bar' => 'Bar - radios', + '>' => "Special Char", + ], + '#default_value' => 0, + ]; + $form['radios-string'] = [ + '#type' => 'radios', + '#title' => 'Radios', + '#options' => [ + 0 => 'Zero', + 'foo' => 'Foo', + 1 => 'One', + 'bar' => 'Bar - radios', + '>' => "Special Char", + ], + '#default_value' => 'bar', + ]; + $form['radios-boolean-true'] = [ + '#type' => 'radios', + '#title' => 'Radios', + '#options' => [ + 'All' => '- Any -', + 1 => 'True', + 0 => 'False', + ], + '#default_value' => TRUE, + ]; + $form['radios-boolean-false'] = [ + '#type' => 'radios', + '#title' => 'Radios', + '#options' => [ + 'All' => '- Any -', + 1 => 'True', + 0 => 'False', + ], + '#default_value' => FALSE, + ]; + $form['radios-boolean-any'] = [ + '#type' => 'radios', + '#title' => 'Radios', + '#options' => [ + 'All' => '- Any -', + 1 => 'True', + 0 => 'False', + ], + '#default_value' => 'All', + ]; + $form['radios-string-zero'] = [ + '#type' => 'radios', + '#title' => 'Radios', + '#options' => [ + 'All' => '- Any -', + '0' => 'Zero', + 100 => 'One hundred', + ], + '#default_value' => 0, + ]; + $form['radios-int-non-zero'] = [ + '#type' => 'radios', + '#title' => 'Radios', + '#options' => [ + 'All' => '- Any -', + 0 => 'Zero', + 10 => 'Ten', + 100 => 'One hundred', + ], + '#default_value' => 10, + ]; + $form['radios-int-non-zero-as-string'] = [ + '#type' => 'radios', + '#title' => 'Radios', + '#options' => [ + 'All' => '- Any -', + '0' => 'Zero', + '10' => 'Ten', + '100' => 'One hundred', + ], + '#default_value' => '100', + ]; + + $form['submit'] = ['#type' => 'submit', '#value' => 'Submit']; + + return $form; + } + + /** + * {@inheritdoc} + */ + public function submitForm(array &$form, FormStateInterface $form_state) { + $form_state->setResponse(new JsonResponse($form_state->getValues())); + } + +}