Cast all integer keys in checkbox element to strings

Created on 30 June 2022, over 2 years ago
Updated 30 December 2023, 12 months ago

Problem/Motivation

Per the comment in Checkbox.php @todo For Drupal 8, cast all integer keys to strings for consistency with \Drupal\Core\Render\Element\Radios::processRadios().

Steps to reproduce

NA

Proposed resolution

Implement what the todo is saying.

Remaining tasks

Review patch
Commit

User interface changes

NA

API changes

NA

Data model changes

NA

Release notes snippet

NA

Original Post by Murz

In the web/core/lib/Drupal/Core/Render/Element/Checkboxes.php file we have a construction to check the default value for disabled elements: https://git.drupalcode.org/project/drupal/-/blob/9.5.x/core/lib/Drupal/C...

        // 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;
        }

And the part in_array($key, $element['#default_value'], TRUE) always fails to check for numeric keys, because in $element['#default_value'] we always have numbers as strings, example:

var_export(array_keys($element['#options']), true)
"array (
  0 => 1,
  1 => 2,
)"
var_export($element['#default_value'], true)
"array (
  0 => '2',
  1 => '1',
)"

We have a strict comparison mode enabled, so this check always fails because of type differences (number with string).

Steps to reproduce

1. Create a field with several items and use 'Checkboxes' element to display them, for example reuse field_tags in articles node bundle from default Drupal installation.
Create two tags: Tag1 (id=1), Tag2 (id=2).

2. Fill the default value for Tag1 and disable its checkbox via 'hook_form_alter':

function my_module_form_alter(&$form, FormStateInterface $form_state, $form_id) {
  if($form_id !== 'node_article_edit_form') {
    return;
  }
  $form['field_tags']['widget']['#default_value'][] = "1";
  $form['field_tags']['widget']["1"]['#disabled'] = TRUE;
}

3. Try to submit the form, the disabled item should be missing in submitted values.

4. See that $default_value for this element is NULL

Also see that the "Tag1" is not assigned to the article node after form submission.

Proposed resolution

We already have a @todo in the current code:

       // @todo For Drupal 8, cast all integer keys to strings for consistency
       // Cast all integer keys to strings for consistency
       //   with \Drupal\Core\Render\Element\Radios::processRadios().

So implementing this todo is fixing the issue:

       if (is_int($key)) {
         $key = strval($key);
       }
📌 Task
Status

Needs work

Version

11.0 🔥

Component
Form 

Last updated 3 days ago

Created by

🇦🇲Armenia murz Yerevan, Armenia

Live updates comments and jobs are added and updated live.

Missing content requested by

🇦🇺Australia dpi
12 months ago
Sign in to follow issues

Comments & Activities

Production build 0.71.5 2024