- Patch #641356 by fago, sun: cache more of () when form caching is enabled.
parent
6c37dbae29
commit
0014a64d37
|
@ -94,7 +94,9 @@ function drupal_get_form($form_id) {
|
|||
* @param &$form_state
|
||||
* An array which stores information about the form. This is passed as a
|
||||
* reference so that the caller can use it to examine what in the form changed
|
||||
* when the form submission process is complete.
|
||||
* when the form submission process is complete. Furthermore, it may be used
|
||||
* to store information related to the processed data in the form, which will
|
||||
* persist across page requests when the 'cache' or 'rebuild' flag is set.
|
||||
* The following parameters may be set in $form_state to affect how the form
|
||||
* is rendered:
|
||||
* - build_info: A keyed array of build information that is necessary to
|
||||
|
@ -104,10 +106,6 @@ function drupal_get_form($form_id) {
|
|||
* - file: An optional include file that contains the form and is
|
||||
* automatically loaded by form_get_cache(). Defaults to the current menu
|
||||
* router item's 'file' definition, if existent.
|
||||
* - storage: An array that may be used to store information related to the
|
||||
* processed data in the form, which can be accessed and used within the
|
||||
* same page request, but also persist across multiple steps in a multi-step
|
||||
* form.
|
||||
* - rebuild: Normally, after the entire form processing is completed and
|
||||
* submit handlers ran, a form is considered to be done and
|
||||
* drupal_redirect_form() will redirect the user to a new page using a GET
|
||||
|
@ -141,6 +139,10 @@ function drupal_get_form($form_id) {
|
|||
* times when a form is resubmitted internally and should be validated
|
||||
* again. Setting this to TRUE will force that to happen. This is most
|
||||
* likely to occur during AHAH or AJAX operations.
|
||||
* - temporary: An array holding temporary data accessible during the current
|
||||
* page request only. It may be used to temporary save any data that doesn't
|
||||
* need to or shouldn't be cached during the whole form workflow, e.g. data
|
||||
* that needs to be accessed during the current form build process only.
|
||||
* - wrapper_callback: Modules that wish to pre-populate certain forms with
|
||||
* common elements, such as back/next/save buttons in multi-step form
|
||||
* wizards, may define a form builder function name that returns a form
|
||||
|
@ -269,11 +271,10 @@ function drupal_build_form($form_id, &$form_state) {
|
|||
*/
|
||||
function form_state_defaults() {
|
||||
return array(
|
||||
'args' => array(),
|
||||
'rebuild' => FALSE,
|
||||
'redirect' => NULL,
|
||||
'build_info' => array(),
|
||||
'storage' => array(),
|
||||
'build_info' => array('args' => array()),
|
||||
'temporary' => array(),
|
||||
'submitted' => FALSE,
|
||||
'programmed' => FALSE,
|
||||
'cache'=> FALSE,
|
||||
|
@ -301,8 +302,7 @@ function form_state_defaults() {
|
|||
* different $form_id values to the proper form constructor function. Examples
|
||||
* may be found in node_forms(), search_forms(), and user_forms().
|
||||
* @param $form_state
|
||||
* A keyed array containing the current state of the form. Most
|
||||
* important is the $form_state['storage'] collection.
|
||||
* A keyed array containing the current state of the form.
|
||||
* @param $form_build_id
|
||||
* If the AHAH callback calling this function only alters part of the form,
|
||||
* then pass in the existing form_build_id so we can re-cache with the same
|
||||
|
@ -355,8 +355,7 @@ function form_get_cache($form_build_id, &$form_state) {
|
|||
if ((isset($form['#cache_token']) && drupal_valid_token($form['#cache_token'])) || (!isset($form['#cache_token']) && !$user->uid)) {
|
||||
if ($cached = cache_get('form_state_' . $form_build_id, 'cache_form')) {
|
||||
// Re-populate $form_state for subsequent rebuilds.
|
||||
$form_state['build_info'] = $cached->data['build_info'];
|
||||
$form_state['storage'] = $cached->data['storage'];
|
||||
$form_state = $cached->data + $form_state;
|
||||
|
||||
// If the original form is contained in an include file, load the file.
|
||||
// @see drupal_build_form()
|
||||
|
@ -385,15 +384,39 @@ function form_set_cache($form_build_id, $form, $form_state) {
|
|||
}
|
||||
|
||||
// Cache form state.
|
||||
if (!empty($form_state['build_info']) || !empty($form_state['storage'])) {
|
||||
$data = array(
|
||||
'build_info' => $form_state['build_info'],
|
||||
'storage' => $form_state['storage'],
|
||||
);
|
||||
if ($data = array_diff_key($form_state, array_flip(form_state_keys_no_cache()))) {
|
||||
cache_set('form_state_' . $form_build_id, $data, 'cache_form', REQUEST_TIME + $expire);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of $form_state keys that shouldn't be cached.
|
||||
*/
|
||||
function form_state_keys_no_cache() {
|
||||
return array(
|
||||
// Public properties defined by form constructors and form handlers.
|
||||
'always_process',
|
||||
'cache',
|
||||
'no_cache',
|
||||
'must_validate',
|
||||
'rebuild',
|
||||
'redirect',
|
||||
'no_redirect',
|
||||
'temporary',
|
||||
// Internal properties defined by form processing.
|
||||
'buttons',
|
||||
'clicked_button',
|
||||
'complete form',
|
||||
'groups',
|
||||
'input',
|
||||
'method',
|
||||
'submit_handlers',
|
||||
'submitted',
|
||||
'validate_handlers',
|
||||
'values',
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a form using a form_id, populates it with $form_state['values'],
|
||||
* processes it, and returns any validation errors encountered. This
|
||||
|
@ -449,14 +472,14 @@ function drupal_form_submit($form_id, &$form_state) {
|
|||
array_shift($args);
|
||||
$form_state['build_info']['args'] = $args;
|
||||
}
|
||||
// Merge in default values.
|
||||
$form_state += form_state_defaults();
|
||||
|
||||
$form = drupal_retrieve_form($form_id, $form_state);
|
||||
$form_state['input'] = $form_state['values'];
|
||||
$form_state['programmed'] = TRUE;
|
||||
// Programmed forms are always submitted.
|
||||
$form_state['submitted'] = TRUE;
|
||||
// Merge in default values.
|
||||
$form_state += form_state_defaults();
|
||||
|
||||
drupal_prepare_form($form_id, $form, $form_state);
|
||||
drupal_process_form($form_id, $form, $form_state);
|
||||
|
|
|
@ -597,6 +597,36 @@ class FormsFormStorageTestCase extends DrupalWebTestCase {
|
|||
$this->assertFieldByName('title', 'title_changed', t('The altered form storage value was updated in cache and taken over.'));
|
||||
$this->assertText('Title: title_changed', t('The form storage has stored the values.'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests a form using form state without using 'storage' to pass data from the
|
||||
* constructor to a submit handler. The data has to persist even when caching
|
||||
* gets activated, what may happen when a modules alter the form and adds
|
||||
* #ajax properties.
|
||||
*/
|
||||
function testFormStatePersist() {
|
||||
// Test the form one time with caching activated and one time without.
|
||||
$run_options = array(
|
||||
array(),
|
||||
array('query' => array('cache' => 1)),
|
||||
);
|
||||
foreach($run_options as $options) {
|
||||
$this->drupalPost('form-test/state-persist', array(), t('Submit'), $options);
|
||||
// The submit handler outputs the value in $form_state, assert it's there.
|
||||
$this->assertText('State persisted.');
|
||||
|
||||
// Test it again, but first trigger a validation error, then test.
|
||||
$this->drupalPost('form-test/state-persist', array('title' => ''), t('Submit'), $options);
|
||||
$this->assertText(t('!name field is required.', array('!name' => 'title')));
|
||||
// Submit the form again triggering no validation error.
|
||||
$this->drupalPost(NULL, array('title' => 'foo'), t('Submit'), $options);
|
||||
$this->assertText('State persisted.');
|
||||
|
||||
// Now post to the rebuilt form and verify it's still there afterwards.
|
||||
$this->drupalPost(NULL, array('title' => 'bar'), t('Submit'), $options);
|
||||
$this->assertText('State persisted.');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -102,6 +102,14 @@ function form_test_menu() {
|
|||
'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;
|
||||
}
|
||||
|
||||
|
@ -742,3 +750,45 @@ 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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1181,7 +1181,7 @@ function system_modules_uninstall($form, $form_state = NULL) {
|
|||
include_once DRUPAL_ROOT . '/includes/install.inc';
|
||||
|
||||
// Display the confirm form if any modules have been submitted.
|
||||
if (!empty($form_state) && $confirm_form = system_modules_uninstall_confirm_form($form_state['storage'])) {
|
||||
if (!empty($form_state['storage']) && $confirm_form = system_modules_uninstall_confirm_form($form_state['storage'])) {
|
||||
return $confirm_form;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue