diff --git a/core/lib/Drupal/Core/Render/Element/Radio.php b/core/lib/Drupal/Core/Render/Element/Radio.php index ae20284..643007b 100644 --- a/core/lib/Drupal/Core/Render/Element/Radio.php +++ b/core/lib/Drupal/Core/Render/Element/Radio.php @@ -37,6 +37,24 @@ public function getInfo() { ); } + /** + * Ensures $element['#default_value'] and $element['#value'] are consistently + * typed. + * + * @param mixed $value + * A bool value which would be casted to string. + * + * @return string + * The casted value of the bool value. + */ + protected static function castValue($value) + { + if (filter_var($value, FILTER_VALIDATE_BOOLEAN)) { + return (string) (int) $value; + } + return $value; + } + /** * Prepares a #type 'radio' render element for input.html.twig. * @@ -54,8 +72,16 @@ public static function preRenderRadio($element) { $element['#attributes']['type'] = 'radio'; Element::setAttributes($element, array('id', 'name', '#return_value' => 'value')); - if (isset($element['#return_value']) && $element['#value'] !== FALSE && $element['#value'] == $element['#return_value']) { - $element['#attributes']['checked'] = 'checked'; + if (isset($element['#return_value']) && $element['#value'] !== FALSE) { + // To avoid auto-casting during '==' we convert int 0 to '0' for both + // operands. It will prevent wrong true-checking for both cases: 0 == + // 'string' and 'string' == 0. + $element['#value'] = static::castValue($element['#value']); + $element['#return_value'] = static::castValue($element['#return_value']); + + if ($element['#value'] == $element['#return_value']) { + $element['#attributes']['checked'] = 'checked'; + } } static::setAttributes($element, array('form-radio')); diff --git a/core/modules/system/src/Tests/Form/ElementTest.php b/core/modules/system/src/Tests/Form/ElementTest.php index 0ae2edc..50865dd 100644 --- a/core/modules/system/src/Tests/Form/ElementTest.php +++ b/core/modules/system/src/Tests/Form/ElementTest.php @@ -89,6 +89,26 @@ function testOptions() { } /** + * Tests correct checked attribute for radios element. + */ + 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); + } + + /** * Tests wrapper ids for checkboxes and radios. */ 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 2250a0b..0ee125c 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 0000000..c46bd8c --- /dev/null +++ b/core/modules/system/tests/modules/form_test/src/Form/FormTestRadiosCheckedForm.php @@ -0,0 +1,82 @@ + 'radios', + '#title' => 'Radios', + '#options' => array( + 0 => 'Zero', + 'foo' => 'Foo', + 1 => 'One', + 'bar' => 'Bar - radios', + '>' => "Special Char", + ), + '#default_value' => 0, + ); + $form['radios-string'] = array( + '#type' => 'radios', + '#title' => 'Radios', + '#options' => array( + 0 => 'Zero', + 'foo' => 'Foo', + 1 => 'One', + 'bar' => 'Bar - radios', + '>' => "Special Char", + ), + '#default_value' => 'bar', + ); + $form['radios-boolean-true'] = array( + '#type' => 'radios', + '#title' => 'Radios', + '#options' => array( + 'All' => '- Any -', + 1 => 'True', + 0 => 'False', + ), + '#default_value' => TRUE, + ); + $form['radios-boolean-false'] = array( + '#type' => 'radios', + '#title' => 'Radios', + '#options' => array( + 'All' => '- Any -', + 1 => 'True', + 0 => 'False', + ), + '#default_value' => FALSE, + ); + + $form['submit'] = array('#type' => 'submit', '#value' => 'Submit'); + + return $form; + } + + /** + * {@inheritdoc} + */ + public function submitForm(array &$form, FormStateInterface $form_state) { + $form_state->setResponse(new JsonResponse($form_state->getValues())); + } + +} diff --git a/core/modules/views_ui/src/Tests/DisplayTest.php b/core/modules/views_ui/src/Tests/DisplayTest.php index 7f5f125..2976120 100644 --- a/core/modules/views_ui/src/Tests/DisplayTest.php +++ b/core/modules/views_ui/src/Tests/DisplayTest.php @@ -163,7 +163,9 @@ public function testLinkDisplay() { $this->assertEqual($result[0], t('None'), 'Make sure that the link option summary shows "None" by default.'); $this->drupalGet($link_display_path); - $this->assertFieldChecked('edit-link-display-0'); + // We are looking for the None option which has a '' key, that's why there + // is no key appended in the ID. + $this->assertFieldChecked('edit-link-display-'); // Test the default radio option on the link display form. $this->drupalPostForm($link_display_path, array('link_display' => 'page_1'), t('Apply')); diff --git a/core/tests/Drupal/Tests/Core/Render/Element/RadioTest.php b/core/tests/Drupal/Tests/Core/Render/Element/RadioTest.php new file mode 100644 index 0000000..7381cfa --- /dev/null +++ b/core/tests/Drupal/Tests/Core/Render/Element/RadioTest.php @@ -0,0 +1,29 @@ + 0, + '#value' => 'All', + '#attributes' => [], + ]; + + $element = Radio::preRenderRadio($element); + + $this->assertArrayNotHasKey('checked', $element['#attributes']); + } + +}