In form.inc, form_type_checkbox_value, line 2195, 0 is returned instead of NULL for a checkbox. This creates a problem when trying to execute a valid form_state that contains an element of type 'checkboxes'. An error will occur on forms that use this element, for example the 'block_admin_configure' form.

I have saved a previously submitted form and try to submit it using drupal_form_submit later on. This form_state has input, values, etc. The complete thing. I'd say that this must be possible.

But drupal_form_submit simply overwrites the input array with the form_state['values'] array. Needless to say, this is only sensible when their formats are identical. In the case of a checkboxes-element, the net result is that 'NULL' values (not-selected checkboxes) in the input field will be overwritten by the value '0'. This is asking for trouble.

In the function 'form_type_checkboxes_value' (form.inc, line 2211) the '0' value is not recognized as a 'not set' value (check the comment block!). isset is used, and as the value is not NULL, it thinks that the 0 value is actually a chosen option and the value is taken into the '#value' array key of the element.

The trouble happens later in the function _form_validate (form.inc, line 1249), where the value 0 is not recognized as a correct 'option', and the error 'An illegal choice has been detected. Please contact the site administrator.' is set. The form will not be accepted.

My solution is to re-implement drupal_form_submit locally, but of course this is not a good solution. Some more intelligence is required in drupal_form_submit, so that form_state['values'] are correctly converted to input values. Personally, I think that the input and form_state['values'] should always have the exact same format if the input array is overwritten.

Issue fork drupal-1195306

Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

Anonymous’s picture

Priority: Minor » Normal

I think that your issue is related to my post here: http://drupal.org/node/1161024 . Basically, reusing the $form_state from a form_submit function should work with drupal_form_submit, but with certain Fields, it doesn't. Something needs to be done to get this fixed in Core.

Sincerely,
Leighton Whiting

SilviaT’s picture

sub

Ben Young’s picture

Version: 7.2 » 7.22

I understand that this isn't likely to receive much attention due to being able to handle things via e.g. node_save() or another alternative method, but I've been struggling against this bug for hours because nowhere does it state that drupal_form_submit() shouldn't just work.

The documentation even includes an example for creating a user. If there were select fields involved, it would fail.

rudolfbyker’s picture

Is there any progress on this? I am working on some advanced forms, which do not work because of this bug. Re-implementing drupal_form_submit is not an option for me... Does this also happen in 7.23?

donquixote’s picture

I am running into the same issue.
My use case is quite advanced so I hesitate trying to explain it here.
It has to do with views_ui and ajax (D7).

Version: 7.22 » 7.x-dev

Core issues are now filed against the dev versions where changes will be made. Document the specific release you are using in your issue comment. More information about choosing a version.

HitchShock’s picture

I reproduced this issue too.
We can reproduce it only when using drupal_form_submit() programmatically. In this case we have to use the input value instead of #return_value because we are setting new values via form_state. Like this:

$form_state['values']['my_checkbox'] = 0;
drupal_form_submit('my_form', $form_state);

See form_type_checkbox_value() and _form_builder_handle_input_element:2119.

I prepared a simple patch to fix it.

HitchShock’s picture

apaderno’s picture

Status: Needs review » Needs work

The latest patches do not apply anymore.

Keshav Patel’s picture

Status: Needs work » Needs review
FileSize
1.56 KB

Updated the #8 patch, the patch on #10 applies cleanly. please review.

apaderno’s picture

Title: Values for checkboxes in form_state do not match input, which breaks drupal_form_submit. » Values for checkboxes in $form_state do not match input

I created a MR with the same changes in the patch in comment #7.

apaderno’s picture

[Please ignore this comment.]

apaderno’s picture

Status: Needs review » Needs work

The description of the return value needs to be changed too.

The data that will appear in $form_state['values'] for this element, or nothing to use the default.

form_type_checkbox_value() always return a value, even if that value is 0. It is not true it can return nothing. That comment cannot be changed to or 0 to use the default either. That would contrast with the comment inside
form_type_checkbox_value(), which contains the following sentence.

Returning NULL from a value callback means to use the default value, which is not what is wanted when an unchecked checkbox is submitted, so we use integer 0 as the value indicating an unchecked checkbox.

For a checkbox, 0 returned from form_type_checkbox_value() means the checkbox is unchecked.

Furthermore, this comment should be changed too, since the code is changed.

// Checked checkboxes are submitted with a value (possibly '0' or ''):
// http://www.w3.org/TR/html401/interact/forms.html#successful-controls.
// For checked checkboxes, browsers submit the string version of
// #return_value, but we return the original #return_value. For unchecked
// checkboxes, browsers submit nothing at all, but
// _form_builder_handle_input_element() detects this, and calls this
// function with $input=NULL. Returning NULL from a value callback means to
// use the default value, which is not what is wanted when an unchecked
// checkbox is submitted, so we use integer 0 as the value indicating an
// unchecked checkbox. Therefore, modules must not use integer 0 as a
// #return_value, as doing so results in the checkbox always being treated
// as unchecked. The string '0' is allowed for #return_value. The most
// common use-case for setting #return_value to either 0 or '0' is for the
// first option within a 0-indexed array of checkboxes, and for this,
// form_process_checkboxes() uses the string rather than the integer.

we return the original #return_value is not always true, as $input is returned for programmatically submitted forms.

apaderno’s picture

Status: Needs work » Needs review

I did not change the other phrase.
Given the context in which it is used (browsers submit the string version of #return_value, but we return the original #return_value), it is not necessary to say that also $input could be returned.