diff --git a/includes/form.inc b/includes/form.inc index 47d8c9908b97c6998deaacd512e01c6c8bd5ad6b..4ae2bb40bde3bbf7b26246a5b6052118da67d764 100644 --- a/includes/form.inc +++ b/includes/form.inc @@ -231,12 +231,12 @@ function drupal_build_form($form_id, &$form_state) { // the form will simply be re-rendered with the values still in its // fields. // - // If $form_state['rebuild'] has been set and the form has been submitted, we + // If $form_state['rebuild'] has been set and input has been processed, we // know that we're in a multi-part process of some sort and the form's // workflow is not complete. We need to construct a fresh copy of the form, // passing in the latest $form_state in addition to any other variables passed // into drupal_get_form(). - if ($form_state['rebuild'] && $form_state['submitted'] && !form_get_errors()) { + if ($form_state['rebuild'] && $form_state['process_input'] && !form_get_errors()) { $form = drupal_rebuild_form($form_id, $form_state); } // After processing the form, the form builder or a #process callback may diff --git a/modules/simpletest/tests/form.test b/modules/simpletest/tests/form.test index f1c40b2293727930276f70366e7bdd9602f3c195..ba6a5d622c7b3efff2af7e73fc9885f42cc805d2 100644 --- a/modules/simpletest/tests/form.test +++ b/modules/simpletest/tests/form.test @@ -559,11 +559,28 @@ class FormsFormStorageTestCase extends DrupalWebTestCase { * Tests using the form in a usual way. */ function testForm() { - $this->drupalPost('form_test/form-storage', array('title' => 'new', 'value' => 'value_is_set'), 'Continue'); - $this->assertText('Form constructions: 2', t('The form has been constructed two times till now.')); + $this->drupalGet('form_test/form-storage'); + $this->assertText('Form constructions: 1'); + + $edit = array('title' => 'new', 'value' => 'value_is_set'); + // Reload the form, but don't rebuild. + $this->drupalPost(NULL, $edit, 'Reload'); + $this->assertText('Form constructions: 2'); + + // Now use form rebuilding triggered by a submit button. + $this->drupalPost(NULL, $edit, 'Continue submit'); + $this->assertText('Form constructions: 3'); + $this->assertText('Form constructions: 4'); + + // Reset the form to the values of the storage, using a form rebuild + // triggered by button of type button. + $this->drupalPost(NULL, array('title' => 'changed'), 'Reset'); + $this->assertFieldByName('title', 'new', 'Values have been resetted.'); + // After rebuilding, the form has been cached. + $this->assertText('Form constructions: 5'); - $this->drupalPost(NULL, array(), 'Save'); - $this->assertText('Form constructions: 3', t('The form has been constructed three times till now.')); + $this->drupalPost(NULL, $edit, 'Save'); + $this->assertText('Form constructions: 5'); $this->assertText('Title: new', t('The form storage has stored the values.')); } @@ -571,11 +588,26 @@ class FormsFormStorageTestCase extends DrupalWebTestCase { * Tests using the form with an activated $form_state['cache'] property. */ function testFormCached() { - $this->drupalPost('form_test/form-storage', array('title' => 'new', 'value' => 'value_is_set'), 'Continue', array('query' => array('cache' => 1))); - $this->assertText('Form constructions: 1', t('The form has been constructed one time till now.')); + $this->drupalGet('form_test/form-storage', array('query' => array('cache' => 1))); + $this->assertText('Form constructions: 1'); + + $edit = array('title' => 'new', 'value' => 'value_is_set'); + // Reload the form, but don't rebuild. + $this->drupalPost(NULL, $edit, 'Reload'); + $this->assertNoText('Form constructions'); - $this->drupalPost(NULL, array(), 'Save', array('query' => array('cache' => 1))); - $this->assertText('Form constructions: 2', t('The form has been constructed two times till now.')); + // Now use form rebuilding triggered by a submit button. + $this->drupalPost(NULL, $edit, 'Continue submit'); + $this->assertText('Form constructions: 2'); + + // Reset the form to the values of the storage, using a form rebuild + // triggered by button of type button. + $this->drupalPost(NULL, array('title' => 'changed'), 'Reset'); + $this->assertFieldByName('title', 'new', 'Values have been resetted.'); + $this->assertText('Form constructions: 3'); + + $this->drupalPost(NULL, $edit, 'Save'); + $this->assertText('Form constructions: 3'); $this->assertText('Title: new', t('The form storage has stored the values.')); } @@ -583,8 +615,8 @@ class FormsFormStorageTestCase extends DrupalWebTestCase { * Tests validation when form storage is used. */ function testValidation() { - $this->drupalPost('form_test/form-storage', array('title' => '', 'value' => 'value_is_set'), 'Continue'); - $this->assertPattern('/value_is_set/', t("The input values have been kept.")); + $this->drupalPost('form_test/form-storage', array('title' => '', 'value' => 'value_is_set'), 'Continue submit'); + $this->assertPattern('/value_is_set/', t('The input values have been kept.')); } /** @@ -605,7 +637,7 @@ class FormsFormStorageTestCase extends DrupalWebTestCase { // 'title' into form storage, but we want to verify that changes in the form // storage are updated in the cache during form validation. $edit = array('title' => 'foo'); - $this->drupalPost(NULL, $edit, 'Continue'); + $this->drupalPost(NULL, $edit, 'Continue submit'); // In step 2, trigger a validation error for the required 'title' field, and // post the special 'change_title' value for the 'value' field, which @@ -616,13 +648,10 @@ class FormsFormStorageTestCase extends DrupalWebTestCase { // At this point, the form storage should contain updated values, but we do // not see them, because the form has not been rebuilt yet due to the - // validation error. Post again with an arbitrary 'title' (which is only - // updated in form storage in step 1) and verify that the rebuilt form - // contains the values of the updated form storage. - $edit = array('title' => 'foo', 'value' => ''); - $this->drupalPost(NULL, $edit, 'Save'); - $this->assertFieldByName('title', 'title_changed', t('The altered form storage value was updated in cache and taken over.')); - $this->assertText('Title: title_changed', t('The form storage has stored the values.')); + // validation error. Post again and verify that the rebuilt form contains + // the values of the updated form storage. + $this->drupalPost(NULL, array('title' => 'foo', 'value' => 'bar'), 'Save'); + $this->assertText("The thing has been changed.", 'The altered form storage value was updated in cache and taken over.'); } /** diff --git a/modules/simpletest/tests/form_test.module b/modules/simpletest/tests/form_test.module index d871a6654463eff262021f68b733774a503b4a28..2036204ba26189157ee30838c00319e13f0c0f77 100644 --- a/modules/simpletest/tests/form_test.module +++ b/modules/simpletest/tests/form_test.module @@ -420,11 +420,10 @@ function form_test_storage_form($form, &$form_state) { 'value' => '', ), ); - $form_state['storage'] += array('step' => 1); } - - // Count how often the form is constructed + // Count how often the form is constructed. $_SESSION['constructions']++; + drupal_set_message("Form constructions: ". $_SESSION['constructions']); $form['title'] = array( '#type' => 'textfield', @@ -438,22 +437,26 @@ function form_test_storage_form($form, &$form_state) { '#default_value' => $form_state['storage']['thing']['value'], '#element_validate' => array('form_test_storage_element_validate_value_cached'), ); - if ($form_state['storage']['step'] == 1) { - $form['submit'] = array( - '#type' => 'submit', - '#value' => 'Continue', - ); - } - else { - $form['body'] = array( - '#type' => 'item', - '#value' => 'This is the second step.', - ); - $form['submit'] = array( - '#type' => 'submit', - '#value' => 'Save', - ); - } + $form['button'] = array( + '#type' => 'button', + '#value' => 'Reload', + // Reload the form (don't rebuild), thus we start at the initial step again. + ); + $form['continue_button'] = array( + '#type' => 'button', + '#value' => 'Reset', + // Rebuilds the form without keeping the values. + '#validate' => array('form_storage_test_form_continue_validate'), + ); + $form['continue_submit'] = array( + '#type' => 'submit', + '#value' => 'Continue submit', + '#submit' => array('form_storage_test_form_continue_submit'), + ); + $form['submit'] = array( + '#type' => 'submit', + '#value' => 'Save', + ); if (isset($_REQUEST['cache'])) { // Manually activate caching, so we can test that the storage keeps working @@ -470,12 +473,12 @@ function form_test_storage_form($form, &$form_state) { * Tests updating of cached form storage during validation. */ function form_test_storage_element_validate_value_cached($element, &$form_state) { - // If caching is enabled and we receive a certain value, change the value of - // 'title'. This presumes that another submitted form value triggers a - // validation error elsewhere in the form. Form API should still update the - // cached form storage though. + // If caching is enabled and we receive a certain value, change the storage. + // This presumes that another submitted form value triggers a validation error + // elsewhere in the form. Form API should still update the cached form storage + // though. if (isset($_REQUEST['cache']) && $form_state['values']['value'] == 'change_title') { - $form_state['storage']['thing']['title'] = 'title_changed'; + $form_state['storage']['thing']['changed'] = TRUE; // @todo Fix FAPI to make it unnecessary to explicitly set the cache flag in // this situation. @see http://drupal.org/node/641356. $form_state['cache'] = TRUE; @@ -483,19 +486,33 @@ function form_test_storage_element_validate_value_cached($element, &$form_state) } /** - * Form submit handler for form_test_storage_form(). + * Form submit handler to continue multi-step form. */ -function form_test_storage_form_submit($form, &$form_state) { - if ($form_state['storage']['step'] == 1) { - $form_state['storage']['thing']['title'] = $form_state['values']['title']; - $form_state['storage']['thing']['value'] = $form_state['values']['value']; - } - else { - drupal_set_message("Title: ". check_plain($form_state['storage']['thing']['title'])); - } +function form_storage_test_form_continue_submit($form, &$form_state) { + $form_state['storage']['thing']['title'] = $form_state['values']['title']; + $form_state['storage']['thing']['value'] = $form_state['values']['value']; + $form_state['rebuild'] = TRUE; +} + +/** + * Form validation handler, which doesn't preserve the values but rebuilds the + * form. We cannot use a submit handler here, as buttons of type button don't + * submit the form. + */ +function form_storage_test_form_continue_validate($form, &$form_state) { $form_state['rebuild'] = TRUE; - $form_state['storage']['step']++; +} + +/** + * Form submit handler to finish multi-step form. + */ +function form_test_storage_form_submit($form, &$form_state) { + drupal_set_message("Title: ". check_plain($form_state['values']['title'])); drupal_set_message("Form constructions: ". $_SESSION['constructions']); + if (isset($form_state['storage']['thing']['changed'])) { + drupal_set_message("The thing has been changed."); + } + $form_state['redirect'] = 'node'; } /**