Index: install.php =================================================================== RCS file: /cvs/drupal/drupal/install.php,v retrieving revision 1.210 diff -u -p -r1.210 install.php --- install.php 18 Sep 2009 00:12:45 -0000 1.210 +++ install.php 24 Sep 2009 00:05:21 -0000 @@ -391,7 +391,7 @@ function install_run_task($task, &$insta // We need to pass $install_state by reference in order for forms to // modify it, since the form API will use it in call_user_func_array(), // which requires that referenced variables be passed explicitly. - 'args' => array(&$install_state), + 'build_info' => array('args' => array(&$install_state)), 'no_redirect' => TRUE, ); $form = drupal_build_form($function, $form_state); Index: includes/ajax.inc =================================================================== RCS file: /cvs/drupal/drupal/includes/ajax.inc,v retrieving revision 1.11 diff -u -p -r1.11 ajax.inc --- includes/ajax.inc 21 Sep 2009 08:54:57 -0000 1.11 +++ includes/ajax.inc 24 Sep 2009 00:05:21 -0000 @@ -189,7 +189,6 @@ function ajax_get_form() { // The form needs to be processed; prepare for that by setting a few internal // variables. $form_state['input'] = $_POST; - $form_state['args'] = $form['#args']; $form_id = $form['#form_id']; return array($form, $form_state, $form_id, $form_build_id); Index: includes/form.inc =================================================================== RCS file: /cvs/drupal/drupal/includes/form.inc,v retrieving revision 1.375 diff -u -p -r1.375 form.inc --- includes/form.inc 21 Sep 2009 06:44:13 -0000 1.375 +++ includes/form.inc 24 Sep 2009 00:21:32 -0000 @@ -72,7 +72,7 @@ function drupal_get_form($form_id) { $args = func_get_args(); // Remove $form_id from the arguments. array_shift($args); - $form_state['args'] = $args; + $form_state['build_info']['args'] = $args; return drupal_build_form($form_id, $form_state); } @@ -93,11 +93,17 @@ function drupal_get_form($form_id) { * search_forms(), and user_forms(). * @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 the form changed + * reference so that the caller can use it to examine what in the form changed * when the form submission process is complete. * The following parameters may be set in $form_state to affect how the form * is rendered: - * - args: An array of arguments to pass to the form builder. + * - build_info: A keyed array of build information that is necessary to + * rebuild the form from cache when the original context may no longer be + * available: + * - args: An array of arguments to pass to the form builder. + * - 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. * - input: An array of input that corresponds to $_POST or $_GET, depending * on the 'method' chosen (see below). * - method: The HTTP form method to use for finding the input for this form. @@ -161,23 +167,22 @@ function drupal_build_form($form_id, &$f // object, we're hitting the form for the first time and we need // to build it from scratch. if (!isset($form)) { - $form = drupal_retrieve_form($form_id, $form_state); - $form_build_id = 'form-' . md5(uniqid(mt_rand(), TRUE)); - $form['#build_id'] = $form_build_id; - // Record the filepath of the include file containing the original form, // so the form builder callbacks can be loaded when the form is being - // rebuilt on a different path (such as 'system/ajax'). + // rebuilt from cache on a different path (such as 'system/ajax'). // @see form_get_cache() - // @see drupal_retrieve_form() // menu_get_item() is not available at installation time. - if (!defined('MAINTENANCE_MODE')) { + if (!isset($form_state['build_info']['file']) && !defined('MAINTENANCE_MODE')) { $item = menu_get_item(); if (!empty($item['file'])) { - $form['#include_file'] = $item['file']; + $form_state['build_info']['file'] = $item['file']; } } + $form = drupal_retrieve_form($form_id, $form_state); + $form_build_id = 'form-' . md5(uniqid(mt_rand(), TRUE)); + $form['#build_id'] = $form_build_id; + // Fix the form method, if it is 'get' in $form_state, but not in $form. if ($form_state['method'] == 'get' && !isset($form['#method'])) { $form['#method'] = 'get'; @@ -217,7 +222,6 @@ function drupal_build_form($form_id, &$f // complete. We need to construct a fresh copy of the form, passing // in the latest $form_state in addition to any other variables passed // into drupal_get_form(). - if ((!empty($form_state['storage']) || $form_state['rebuild']) && $form_state['submitted'] && !form_get_errors()) { $form = drupal_rebuild_form($form_id, $form_state); } @@ -241,6 +245,7 @@ function form_state_defaults() { return array( 'rebuild' => FALSE, 'redirect' => NULL, + 'build_info' => array(), 'storage' => NULL, 'submitted' => FALSE, 'programmed' => FALSE, @@ -264,9 +269,6 @@ function form_state_defaults() { * $form_state['clicked_button']['#array_parents'] will help you to find which * part. * - * When getting a form from the cache, the $form_id must be shifted off from - * $form['#args'], so the resulting array can be given to $form_state['args']. - * * @param $form_id * The unique string identifying the desired form. If a function * with that name exists, it is called to build the form array. @@ -322,19 +324,19 @@ function drupal_rebuild_form($form_id, & function form_get_cache($form_build_id, &$form_state) { if ($cached = cache_get('form_' . $form_build_id, 'cache_form')) { $form = $cached->data; - // If the original form is contained in an optional include file, load the - // file and re-populate $form_state for subsequent rebuilds. - // @see drupal_build_form() - // @see drupal_retrieve_form() - if (!empty($form['#include_file']) && file_exists($form['#include_file'])) { - require_once DRUPAL_ROOT . '/' . $form['#include_file']; - $form_state['include_file'] = $form['#include_file']; - } global $user; if ((isset($form['#cache_token']) && drupal_valid_token($form['#cache_token'])) || (!isset($form['#cache_token']) && !$user->uid)) { - if ($cached = cache_get('storage_' . $form_build_id, 'cache_form')) { - $form_state['storage'] = $cached->data; + 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']; + + // If the original form is contained in an include file, load the file. + // @see drupal_build_form() + if (!empty($form_state['build_info']['file']) && file_exists($form_state['build_info']['file'])) { + require_once DRUPAL_ROOT . '/' . $form_state['build_info']['file']; + } } return $form; } @@ -342,7 +344,7 @@ function form_get_cache($form_build_id, } /** - * Store a form in the cache + * Store a form in the cache. */ function form_set_cache($form_build_id, $form, $form_state) { // 6 hours cache life time for forms should be plenty. @@ -352,8 +354,12 @@ function form_set_cache($form_build_id, $form['#cache_token'] = drupal_get_token(); } cache_set('form_' . $form_build_id, $form, 'cache_form', REQUEST_TIME + $expire); - if (!empty($form_state['storage'])) { - cache_set('storage_' . $form_build_id, $form_state['storage'], 'cache_form', REQUEST_TIME + $expire); + if (!empty($form_state['build_info']) || !empty($form_state['storage'])) { + $data = array( + 'build_info' => $form_state['build_info'], + 'storage' => $form_state['storage'], + ); + cache_set('form_state_' . $form_build_id, $data, 'cache_form', REQUEST_TIME + $expire); } } @@ -402,11 +408,11 @@ function form_set_cache($form_build_id, * @endcode */ function drupal_form_submit($form_id, &$form_state) { - if (!isset($form_state['args'])) { + if (!isset($form_state['build_info']['args'])) { $args = func_get_args(); array_shift($args); array_shift($args); - $form_state['args'] = $args; + $form_state['build_info']['args'] = $args; } $form = drupal_retrieve_form($form_id, $form_state); @@ -446,7 +452,7 @@ function drupal_retrieve_form($form_id, // We save two copies of the incoming arguments: one for modules to use // when mapping form ids to constructor functions, and another to pass to // the constructor function itself. - $args = $form_state['args']; + $args = $form_state['build_info']['args']; // We first check to see if there's a function named after the $form_id. // If there is, we simply pass the arguments on to it to get the form. @@ -494,15 +500,6 @@ function drupal_retrieve_form($form_id, // Otherwise, call the function named after the form id. $form = call_user_func_array(isset($callback) ? $callback : $form_id, $args); $form['#form_id'] = $form_id; - $form['#args'] = $form_state['args']; - - // Whenever this form is (re)built, restore the include file property from - // $form_state, if existent. - // @see drupal_build_form() - // @see form_get_cache() - if (!empty($form_state['include_file'])) { - $form['#include_file'] = $form_state['include_file']; - } return $form; } Index: modules/color/color.module =================================================================== RCS file: /cvs/drupal/drupal/modules/color/color.module,v retrieving revision 1.72 diff -u -p -r1.72 color.module --- modules/color/color.module 18 Sep 2009 00:12:45 -0000 1.72 +++ modules/color/color.module 24 Sep 2009 00:05:21 -0000 @@ -31,7 +31,7 @@ function color_theme() { * Implement hook_form_FORM_ID_alter(). */ function color_form_system_theme_settings_alter(&$form, &$form_state) { - if (isset($form_state['args'][0]) && ($theme = $form_state['args'][0]) && color_get_info($theme) && function_exists('gd_info')) { + if (isset($form_state['build_info']['args'][0]) && ($theme = $form_state['build_info']['args'][0]) && color_get_info($theme) && function_exists('gd_info')) { $form['color'] = array( '#type' => 'fieldset', '#title' => t('Color scheme'), Index: modules/openid/openid.module =================================================================== RCS file: /cvs/drupal/drupal/modules/openid/openid.module,v retrieving revision 1.61 diff -u -p -r1.61 openid.module --- modules/openid/openid.module 22 Sep 2009 07:50:16 -0000 1.61 +++ modules/openid/openid.module 24 Sep 2009 00:05:21 -0000 @@ -430,7 +430,7 @@ function openid_authentication($response } elseif (variable_get('user_register', 1)) { // Register new user - $form_state['args'] = array(); + $form_state['build_info']['args'] = array(); $form_state['redirect'] = NULL; $form_state['values']['name'] = (empty($response['openid.sreg.nickname'])) ? $identity : $response['openid.sreg.nickname']; $form_state['values']['mail'] = (empty($response['openid.sreg.email'])) ? '' : $response['openid.sreg.email']; Index: modules/openid/openid.pages.inc =================================================================== RCS file: /cvs/drupal/drupal/modules/openid/openid.pages.inc,v retrieving revision 1.22 diff -u -p -r1.22 openid.pages.inc --- modules/openid/openid.pages.inc 21 Sep 2009 06:44:14 -0000 1.22 +++ modules/openid/openid.pages.inc 24 Sep 2009 00:05:21 -0000 @@ -104,12 +104,12 @@ function openid_user_delete_form($form, function openid_user_delete_form_submit($form, &$form_state) { $query = db_delete('authmap') - ->condition('uid', $form_state['args'][0]->uid) - ->condition('aid', $form_state['args'][1]) + ->condition('uid', $form_state['build_info']['args'][0]->uid) + ->condition('aid', $form_state['build_info']['args'][1]) ->condition('module', 'openid') ->execute(); if ($query) { drupal_set_message(t('OpenID deleted.')); } - $form_state['redirect'] = 'user/' . $form_state['args'][0]->uid . '/openid'; + $form_state['redirect'] = 'user/' . $form_state['build_info']['args'][0]->uid . '/openid'; } Index: modules/simpletest/tests/form_test.module =================================================================== RCS file: /cvs/drupal/drupal/modules/simpletest/tests/form_test.module,v retrieving revision 1.9 diff -u -p -r1.9 form_test.module --- modules/simpletest/tests/form_test.module 18 Sep 2009 00:12:48 -0000 1.9 +++ modules/simpletest/tests/form_test.module 24 Sep 2009 00:05:21 -0000 @@ -368,7 +368,7 @@ function form_storage_test_form_submit($ */ function form_test_wrapper_callback($form_id) { $form_state = array( - 'args' => array(), + 'build_info' => array('args' => array()), 'wrapper_callback' => 'form_test_wrapper_callback_wrapper', ); return drupal_build_form($form_id, $form_state);