Issue #2337709 by tim.plunkett: Convert form_state_values_clean() to FormStateInterface::cleanValues().

8.0.x
Alex Pott 2014-09-16 12:16:27 +01:00
parent 332fad7c22
commit 179e7c2bd1
13 changed files with 87 additions and 72 deletions

View File

@ -99,59 +99,11 @@ function form_builder($form_id, &$element, FormStateInterface $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
* The current state of the form, including submitted form values.
* @deprecated in Drupal 8.x-dev, will be removed before Drupal 8.0.0.
* Use $form_state->cleanValues().
*/
function form_state_values_clean(FormStateInterface $form_state) {
// Remove internal Form API values.
$form_state
->unsetValue('form_id')
->unsetValue('form_token')
->unsetValue('form_build_id')
->unsetValue('op');
// Remove button values.
// form_builder() collects all button elements in a form. We remove the button
// value separately for each button element.
foreach ($form_state->getButtons() 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->getValues(). For example, if #parents is:
// array('foo', 'bar', 'baz')
// then the corresponding $form_state->getValues() 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->getValues(), but in the iteration we move the
// reference to $form_state->getValue('foo'), and finally to
// $form_state->getValue(array('foo', 'bar')), which is the level where we
// can unset 'baz' (that is stored in $last_parent).
$parents = $button['#parents'];
$last_parent = array_pop($parents);
$key_exists = NULL;
$values = &NestedArray::getValue($form_state->getValues(), $parents, $key_exists);
if ($key_exists && is_array($values)) {
unset($values[$last_parent]);
}
}
$form_state->cleanValues();
}
/**

View File

@ -258,7 +258,7 @@ class EntityForm extends FormBase implements EntityFormInterface {
*/
public function submitForm(array &$form, FormStateInterface $form_state) {
// Remove button and internal Form API values from submitted values.
form_state_values_clean($form_state);
$form_state->cleanValues();
$this->entity = $this->buildEntity($form, $form_state);
}

View File

@ -972,8 +972,8 @@ class FormBuilder implements FormBuilderInterface, FormValidatorInterface, FormS
// Determine which element (if any) triggered the submission of the form and
// keep track of all the clickable buttons in the form for
// form_state_values_clean(). Enforce the same input processing restrictions
// as above.
// \Drupal\Core\Form\FormState::cleanValues(). Enforce the same input
// processing restrictions as above.
if ($process_input) {
// Detect if the element triggered the submission via Ajax.
if ($this->elementTriggeredScriptedSubmission($element, $form_state)) {
@ -986,9 +986,9 @@ class FormBuilder implements FormBuilderInterface, FormValidatorInterface, FormS
// information.
if (!empty($element['#is_button'])) {
// All buttons in the form need to be tracked for
// form_state_values_clean() and for the self::doBuildForm() code that
// handles a form submission containing no button information in
// \Drupal::request()->request.
// \Drupal\Core\Form\FormState::cleanValues() and for the
// self::doBuildForm() code that handles a form submission containing no
// button information in \Drupal::request()->request.
$buttons = $form_state->getButtons();
$buttons[] = $element;
$form_state->setButtons($buttons);

View File

@ -1128,6 +1128,50 @@ class FormState implements FormStateInterface {
return $this->getBuildInfo()['callback_object'];
}
/**
* {@inheritdoc}
*/
public function cleanValues() {
// Remove internal Form API values.
$this
->unsetValue('form_id')
->unsetValue('form_token')
->unsetValue('form_build_id')
->unsetValue('op');
// Remove button values.
// form_builder() collects all button elements in a form. We remove the button
// value separately for each button element.
foreach ($this->getButtons() 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 self::getValues(). For example, if #parents is:
// array('foo', 'bar', 'baz')
// then the corresponding self::getValues() 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 self::getValues(), but in the iteration we move the
// reference to self::getValue('foo'), and finally to
// self::getValue(array('foo', 'bar')), which is the level where we
// can unset 'baz' (that is stored in $last_parent).
$parents = $button['#parents'];
$last_parent = array_pop($parents);
$key_exists = NULL;
$values = &NestedArray::getValue($this->getValues(), $parents, $key_exists);
if ($key_exists && is_array($values)) {
unset($values[$last_parent]);
}
}
}
/**
* Wraps drupal_set_message().
*

View File

@ -987,4 +987,22 @@ interface FormStateInterface {
*/
public function isValidationComplete();
/**
* 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
*
* @return $this
*/
public function cleanValues();
}

View File

@ -116,7 +116,7 @@ abstract class ImageEffectFormBase extends FormBase {
* {@inheritdoc}
*/
public function submitForm(array &$form, FormStateInterface $form_state) {
form_state_values_clean($form_state);
$form_state->cleanValues();
// The image effect configuration is stored in the 'data' key in the form,
// pass that through for submission.

View File

@ -168,7 +168,7 @@ abstract class PathFormBase extends FormBase {
*/
public function submitForm(array &$form, FormStateInterface $form_state) {
// Remove unnecessary values.
form_state_values_clean($form_state);
$form_state->cleanValues();
$pid = $form_state->getValue('pid', 0);
$source = &$form_state->getValue('source');

View File

@ -383,7 +383,7 @@ class ThemeSettingsForm extends ConfigFormBase {
$config = $this->config($form_state->getValue('config_key'));
// Exclude unnecessary elements before saving.
form_state_values_clean($form_state);
$form_state->cleanValues();
$form_state->unsetValue('var');
$form_state->unsetValue('config_key');

View File

@ -10,8 +10,9 @@ namespace Drupal\system\Tests\Form;
use Drupal\simpletest\WebTestBase;
/**
* Tests proper removal of submitted form values using form_state_values_clean()
* when having forms with elements containing buttons like "managed_file".
* Tests proper removal of submitted form values using
* \Drupal\Core\Form\FormState::cleanValues() when having forms with elements
* containing buttons like "managed_file".
*
* @group Form
*/
@ -30,7 +31,7 @@ class StateValuesCleanAdvancedTest extends WebTestBase {
protected $image;
/**
* Tests form_state_values_clean().
* Tests \Drupal\Core\Form\FormState::cleanValues().
*/
function testFormStateValuesCleanAdvanced() {

View File

@ -12,7 +12,7 @@ use Drupal\simpletest\WebTestBase;
/**
* Tests proper removal of submitted form values using
* form_state_values_clean().
* \Drupal\Core\Form\FormState::cleanValues().
*
* @group Form
*/
@ -26,7 +26,7 @@ class StateValuesCleanTest extends WebTestBase {
public static $modules = array('form_test');
/**
* Tests form_state_values_clean().
* Tests \Drupal\Core\Form\FormState::cleanValues().
*/
function testFormStateValuesClean() {
$values = Json::decode($this->drupalPostForm('form_test/form-state-values-clean', array(), t('Submit')));

View File

@ -11,7 +11,7 @@ use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormStateInterface;
/**
* Form builder for form_state_values_clean() test.
* Form builder for \Drupal\Core\Form\FormState::cleanValues() test.
*/
class FormTestFormStateValuesCleanAdvancedForm extends FormBase {
@ -19,7 +19,7 @@ class FormTestFormStateValuesCleanAdvancedForm extends FormBase {
* {@inheritdoc}
*/
public function getFormId() {
return 'form_test_form_state_values_clean_advanced_form';
return 'form_test_form_state_clean_values_advanced_form';
}
/**
@ -44,7 +44,7 @@ class FormTestFormStateValuesCleanAdvancedForm extends FormBase {
* {@inheritdoc}
*/
public function submitForm(array &$form, FormStateInterface $form_state) {
form_state_values_clean($form_state);
$form_state->cleanValues();
print t('You WIN!');
exit;
}

View File

@ -12,7 +12,7 @@ use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormStateInterface;
/**
* Form builder for form_state_values_clean() test.
* Form builder for \Drupal\Core\Form\FormState::cleanValues() test.
*/
class FormTestFormStateValuesCleanForm extends FormBase {
@ -20,7 +20,7 @@ class FormTestFormStateValuesCleanForm extends FormBase {
* {@inheritdoc}
*/
public function getFormId() {
return 'form_test_form_state_values_clean_form';
return 'form_test_form_state_clean_values_form';
}
/**
@ -43,7 +43,7 @@ class FormTestFormStateValuesCleanForm extends FormBase {
* {@inheritdoc}
*/
public function submitForm(array &$form, FormStateInterface $form_state) {
form_state_values_clean($form_state);
$form_state->cleanValues();
// This won't have a proper JSON header, but Drupal doesn't check for that
// anyway so this is fine until it's replaced with a JsonResponse.
print Json::encode($form_state->getValues());

View File

@ -91,7 +91,7 @@ class RegisterForm extends AccountForm {
}
// Remove unneeded values.
form_state_values_clean($form_state);
$form_state->cleanValues();
$form_state->setValue('pass', $pass);
$form_state->setValue('init', $form_state->getValue('mail'));