Hey Webformers!
Short but important: In my case, the webform submission is triggered too early when I make use of pagebreaks -- after pressing 'next page', webform behaves as if I had presse 'submit'. Strange error. Thanks for fixing it.

Comments

Blooniverse’s picture

Title: Webform submission triggered too early when using pagebreaks » Submission triggered too early -- when using pagebreaks

... as described on #1084464: Webform submission fails -- when pagebreaks & option 'automatically save as draft between pages' are on , my multi-step webforms still trigger the submission process too early, even after ticking off the checkbox 'Automatically save draft between pages'!

Blooniverse’s picture

... the bug can surely be found in webform_client_form_pages($form, &$form_state) (from line 2039 on). Although I am not a webform maintainer, I cannot resist to experiment briefly -- will inform you about the outcome in ~1h!

/**
 * Handle the processing of pages and conditional logic.
 */
function webform_client_form_pages($form, &$form_state) {
  $node = node_load($form_state['values']['details']['nid']);

  // Move special settings to storage.
  if (isset($form_state['webform']['component_tree'])) {
    $form_state['storage']['component_tree'] = $form_state['webform']['component_tree'];
    $form_state['storage']['page_count'] = $form_state['webform']['page_count'];
    $form_state['storage']['page_num'] = $form_state['webform']['page_num'];
  }

  // Perform post processing by components.
  _webform_client_form_submit_process($node, $form_state['values']['submitted']);

  // Flatten trees within the submission.
  $form_state['values']['submitted_tree'] = $form_state['values']['submitted'];
  $form_state['values']['submitted'] = _webform_client_form_submit_flatten($node, $form_state['values']['submitted']);

  // Assume the form is completed unless the page logic says otherwise.
  $form_state['webform_completed'] = TRUE;

  // Check for a multi-page form that is not yet complete.
  $submit_op = !empty($form['actions']['submit']['#value']) ? $form['actions']['submit']['#value'] : t('Submit');
  $draft_op = !empty($form['actions']['draft']['#value']) ? $form['actions']['draft']['#value'] : t('Save Draft');
  if (!in_array($form_state['values']['op'], array($submit_op, $draft_op))) {
    // Checkboxes need post-processing to maintain their values.
    _webform_client_form_submit_process($node, $form_state['values']['submitted'], array('select', 'grid'));

    // Store values from the current page in the form state storage.
    if (is_array($form_state['values']['submitted'])) {
      foreach ($form_state['values']['submitted'] as $key => $val) {
        $form_state['storage']['submitted'][$key] = $val;
      }
    }

    // Update form state values with those from storage.
    if (isset($form_state['storage']['submitted'])) {
      foreach ($form_state['storage']['submitted'] as $key => $val) {
        $form_state['values']['submitted'][$key] = $val;
      }
    }

    // Set the page number.
    if (!isset($form_state['storage']['page_num'])) {
      $form_state['storage']['page_num'] = 1;
    }
    if (end($form_state['clicked_button']['#parents']) == 'next') {
      $direction = 1;
    }
    else {
      $direction = 0;
    }

    // If the next page has no components that need to be displayed, skip it.
    if (isset($direction)) {
      $components = $direction ? $node->webform['components'] : array_reverse($node->webform['components'], TRUE);
      $last_component = end($node->webform['components']);
      foreach ($components as $component) {
        if ($component['type'] == 'pagebreak' && (
            $direction == 1 && $component['page_num'] > $form_state['storage']['page_num'] ||
            $direction == 0 && $component['page_num'] <= $form_state['storage']['page_num'])) {
          $previous_pagebreak = $component;
          continue;
        }
        if (isset($previous_pagebreak)) {
          $page_num = $previous_pagebreak['page_num'] + $direction - 1;
          // If we've found an component on this page, advance to that page.
          if ($component['page_num'] == $page_num && _webform_client_form_rule_check($node, $component, $page_num, $form_state)) {
            $form_state['storage']['page_num'] = $page_num;
            break;
          }
          // If we've gotten to the end of the form without finding any more
          // components, set the page number more than the max, ending the form.
          elseif ($direction && $component['cid'] == $last_component['cid']) {
            $form_state['storage']['page_num'] = $page_num + 1;
          }
        }
      }
    }

    // The form is done if the page number is greater than the page count.
    $form_state['webform_completed'] = $form_state['storage']['page_num'] > $form_state['storage']['page_count'];
  }

  // Merge any stored submission data for multistep forms.
  if (isset($form_state['storage']['submitted'])) {
    $original_values = is_array($form_state['values']['submitted']) ? $form_state['values']['submitted'] : array();
    unset($form_state['values']['submitted']);

    foreach ($form_state['storage']['submitted'] as $key => $val) {
      $form_state['values']['submitted'][$key] = $val;
    }
    foreach ($original_values as $key => $val) {
      $form_state['values']['submitted'][$key] = $val;
    }

    // Remove the variable so it doesn't show up in the additional processing.
    unset($original_values);
  }

  // Inform the submit handlers that a draft will be saved.
  if ($form_state['values']['op'] == $draft_op || ($node->webform['auto_save'] && !$form_state['webform_completed'])) {
    $form_state['save_draft'] = TRUE;
  }

  // Determine what we need to do on the next page.
  if (!empty($form_state['save_draft']) || !$form_state['webform_completed']) {
    // Rebuild the form and display the current (on drafts) or next page.
    $form_state['rebuild'] = TRUE;
  }
  else {
    // Remove the form state storage now that we're done with the pages.
    unset($form_state['rebuild']);
    unset($form_state['storage']);
  }
}
Blooniverse’s picture

Title: Submission triggered too early -- when using pagebreaks » Webform submission triggered too early -- when using pagebreaks
Project: Webform » Webform Validation
Version: 7.x-3.9 » 7.x-1.0-rc1
Issue tags: +webform

This is clearly a bug of the module 'Webform Validation' (http://drupal.org/project/webform_validation). Changing the issue settings accordingly.

I tested this procedure on a Drupal7 test system with barely any contributed/optional modules. As soon as I switch on 'Webform Validation', I get the error as described above.

Thanks for fixing!!!

jtwalters’s picture

Isn't it desired behavior to validate the page at each form submit?

Blooniverse’s picture

Hey @jtwalters! Thanks for asking this.
Well, yes, naturally after every multi-step procedure/page 'Webform Validation' should check. It is absolutely correct if the validation module checks after pressing the 'next' button -- but this action should not lead to a premature submission! Which it does on my system (barebone test system & full ~80+contrib modules edition/system).

svendecabooter’s picture

Hmm the webform_validation module basically only adds a validate function to webforms, and sets form_set_error() when a validation rule was not met, so I can't see how it would trigger a (premature or other) form submission, as that part is totally handled by Webform / Form API.

Could you elaborate some more on what you are doing, what the desired outcome is, and what the desired outcome is, so I can have a better view on the issue?
Thanks

Blooniverse’s picture

Hey @svendecabooter! Thanks for your question.

  1. This case is just about creating a multi-step webform. Its submission should take place at the end, not after the first step.
  2. As described in #3 & #5 a 'bug relation/link' to 'Webform Validation' seems to be evident.

Comment#2

If there is a bug link to the Webform module, then it must be found somewhere here (below), I guess:

  • // Check for a multi-page form that is not yet complete.
  • // If the next page has no components that need to be displayed, skip it.
  • // The form is done if the page number is greater than the page count.
svendecabooter’s picture

Status: Active » Postponed (maintainer needs more info)

Can anyone else reproduce this?
I have tested this module with tons of different webforms, on different sites, and different branches (D6/D7 - Webform 2.x / 3.x), and never was my webform submitted (i.e. stored in the database) before the whole form was completed without validation errors.

There was a problem with the counting of pages in the webform (see #833500: Doesn't work for fields inside a fieldset), so if you do a git clone of the latest code, that might solve your issue.
However I can't see why that would be the case, since webform_validation doesn't trigger form submissions at all, but who knows, I might be wrong :)

Sven

Blooniverse’s picture

... thanks, @svendecabooter. I am going to check out your advice coming week, when I have more time.

Blooniverse’s picture

... still haven't found time yet. Sorry!

branana’s picture

I can confirm I'm getting this error as well. I'm going to debug webform_client_form_pages() a bit. I don't have webform validations

branana’s picture

I found that neither submit handlers webform_client_form_pages() nor webform_client_form_submit() due to my "component tree" index in form_state being too large and whatever webform is doing to the database in between each page break is trying to write too much to the database. I was able to get around this problem by increasing the max_allowed_packet variable to 32M, up from 1M in my.cnf.

dazrour’s picture

So has something changed in Webform to increase the amount of data being wrote to the database. I had a number of working multipage forms then for some reason they now dont work. I am unable to increase the max_allowed_packets, has anyone found another work around or fix?

svendecabooter’s picture

Webform validation doesn't add anything extra to the database when you try to submit a form that has validation rules.
It merely checks which rules are applicable, and uses form_set_error() to mark specific form component(s) as invalid, based on the rules you defined. No database interactions there (except getting the rules from the database, but those are just retrieval queries).

Can you elaborate on what's not working with the forms? Note that there are some options in the Webform module itself regarding multipage forms (e.g. saving drafts each step of the form, etc...) that might cause problems in your setup.

jansenCreative’s picture

Version: 7.x-1.0-rc1 » 7.x-1.1
Component: Code » Documentation
Category: bug » support
Priority: Major » Critical

I am a front end user for Drupal and I have created a webform with 3 pagebreaks and multiple selections. I am encountering the issue listed above. I am fairly certain my issue is how my form is set up or organized, I just can't find documentation/education on advanced webforms without using PHP.

I am trying to find any documentation or tutorials on:

  1. Creating webforms with more than two pagebreaks
  2. and since the above advocates the installation of Webform Validation, the documentation I have found tells me on overview of what the module does but not how to create and implement rules to my webform
Liam Morland’s picture

Project: Webform Validation » Webform
Version: 7.x-1.1 » 7.x-4.x-dev
Component: Documentation » Code
Category: support » bug
Priority: Critical » Normal
Status: Postponed (maintainer needs more info) » Closed (duplicate)

I think the original issue is the same as #1781490: Conditional fields can cause form to submit unexpectedly. The issue is clicking on "Next Page" causing a form submit because conditionals hide all following form components. I am closing this as a duplicate because the discussion there is more focused on what the desired behavior should be. I don't think this has anything to do with Webform Validation; I have it turned off and I still see this issue.