From 28a3a8779dad1e2346a86c95d6508885c7e57424 Mon Sep 17 00:00:00 2001 From: Alex Pott Date: Mon, 14 Mar 2022 16:39:27 +0000 Subject: [PATCH] Issue #2911473 by Maouna, joachim, adinac, dhirendra.mishra, ravi.shankar, MaskOta, ranjith_kumar_k_u, kuldeep_mehra27, mahtab_alam, fabienly, carolpettirossi, joelpittet, jenlampton, dww: Selected yet disabled individual options from checkboxes element don't persist through save --- .../Drupal/Core/Render/Element/Checkboxes.php | 20 ++++++++++++- .../src/Form/FormTestDisabledElementsForm.php | 30 ++++++++++++++++++- .../tests/src/Functional/Form/FormTest.php | 4 +-- 3 files changed, 50 insertions(+), 4 deletions(-) diff --git a/core/lib/Drupal/Core/Render/Element/Checkboxes.php b/core/lib/Drupal/Core/Render/Element/Checkboxes.php index cdf05548732..8d6919821f1 100644 --- a/core/lib/Drupal/Core/Render/Element/Checkboxes.php +++ b/core/lib/Drupal/Core/Render/Element/Checkboxes.php @@ -73,12 +73,19 @@ class Checkboxes extends FormElement { // sub-elements. $weight += 0.001; + // Only enabled checkboxes receive their values from the form + // submission, the disabled checkboxes use their default value. + $default_value = NULL; + if (isset($value[$key]) || (!empty($element[$key]['#disabled']) && in_array($key, $element['#default_value'], TRUE))) { + $default_value = $key; + } + $element += [$key => []]; $element[$key] += [ '#type' => 'checkbox', '#title' => $choice, '#return_value' => $key, - '#default_value' => isset($value[$key]) ? $key : NULL, + '#default_value' => $default_value, '#attributes' => $element['#attributes'], '#ajax' => $element['#ajax'] ?? NULL, // Errors should only be shown on the parent checkboxes element. @@ -115,6 +122,17 @@ class Checkboxes extends FormElement { unset($input[$key]); } } + + // Because the disabled checkboxes don't receive their input from the + // form submission, we use their default value. + if (!empty($element['#default_value'])) { + foreach ($element['#default_value'] as $key) { + if (!empty($element[$key]['#disabled'])) { + $input[$key] = $key; + } + } + } + return array_combine($input, $input); } else { diff --git a/core/modules/system/tests/modules/form_test/src/Form/FormTestDisabledElementsForm.php b/core/modules/system/tests/modules/form_test/src/Form/FormTestDisabledElementsForm.php index eef9efae5c8..bd8d2841e09 100644 --- a/core/modules/system/tests/modules/form_test/src/Form/FormTestDisabledElementsForm.php +++ b/core/modules/system/tests/modules/form_test/src/Form/FormTestDisabledElementsForm.php @@ -36,7 +36,7 @@ class FormTestDisabledElementsForm extends FormBase { ]; } - // Multiple values option elements. + // Multiple values option elements, disabled as a whole. foreach (['checkboxes', 'select'] as $type) { $form[$type . '_multiple'] = [ '#type' => $type, @@ -54,6 +54,34 @@ class FormTestDisabledElementsForm extends FormBase { ]; } + // Multiple values option elements, only single options disabled. + $form['checkboxes_single_select'] = [ + '#type' => 'checkboxes', + '#title' => 'checkboxes (multiple)', + '#options' => [ + 'test_1' => 'Test 1', + 'test_2' => 'Test 2', + ], + '#multiple' => TRUE, + '#default_value' => ['test_2' => 'test_2'], + 'test_1' => [ + '#disabled' => TRUE, + ], + ]; + $form['checkboxes_single_unselect'] = [ + '#type' => 'checkboxes', + '#title' => 'checkboxes (multiple)', + '#options' => [ + 'test_1' => 'Test 1', + 'test_2' => 'Test 2', + ], + '#multiple' => TRUE, + '#default_value' => ['test_2' => 'test_2'], + 'test_2' => [ + '#disabled' => TRUE, + ], + ]; + // Single values option elements. foreach (['radios', 'select'] as $type) { $form[$type . '_single'] = [ diff --git a/core/modules/system/tests/src/Functional/Form/FormTest.php b/core/modules/system/tests/src/Functional/Form/FormTest.php index 471f3039049..505bc76dbce 100644 --- a/core/modules/system/tests/src/Functional/Form/FormTest.php +++ b/core/modules/system/tests/src/Functional/Form/FormTest.php @@ -769,7 +769,7 @@ class FormTest extends BrowserTestBase { // All the elements should be marked as disabled, including the ones below // the disabled container. $actual_count = count($disabled_elements); - $expected_count = 42; + $expected_count = 44; $this->assertEquals($expected_count, $actual_count, new FormattableMarkup('Found @actual elements with disabled property (expected @expected).', ['@actual' => count($disabled_elements), '@expected' => $expected_count])); // Mink does not "see" hidden elements, so we need to set the value of the @@ -803,7 +803,7 @@ class FormTest extends BrowserTestBase { $expected_value = $form[$key]['#default_value']; } - if ($key == 'checkboxes_multiple') { + if (in_array($key, ['checkboxes_multiple', 'checkboxes_single_select', 'checkboxes_single_unselect'], TRUE)) { // Checkboxes values are not filtered out. $values[$key] = array_filter($values[$key]); }