drupal/modules/simpletest/tests/form_test.module

891 lines
26 KiB
Plaintext

<?php
// $Id$
/**
* @file
* Helper module for the form API tests.
*/
/**
* Implements 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/limit-validation-errors'] = array(
'title' => 'Form validation with some error suppression',
'page callback' => 'drupal_get_form',
'page arguments' => array('form_test_limit_validation_errors_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',
'page arguments' => array('_form_test_tableselect_multiple_true_form'),
'access arguments' => array('access content'),
'type' => MENU_CALLBACK,
);
$items['form_test/tableselect/multiple-false'] = array(
'title' => 'Tableselect radio button test',
'page callback' => 'drupal_get_form',
'page arguments' => array('_form_test_tableselect_multiple_false_form'),
'access arguments' => array('access content'),
'type' => MENU_CALLBACK,
);
$items['form_test/tableselect/empty-text'] = array(
'title' => 'Tableselect empty text test',
'page callback' => 'drupal_get_form',
'page arguments' => array('_form_test_tableselect_empty_form'),
'access arguments' => array('access content'),
'type' => MENU_CALLBACK,
);
$items['form_test/tableselect/advanced-select'] = array(
'title' => 'Tableselect js_select tests',
'page callback' => 'drupal_get_form',
'page arguments' => array('_form_test_tableselect_js_select_form'),
'access arguments' => array('access content'),
'type' => MENU_CALLBACK,
);
$items['form_test/form-storage'] = array(
'title' => 'Form storage test',
'page callback' => 'drupal_get_form',
'page arguments' => array('form_test_storage_form'),
'access arguments' => array('access content'),
'type' => MENU_CALLBACK,
);
$items['form_test/wrapper-callback'] = array(
'title' => 'Form wrapper callback test',
'page callback' => 'form_test_wrapper_callback',
'page arguments' => array('form_test_wrapper_callback_form'),
'access arguments' => array('access content'),
'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,
);
$items['form-test/checkbox'] = array(
'title' => t('Form test'),
'page callback' => 'drupal_get_form',
'page arguments' => array('_form_test_checkbox'),
'access callback' => TRUE,
'type' => MENU_CALLBACK,
);
$items['form-test/disabled-elements'] = array(
'title' => t('Form test'),
'page callback' => 'drupal_get_form',
'page arguments' => array('_form_test_disabled_elements'),
'access callback' => TRUE,
'type' => MENU_CALLBACK,
);
$items['form-test/form-rebuild-preserve-values'] = array(
'title' => 'Form values preservation during rebuild test',
'page callback' => 'drupal_get_form',
'page arguments' => array('form_test_form_rebuild_preserve_values_form'),
'access arguments' => array('access content'),
'type' => MENU_CALLBACK,
);
$items['form_test/form-labels'] = array(
'title' => 'Form label test',
'page callback' => 'drupal_get_form',
'page arguments' => array('form_label_test_form'),
'access arguments' => array('access content'),
'type' => MENU_CALLBACK,
);
$items['form-test/state-persist'] = array(
'title' => 'Form state persistence without storage',
'page callback' => 'drupal_get_form',
'page arguments' => array('form_test_state_persist'),
'access callback' => TRUE,
'type' => MENU_CALLBACK,
);
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',
);
// To simplify this test, enable form caching and use form storage to
// remember our alteration.
$form_state['cache'] = TRUE;
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') {
$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('');
}
}
/**
* Builds a simple form with a button triggering partial validation.
*/
function form_test_limit_validation_errors_form($form, &$form_state) {
$form['title'] = array(
'#type' => 'textfield',
'#title' => 'Title',
'#required' => TRUE,
);
$form['test'] = array(
'#type' => 'textfield',
'#element_validate' => array('form_test_limit_validation_errors_element_validate_test'),
);
$form['actions']['partial'] = array(
'#type' => 'submit',
'#limit_validation_errors' => array(array('test')),
'#submit' => array(),
'#value' => t('Partial validate'),
);
$form['actions']['full'] = array(
'#type' => 'submit',
'#value' => t('Full validate'),
);
return $form;
}
/**
* Form element validation handler for the 'test' element.
*/
function form_test_limit_validation_errors_element_validate_test(&$element, &$form_state) {
if ($element['#value'] == 'invalid') {
form_error($element, 'Test element is invalid');
}
}
/**
* Create a header and options array. Helper function for callbacks.
*/
function _form_test_tableselect_get_data() {
$header = array(
'one' => t('One'),
'two' => t('Two'),
'three' => t('Three'),
'four' => t('Four'),
);
$options['row1'] = array(
'one' => 'row1col1',
'two' => t('row1col2'),
'three' => t('row1col3'),
'four' => t('row1col4'),
);
$options['row2'] = array(
'one' => 'row2col1',
'two' => t('row2col2'),
'three' => t('row2col3'),
'four' => t('row2col4'),
);
$options['row3'] = array(
'one' => 'row3col1',
'two' => t('row3col2'),
'three' => t('row3col3'),
'four' => t('row3col4'),
);
return array($header, $options);
}
/**
* Build a form to test the tableselect element.
*
* @param $form_state
* The form_state
* @param $element_properties
* An array of element properties for the tableselect element.
*
* @return
* A form with a tableselect element and a submit button.
*/
function _form_test_tableselect_form_builder($form, $form_state, $element_properties) {
list($header, $options) = _form_test_tableselect_get_data();
$form['tableselect'] = $element_properties;
$form['tableselect'] += array(
'#type' => 'tableselect',
'#header' => $header,
'#options' => $options,
'#multiple' => FALSE,
'#empty' => t('Empty text.'),
);
$form['submit'] = array(
'#type' => 'submit',
'#value' => t('Submit'),
);
return $form;
}
/**
* Test the tableselect #multiple = TRUE functionality.
*/
function _form_test_tableselect_multiple_true_form($form, $form_state) {
return _form_test_tableselect_form_builder($form, $form_state, array('#multiple' => TRUE));
}
/**
* Process the tableselect #multiple = TRUE submitted values.
*/
function _form_test_tableselect_multiple_true_form_submit($form, &$form_state) {
$selected = $form_state['values']['tableselect'];
foreach ($selected as $key => $value) {
drupal_set_message(t('Submitted: @key = @value', array('@key' => $key, '@value' => $value)));
}
}
/**
* Test the tableselect #multiple = FALSE functionality.
*/
function _form_test_tableselect_multiple_false_form($form, $form_state) {
return _form_test_tableselect_form_builder($form, $form_state, array('#multiple' => FALSE));
}
/**
* Process the tableselect #multiple = FALSE submitted values.
*/
function _form_test_tableselect_multiple_false_form_submit($form, &$form_state) {
drupal_set_message(t('Submitted: @value', array('@value' => $form_state['values']['tableselect'])));
}
/**
* Test functionality of the tableselect #empty property.
*/
function _form_test_tableselect_empty_form($form, $form_state) {
return _form_test_tableselect_form_builder($form, $form_state, array('#options' => array()));
}
/**
* Test functionality of the tableselect #js_select property.
*/
function _form_test_tableselect_js_select_form($form, $form_state, $action) {
switch ($action) {
case 'multiple-true-default':
$options = array('#multiple' => TRUE);
break;
case 'multiple-false-default':
$options = array('#multiple' => FALSE);
break;
case 'multiple-true-no-advanced-select':
$options = array('#multiple' => TRUE, '#js_select' => FALSE);
break;
case 'multiple-false-advanced-select':
$options = array('#multiple' => FALSE, '#js_select' => TRUE);
break;
}
return _form_test_tableselect_form_builder($form, $form_state, $options);
}
/**
* A multistep form for testing the form storage.
*
* It uses two steps for editing a virtual "thing". Any changes to it are saved
* in the form storage and have to be present during any step. By setting the
* request parameter "cache" the form can be tested with caching enabled, as
* it would be the case, if the form would contain some #ajax callbacks.
*
* @see form_test_storage_form_submit().
*/
function form_test_storage_form($form, &$form_state) {
if ($form_state['rebuild']) {
$form_state['input'] = array();
}
// Initialize
if (empty($form_state['storage'])) {
if (empty($form_state['input'])) {
$_SESSION['constructions'] = 0;
}
// Put the initial thing into the storage
$form_state['storage'] = array(
'thing' => array(
'title' => 'none',
'value' => '',
),
);
}
// Count how often the form is constructed.
$_SESSION['constructions']++;
drupal_set_message("Form constructions: ". $_SESSION['constructions']);
$form['title'] = array(
'#type' => 'textfield',
'#title' => 'Title',
'#default_value' => $form_state['storage']['thing']['title'],
'#required' => TRUE,
);
$form['value'] = array(
'#type' => 'textfield',
'#title' => 'Value',
'#default_value' => $form_state['storage']['thing']['value'],
'#element_validate' => array('form_test_storage_element_validate_value_cached'),
);
$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
// when it's enabled.
$form_state['cache'] = TRUE;
}
return $form;
}
/**
* Form element validation handler for 'value' element in form_test_storage_form().
*
* 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 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']['changed'] = TRUE;
}
}
/**
* Form submit handler to continue multi-step form.
*/
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 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';
}
/**
* A form for testing form labels and required marks.
*/
function form_label_test_form(&$form_state) {
$form['form_checkboxes_test'] = array(
'#type' => 'checkboxes',
'#title' => t('Checkboxes test'),
'#options' => array(
'first-checkbox' => t('First checkbox'),
'second-checkbox' => t('Second checkbox'),
'third-checkbox' => t('Third checkbox'),
),
);
$form['form_radios_test'] = array(
'#type' => 'radios',
'#title' => t('Radios test'),
'#options' => array(
'first-radio' => t('First radio'),
'second-radio' => t('Second radio'),
'third-radio' => t('Third radio'),
),
);
$form['form_checkbox_test'] = array(
'#type' => 'checkbox',
'#title' => t('Checkbox test'),
);
$form['form_textfield_test_title_and_required'] = array(
'#type' => 'textfield',
'#title' => t('Textfield test for required with title'),
'#required' => TRUE,
);
$form['form_textfield_test_no_title_required'] = array(
'#type' => 'textfield',
// We use an empty title, since not setting #title supresses the label
// and required marker.
'#title' => '',
'#required' => TRUE,
);
$form['form_textfield_test_title'] = array(
'#type' => 'textfield',
'#title' => t('Textfield test for title only'),
// Not required.
);
$form['form_textfield_test_title_after'] = array(
'#type' => 'textfield',
'#title' => t('Textfield test for title after element'),
'#title_display' => 'after',
);
// Textfield test for title set not to display
$form['form_textfield_test_title_no_show'] = array(
'#type' => 'textfield',
);
return $form;
}
/**
* Menu callback; Invokes a form builder function with a wrapper callback.
*/
function form_test_wrapper_callback($form_id) {
$form_state = array(
'build_info' => array('args' => array()),
'wrapper_callback' => 'form_test_wrapper_callback_wrapper',
);
return drupal_build_form($form_id, $form_state);
}
/**
* Form wrapper for form_test_wrapper_callback_form().
*/
function form_test_wrapper_callback_wrapper($form, &$form_state) {
$form['wrapper'] = array('#markup' => 'Form wrapper callback element output.');
return $form;
}
/**
* Form builder for form wrapper callback test.
*/
function form_test_wrapper_callback_form($form, &$form_state) {
$form['builder'] = array('#markup' => 'Form builder element output.');
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;
}
/**
* Build a form to test a checkbox.
*/
function _form_test_checkbox($form, &$form_state) {
// A required checkbox.
$form['required_checkbox'] = array(
'#type' => 'checkbox',
'#required' => TRUE,
'#title' => 'required_checkbox',
);
// A disabled checkbox should get its default value back.
$form['disabled_checkbox_on'] = array(
'#type' => 'checkbox',
'#disabled' => TRUE,
'#return_value' => 'disabled_checkbox_on',
'#default_value' => 'disabled_checkbox_on',
'#title' => 'disabled_checkbox_on',
);
$form['disabled_checkbox_off'] = array(
'#type' => 'checkbox',
'#disabled' => TRUE,
'#return_value' => 'disabled_checkbox_off',
'#default_value' => NULL,
'#title' => 'disabled_checkbox_off',
);
// A checkbox is active when #default_value == #return_value.
$form['checkbox_on'] = array(
'#type' => 'checkbox',
'#return_value' => 'checkbox_on',
'#default_value' => 'checkbox_on',
'#title' => 'checkbox_on',
);
// But inactive in any other case.
$form['checkbox_off'] = array(
'#type' => 'checkbox',
'#return_value' => 'checkbox_off',
'#default_value' => 'checkbox_on',
'#title' => 'checkbox_off',
);
// Checkboxes with a #return_value of '0' are supported.
$form['zero_checkbox_on'] = array(
'#type' => 'checkbox',
'#return_value' => '0',
'#default_value' => '0',
'#title' => 'zero_checkbox_on',
);
// In that case, passing a #default_value != '0' means that the checkbox is off.
$form['zero_checkbox_off'] = array(
'#type' => 'checkbox',
'#return_value' => '0',
'#default_value' => '1',
'#title' => 'zero_checkbox_off',
);
$form['submit'] = array(
'#type' => 'submit',
'#value' => t('Submit')
);
return $form;
}
/**
* Return the form values via JSON.
*/
function _form_test_checkbox_submit($form, &$form_state) {
drupal_json_output($form_state['values']);
exit();
}
/**
* Build a form to test disabled elements.
*/
function _form_test_disabled_elements($form, &$form_state) {
// Elements that take a simple default value.
foreach (array('textfield', 'textarea', 'hidden') as $type) {
$form[$type] = array(
'#type' => $type,
'#title' => $type,
'#default_value' => $type,
'#disabled' => TRUE,
);
}
// Multiple values option elements.
foreach (array('checkboxes', 'select') as $type) {
$form[$type . '_multiple'] = array(
'#type' => $type,
'#title' => $type . ' (multiple)',
'#options' => array(
'test_1' => 'Test 1',
'test_2' => 'Test 2',
),
'#multiple' => TRUE,
'#default_value' => array('test_2' => 'test_2'),
'#disabled' => TRUE,
);
}
// Single values option elements.
foreach (array('radios', 'select') as $type) {
$form[$type . '_single'] = array(
'#type' => $type,
'#title' => $type . ' (single)',
'#options' => array(
'test_1' => 'Test 1',
'test_2' => 'Test 2',
),
'#multiple' => FALSE,
'#default_value' => 'test_2',
'#disabled' => TRUE,
);
}
// Checkbox and radio.
foreach (array('checkbox', 'radio') as $type) {
$form[$type . '_unchecked'] = array(
'#type' => $type,
'#title' => $type . ' (unchecked)',
'#return_value' => 1,
'#default_value' => 0,
'#disabled' => TRUE,
);
$form[$type . '_checked'] = array(
'#type' => $type,
'#title' => $type . ' (checked)',
'#return_value' => 1,
'#default_value' => 1,
'#disabled' => TRUE,
);
}
// Weight.
$form['weight'] = array(
'#type' => 'weight',
'#title' => 'weight',
'#default_value' => 10,
'#disabled' => TRUE,
);
// Date.
$form['date'] = array(
'#type' => 'date',
'#title' => 'date',
'#disabled' => TRUE,
'#default_value' => array(
'day' => 19,
'month' => 11,
'year' => 1978,
),
);
$form['submit'] = array(
'#type' => 'submit',
'#value' => t('Submit'),
);
return $form;
}
/**
* Return the form values via JSON.
*/
function _form_test_disabled_elements_submit($form, &$form_state) {
drupal_json_output($form_state['values']);
exit();
}
/**
* Form builder for testing preservation of values during a rebuild.
*/
function form_test_form_rebuild_preserve_values_form($form, &$form_state) {
// Start the form with two checkboxes, to test different defaults, and a
// textfield, to test more than one element type.
$form = array(
'checkbox_1_default_off' => array(
'#type' => 'checkbox',
'#title' => t('This checkbox defaults to unchecked.'),
'#default_value' => FALSE,
),
'checkbox_1_default_on' => array(
'#type' => 'checkbox',
'#title' => t('This checkbox defaults to checked.'),
'#default_value' => TRUE,
),
'text_1' => array(
'#type' => 'textfield',
'#title' => t('This textfield has a non-empty default value.'),
'#default_value' => 'DEFAULT 1',
),
);
// Provide an 'add more' button that rebuilds the form with an additional two
// checkboxes and a textfield. The test is to make sure that the rebuild
// triggered by this button preserves the user input values for the initial
// elements and initializes the new elements with the correct default values.
if (empty($form_state['storage']['add_more'])) {
$form['add_more'] = array(
'#type' => 'submit',
'#value' => 'Add more',
'#submit' => array('form_test_form_rebuild_preserve_values_form_add_more'),
);
}
else {
$form += array(
'checkbox_2_default_off' => array(
'#type' => 'checkbox',
'#title' => t('This checkbox defaults to unchecked.'),
'#default_value' => FALSE,
),
'checkbox_2_default_on' => array(
'#type' => 'checkbox',
'#title' => t('This checkbox defaults to checked.'),
'#default_value' => TRUE,
),
'text_2' => array(
'#type' => 'textfield',
'#title' => t('This textfield has a non-empty default value.'),
'#default_value' => 'DEFAULT 2',
),
);
}
// A submit button that finishes the form workflow (does not rebuild).
$form['submit'] = array(
'#type' => 'submit',
'#value' => 'Submit',
);
return $form;
}
/**
* Button submit handler for form_test_form_rebuild_preserve_values_form().
*/
function form_test_form_rebuild_preserve_values_form_add_more($form, &$form_state) {
// Rebuild, to test preservation of input values.
$form_state['storage']['add_more'] = TRUE;
$form_state['rebuild'] = TRUE;
}
/**
* Form submit handler for form_test_form_rebuild_preserve_values_form().
*/
function form_test_form_rebuild_preserve_values_form_submit($form, &$form_state) {
// Finish the workflow. Do not rebuild.
drupal_set_message(t('Form values: %values', array('%values' => var_export($form_state['values'], TRUE))));
}
/**
* Form constructor for testing form state persistence.
*/
function form_test_state_persist($form, &$form_state) {
$form['title'] = array(
'#type' => 'textfield',
'#title' => 'title',
'#default_value' => 'DEFAULT',
'#required' => TRUE,
);
$form_state['value'] = 'State persisted.';
$form['submit'] = array(
'#type' => 'submit',
'#value' => t('Submit'),
);
return $form;
}
/**
* Submit handler.
*
* @see form_test_state_persist()
*/
function form_test_state_persist_submit($form, &$form_state) {
drupal_set_message($form_state['value']);
$form_state['rebuild'] = TRUE;
}
/**
* Implements hook_form_FORM_ID_alter().
*
* @see form_test_state_persist()
*/
function form_test_form_form_test_state_persist_alter(&$form, &$form_state) {
// Simulate a form alter implementation inserting form elements that enable
// caching of the form, e.g. elements having #ajax.
if (!empty($_REQUEST['cache'])) {
$form_state['cache'] = TRUE;
}
}