Fields within a fieldset (i.e. nested components) do not display any saved value when resuming a form after using the Save Draft feature. The value is not displayed in the form and the PHP warning Warning: htmlspecialchars() expects parameter 1 to be string, array given in check_plain() (line 1582 of includes/bootstrap.inc). is displayed for each nested field.

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

fenstrat’s picture

Status: Active » Needs review
FileSize
839 bytes

I'm tempted to go ahead and commit the attached patch, it certainly fixes the error. However I'd like @quicksketch's feedback as this may be just fixing the symptom rather than the cause. I'm thinking the cause could be connected to the change to the $submission structure introduced with the conditionals patch (see the $subcomponent_value section, alas drupalcode.org returns a 500 for specific line links within a diff).

So is there a bigger issue when we need to look into the [0] element of the value array()? Or am I reading too much into this?

Also (somewhat) related #1702948: PHP notice when saving draft in email and textarea components

quicksketch’s picture

So is there a bigger issue when we need to look into the [0] element of the value array()? Or am I reading too much into this?

Yeah we have a problem with our submission structure (and have had it for some time), that the values aren't fully "processed" in a way that would make $form_state['values'] match $submission->data. In our code we try to treat them the same, but they have slightly different structures still. I'd be worried that this patch might have further reaching consequences than expected, such as breaking the conditional checking between pages.

The difference right now looks pretty much like this:

In a $submission object with a textfield, the value is stored as:

$submission->data[$cid][0] = 'value';

However in $form_state['values'] it is stored as:

$form_state['values'][$cid] = 'value';

When we call _webform_client_form_add_component(), $input_values may be *either* $submission->data or $form_state['values'], based on this segment of code:

    // Set the input values based on whether we're editing an existing
    // submission or not.
    $input_values = isset($submission->data) ? $submission->data : array();
    if (isset($form_state['values']['submitted'])) {
      foreach ($form_state['values']['submitted'] as $cid => $data) {
        $input_values[$cid] = $data;
      }
    }

This really isn't super pretty, but it's largely necessary because $form_state['values'] can contain "raw" (unvalidated) information, such as when you use the "Save Draft" or "Back" buttons. Forms are only validated when moving forward to the next page or finishing a submission.

quicksketch’s picture

Status: Needs review » Needs work

So regarding the actual patch: I've confirmed that this fixes problems with several types of components: times and dates at least. But it also breaks any component that can have multiple values, such as checkboxes. Things also act very weird when you have a checkboxes component that includes a key of "0", then #default_value ends up being set to a string, rather than an array, causing a PHP warning after saving then loading a draft.

quicksketch’s picture

Status: Needs work » Needs review
FileSize
1.4 KB

As I mentioned above, trying to turn an array into a string presents problems with multi-value fields like checkboxes. So rather than trying to "un-arrayify" the values, let's try the opposite approach an enforce an "always an array" approach. When we rewrote the value handling for the conditional support, it included a hack to get the values to set properly (presumably because things weren't always an array, the form-building wasn't setting default values correctly in the first place). This patch makes it so that the values are *always* arrays by cleaning up the $form_state['values'] (the $submission->data is left alone, since it's already in that format). This makes it so that the form is built correctly to begin with, and we can remove the overriding of #default_value that seems to be causing the problem.

quicksketch’s picture

Status: Needs review » Fixed

Hm, well this patch works so well (corrects both saving of drafts and multiple page forward/back support) that I think we should include it in the next release to get more testing on it. Feels good to remove a hack that shouldn't have been needed to begin with. Committed this to 7.x-4.x.

fenstrat’s picture

Great work Nate. And thanks for the explanation. Forcing the values into an array makes sense. I can confirm it fixes the draft errors I was seeing.

Also, I've cleared some time later in the week to dive into the webform issue queue.

Status: Fixed » Closed (fixed)

Automatically closed -- issue fixed for 2 weeks with no activity.