- Patch #594650 by sun, c960657: provide central ()['values'] clearance.
parent
3cb2a5eff4
commit
c5c46c739c
|
@ -1107,14 +1107,6 @@ function form_builder($form_id, $element, &$form_state) {
|
||||||
// Internet Explorer button-click scenario.
|
// Internet Explorer button-click scenario.
|
||||||
_form_builder_ie_cleanup($element, $form_state);
|
_form_builder_ie_cleanup($element, $form_state);
|
||||||
|
|
||||||
// We should keep the buttons array until the IE clean up function
|
|
||||||
// has recognized the submit button so the form has been marked
|
|
||||||
// as submitted. If we already know which button was submitted,
|
|
||||||
// we don't need the array.
|
|
||||||
if (!empty($form_state['submitted'])) {
|
|
||||||
unset($form_state['buttons']);
|
|
||||||
}
|
|
||||||
|
|
||||||
// If some callback set #cache, we need to flip a flag so later it
|
// If some callback set #cache, we need to flip a flag so later it
|
||||||
// can be found.
|
// can be found.
|
||||||
if (!empty($element['#cache'])) {
|
if (!empty($element['#cache'])) {
|
||||||
|
@ -1290,6 +1282,63 @@ function _form_builder_ie_cleanup($form, &$form_state) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes internal Form API elements and buttons from submitted form values.
|
||||||
|
*
|
||||||
|
* This function can be used when a module wants to store all submitted form
|
||||||
|
* values, for example, by serializing them into a single database column. In
|
||||||
|
* such cases, all internal Form API values and all form button elements should
|
||||||
|
* not be contained, and this function allows to remove them before the module
|
||||||
|
* proceeds to storage. Next to button elements, the following internal values
|
||||||
|
* are removed:
|
||||||
|
* - form_id
|
||||||
|
* - form_token
|
||||||
|
* - form_build_id
|
||||||
|
* - op
|
||||||
|
*
|
||||||
|
* @param &$form_state
|
||||||
|
* A keyed array containing the current state of the form, including
|
||||||
|
* submitted form values; altered by reference.
|
||||||
|
*/
|
||||||
|
function form_state_values_clean(&$form_state) {
|
||||||
|
// Remove internal Form API values.
|
||||||
|
unset($form_state['values']['form_id'], $form_state['values']['form_token'], $form_state['values']['form_build_id'], $form_state['values']['op']);
|
||||||
|
|
||||||
|
// Remove button values.
|
||||||
|
// form_builder() collects all button elements in a form, keyed by button
|
||||||
|
// type. We remove the button value separately for each button element.
|
||||||
|
foreach ($form_state['buttons'] as $button_type => $buttons) {
|
||||||
|
foreach ($buttons as $button) {
|
||||||
|
// Remove this button's value from the submitted form values by finding
|
||||||
|
// the value corresponding to this button.
|
||||||
|
// We iterate over the #parents of this button and move a reference to
|
||||||
|
// each parent in $form_state['values']. For example, if #parents is:
|
||||||
|
// array('foo', 'bar', 'baz')
|
||||||
|
// then the corresponding $form_state['values'] part will look like this:
|
||||||
|
// array(
|
||||||
|
// 'foo' => array(
|
||||||
|
// 'bar' => array(
|
||||||
|
// 'baz' => 'button_value',
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
// )
|
||||||
|
// We start by (re)moving 'baz' to $last_parent, so we are able unset it
|
||||||
|
// at the end of the iteration. Initially, $values will contain a
|
||||||
|
// reference to $form_state['values'], but in the iteration we move the
|
||||||
|
// reference to $form_state['values']['foo'], and finally to
|
||||||
|
// $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];
|
||||||
|
}
|
||||||
|
unset($values[$last_parent]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper function to determine the value for an image button form element.
|
* Helper function to determine the value for an image button form element.
|
||||||
*
|
*
|
||||||
|
|
|
@ -463,3 +463,52 @@ class FormsFormWrapperTestCase extends DrupalWebTestCase {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test $form_state clearance.
|
||||||
|
*/
|
||||||
|
class FormStateValuesCleanTestCase extends DrupalWebTestCase {
|
||||||
|
public static function getInfo() {
|
||||||
|
return array(
|
||||||
|
'name' => 'Form state values clearance',
|
||||||
|
'description' => 'Test proper removal of submitted form values using form_state_values_clean().',
|
||||||
|
'group' => 'Form API',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function setUp() {
|
||||||
|
parent::setUp('form_test');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests form_state_values_clean().
|
||||||
|
*/
|
||||||
|
function testFormStateValuesClean() {
|
||||||
|
$this->drupalPost('form_test/form-state-values-clean', array(), t('Submit'));
|
||||||
|
$values = json_decode($this->content, TRUE);
|
||||||
|
|
||||||
|
// Setup the expected result.
|
||||||
|
$result = array(
|
||||||
|
'beer' => 1000,
|
||||||
|
'baz' => array('beer' => 2000),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Verify that all internal Form API elements were removed.
|
||||||
|
$this->assertFalse(isset($values['form_id']), t('%element was removed.', array('%element' => 'form_id')));
|
||||||
|
$this->assertFalse(isset($values['form_token']), t('%element was removed.', array('%element' => 'form_token')));
|
||||||
|
$this->assertFalse(isset($values['form_build_id']), t('%element was removed.', array('%element' => 'form_build_id')));
|
||||||
|
$this->assertFalse(isset($values['op']), t('%element was removed.', array('%element' => 'op')));
|
||||||
|
|
||||||
|
// Verify that all buttons were removed.
|
||||||
|
$this->assertFalse(isset($values['foo']), t('%element was removed.', array('%element' => 'foo')));
|
||||||
|
$this->assertFalse(isset($values['bar']), t('%element was removed.', array('%element' => 'bar')));
|
||||||
|
$this->assertFalse(isset($values['baz']['foo']), t('%element was removed.', array('%element' => 'foo')));
|
||||||
|
$this->assertFalse(isset($values['baz']['baz']), t('%element was removed.', array('%element' => 'baz')));
|
||||||
|
|
||||||
|
// Verify that nested form value still exists.
|
||||||
|
$this->assertTrue(isset($values['baz']['beer']), t('Nested form value still exists.'));
|
||||||
|
|
||||||
|
// Verify that actual form values equal resulting form values.
|
||||||
|
$this->assertEqual($values, $result, t('Expected form values equal actual form values.'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -62,6 +62,14 @@ function form_test_menu() {
|
||||||
'type' => MENU_CALLBACK,
|
'type' => MENU_CALLBACK,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
$items['form_test/form-state-values-clean'] = array(
|
||||||
|
'title' => 'Form state values clearance test',
|
||||||
|
'page callback' => 'drupal_get_form',
|
||||||
|
'page arguments' => array('form_test_form_state_values_clean_form'),
|
||||||
|
'access arguments' => array('access content'),
|
||||||
|
'type' => MENU_CALLBACK,
|
||||||
|
);
|
||||||
|
|
||||||
return $items;
|
return $items;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -361,3 +369,27 @@ function form_test_wrapper_callback_form($form, &$form_state) {
|
||||||
return $form;
|
return $form;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Form builder for form_state_values_clean() test.
|
||||||
|
*/
|
||||||
|
function form_test_form_state_values_clean_form($form, &$form_state) {
|
||||||
|
// Build an example form containing multiple submit and button elements; not
|
||||||
|
// only on the top-level.
|
||||||
|
$form = array('#tree' => TRUE);
|
||||||
|
$form['foo'] = array('#type' => 'submit', '#value' => t('Submit'));
|
||||||
|
$form['bar'] = array('#type' => 'submit', '#value' => t('Submit'));
|
||||||
|
$form['beer'] = array('#type' => 'value', '#value' => 1000);
|
||||||
|
$form['baz']['foo'] = array('#type' => 'button', '#value' => t('Submit'));
|
||||||
|
$form['baz']['baz'] = array('#type' => 'submit', '#value' => t('Submit'));
|
||||||
|
$form['baz']['beer'] = array('#type' => 'value', '#value' => 2000);
|
||||||
|
return $form;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Form submit handler for form_state_values_clean() test form.
|
||||||
|
*/
|
||||||
|
function form_test_form_state_values_clean_form_submit($form, &$form_state) {
|
||||||
|
form_state_values_clean($form_state);
|
||||||
|
drupal_json_output($form_state['values']);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
|
@ -2332,7 +2332,7 @@ function system_settings_form($form, $automatic_defaults = TRUE) {
|
||||||
*/
|
*/
|
||||||
function system_settings_form_submit($form, &$form_state) {
|
function system_settings_form_submit($form, &$form_state) {
|
||||||
// Exclude unnecessary elements.
|
// Exclude unnecessary elements.
|
||||||
unset($form_state['values']['submit'], $form_state['values']['reset'], $form_state['values']['form_id'], $form_state['values']['op'], $form_state['values']['form_token'], $form_state['values']['form_build_id']);
|
form_state_values_clean($form_state);
|
||||||
|
|
||||||
foreach ($form_state['values'] as $key => $value) {
|
foreach ($form_state['values'] as $key => $value) {
|
||||||
if (is_array($value) && isset($form_state['values']['array_filter'])) {
|
if (is_array($value) && isset($form_state['values']['array_filter'])) {
|
||||||
|
|
|
@ -3116,7 +3116,8 @@ function user_register_submit($form, &$form_state) {
|
||||||
|
|
||||||
// The unset below is needed to prevent these form values from being saved as
|
// The unset below is needed to prevent these form values from being saved as
|
||||||
// user data.
|
// user data.
|
||||||
unset($form_state['values']['form_token'], $form_state['values']['submit'], $form_state['values']['op'], $form_state['values']['notify'], $form_state['values']['form_id'], $form_state['values']['affiliates'], $form_state['values']['destination'], $form_state['values']['form_build_id']);
|
form_state_values_clean($form_state);
|
||||||
|
unset($form_state['values']['notify']);
|
||||||
|
|
||||||
$form_state['values']['pass'] = $pass;
|
$form_state['values']['pass'] = $pass;
|
||||||
$form_state['values']['init'] = $form_state['values']['mail'];
|
$form_state['values']['init'] = $form_state['values']['mail'];
|
||||||
|
|
|
@ -269,7 +269,8 @@ function user_profile_form_validate($form, &$form_state) {
|
||||||
function user_profile_form_submit($form, &$form_state) {
|
function user_profile_form_submit($form, &$form_state) {
|
||||||
$account = $form['#user'];
|
$account = $form['#user'];
|
||||||
$category = $form['#user_category'];
|
$category = $form['#user_category'];
|
||||||
unset($form_state['values']['op'], $form_state['values']['submit'], $form_state['values']['cancel'], $form_state['values']['form_token'], $form_state['values']['form_id'], $form_state['values']['form_build_id']);
|
// Remove unneeded values.
|
||||||
|
form_state_values_clean($form_state);
|
||||||
|
|
||||||
$edit = (object)$form_state['values'];
|
$edit = (object)$form_state['values'];
|
||||||
field_attach_submit('user', $edit, $form, $form_state);
|
field_attach_submit('user', $edit, $form, $form_state);
|
||||||
|
|
Loading…
Reference in New Issue