- Patch #642702 by sun: form validation handlers cannot alter structure.
parent
0ba214f943
commit
b608482678
|
@ -726,7 +726,13 @@ function drupal_prepare_form($form_id, &$form, &$form_state) {
|
|||
* A unique string identifying the form for validation, submission,
|
||||
* theming, and hook_form_alter functions.
|
||||
* @param $form
|
||||
* An associative array containing the structure of the form.
|
||||
* An associative array containing the structure of the form, which is passed
|
||||
* by reference. Form validation handlers are able to alter the form structure
|
||||
* (like #process and #after_build callbacks during form building) in case of
|
||||
* a validation error. If a validation handler alters the form structure, it
|
||||
* is responsible for validating the values of changed form elements in
|
||||
* $form_state['values'] to prevent form submit handlers from receiving
|
||||
* unvalidated values.
|
||||
* @param $form_state
|
||||
* A keyed array containing the current state of the form. The current
|
||||
* user-submitted data is stored in $form_state['values'], though
|
||||
|
@ -738,7 +744,7 @@ function drupal_prepare_form($form_id, &$form, &$form_state) {
|
|||
* web service requests, or other expensive requests that should
|
||||
* not be repeated in the submission step.
|
||||
*/
|
||||
function drupal_validate_form($form_id, $form, &$form_state) {
|
||||
function drupal_validate_form($form_id, &$form, &$form_state) {
|
||||
$validated_forms = &drupal_static(__FUNCTION__, array());
|
||||
|
||||
if (isset($validated_forms[$form_id]) && empty($form_state['must_validate'])) {
|
||||
|
@ -846,7 +852,7 @@ function drupal_redirect_form($form_state) {
|
|||
* A unique string identifying the form for validation, submission,
|
||||
* theming, and hook_form_alter functions.
|
||||
*/
|
||||
function _form_validate($elements, &$form_state, $form_id = NULL) {
|
||||
function _form_validate(&$elements, &$form_state, $form_id = NULL) {
|
||||
// Also used in the installer, pre-database setup.
|
||||
$t = get_t();
|
||||
|
||||
|
|
|
@ -152,6 +152,61 @@ class FormsTestCase extends DrupalWebTestCase {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test form validation handlers.
|
||||
*/
|
||||
class FormValidationTestCase extends DrupalWebTestCase {
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'Form validation handlers',
|
||||
'description' => 'Tests form processing and alteration via form validation handlers.',
|
||||
'group' => 'Form API',
|
||||
);
|
||||
}
|
||||
|
||||
function setUp() {
|
||||
parent::setUp('form_test');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests form alterations by #element_validate, #validate, and form_set_value().
|
||||
*/
|
||||
function testValidate() {
|
||||
$this->drupalGet('form-test/validate');
|
||||
// Verify that #element_validate handlers can alter the form and submitted
|
||||
// form values.
|
||||
$edit = array(
|
||||
'name' => 'element_validate',
|
||||
);
|
||||
$this->drupalPost(NULL, $edit, 'Save');
|
||||
$this->assertFieldByName('name', '#value changed by #element_validate', t('Form element #value was altered.'));
|
||||
$this->assertText('Name value: value changed by form_set_value() in #element_validate', t('Form element value in $form_state was altered.'));
|
||||
|
||||
// Verify that #validate handlers can alter the form and submitted
|
||||
// form values.
|
||||
$edit = array(
|
||||
'name' => 'validate',
|
||||
);
|
||||
$this->drupalPost(NULL, $edit, 'Save');
|
||||
$this->assertFieldByName('name', '#value changed by #validate', t('Form element #value was altered.'));
|
||||
$this->assertText('Name value: value changed by form_set_value() in #validate', t('Form element value in $form_state was altered.'));
|
||||
|
||||
// Verify that #element_validate handlers can make form elements
|
||||
// inaccessible, but values persist.
|
||||
$edit = array(
|
||||
'name' => 'element_validate_access',
|
||||
);
|
||||
$this->drupalPost(NULL, $edit, 'Save');
|
||||
$this->assertNoFieldByName('name', t('Form element was hidden.'));
|
||||
$this->assertText('Name value: element_validate_access', t('Value for inaccessible form element exists.'));
|
||||
|
||||
// Verify that value for inaccessible form element persists.
|
||||
$this->drupalPost(NULL, array(), 'Save');
|
||||
$this->assertNoFieldByName('name', t('Form element was hidden.'));
|
||||
$this->assertText('Name value: element_validate_access', t('Value for inaccessible form element exists.'));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the tableselect form element for expected behavior.
|
||||
*/
|
||||
|
|
|
@ -10,6 +10,14 @@
|
|||
* Implement hook_menu().
|
||||
*/
|
||||
function form_test_menu() {
|
||||
$items['form-test/validate'] = array(
|
||||
'title' => 'Form validation handlers test',
|
||||
'page callback' => 'drupal_get_form',
|
||||
'page arguments' => array('form_test_validate_form'),
|
||||
'access arguments' => array('access content'),
|
||||
'type' => MENU_CALLBACK,
|
||||
);
|
||||
|
||||
$items['form_test/tableselect/multiple-true'] = array(
|
||||
'title' => 'Tableselect checkboxes test',
|
||||
'page callback' => 'drupal_get_form',
|
||||
|
@ -81,6 +89,88 @@ function form_test_menu() {
|
|||
return $items;
|
||||
}
|
||||
|
||||
/**
|
||||
* Form builder for testing drupal_validate_form().
|
||||
*
|
||||
* Serves for testing form processing and alterations by form validation
|
||||
* handlers, especially for the case of a validation error:
|
||||
* - form_set_value() should be able to alter submitted values in
|
||||
* $form_state['values'] without affecting the form element.
|
||||
* - #element_validate handlers should be able to alter the $element in the form
|
||||
* structure and the alterations should be contained in the rebuilt form.
|
||||
* - #validate handlers should be able to alter the $form and the alterations
|
||||
* should be contained in the rebuilt form.
|
||||
*/
|
||||
function form_test_validate_form($form, &$form_state) {
|
||||
$form['name'] = array(
|
||||
'#type' => 'textfield',
|
||||
'#title' => 'Name',
|
||||
'#default_value' => '',
|
||||
'#element_validate' => array('form_test_element_validate_name'),
|
||||
);
|
||||
$form['submit'] = array(
|
||||
'#type' => 'submit',
|
||||
'#value' => 'Save',
|
||||
);
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* Form element validation handler for 'name' in form_test_validate_form().
|
||||
*/
|
||||
function form_test_element_validate_name(&$element, &$form_state) {
|
||||
$triggered = FALSE;
|
||||
if ($form_state['values']['name'] == 'element_validate') {
|
||||
// Alter the form element.
|
||||
$element['#value'] = '#value changed by #element_validate';
|
||||
// Alter the submitted value in $form_state.
|
||||
form_set_value($element, 'value changed by form_set_value() in #element_validate', $form_state);
|
||||
|
||||
$triggered = TRUE;
|
||||
}
|
||||
if ($form_state['values']['name'] == 'element_validate_access') {
|
||||
// To simplify this test, enable form caching and use form storage to
|
||||
// remember our alteration.
|
||||
$form_state['cache'] = TRUE;
|
||||
$form_state['storage']['form_test_name'] = $form_state['values']['name'];
|
||||
// Alter the form element.
|
||||
$element['#access'] = FALSE;
|
||||
|
||||
$triggered = TRUE;
|
||||
}
|
||||
elseif (!empty($form_state['storage']['form_test_name'])) {
|
||||
// To simplify this test, just take over the element's value into $form_state.
|
||||
form_set_value($element, $form_state['storage']['form_test_name'], $form_state);
|
||||
|
||||
$triggered = TRUE;
|
||||
}
|
||||
|
||||
if ($triggered) {
|
||||
// Output the element's value from $form_state.
|
||||
drupal_set_message(t('@label value: @value', array('@label' => $element['#title'], '@value' => $form_state['values']['name'])));
|
||||
|
||||
// Trigger a form validation error to see our changes.
|
||||
form_set_error('');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Form validation handler for form_test_validate_form().
|
||||
*/
|
||||
function form_test_validate_form_validate(&$form, &$form_state) {
|
||||
if ($form_state['values']['name'] == 'validate') {
|
||||
// Alter the form element.
|
||||
$form['name']['#value'] = '#value changed by #validate';
|
||||
// Alter the submitted value in $form_state.
|
||||
form_set_value($form['name'], 'value changed by form_set_value() in #validate', $form_state);
|
||||
// Output the element's value from $form_state.
|
||||
drupal_set_message(t('@label value: @value', array('@label' => $form['name']['#title'], '@value' => $form_state['values']['name'])));
|
||||
|
||||
// Trigger a form validation error to see our changes.
|
||||
form_set_error('');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a header and options array. Helper function for callbacks.
|
||||
*/
|
||||
|
|
Loading…
Reference in New Issue