diff --git a/includes/common.inc b/includes/common.inc index y75dacc2..e50791f 100644 --- a/includes/common.inc +++ b/includes/common.inc @@ -6358,7 +6358,7 @@ function drupal_array_set_nested_value(array &$array, array $parents, $value, $f * * @see drupal_array_set_nested_value() */ -function drupal_array_get_nested_value(array &$array, array $parents, &$key_exists = NULL) { +function &drupal_array_get_nested_value(array &$array, array $parents, &$key_exists = NULL) { $ref = &$array; foreach ($parents as $parent) { if (is_array($ref) && array_key_exists($parent, $ref)) { @@ -6366,7 +6366,8 @@ function drupal_array_get_nested_value(array &$array, array $parents, &$key_exis } else { $key_exists = FALSE; - return NULL; + $null = NULL; + return $null; } } $key_exists = TRUE; diff --git a/includes/form.inc b/includes/form.inc index 00f9533..a12fb34 100644 --- a/includes/form.inc +++ b/includes/form.inc @@ -2142,12 +2142,12 @@ function form_state_values_clean(&$form_state) { // $form_state['values']['foo']['bar'], which is the level where we can // unset 'baz' (that is stored in $last_parent). $parents = $button['#parents']; - $values = &$form_state['values']; $last_parent = array_pop($parents); - foreach ($parents as $parent) { - $values = &$values[$parent]; + $key_exists = NULL; + $values = &drupal_array_get_nested_value($form_state['values'], $parents, $key_exists); + if ($key_exists && is_array($values)) { + unset($values[$last_parent]); } - unset($values[$last_parent]); } } diff --git a/modules/simpletest/tests/form.test b/modules/simpletest/tests/form.test index 1508f4c..70ebf86 100644 --- a/modules/simpletest/tests/form.test +++ b/modules/simpletest/tests/form.test @@ -545,7 +545,7 @@ class FormValidationTestCase extends DrupalWebTestCase { */ function testValidateLimitErrors() { $edit = array( - 'test' => 'invalid', + 'test' => 'invalid', 'test_numeric_index[0]' => 'invalid', 'test_substring[foo]' => 'invalid', ); @@ -1112,6 +1112,51 @@ class FormStateValuesCleanTestCase extends DrupalWebTestCase { } /** + * Tests $form_state clearance with form elements having buttons. + */ +class FormStateValuesCleanAdvancedTestCase extends DrupalWebTestCase { + /** + * An image file path for uploading. + */ + protected $image; + + public static function getInfo() { + return array( + 'name' => 'Form state values clearance (advanced)', + 'description' => 'Test proper removal of submitted form values using form_state_values_clean() when having forms with elements containing buttons like "managed_file".', + 'group' => 'Form API', + ); + } + + function setUp() { + parent::setUp('form_test'); + } + + /** + * Tests form_state_values_clean(). + */ + function testFormStateValuesCleanAdvanced() { + + // Get an image for uploading. + $image_files = $this->drupalGetTestFiles('image'); + $this->image = current($image_files); + + // Check if the physical file is there. + $this->assertTrue(is_file($this->image->uri), t("The image file we're going to upload exists.")); + + // "Browse" for the desired file. + $edit = array('files[image]' => drupal_realpath($this->image->uri)); + + // Post the form. + $this->drupalPost('form_test/form-state-values-clean-advanced', $edit, t('Submit')); + + // Expecting a 200 HTTP code. + $this->assertResponse(200, t('Received a 200 response for posted test file.')); + $this->assertRaw(t('You WIN!'), t('Found the success message.')); + } +} + +/** * Tests form rebuilding. * * @todo Add tests for other aspects of form rebuilding. diff --git a/modules/simpletest/tests/form_test.module b/modules/simpletest/tests/form_test.module index 50b1c68..0393b18 100644 --- a/modules/simpletest/tests/form_test.module +++ b/modules/simpletest/tests/form_test.module @@ -92,6 +92,14 @@ function form_test_menu() { 'type' => MENU_CALLBACK, ); + $items['form_test/form-state-values-clean-advanced'] = array( + 'title' => 'Form state values clearance advanced test', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('form_test_form_state_values_clean_advanced_form'), + 'access arguments' => array('access content'), + 'type' => MENU_CALLBACK, + ); + $items['form-test/checkbox'] = array( 'title' => t('Form test'), 'page callback' => 'drupal_get_form', @@ -803,6 +811,33 @@ function form_test_form_state_values_clean_form_submit($form, &$form_state) { } /** + * Form constructor for the form_state_values_clean() test. + */ +function form_test_form_state_values_clean_advanced_form($form, &$form_state) { + // Build an example form containing a managed file and a submit form element. + $form['image'] = array( + '#type' => 'managed_file', + '#title' => t('Image'), + '#upload_location' => 'public://', + '#default_value' => 0, + ); + $form['submit'] = array( + '#type' => 'submit', + '#value' => t('Submit'), + ); + return $form; +} + +/** + * Form submission handler for form_test_form_state_values_clean_advanced_form(). + */ +function form_test_form_state_values_clean_advanced_form_submit($form, &$form_state) { + form_state_values_clean($form_state); + print t('You WIN!'); + exit; +} + +/** * Build a form to test a checkbox. */ function _form_test_checkbox($form, &$form_state) {