? .DS_Store ? form.patch ? form_7.patch ? includes/.DS_Store ? sites/form Index: install.php =================================================================== RCS file: /cvs/drupal/drupal/install.php,v retrieving revision 1.44 diff -u -F^f -r1.44 install.php --- install.php 8 May 2007 22:10:22 -0000 1.44 +++ install.php 9 May 2007 19:49:56 -0000 @@ -15,9 +15,17 @@ * The installation phase we should proceed to. */ function install_main() { - global $profile, $install_locale; + global $profile, $install_locale, $conf; + require_once './includes/cache-install.inc'; require_once './includes/bootstrap.inc'; drupal_bootstrap(DRUPAL_BOOTSTRAP_CONFIGURATION); + + // Because no persistent storage is available yet, functions + // that check for cached data will fail. During the installation + // process, we temporarily replace the normal cache system with + // a stubbed-out version that short-circuits the actual caching + // process and avoids any errors. + $conf['cache_inc'] = './includes/cache-install.inc'; require_once './modules/system/system.install'; require_once './includes/file.inc'; @@ -126,7 +134,8 @@ function install_verify_settings() { $db_path = ltrim(urldecode($url['path']), '/'); $settings_file = './'. conf_path() .'/settings.php'; - _install_settings_form_validate($db_prefix, $db_type, $db_user, $db_pass, $db_host, $db_port, $db_path, $settings_file); + $form_state = array(); + _install_settings_form_validate($db_prefix, $db_type, $db_user, $db_pass, $db_host, $db_port, $db_path, $settings_file, $form_state); if (!form_get_errors()) { return TRUE; } @@ -313,18 +322,19 @@ function install_settings_form($profile, } return $form; } + /** * Form API validate for install_settings form. */ -function install_settings_form_validate($form_id, $form_values, $form) { +function install_settings_form_validate($form_values, $form, &$form_state) { global $db_url; - _install_settings_form_validate($form_values['db_prefix'], $form_values['db_type'], $form_values['db_user'], $form_values['db_pass'], $form_values['db_host'], $form_values['db_port'], $form_values['db_path'], $form_values['settings_file'], $form); + _install_settings_form_validate($form_values['db_prefix'], $form_values['db_type'], $form_values['db_user'], $form_values['db_pass'], $form_values['db_host'], $form_values['db_port'], $form_values['db_path'], $form_values['settings_file'], $form_state, $form); } /** * Helper function for install_settings_validate. */ -function _install_settings_form_validate($db_prefix, $db_type, $db_user, $db_pass, $db_host, $db_port, $db_path, $settings_file, $form = NULL) { +function _install_settings_form_validate($db_prefix, $db_type, $db_user, $db_pass, $db_host, $db_port, $db_path, $settings_file, &$form_state, $form = NULL) { global $db_url; // Verify the table prefix @@ -349,7 +359,7 @@ function _install_settings_form_validate // Verify $db_url = $db_type .'://'. urlencode($db_user) . ($db_pass ? ':'. urlencode($db_pass) : '') .'@'. ($db_host ? urlencode($db_host) : 'localhost') . ($db_port ? ":$db_port" : '') .'/'. urlencode($db_path); if (isset($form)) { - form_set_value($form['_db_url'], $db_url); + form_set_value($form['_db_url'], $db_url, $form_state); } $success = array(); @@ -368,7 +378,7 @@ function _install_settings_form_validate /** * Form API submit for install_settings form. */ -function install_settings_form_submit($form_id, $form_values) { +function install_settings_form_submit($form_values) { global $profile, $install_locale; // Update global settings array and save Index: includes/batch.inc =================================================================== RCS file: /cvs/drupal/drupal/includes/batch.inc,v retrieving revision 1.1 diff -u -F^f -r1.1 batch.inc --- includes/batch.inc 4 May 2007 09:41:36 -0000 1.1 +++ includes/batch.inc 9 May 2007 19:49:56 -0000 @@ -188,6 +188,7 @@ function _batch_process() { } } + // TODO : if the last set was a 'form_submit', there is no 'operations', 'total', 'progress message' in $current_set => warnings if ($batch['progressive']) { $remaining = count($current_set['operations']); $total = $current_set['total']; @@ -222,28 +223,24 @@ function &_batch_current_set() { /** * Move execution to the next batch set if any, executing the stored - * form _submit callbacks along the way (possibly inserting additional batch sets) + * form _submit callbacks along the way (thus possibly inserting + * additional batch sets) */ function _batch_next_set() { $batch =& batch_get(); - if (isset($batch['sets'][$batch['current_set']+1])) { + if (isset($batch['sets'][$batch['current_set'] + 1])) { $batch['current_set']++; $current_set =& _batch_current_set(); - if (isset($current_set['form submit']) && (list($function, $args) = $current_set['form submit']) && function_exists($function)) { - // We have to keep our own copy of $form_values, to account + if (isset($current_set['form_submit']) && (list($function, $form, $form_state) = $current_set['form_submit']) && function_exists($function)) { + // We use our own copy of $form_state, to account // for possible alteration by the submit callback. - if (isset($batch['form_values'])) { - $args[1] = $batch['form_values']; - } - $redirect = call_user_func_array($function, $args); - // Store the form_values only if needed, to limit the - // amount of data we store in the batch. - if (isset($batch['sets'][$batch['current_set']+1])) { - $batch['form_values'] = $args[1]; - } - if (isset($redirect)) { - $batch['redirect'] = $redirect; - } + $function($batch['form_state']['values'], $batch['form'], $batch['form_state']); + // Store a bare pseudo-form with only the information we need for redirection, + // to limit the amount of data we store in the batch. + // TODO : $form can be altered by submit callbacks - Do we have to store the whole $form ? + // (would be better using the cache_form table...) + // Plus this might is the key to batching multistep forms ? +// $batch['form'] = isset($form['#redirect']) ? array('#redirect' => $form['#redirect']) : array(); } return TRUE; } @@ -274,15 +271,26 @@ function _batch_finished() { if (isset($_batch['destination'])) { $_REQUEST['destination'] = $_batch['destination']; } - $redirect = isset($_batch['redirect']) ? $_batch['redirect'] : $_batch['source_page']; - $form_redirect = isset($_batch['form_redirect']) ? $_batch['form_redirect'] : NULL; - // Let drupal_redirect_form handle redirection logic, using a bare pseudo form - // to limit the amount of data we store in the batch. - drupal_redirect_form(array('#redirect' => $form_redirect), $redirect); - - // If we get here, $form['redirect']['#redirect'] was FALSE, and we are most - // probably dealing with a multistep form - not supported at the moment. - // Redirect to the originating page - first step of the form. + + // Use $_batch['form_state']['redirect'], or $_batch['redirect'], or $_batch['source_page']. + if (isset($_batch['form_state']['redirect'])) { + $redirect = $_batch['form_state']['redirect']; + } + elseif (isset($_batch['redirect'])) { + $redirect = $_batch['redirect']; + } + else { + $redirect = $_batch['source_page']; + } + // Let drupal_redirect_form handle redirection logic. + $form = isset($batch['form']) ? $batch['form'] : array(); + if (empty($_batch['form_state']['rebuild']) && empty($_batch['form_state']['storage'])) { + drupal_redirect_form($form, $redirect); + } + + // If we get here, $form['#redirect'] was FALSE. + // Redirect to the originating page. + $_SESSION['batch_form_state'] = $_batch['form_state']; drupal_goto($_batch['source_page']); } } Index: includes/cache-install.inc =================================================================== RCS file: includes/cache-install.inc diff -N includes/cache-install.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ includes/cache-install.inc 9 May 2007 19:49:56 -0000 @@ -0,0 +1,23 @@ + NULL, 'submitted' => FALSE); + $expire = max(ini_get('session.cookie_lifetime'), 86400); + + $args = func_get_args(); + + if (isset($_SESSION['batch_form_state'])) { + $form_state = $_SESSION['batch_form_state']; + unset($_SESSION['batch_form_state']); } else { - // We're coming in fresh; build things as they would be. If the - // form's #multistep flag is set, store the build parameters so - // the same form can be reconstituted for validation. - $args = func_get_args(); - $form = call_user_func_array('drupal_retrieve_form', $args); - if (isset($form['#multistep']) && $form['#multistep']) { - // Clean up old multistep form session data. - _drupal_clean_form_sessions(); - $_SESSION['form'][$form_build_id] = array('timestamp' => time(), 'args' => $args); - $form['#build_id'] = $form_build_id; + // If the incoming $_POST contains a form_build_id, we'll check the + // cache for a copy of the form in question. If it's there, we don't + // have to rebuild the form to proceed. In addition, if there is stored + // form_state data from a previous step, we'll retrieve it so it can + // be passed on to the form processing code. + if (isset($_POST['form_id']) && $_POST['form_id'] == $form_id && !empty($_POST['form_build_id'])) { + if ($cached = cache_get('form_'. $_POST['form_build_id'], 'cache_form')) { + $form = $cached->data; + if ($cached = cache_get('storage_'. $_POST['form_build_id'], 'cache_form')) { + $form_state['storage'] = $cached->data; + } + } } - $stored = FALSE; - } - // Process the form, submit it, and store any errors if necessary. - drupal_process_form($args[0], $form); - - if ($stored && !form_get_errors()) { - // If it's a stored form and there were no errors, we processed the - // stored form successfully. Now we need to build the form that was - // actually requested. We always pass in the current $_POST values - // to the builder function, as values from one stage of a multistep - // form can determine how subsequent steps are displayed. - $args = func_get_args(); - $args[] = $_POST; - $form = call_user_func_array('drupal_retrieve_form', $args); - unset($_SESSION['form'][$_POST['form_build_id']]); - if (isset($form['#multistep']) && $form['#multistep']) { - $_SESSION['form'][$form_build_id] = array('timestamp' => time(), 'args' => $args); + // If the previous bit of code didn't result in a populated $form + // object, we're hitting the form for the first time and we need + // to build it from scratch. + if (!isset($form)) { + $form = call_user_func_array('drupal_retrieve_form', $args); + $form_build_id = md5(mt_rand()); $form['#build_id'] = $form_build_id; + drupal_prepare_form($form_id, $form, $form_state); + if (!empty($form['#cache'])) { + cache_set('form_'. $form_build_id, $form, 'cache_form', $expire); + } } - drupal_prepare_form($args[0], $form); - } + $form['#post'] = $_POST; - return drupal_render_form($args[0], $form); -} + // Now that we know we have a form, we'll process it (validating, + // submitting, and handling the results returned by its submission + // handlers. Submit handlers accumulate data in the form_state by + // altering the $form_state variable, which is passed into them by + // reference. + drupal_process_form($form_id, $form, $form_state); + } + + // Most simple, single-step forms will be finished by this point -- + // drupal_process_form() usually redirects to another page (or to + // a 'fresh' copy of the form) once processing is complete. If one + // of the form's handlers has set $form_state['redirect'] to FALSE, + // the form will simply be re-rendered with the values still in its + // fields. + // + // If $form_state['storage'] or $form_state['rebuild'] have been + // set by any submit or validate handlers, however, we know that + // we're in a complex multi-part process of some sort and the form's + // workflow is NOT 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['rebuild']) || !empty($form_state['storage'])) { + $args[] = $form_state; + $form = call_user_func_array('drupal_retrieve_form', $args); -/** - * Remove form information that's at least a day old from the - * $_SESSION['form'] array. - */ -function _drupal_clean_form_sessions() { - if (isset($_SESSION['form'])) { - foreach ($_SESSION['form'] as $build_id => $data) { - if ($data['timestamp'] < (time() - 84600)) { - unset($_SESSION['form'][$build_id]); - } + // We need a new build_id for the new version of the form. + $form_build_id = md5(mt_rand()); + $form['#build_id'] = $form_build_id; + drupal_prepare_form($form_id, $form, $form_state); + + // Now, we cache the form structure so it can be retrieved later for + // validation. If $form_state['storage'] is populated, we'll also cache + // it so that it can be used to resume complex multi-step processes. + cache_set('form_'. $form_build_id, $form, 'cache_form', $expire); + if (!empty($form_state['storage'])) { + cache_set('storage_'. $form_build_id, $form_state['storage'], 'cache_form', $expire); } + + // Clear out all post data, as we don't want the previous step's + // data to pollute this one and trigger validate/submit handling, + // then process the form for rendering. + $_POST = array(); + $form['#post'] = array(); + drupal_process_form($form_id, $form, $form_state); } -} + // If we haven't redirected to a new location by now, we want to + // render whatever form array is currently in hand. + return drupal_render_form($form_id, $form); +} /** - * Retrieves a form using a form_id, populates it with $form_values, + * Retrieves a form using a form_id, populates it with $form_state['values'], * processes it, and returns any validation errors encountered. This * function is the programmatic counterpart to drupal_get_form(). * @@ -124,43 +143,47 @@ function _drupal_clean_form_sessions() { * with that name exists, it is called to build the form array. * Modules that need to generate the same form (or very similar forms) * using different $form_ids can implement hook_forms(), which maps - * different $form_id values to the proper form building function. Examples + * different $form_id values to the proper form constructor function. Examples * may be found in node_forms(), search_forms(), and user_forms(). - * @param $form_values - * An array of values mirroring the values returned by a given form - * when it is submitted by a user. + * @param $form_state + * A keyed array containing the current state of the form. Most + * important is the $form_state['values'] collection, a tree of data + * used to simulate the incoming $_POST information from a user's + * form submission. * @param ... - * Any additional arguments needed by the form building function. - * @return - * Any form validation errors encountered. + * Any additional arguments needed by the form constructor function. * * For example: * * // register a new user - * $values['name'] = 'robo-user'; - * $values['mail'] = 'robouser@example.com'; - * $values['pass'] = 'password'; - * drupal_execute('user_register', $values); + * $form_state = array(); + * $form_state['values']['name'] = 'robo-user'; + * $form_state['values']['mail'] = 'robouser@example.com'; + * $form_state['values']['pass'] = 'password'; + * drupal_execute('user_register', $form_state); * * // Create a new node + * $form_state = array(); * $node = array('type' => 'story'); - * $values['title'] = 'My node'; - * $values['body'] = 'This is the body text!'; - * $values['name'] = 'robo-user'; - * drupal_execute('story_node_form', $values, $node); + * $form_state['values']['title'] = 'My node'; + * $form_state['values']['body'] = 'This is the body text!'; + * $form_state['values']['name'] = 'robo-user'; + * drupal_execute('story_node_form', $form_state, $node); */ -function drupal_execute($form_id, $form_values) { +function drupal_execute($form_id, &$form_state) { $args = func_get_args(); - $form_id = array_shift($args); - $form_values = array_shift($args); + // We do a bit of juggling here because drupal_retrieve_form() expects + // the $form_state to be the last parameter, while drupal_execute() + // always takes it in as the second parameter. + $args = array_slice($args, 3); array_unshift($args, $form_id); + $args[] = $form_state; - if (isset($form_values)) { - $form = call_user_func_array('drupal_retrieve_form', $args); - $form['#post'] = $form_values; - return drupal_process_form($form_id, $form); - } + $form = call_user_func_array('drupal_retrieve_form', $args); + $form['#post'] = $form_state['values']; + drupal_prepare_form($form_id, $form, $form_state); + drupal_process_form($form_id, $form, $form_state); } /** @@ -171,17 +194,17 @@ function drupal_execute($form_id, $form_ * with that name exists, it is called to build the form array. * Modules that need to generate the same form (or very similar forms) * using different $form_ids can implement hook_forms(), which maps - * different $form_id values to the proper form building function. + * different $form_id values to the proper form constructor function. * @param ... - * Any additional arguments needed by the form building function. + * Any additional arguments needed by the form constructor function. */ function drupal_retrieve_form($form_id) { static $forms; // We save two copies of the incoming arguments: one for modules to use - // when mapping form ids to builder functions, and another to pass to - // the builder function itself. We shift out the first argument -- the - // $form_id itself -- from the list to pass into the builder function, + // when mapping form ids to constructor functions, and another to pass to + // the constructor function itself. We shift out the first argument -- the + // $form_id itself -- from the list to pass into the constructor function, // since it's already known. $args = func_get_args(); $saved_args = $args; @@ -190,9 +213,9 @@ function drupal_retrieve_form($form_id) // 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. if (!function_exists($form_id)) { - // In cases where many form_ids need to share a central builder function, + // In cases where many form_ids need to share a central constructor function, // such as the node editing form, modules can implement hook_forms(). It - // maps one or more form_ids to the correct builder functions. + // maps one or more form_ids to the correct constructor functions. // // We cache the results of that hook to save time, but that only works // for modules that know all their form_ids in advance. (A module that @@ -202,7 +225,7 @@ function drupal_retrieve_form($form_id) // So, we call the hook if $forms isn't yet populated, OR if it doesn't // yet have an entry for the requested form_id. if (!isset($forms) || !isset($forms[$form_id])) { - $forms = module_invoke_all('forms', $saved_args); + $forms = module_invoke_all('forms', $form_id, $args); } $form_definition = $forms[$form_id]; if (isset($form_definition['callback arguments'])) { @@ -232,47 +255,52 @@ function drupal_retrieve_form($form_id) * The unique string identifying the current form. * @param $form * An associative array containing the structure of the form. - * @return - * The path to redirect the user to upon completion. - */ -function drupal_process_form($form_id, &$form) { - global $form_values, $form_submitted, $user, $form_button_counter; - static $saved_globals = array(); - // In some scenarios, this function can be called recursively. Pushing any pre-existing - // $form_values and form submission data lets us start fresh without clobbering work done - // in earlier recursive calls. - array_push($saved_globals, array($form_values, $form_submitted, $form_button_counter)); - - $form_values = array(); - $form_submitted = FALSE; - $form_button_counter = array(0, 0); - - drupal_prepare_form($form_id, $form); - if (($form['#programmed']) || (!empty($_POST) && (($_POST['form_id'] == $form_id)))) { - drupal_validate_form($form_id, $form); - // IE does not send a button value when there is only one submit button (and no non-submit buttons) - // and you submit by pressing enter. - // In that case we accept a submission without button values. - if ((($form['#programmed']) || $form_submitted || (!$form_button_counter[0] && $form_button_counter[1])) && !form_get_errors()) { - $redirect = drupal_submit_form($form_id, $form); + * @param $form_state + * A keyed array containing the current state of the form. This + * includes the current persistant storage data for the form, and + * any data passed along by earlier steps when displaying a + * multi-step form. Additional information, like the sanitized $_POST + * data, is also accumulated here. + */ +function drupal_process_form($form_id, &$form, &$form_state) { + $form_state['values'] = array(); + + $form = form_builder($form_id, $form, $form_state); + if ((!empty($form['#programmed'])) || (!empty($form['#post']) && (($form['#post']['form_id'] == $form_id)))) { + drupal_validate_form($form_id, $form, $form_state); + + if ((!empty($form_state['submitted'])) && !form_get_errors() && empty($form_state['rebuild'])) { + $form_state['redirect'] = NULL; + form_execute_handlers('submit', $form, $form_state); + + // We'll clear out the cached copies of the form and its stored data + // here, as we've finished with them. The in-memory copies are still + // here, though. + if (variable_get('cache', CACHE_DISABLED) == CACHE_DISABLED) { + cache_clear_all('form_'. $form_state['values']['form_build_id'], 'cache_form'); + cache_clear_all('storage_'. $form_state['values']['form_build_id'], 'cache_form'); + } + if ($batch =& batch_get()) { + $batch['form'] = $form; + $batch['form_state'] = $form_state; $batch['progressive'] = !$form['#programmed']; batch_process(); // Progressive batch processing redirects to the progress page. // Execution continues only if programmed form. } - if (!$form['#programmed']) { - drupal_redirect_form($form, $redirect); + // If no submit handlers have populated the $form_state['storage'] + // bundle, and the $form_state['rebuild'] flag has not been set, + // we're finished and should redirect to a new destination page + // if one has been set (and a fresh, unpopulated copy of the form + // if one hasn't). If the form was called by drupal_execute(), + // however, we'll skip this and let the calling function examine + // the resulting $form_state bundle itself. + if (!$form['#programmed'] && empty($form_state['rebuild']) && empty($form_state['storage'])) { + drupal_redirect_form($form, $form_state['redirect']); } } } - - // We've finished calling functions that alter the global values, so we can - // restore the ones that were there before this function was called. - list($form_values, $form_submitted, $form_button_counter) = array_pop($saved_globals); - if (isset($redirect)) { - return $redirect; - } } /** @@ -285,25 +313,16 @@ function drupal_process_form($form_id, & * theming, and hook_form_alter functions. * @param $form * An associative array containing the structure of the form. + * @param $form_state + * A keyed array containing the current state of the form. Passed + * in here so that hook_form_alter() calls can use it, as well. */ -function drupal_prepare_form($form_id, &$form) { +function drupal_prepare_form($form_id, &$form, &$form_state) { global $user; $form['#type'] = 'form'; - if (!isset($form['#skip_duplicate_check'])) { - $form['#skip_duplicate_check'] = FALSE; - } + $form['#programmed'] = isset($form['#post']); - if (!isset($form['#post'])) { - $form['#post'] = $_POST; - $form['#programmed'] = FALSE; - } - else { - $form['#programmed'] = TRUE; - } - - // In multi-step form scenarios, this id is used to identify - // a unique instance of a particular form for retrieval. if (isset($form['#build_id'])) { $form['form_build_id'] = array( '#type' => 'hidden', @@ -334,9 +353,12 @@ function drupal_prepare_form($form_id, & ); } - if (isset($form_id)) { - $form['form_id'] = array('#type' => 'hidden', '#value' => $form_id, '#id' => form_clean_id("edit-$form_id")); + $form['form_id'] = array( + '#type' => 'hidden', + '#value' => $form_id, + '#id' => form_clean_id("edit-$form_id"), + ); } if (!isset($form['#id'])) { $form['#id'] = form_clean_id($form_id); @@ -346,25 +368,24 @@ function drupal_prepare_form($form_id, & if (!isset($form['#validate'])) { if (function_exists($form_id .'_validate')) { - $form['#validate'] = array($form_id .'_validate' => array()); + $form['#validate'] = array($form_id .'_validate'); } } if (!isset($form['#submit'])) { if (function_exists($form_id .'_submit')) { // We set submit here so that it can be altered. - $form['#submit'] = array($form_id .'_submit' => array()); + $form['#submit'] = array($form_id .'_submit'); } } - drupal_alter('form', $form, $form_id); - - $form = form_builder($form_id, $form); + drupal_alter('form_'. $form_id, $form, $form_state); + drupal_alter('form', $form, $form_id, $form_state); } /** - * Validates user-submitted form data from a global variable using + * Validates user-submitted form data from the $form_state using * the validate functions defined in a structured form array. * * @param $form_id @@ -372,10 +393,18 @@ function drupal_prepare_form($form_id, & * theming, and hook_form_alter functions. * @param $form * An associative array containing the structure of the form. - * + * @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 + * form validation functions are passed an explicit copy of the + * values for the sake of simplicity. Validation handlers can also + * $form_state to pass information on to submit handlers. For example: + * $form_state['data_for_submision'] = $data; + * This technique is useful when validation requires file parsing, + * web service requests, or other expensive requests that should + * not be repeated in the submission step. */ -function drupal_validate_form($form_id, $form) { - global $form_values; +function drupal_validate_form($form_id, $form, &$form_state) { static $validated_forms = array(); if (isset($validated_forms[$form_id])) { @@ -385,80 +414,17 @@ function drupal_validate_form($form_id, // If the session token was set by drupal_prepare_form(), ensure that it // matches the current user's session. if (isset($form['#token'])) { - if (!drupal_valid_token($form_values['form_token'], $form['#token'])) { + if (!drupal_valid_token($form_state['values']['form_token'], $form['#token'])) { // Setting this error will cause the form to fail validation. form_set_error('form_token', t('Validation error, please try again. If this error persists, please contact the site administrator.')); } } - if (!$form['#programmed'] && !$form['#skip_duplicate_check'] && isset($_SESSION['last_submitted']['hash']) && $_SESSION['last_submitted']['hash'] == md5(serialize($form['form_id']['#post']))) { - // This is a repeat submission. - drupal_redirect_form(NULL, $_SESSION['last_submitted']['destination']); - } - - _form_validate($form, $form_id); + _form_validate($form, $form_state, $form_id); $validated_forms[$form_id] = TRUE; } /** - * Processes user-submitted form data from a global variable using - * the submit functions defined in a structured form array. - * - * @param $form_id - * 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. - * @return - * A string containing the path of the page to display when processing - * is complete. - * - */ -function drupal_submit_form($form_id, $form) { - global $form_values; - $default_args = array($form_id, &$form_values); - $submitted = FALSE; - $goto = NULL; - - if (isset($form['#submit'])) { - foreach ($form['#submit'] as $function => $args) { - if (function_exists($function)) { - $args = array_merge($default_args, (array) $args); - // Since we can only redirect to one page, only the last redirect - // will work. - if ($batch =& batch_get()) { - // Some previous _submit callback has set a batch. - // We store the call in a special 'control' batch set for execution - // at the correct time during the batch processing workflow. - $batch['sets'][] = array('form submit' => array($function, $args)); - } - else { - $redirect = call_user_func_array($function, $args); - if ($batch =& batch_get()) { - // The _submit callback has opened a batch: store the needed form info. - $batch['form_redirect'] = isset($form['#redirect']) ? $form['#redirect'] : NULL; - } - } - $submitted = TRUE; - if (isset($redirect)) { - $goto = $redirect; - } - } - } - } - // Successful submit. Hash this form's POST and store the hash in the - // session. We'll use this hash later whenever this user submits another - // form to make sure no identical forms get submitted twice. - if ($submitted && !$form['#skip_duplicate_check']) { - $_SESSION['last_submitted'] = array('destination' => $goto, 'hash' => md5(serialize($form['form_id']['#post']))); - } - - if (isset($goto)) { - return $goto; - } -} - -/** * Renders a structured form array into themed HTML. * * @param $form_id @@ -469,11 +435,9 @@ function drupal_submit_form($form_id, $f * @return * A string containing the path of the page to display when processing * is complete. - * */ function drupal_render_form($form_id, &$form) { // Don't override #theme if someone already set it. - if (!isset($form['#theme'])) { init_theme(); $registry = theme_get_registry(); @@ -482,14 +446,6 @@ function drupal_render_form($form_id, &$ } } - if (isset($form['#pre_render'])) { - foreach ($form['#pre_render'] as $function) { - if (function_exists($function)) { - $function($form_id, $form); - } - } - } - $output = drupal_render($form); return $output; } @@ -500,15 +456,15 @@ function drupal_render_form($form_id, &$ * @param $form * An associative array containing the structure of the form. * @param $redirect - * An optional string containing the destination path to redirect + * An optional value containing the destination path to redirect * to if none is specified by the form. - * */ function drupal_redirect_form($form, $redirect = NULL) { + $goto = NULL; if (isset($redirect)) { $goto = $redirect; } - if (isset($form['#redirect'])) { + if ($goto !== FALSE && isset($form['#redirect'])) { $goto = $form['#redirect']; } if (!isset($goto) || ($goto !== FALSE)) { @@ -531,15 +487,25 @@ function drupal_redirect_form($form, $re * * @param $elements * An associative array containing the structure of the form. + * @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 + * form validation functions are passed an explicit copy of the + * values for the sake of simplicity. Validation handlers can also + * $form_state to pass information on to submit handlers. For example: + * $form_state['data_for_submision'] = $data; + * This technique is useful when validation requires file parsing, + * web service requests, or other expensive requests that should + * not be repeated in the submission step. * @param $form_id * A unique string identifying the form for validation, submission, * theming, and hook_form_alter functions. */ -function _form_validate($elements, $form_id = NULL) { +function _form_validate($elements, &$form_state, $form_id = NULL) { // Recurse through all children. foreach (element_children($elements) as $key) { if (isset($elements[$key]) && $elements[$key]) { - _form_validate($elements[$key]); + _form_validate($elements[$key], $form_state); } } /* Validate the current input */ @@ -571,27 +537,27 @@ function _form_validate($elements, $form foreach ($value as $v) { if (!isset($options[$v])) { form_error($elements, t('An illegal choice has been detected. Please contact the site administrator.')); - watchdog('form', 'Illegal choice %choice in !name element.', array('%choice' => $v, '!name' => empty($elements['#title']) ? $elements['#parents'][0] : $elements['#title']), WATCHDOG_ERROR); + watchdog('form', t('Illegal choice %choice in !name element.', array('%choice' => $v, '!name' => empty($elements['#title']) ? $elements['#parents'][0] : $elements['#title'])), WATCHDOG_ERROR); } } } elseif (!isset($options[$elements['#value']])) { form_error($elements, t('An illegal choice has been detected. Please contact the site administrator.')); - watchdog('form', 'Illegal choice %choice in %name element.', array('%choice' => $elements['#value'], '%name' => empty($elements['#title']) ? $elements['#parents'][0] : $elements['#title']), WATCHDOG_ERROR); + watchdog('form', t('Illegal choice %choice in %name element.', array('%choice' => $elements['#value'], '%name' => empty($elements['#title']) ? $elements['#parents'][0] : $elements['#title'])), WATCHDOG_ERROR); } } } - // Call user-defined validators. - if (isset($elements['#validate'])) { - foreach ($elements['#validate'] as $function => $args) { - $args = array_merge(array($elements), $args); - // For the full form we hand over a copy of $form_values. - if (isset($form_id)) { - $args = array_merge(array($form_id, $GLOBALS['form_values']), $args); - } + // Call user-defined form level validators. + if (isset($form_id)) { + form_execute_handlers('validate', $elements, $form_state); + } + // Call any element-specific validators. These must act on the element + // #value data. + elseif (isset($elements['#element_validate'])) { + foreach ($elements['#element_validate'] as $function) { if (function_exists($function)) { - call_user_func_array($function, $args); + $function($elements, $form_state); } } } @@ -600,6 +566,50 @@ function _form_validate($elements, $form } /** + * A helper function used to execute custom validation and submission + * handlers for a given form. Button-specific handlers are checked + * first. If none exist, the function falls back to form-level handlers. + * + * @param $type + * The type of handler to execute. 'validate' or 'submit' are the + * defaults used by Form API. + * @param $form + * An associative array containing the structure of the form. + * @param $form_state + * A keyed array containing the current state of the form. If the user + * submitted the form by clicking a button with custom handler functions + * defined, those handlers will be stored here. + */ +function form_execute_handlers($type, &$form, &$form_state) { + $return = FALSE; + if (isset($form_state[$type .'_handlers'])) { + $handlers = $form_state[$type .'_handlers']; + } + elseif (isset($form['#'. $type])) { + $handlers = $form['#'. $type]; + } + else { + $handlers = array(); + } + + foreach ($handlers as $function) { + if (function_exists($function)) { + if ($type == 'submit' && ($batch =& batch_get())) { + // Some previous _submit callback has set a batch. + // We store the call in a special 'control' batch set for execution + // at the correct time during the batch processing workflow (see _batch_next_set). + $batch['sets'][] = array('form_submit' => array($function, $form, $form_state)); + } + else { + $function($form_state['values'], $form, $form_state); + } + $return = TRUE; + } + } + return $return; +} + +/** * File an error against a form element. If the name of the element is * edit[foo][bar] then you may pass either foo or foo][bar as $name * foo will set an error for all its children. @@ -649,20 +659,22 @@ function form_error(&$element, $message } /** - * Adds some required properties to each form element, which are used - * internally in the form API. This function also automatically assigns - * the value property from the $edit array, provided the element doesn't - * already have an assigned value. + * Walk through the structured form array, adding any required + * properties to each element and mapping the incoming $_POST + * data to the proper elements. * * @param $form_id * 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. + * @param $form_state + * A keyed array containing the current state of the form. In this + * context, it is used to accumulate information about which button + * was clicked when the form was submitted, as well as the sanitized + * $_POST data. */ -function form_builder($form_id, $form) { - global $form_values, $form_submitted, $form_button_counter; - +function form_builder($form_id, $form, &$form_state) { // Initialize as unprocessed. $form['#processed'] = FALSE; @@ -673,120 +685,7 @@ function form_builder($form_id, $form) { } if (isset($form['#input']) && $form['#input']) { - if (!isset($form['#name'])) { - $name = array_shift($form['#parents']); - $form['#name'] = $name; - if ($form['#type'] == 'file') { - // To make it easier to handle $_FILES in file.inc, we place all - // file fields in the 'files' array. Also, we do not support - // nested file names. - $form['#name'] = 'files['. $form['#name'] .']'; - } - elseif (count($form['#parents'])) { - $form['#name'] .= '['. implode('][', $form['#parents']) .']'; - } - array_unshift($form['#parents'], $name); - } - if (!isset($form['#id'])) { - $form['#id'] = form_clean_id('edit-'. implode('-', $form['#parents'])); - } - - if (isset($form['#disabled']) && $form['#disabled']) { - $form['#attributes']['disabled'] = 'disabled'; - } - - if (!isset($form['#value']) && !array_key_exists('#value', $form)) { - if (($form['#programmed']) || ((!isset($form['#access']) || $form['#access']) && isset($form['#post']) && (isset($form['#post']['form_id']) && $form['#post']['form_id'] == $form_id))) { - $edit = $form['#post']; - foreach ($form['#parents'] as $parent) { - $edit = isset($edit[$parent]) ? $edit[$parent] : NULL; - } - if (!$form['#programmed'] || isset($edit)) { - switch ($form['#type']) { - case 'checkbox': - $form['#value'] = !empty($edit) ? $form['#return_value'] : 0; - break; - - case 'select': - if (isset($form['#multiple']) && $form['#multiple']) { - if (isset($edit) && is_array($edit)) { - $form['#value'] = drupal_map_assoc($edit); - } - else { - $form['#value'] = array(); - } - } - elseif (isset($edit)) { - $form['#value'] = $edit; - } - break; - - case 'textfield': - if (isset($edit)) { - // Equate $edit to the form value to ensure it's marked for - // validation. - $edit = str_replace(array("\r", "\n"), '', $edit); - $form['#value'] = $edit; - } - break; - - case 'token': - $form['#value'] = (string)$edit; - break; - - default: - if (isset($edit)) { - $form['#value'] = $edit; - } - } - // Mark all posted values for validation. - if ((isset($form['#value']) && $form['#value'] === $edit) || (isset($form['#required']) && $form['#required'])) { - $form['#needs_validation'] = TRUE; - } - } - } - if (!isset($form['#value'])) { - $function = $form['#type'] .'_value'; - if (function_exists($function)) { - $function($form); - } - else { - $form['#value'] = isset($form['#default_value']) ? $form['#default_value'] : ''; - } - } - } - if (isset($form['#executes_submit_callback'])) { - // Count submit and non-submit buttons. - $form_button_counter[$form['#executes_submit_callback']]++; - // See if a submit button was pressed. - if (isset($form['#post'][$form['#name']]) && $form['#post'][$form['#name']] == $form['#value']) { - $form_submitted = $form_submitted || $form['#executes_submit_callback']; - - // In most cases, we want to use form_set_value() to manipulate the - // global variables. In this special case, we want to make sure that - // the value of this element is listed in $form_variables under 'op'. - $form_values[$form['#name']] = $form['#value']; - } - } - } - - // Allow for elements to expand to multiple elements, e.g., radios, - // checkboxes and files. - if (isset($form['#process']) && !$form['#processed']) { - foreach ($form['#process'] as $process => $args) { - if (function_exists($process)) { - $args = array_merge(array($form), array(isset($edit) ? $edit : NULL), $args); - $form = call_user_func_array($process, $args); - } - } - $form['#processed'] = TRUE; - } - - // Set the $form_values key that gets passed to validate and submit. - // We call this after #process gets called so that #process has a - // chance to update #value if desired. - if (isset($form['#input']) && $form['#input']) { - form_set_value($form, $form['#value']); + _form_builder_handle_input_element($form_id, $form, $form_state); } // We start off assuming all form elements are in the correct order. @@ -823,25 +722,187 @@ function form_builder($form_id, $form) { // later. unset($form['#sorted']); } - $form[$key] = form_builder($form_id, $form[$key]); + $form[$key] = form_builder($form_id, $form[$key], $form_state); $count++; } + // The #after_build flag allows any piece of a form to be altered + // after normal input parsing has been completed. if (isset($form['#after_build']) && !isset($form['#after_build_done'])) { foreach ($form['#after_build'] as $function) { + $form = $function($form, $form_state['values'], $form_state); + $form['#after_build_done'] = TRUE; + } + } + + // Now that we've processed everything, we can go back to handle the funky + // Internet Explorer button-click scenerio. + _form_builder_ie_cleanup($form, $form_state); + + return $form; +} + +/** + * Populate the #value and #name properties of input elements so they + * can be processed and rendered. Also, execute any #process handlers + * attached to a specific element. + */ +function _form_builder_handle_input_element($form_id, &$form, &$form_state) { + if (isset($form['#type']) && $form['#type'] == 'form' && !empty($form['#programed'])) { + $form_state['submitted'] = TRUE; + } + + if (!isset($form['#name'])) { + $name = array_shift($form['#parents']); + $form['#name'] = $name; + if ($form['#type'] == 'file') { + // To make it easier to handle $_FILES in file.inc, we place all + // file fields in the 'files' array. Also, we do not support + // nested file names. + $form['#name'] = 'files['. $form['#name'] .']'; + } + elseif (count($form['#parents'])) { + $form['#name'] .= '['. implode('][', $form['#parents']) .']'; + } + array_unshift($form['#parents'], $name); + } + if (!isset($form['#id'])) { + $form['#id'] = form_clean_id('edit-'. implode('-', $form['#parents'])); + } + + if (!empty($form['#disabled'])) { + $form['#attributes']['disabled'] = 'disabled'; + } + + if (!isset($form['#value']) && !array_key_exists('#value', $form)) { + if (($form['#programmed']) || ((!isset($form['#access']) || $form['#access']) && isset($form['#post']) && (isset($form['#post']['form_id']) && $form['#post']['form_id'] == $form_id))) { + $edit = $form['#post']; + foreach ($form['#parents'] as $parent) { + $edit = isset($edit[$parent]) ? $edit[$parent] : NULL; + } + if (!$form['#programmed'] || isset($edit)) { + switch ($form['#type']) { + case 'checkbox': + $form['#value'] = !empty($edit) ? $form['#return_value'] : 0; + break; + + case 'select': + if (isset($form['#multiple']) && $form['#multiple']) { + if (isset($edit) && is_array($edit)) { + $form['#value'] = drupal_map_assoc($edit); + } + else { + $form['#value'] = array(); + } + } + elseif (isset($edit)) { + $form['#value'] = $edit; + } + break; + + case 'textfield': + if (isset($edit)) { + // Equate $edit to the form value to ensure it's marked for + // validation. + $edit = str_replace(array("\r", "\n"), '', $edit); + $form['#value'] = $edit; + } + break; + + case 'token': + $form['#value'] = (string)$edit; + break; + + default: + if (isset($edit)) { + $form['#value'] = $edit; + } + } + // Mark all posted values for validation. + if ((isset($form['#value']) && $form['#value'] === $edit) || (isset($form['#required']) && $form['#required'])) { + $form['#needs_validation'] = TRUE; + } + } + } + if (!isset($form['#value'])) { + $function = 'form_'. $form['#type'] .'_value'; if (function_exists($function)) { - $form = $function($form, $form_values); + $function($form); + } + else { + $form['#value'] = isset($form['#default_value']) ? $form['#default_value'] : ''; } } - $form['#after_build_done'] = TRUE; } - return $form; + // Determine which button (if any) was clicked to submit the form. + // We compare the incoming values with the buttons defined in the form, + // and flag the one that matches. We have to do some funky tricks to + // deal with Internet Explorer's handling of single-button forms, though. + if (!empty($form['#post']) && isset($form['#executes_submit_callback'])) { + // First, accumulate a collection of buttons, divided into two bins: + // those that execute full submit callbacks and those that only validate. + $button_type = $form['#executes_submit_callback'] ? 'submit' : 'button'; + $form_state['buttons'][$button_type][] = $form; + + // See if a submit button was clicked. In Internet Explorer, if ONLY + // one submit button is present, AND the enter key is used to submit + // the form, no form value is sent for it and we'll never detect a + // match. In most cases, though, the following code will properly handle + // finding the clicked button and storing any custom validate and + // submit handlers it has defined. + if (isset($form['#post'][$form['#name']]) && $form['#post'][$form['#name']] == $form['#value']) { + $form_state['submitted'] = $form_state['submitted'] || $form['#executes_submit_callback']; + + // In most cases, we want to use form_set_value() to manipulate + // the global variables. In this special case, we want to make sure that + // the value of this element is listed in $form_variables under 'op'. + $form_state['values'][$form['#name']] = $form['#value']; + + if (isset($form['#validate'])) { + $form_state['validate_handlers'] = $form['#validate']; + } + if (isset($form['#submit'])) { + $form_state['submit_handlers'] = $form['#submit']; + } + } + } + // Allow for elements to expand to multiple elements, e.g., radios, + // checkboxes and files. + if (isset($form['#process']) && !$form['#processed']) { + foreach ($form['#process'] as $process) { + if (function_exists($process)) { + $args = array_merge(array($form), array(isset($edit) ? $edit : NULL), array($form_state)); + $form = call_user_func_array($process, $args); + } + } + $form['#processed'] = TRUE; + } + form_set_value($form, $form['#value'], $form_state); +} + +/** + * Handle the special Internet Explorer one-button-form hit-enter- + * instead-of-clicking scenerio. + */ +function _form_builder_ie_cleanup($form, &$form_state) { + if (!empty($form['#type']) && $form['#type'] == 'form') { + // If the 'submitted' flag isn't tripped, but there is only one submit button... + if (empty($form_state['submitted']) && !empty($form_state['buttons']['submit']) && empty($form_state['buttons']['button'])) { + $button = $form_state['buttons']['submit'][0]; + $form_state['submitted'] = TRUE; + $form_state['submit_handlers'] = empty($button['#submit']) ? NULL : $button['#submit']; + $form_state['validate_handlers'] = empty($button['#validate']) ? NULL : $button['#validate']; + $form_state['values'][$button['#name']] = $button['#value']; + } + // After handling the special IE case, we no longer need the buttons collection. + unset($form_state['buttons']); + } } /** * Use this function to make changes to form values in the form validate - * phase, so they will be available in the submit phase in $form_values. + * phase, so they will be available in the submit phase in $form_state. * * Specifically, if $form['#parents'] is array('foo', 'bar') * and $value is 'baz' then this function will make @@ -852,9 +913,8 @@ function form_builder($form_id, $form) { * @param $value * The value for the form item. */ -function form_set_value($form, $value) { - global $form_values; - _form_set_value($form_values, $form, $form['#parents'], $value); +function form_set_value($form, $value, &$form_state) { + _form_set_value($form_state['values'], $form, $form['#parents'], $value); } /** @@ -875,7 +935,6 @@ function _form_set_value(&$form_values, } _form_set_value($form_values[$parent], $form, $parents, $value); } - return $form; } /** @@ -1128,14 +1187,14 @@ function expand_password_confirm($elemen $element['pass1'] = array( '#type' => 'password', '#title' => t('Password'), - '#value' => $element['#value']['pass1'], + '#value' => empty($element['#value']) ? NULL : $element['#value']['pass1'], ); $element['pass2'] = array( '#type' => 'password', '#title' => t('Confirm password'), - '#value' => $element['#value']['pass2'], + '#value' => empty($element['#value']) ? NULL : $element['#value']['pass2'], ); - $element['#validate'] = array('password_confirm_validate' => array()); + $element['#element_validate'] = array('password_confirm_validate'); $element['#tree'] = TRUE; if (isset($element['#size'])) { @@ -1148,7 +1207,7 @@ function expand_password_confirm($elemen /** * Validate password_confirm element. */ -function password_confirm_validate($form) { +function password_confirm_validate($form, &$form_state) { $pass1 = trim($form['pass1']['#value']); if (!empty($pass1)) { $pass2 = trim($form['pass2']['#value']); @@ -1162,9 +1221,9 @@ function password_confirm_validate($form // Password field must be converted from a two-element array into a single // string regardless of validation results. - form_set_value($form['pass1'], NULL); - form_set_value($form['pass2'], NULL); - form_set_value($form, $pass1); + form_set_value($form['pass1'], NULL, $form_state); + form_set_value($form['pass2'], NULL, $form_state); + form_set_value($form, $pass1, $form_state); return $form; } @@ -1249,7 +1308,7 @@ function map_month($month) { /** * Helper function to load value from default value for checkboxes. */ -function checkboxes_value(&$form) { +function form_checkboxes_value(&$form) { $value = array(); $form += array('#default_value' => array()); foreach ($form['#default_value'] as $key) { @@ -1834,14 +1893,11 @@ function batch_set($batch_definition) { * URL of the batch processing page. */ function batch_process($redirect = NULL, $url = NULL) { - global $form_values, $user; + global $user; $batch =& batch_get(); // batch_process should not be called inside form _submit callbacks, or while a // batch is already running. Neutralize the call if it is the case. - if (isset($batch['current_set']) || (isset($form_values) && !isset($batch['progressive']))) { - return; - } if (isset($batch)) { // Add process information @@ -1868,6 +1924,7 @@ function batch_process($redirect = NULL, $batch['destination'] = $_REQUEST['edit']['destination']; unset($_REQUEST['edit']['destination']); } + db_query("INSERT INTO {batch} (bid, sid, timestamp, batch) VALUES (%d, %d, %d, '%s')", $batch['id'], $user->sid, time(), serialize($batch)); drupal_goto($batch['url'], 'op=start&id='. $batch['id']); } Index: includes/locale.inc =================================================================== RCS file: /cvs/drupal/drupal/includes/locale.inc,v retrieving revision 1.122 diff -u -F^f -r1.122 locale.inc --- includes/locale.inc 8 May 2007 09:48:14 -0000 1.122 +++ includes/locale.inc 9 May 2007 19:49:56 -0000 @@ -69,7 +69,7 @@ function theme_locale_languages_overview /** * Process language overview form submissions, updating existing languages. */ -function locale_languages_overview_form_submit($form_id, $form_values) { +function locale_languages_overview_form_submit($form_values, $form, &$form_state) { $languages = language_list(); $enabled_count = 0; foreach ($languages as $langcode => $language) { @@ -95,7 +95,8 @@ function locale_languages_overview_form_ // Changing the language settings impacts the interface. cache_clear_all('*', 'cache_page', TRUE); - return 'admin/settings/language'; + $form_state['redirect'] = 'admin/settings/language'; + return; } /** * @} End of "locale-language-overview" @@ -151,8 +152,8 @@ function locale_languages_custom_form() '#value' => t('Add custom language') ); // Reuse the validation and submit functions of the predefined language setup form. - $form['#submit']['locale_languages_predefined_form_submit'] = array(); - $form['#validate']['locale_languages_predefined_form_validate'] = array(); + $form['#submit'][] = 'locale_languages_predefined_form_submit'; + $form['#validate'][] = 'locale_languages_predefined_form_validate'; return $form; } @@ -170,8 +171,8 @@ function locale_languages_edit_form($lan '#type' => 'submit', '#value' => t('Save language') ); - $form['#submit']['locale_languages_edit_form_submit'] = array(); - $form['#validate']['locale_languages_edit_form_validate'] = array(); + $form['#submit'][] = 'locale_languages_edit_form_submit'; + $form['#validate'][] = 'locale_languages_edit_form_validate'; return $form; } else { @@ -252,7 +253,7 @@ function _locale_languages_common_contro /** * Validate the language addition form. */ -function locale_languages_predefined_form_validate($form_id, $form_values) { +function locale_languages_predefined_form_validate($form_values, $form, &$form_state) { $langcode = $form_values['langcode']; if ($duplicate = db_num_rows(db_query("SELECT language FROM {languages} WHERE language = '%s'", $langcode)) != 0) { @@ -268,14 +269,14 @@ function locale_languages_predefined_for } else { // Reuse the editing form validation routine if we add a custom language. - locale_languages_edit_form_validate($form_id, $form_values); + locale_languages_edit_form_validate($form_values, $form, $form_state); } } /** * Process the language addition form submission. */ -function locale_languages_predefined_form_submit($form_id, $form_values) { +function locale_languages_predefined_form_submit($form_values, $form, &$form_state) { $langcode = $form_values['langcode']; if (isset($form_values['name'])) { // Custom language form. @@ -288,13 +289,14 @@ function locale_languages_predefined_for locale_add_language($langcode, $lang[0], isset($lang[1]) ? $lang[1] : $lang[0], isset($lang[2]) ? $lang[2] : 0, '', $langcode); } - return 'admin/settings/language'; + $form_state['redirect'] = 'admin/settings/language'; + return; } /** * Validate the language editing form. Reused for custom language addition too. */ -function locale_languages_edit_form_validate($form_id, $form_values) { +function locale_languages_edit_form_validate($form_values, $form, &$form_state) { if (!empty($form_values['domain']) && !empty($form_values['prefix'])) { form_set_error('prefix', t('Domain and path prefix values should not be set at the same time.')); } @@ -313,7 +315,7 @@ function locale_languages_edit_form_vali /** * Process the language editing form submission. */ -function locale_languages_edit_form_submit($form_id, $form_values) { +function locale_languages_edit_form_submit($form_values, $form, &$form_state) { db_query("UPDATE {languages} SET name = '%s', native = '%s', domain = '%s', prefix = '%s', direction = %d WHERE language = '%s'", $form_values['name'], $form_values['native'], $form_values['domain'], $form_values['prefix'], $form_values['direction'], $form_values['langcode']); $default = language_default(); if ($default->language == $form_values['langcode']) { @@ -323,7 +325,8 @@ function locale_languages_edit_form_subm } variable_set('language_default', $default); } - return 'admin/settings/language'; + $form_state['redirect'] = 'admin/settings/language'; + return; } /** * @} End of "locale-language-add-edit" @@ -366,7 +369,7 @@ function locale_languages_delete_form($l /** * Process language deletion submissions. */ -function locale_languages_delete_form_submit($form_id, $form_values) { +function locale_languages_delete_form_submit($form_values, $form, &$form_state) { $languages = language_list(); if (isset($languages[$form_values['langcode']])) { db_query("DELETE FROM {languages} WHERE language = '%s'", $form_values['langcode']); @@ -380,7 +383,8 @@ function locale_languages_delete_form_su // Changing the language settings impacts the interface: cache_clear_all('*', 'cache_page', TRUE); - return 'admin/settings/language'; + $form_state['redirect'] = 'admin/settings/language'; + return; } /** * @} End of "locale-language-add-edit" @@ -416,10 +420,11 @@ function locale_languages_configure_form /** * Submit function for language negotiation settings. */ -function locale_languages_configure_form_submit($form_id, $form_values) { +function locale_languages_configure_form_submit($form_values, $form, &$form_state) { variable_set('language_negotiation', $form_values['language_negotiation']); drupal_set_message(t('Language negotiation configuration saved.')); - return 'admin/settings/language'; + $form_state['redirect'] = 'admin/settings/language'; + return; } /** * @} End of "locale-languages-negotiation" @@ -588,7 +593,7 @@ function locale_translate_import_form() /** * Process the locale import form submission. */ -function locale_translate_import_form_submit($form_id, $form_values) { +function locale_translate_import_form_submit($form_values, $form, &$form_state) { // Ensure we have the file uploaded if ($file = file_check_upload('file')) { @@ -613,7 +618,8 @@ function locale_translate_import_form_su return 'admin/build/translate/import'; } - return 'admin/build/translate'; + $form_state['redirect'] = 'admin/build/translate'; + return; } /** * @} End of "locale-translate-import" @@ -682,15 +688,15 @@ function locale_translate_export_pot_for ); $form['export']['submit'] = array('#type' => 'submit', '#value' => t('Export')); // Reuse PO export submission callback. - $form['#submit']['locale_translate_export_po_form_submit'] = array(); - $form['#validate']['locale_translate_export_po_form_validate'] = array(); + $form['#submit'][] = 'locale_translate_export_po_form_submit'; + $form['#validate'][] = 'locale_translate_export_po_form_validate'; return $form; } /** * Process a translation (or template) export form submission. */ -function locale_translate_export_po_form_submit($form_id, $form_values) { +function locale_translate_export_po_form_submit($form_values, $form, &$form_state) { // If template is required, language code is not given. _locale_export_po(isset($form_values['langcode']) ? $form_values['langcode'] : NULL, $form_values['group']); } @@ -759,7 +765,7 @@ function locale_translate_edit_form($lid * Process string editing form submissions. * Saves all translations of one string submitted from a form. */ -function locale_translate_edit_form_submit($form_id, $form_values) { +function locale_translate_edit_form_submit($form_values, $form, &$form_state) { $lid = $form_values['lid']; foreach ($form_values['translations'] as $key => $value) { $trans = db_fetch_object(db_query("SELECT translation FROM {locales_target} WHERE lid = %d AND language = '%s'", $lid, $key)); @@ -777,7 +783,8 @@ function locale_translate_edit_form_subm // Rebuild the menu, strings may have changed. menu_rebuild(); - return 'admin/build/translate/search'; + $form_state['redirect'] = 'admin/build/translate/search'; + return; } /** * @} End of "locale-translate-edit" @@ -1914,12 +1921,12 @@ function _locale_get_predefined_list() { "bo" => array("Tibetan"), "br" => array("Breton"), "bs" => array("Bosnian", "Bosanski"), - "ca" => array("Catalan", "Català "), + "ca" => array("Catalan", "Catal�"), "ce" => array("Chechen"), "ch" => array("Chamorro"), "co" => array("Corsican"), "cr" => array("Cree"), - "cs" => array("Czech", "Čeština"), + "cs" => array("Czech", "?e�tina"), "cu" => array("Old Slavonic"), "cv" => array("Chuvash"), "cy" => array("Welsh", "Cymraeg"), @@ -2003,7 +2010,7 @@ function _locale_get_predefined_list() { "ne" => array("Nepali"), "ng" => array("Ndonga"), "nl" => array("Dutch", "Nederlands"), - "nb" => array("Norwegian Bokmål", "Bokmål"), + "nb" => array("Norwegian Bokm�l", "Bokm�l"), "nn" => array("Norwegian Nynorsk", "Nynorsk"), "nr" => array("South Ndebele"), "nv" => array("Navajo"), Index: modules/aggregator/aggregator.module =================================================================== RCS file: /cvs/drupal/drupal/modules/aggregator/aggregator.module,v retrieving revision 1.338 diff -u -F^f -r1.338 aggregator.module --- modules/aggregator/aggregator.module 30 Apr 2007 17:03:22 -0000 1.338 +++ modules/aggregator/aggregator.module 9 May 2007 19:49:56 -0000 @@ -357,7 +357,7 @@ function aggregator_form_category($edit /** * Validate aggregator_form_feed form submissions. */ -function aggregator_form_category_validate($form_id, $form_values) { +function aggregator_form_category_validate($form_values, $form, &$form_state) { if ($form_values['op'] == t('Submit')) { // Check for duplicate titles if (isset($form_values['cid'])) { @@ -376,7 +376,7 @@ function aggregator_form_category_valida * Process aggregator_form_category form submissions. * @todo Add delete confirmation dialog. */ -function aggregator_form_category_submit($form_id, $form_values) { +function aggregator_form_category_submit($form_values, $form, &$form_state) { if ($form_values['op'] == t('Delete')) { $title = $form_values['title']; // Unset the title: @@ -388,20 +388,24 @@ function aggregator_form_category_submit if (isset($form_values['title'])) { drupal_set_message(t('The category %category has been updated.', array('%category' => $form_values['title']))); if (arg(0) == 'admin') { - return 'admin/content/aggregator/'; + $form_state['redirect'] = 'admin/content/aggregator/'; + return; } else { - return 'aggregator/categories/'. $form_values['cid']; + $form_state['redirect'] = 'aggregator/categories/'. $form_values['cid']; + return; } } else { watchdog('aggregator', 'Category %category deleted.', array('%category' => $title)); drupal_set_message(t('The category %category has been deleted.', array('%category' => $title))); if (arg(0) == 'admin') { - return 'admin/content/aggregator/'; + $form_state['redirect'] = 'admin/content/aggregator/'; + return; } else { - return 'aggregator/categories/'; + $form_state['redirect'] = 'aggregator/categories/'; + return; } } } @@ -488,7 +492,7 @@ function aggregator_form_feed($edit = ar /** * Validate aggregator_form_feed form submissions. */ -function aggregator_form_feed_validate($form_id, $form_values) { +function aggregator_form_feed_validate($form_values, $form, &$form_state) { if ($form_values['op'] == t('Submit')) { // Check for duplicate titles if (isset($form_values['fid'])) { @@ -512,7 +516,7 @@ function aggregator_form_feed_validate($ * Process aggregator_form_feed form submissions. * @todo Add delete confirmation dialog. */ -function aggregator_form_feed_submit($form_id, $form_values) { +function aggregator_form_feed_submit($form_values, $form, &$form_state) { if ($form_values['op'] == t('Delete')) { $title = $form_values['title']; // Unset the title: @@ -524,20 +528,24 @@ function aggregator_form_feed_submit($fo if (isset($form_values['title'])) { drupal_set_message(t('The feed %feed has been updated.', array('%feed' => $form_values['title']))); if (arg(0) == 'admin') { - return 'admin/content/aggregator/'; + $form_state['redirect'] = 'admin/content/aggregator/'; + return; } else { - return 'aggregator/sources/'. $form_values['fid']; + $form_state['redirect'] = 'aggregator/sources/'. $form_values['fid']; + return; } } else { watchdog('aggregator', 'Feed %feed deleted.', array('%feed' => $title)); drupal_set_message(t('The feed %feed has been deleted.', array('%feed' => $title))); if (arg(0) == 'admin') { - return 'admin/content/aggregator/'; + $form_state['redirect'] = 'admin/content/aggregator/'; + return; } else { - return 'aggregator/sources/'; + $form_state['redirect'] = 'aggregator/sources/'; + return; } } } @@ -1076,8 +1084,8 @@ function aggregator_page_category() { } function aggregator_page_list($sql, $header, $categorize) { - $form['#submit']['aggregator_page_list_submit'] = array(); - $form['#validate']['aggregator_page_list_validate'] = array(); + $form['#submit'][] = 'aggregator_page_list_submit'; + $form['#validate'][] = 'aggregator_page_list_validate'; $form['#theme'] = 'aggregator_page_list'; $form['header'] = array('#value' => $header); $result = pager_query($sql, 20); @@ -1162,7 +1170,7 @@ function aggregator_page_list_validate($ } } -function aggregator_page_list_submit($form_id, $form_values) { +function aggregator_page_list_submit($form_values, $form, &$form_state) { foreach ($form_values['categories'] as $iid => $selection) { db_query('DELETE FROM {aggregator_category_item} WHERE iid = %d', $iid); foreach ($selection as $cid) { Index: modules/block/block.module =================================================================== RCS file: /cvs/drupal/drupal/modules/block/block.module,v retrieving revision 1.258 diff -u -F^f -r1.258 block.module --- modules/block/block.module 30 Apr 2007 17:03:23 -0000 1.258 +++ modules/block/block.module 9 May 2007 19:49:56 -0000 @@ -292,7 +292,7 @@ function _block_compare($a, $b) { /** * Process main block administration form submission. */ -function block_admin_display_submit($form_id, $form_values) { +function block_admin_display_submit($form_values, $form, &$form_state) { foreach ($form_values as $block) { $block['status'] = $block['region'] != BLOCK_REGION_NONE; $block['region'] = $block['status'] ? $block['region'] : ''; @@ -498,7 +498,7 @@ function block_admin_configure($module = return $form; } -function block_admin_configure_validate($form_id, $form_values) { +function block_admin_configure_validate($form_values, $form, &$form_state) { if ($form_values['module'] == 'block') { if (empty($form_values['info']) || db_num_rows(db_query("SELECT bid FROM {boxes} WHERE bid != %d AND info = '%s'", $form_values['delta'], $form_values['info']))) { form_set_error('info', t('Please ensure that each block description is unique.')); @@ -506,7 +506,7 @@ function block_admin_configure_validate( } } -function block_admin_configure_submit($form_id, $form_values) { +function block_admin_configure_submit($form_values, $form, &$form_state) { if (!form_get_errors()) { db_query("UPDATE {blocks} SET visibility = %d, pages = '%s', custom = %d, title = '%s' WHERE module = '%s' AND delta = '%s'", $form_values['visibility'], trim($form_values['pages']), $form_values['custom'], $form_values['title'], $form_values['module'], $form_values['delta']); db_query("DELETE FROM {blocks_roles} WHERE module = '%s' AND delta = '%s'", $form_values['module'], $form_values['delta']); @@ -516,7 +516,8 @@ function block_admin_configure_submit($f module_invoke($form_values['module'], 'block', 'save', $form_values['delta'], $form_values); drupal_set_message(t('The block configuration has been saved.')); cache_clear_all(); - return 'admin/build/block'; + $form_state['redirect'] = 'admin/build/block'; + return; } } @@ -527,7 +528,7 @@ function block_add_block_form() { return block_admin_configure('block', NULL); } -function block_add_block_form_validate($form_id, $form_values) { +function block_add_block_form_validate($form_values, $form, &$form_state) { if (empty($form_values['info']) || db_num_rows(db_query("SELECT info FROM {boxes} WHERE info = '%s'", $form_values['info']))) { form_set_error('info', t('Please ensure that each block description is unique.')); } @@ -536,7 +537,7 @@ function block_add_block_form_validate($ /** * Save the new custom block. */ -function block_add_block_form_submit($form_id, $form_values) { +function block_add_block_form_submit($form_values, $form, &$form_state) { $delta = db_next_id('{boxes}_bid'); foreach (list_themes() as $key => $theme) { @@ -554,7 +555,8 @@ function block_add_block_form_submit($fo drupal_set_message(t('The block has been created.')); cache_clear_all(); - return 'admin/build/block'; + $form_state['redirect'] = 'admin/build/block'; + return; } /** @@ -571,12 +573,13 @@ function block_box_delete($bid = 0) { /** * Deletion of custom blocks. */ -function block_box_delete_submit($form_id, $form_values) { +function block_box_delete_submit($form_values, $form, &$form_state) { db_query('DELETE FROM {boxes} WHERE bid = %d', $form_values['bid']); db_query("DELETE FROM {blocks} WHERE module = 'block' AND delta = %d", $form_values['bid']); drupal_set_message(t('The block %name has been removed.', array('%name' => $form_values['info']))); cache_clear_all(); - return 'admin/build/block'; + $form_state['redirect'] = 'admin/build/block'; + return; }; /** Index: modules/book/book.module =================================================================== RCS file: /cvs/drupal/drupal/modules/book/book.module,v retrieving revision 1.419 diff -u -F^f -r1.419 book.module --- modules/book/book.module 30 Apr 2007 17:03:24 -0000 1.419 +++ modules/book/book.module 9 May 2007 19:49:56 -0000 @@ -199,12 +199,12 @@ function book_insert($node) { /** * Implementation of hook_submit(). */ -function book_submit(&$node) { +function book_submit(&$form_values) { global $user; // Set default values for non-administrators. if (!user_access('administer nodes')) { - $node->revision = 1; - $node->uid = $user->uid; + $form_values['revision'] = 1; + $form_values['uid'] = $user->uid; } } @@ -298,7 +298,7 @@ function book_outline($node) { /** * Handles book outline form submissions. */ -function book_outline_submit($form_id, $form_values) { +function book_outline_submit($form_values, $form, &$form_state) { $op = $form_values['op']; $node = node_load($form_values['nid']); @@ -318,7 +318,8 @@ function book_outline_submit($form_id, $ drupal_set_message(t('The post has been removed from the book.')); break; } - return "node/$node->nid"; + $form_state['redirect'] = "node/$node->nid"; + return; } /** @@ -924,13 +925,13 @@ function book_admin_orphan() { else { $form['error'] = array('#value' => '
'. t('There are no orphan pages.') .'
'); } - $form['#submit']['book_admin_edit_submit'] = array(); - $form['#validate']['book_admin_edit_validate'] = array(); + $form['#submit'][] = 'book_admin_edit_submit'; + $form['#validate'][] = 'book_admin_edit_validate'; $form['#theme'] = 'book_admin_edit'; return $form; } -function book_admin_edit_submit($form_id, $form_values) { +function book_admin_edit_submit($form_values, $form, &$form_state) { foreach ($form_values['table'] as $row) { $node = node_load($row['nid']); Index: modules/color/color.module =================================================================== RCS file: /cvs/drupal/drupal/modules/color/color.module,v retrieving revision 1.19 diff -u -F^f -r1.19 color.module --- modules/color/color.module 6 May 2007 05:47:51 -0000 1.19 +++ modules/color/color.module 9 May 2007 19:49:57 -0000 @@ -26,7 +26,7 @@ function color_form_alter(&$form, $form_ '#theme' => 'color_scheme_form', ); $form['color'] += color_scheme_form(arg(4)); - $form['#submit']['color_scheme_form_submit'] = array(); + $form['#submit'][] = 'color_scheme_form_submit'; } // Use the generated screenshot in the theme list @@ -183,7 +183,7 @@ function theme_color_scheme_form($form) /** * Submit handler for color change form. */ -function color_scheme_form_submit($form_id, $values) { +function color_scheme_form_submit($values, $form, &$form_state) { // Get theme coloring info if (!isset($values['info'])) { return; Index: modules/comment/comment.module =================================================================== RCS file: /cvs/drupal/drupal/modules/comment/comment.module,v retrieving revision 1.541 diff -u -F^f -r1.541 comment.module --- modules/comment/comment.module 30 Apr 2007 17:03:24 -0000 1.541 +++ modules/comment/comment.module 9 May 2007 19:49:57 -0000 @@ -1224,7 +1224,7 @@ function comment_admin_overview($type = /** * We can't execute any 'Update options' if no comments were selected. */ -function comment_admin_overview_validate($form_id, $form_values) { +function comment_admin_overview_validate($form_values, $form, &$form_state) { $form_values['comments'] = array_diff($form_values['comments'], array(0)); if (count($form_values['comments']) == 0) { form_set_error('', t('Please select one or more comments to perform the update on.')); @@ -1236,7 +1236,7 @@ function comment_admin_overview_validate * Execute the chosen 'Update option' on the selected comments, such as * publishing, unpublishing or deleting. */ -function comment_admin_overview_submit($form_id, $form_values) { +function comment_admin_overview_submit($form_values, $form, &$form_state) { $operations = comment_operations(); if ($operations[$form_values['operation']][1]) { // extract the appropriate database query operation @@ -1321,7 +1321,7 @@ function comment_multiple_delete_confirm /** * Perform the actual comment deletion. */ -function comment_multiple_delete_confirm_submit($form_id, $form_values) { +function comment_multiple_delete_confirm_submit($form_values, $form, &$form_state) { if ($form_values['confirm']) { foreach ($form_values['comments'] as $cid => $value) { $comment = _comment_load($cid); @@ -1676,7 +1676,7 @@ function comment_form_add_preview($form, return $form; } -function comment_form_validate($form_id, $form_values) { +function comment_form_validate($form_values, $form, &$form_state) { comment_validate($form_values); } @@ -1706,13 +1706,15 @@ function _comment_form_submit($form_valu } } - return $form_values; + $form_state['redirect'] = $form_values; + return; } -function comment_form_submit($form_id, $form_values) { +function comment_form_submit($form_values, $form, &$form_state) { $form_values = _comment_form_submit($form_values); if ($cid = comment_save($form_values)) { - return array('node/'. $form_values['nid'], NULL, "comment-$cid"); + $form_state['redirect'] = array('node/'. $form_values['nid'], NULL, "comment-$cid"); + return; } } @@ -1795,7 +1797,7 @@ function theme_comment_controls($form) { return theme('box', t('Comment viewing options'), $output); } -function comment_controls_submit($form_id, $form_values) { +function comment_controls_submit($form_values, $form, &$form_state) { global $user; $mode = $form_values['mode']; Index: modules/contact/contact.module =================================================================== RCS file: /cvs/drupal/drupal/modules/contact/contact.module,v retrieving revision 1.83 diff -u -F^f -r1.83 contact.module --- modules/contact/contact.module 30 Apr 2007 17:03:24 -0000 1.83 +++ modules/contact/contact.module 9 May 2007 19:49:57 -0000 @@ -209,7 +209,7 @@ function contact_admin_edit($cid = NULL) /** * Validate the contact category edit page form submission. */ -function contact_admin_edit_validate($form_id, $form_values) { +function contact_admin_edit_validate($form_values, $form, &$form_state) { if (empty($form_values['category'])) { form_set_error('category', t('You must enter a category.')); } @@ -229,7 +229,7 @@ function contact_admin_edit_validate($fo /** * Process the contact category edit page form submission. */ -function contact_admin_edit_submit($form_id, $form_values) { +function contact_admin_edit_submit($form_values, $form, &$form_state) { if ($form_values['selected']) { // Unselect all other contact categories. db_query('UPDATE {contact} SET selected = 0'); @@ -252,7 +252,8 @@ function contact_admin_edit_submit($form watchdog('mail', 'Contact form: category %category updated.', array('%category' => $form_values['category']), WATCHDOG_NOTICE, l(t('view'), 'admin/build/contact')); } - return 'admin/build/contact'; + $form_state['redirect'] = 'admin/build/contact'; + return; } /** @@ -275,12 +276,13 @@ function contact_admin_delete($cid = NUL /** * Process category delete form submission. */ -function contact_admin_delete_submit($form_id, $form_values) { +function contact_admin_delete_submit($form_values, $form, &$form_state) { db_query("DELETE FROM {contact} WHERE cid = %d", arg(4)); drupal_set_message(t('Category %category has been deleted.', array('%category' => $form_values['category']))); watchdog('mail', 'Contact form: category %category deleted.', array('%category' => $form_values['category']), WATCHDOG_NOTICE); - return 'admin/build/contact'; + $form_state['redirect'] = 'admin/build/contact'; + return; } function contact_admin_settings() { @@ -357,7 +359,7 @@ function contact_mail_user($recipient) { /** * Process the personal contact page form submission. */ -function contact_mail_user_submit($form_id, $form_values) { +function contact_mail_user_submit($form_values, $form, &$form_state) { global $user; $account = user_load(array('uid' => arg(1), 'status' => 1)); @@ -399,7 +401,8 @@ function contact_mail_user_submit($form_ drupal_set_message(t('The message has been sent.')); // Jump to the user's profile page: - return "user/$account->uid"; + $form_state['redirect'] = "user/$account->uid"; + return; } /** @@ -493,7 +496,7 @@ function contact_mail_page() { /** * Validate the site-wide contact page form submission. */ -function contact_mail_page_validate($form_id, $form_values) { +function contact_mail_page_validate($form_values, $form, &$form_state) { if (!$form_values['cid']) { form_set_error('category', t('You must select a valid category.')); } @@ -505,7 +508,7 @@ function contact_mail_page_validate($for /** * Process the site-wide contact page form submission. */ -function contact_mail_page_submit($form_id, $form_values) { +function contact_mail_page_submit($form_values, $form, &$form_state) { // E-mail address of the sender: as the form field is a text field, // all instances of \r and \n have been automatically stripped from it. @@ -550,6 +553,7 @@ function contact_mail_page_submit($form_ drupal_set_message(t('Your message has been sent.')); // Jump to home page rather than back to contact page to avoid contradictory messages if flood control has been activated. - return ''; + $form_state['redirect'] = ''; + return; } Index: modules/dblog/dblog.module =================================================================== RCS file: /cvs/drupal/drupal/modules/dblog/dblog.module,v retrieving revision 1.5 diff -u -F^f -r1.5 dblog.module --- modules/dblog/dblog.module 30 Apr 2007 17:03:24 -0000 1.5 +++ modules/dblog/dblog.module 9 May 2007 19:49:57 -0000 @@ -369,7 +369,7 @@ function theme_dblog_filters($form) { return $output; } -function dblog_filter_form_validate($form_id, $form_values) { +function dblog_filter_form_validate($form_values, $form, &$form_state) { if ($form_values['op'] == t('Filter') && empty($form_values['type']) && empty($form_values['severity'])) { form_set_error('type', t('You must select something to filter by.')); } @@ -378,7 +378,7 @@ function dblog_filter_form_validate($for /** * Process result from dblog administration filter form. */ -function dblog_filter_form_submit($form_id, $form_values) { +function dblog_filter_form_submit($form_id, $form_values, &$form_state) { $op = $form_values['op']; $filters = dblog_filters(); switch ($op) { Index: modules/filter/filter.module =================================================================== RCS file: /cvs/drupal/drupal/modules/filter/filter.module,v retrieving revision 1.172 diff -u -F^f -r1.172 filter.module --- modules/filter/filter.module 30 Apr 2007 17:03:24 -0000 1.172 +++ modules/filter/filter.module 9 May 2007 19:49:57 -0000 @@ -296,7 +296,7 @@ function filter_admin_overview() { return $form; } -function filter_admin_overview_submit($form_id, $form_values) { +function filter_admin_overview_submit($form_values, $form, &$form_state) { // Process form submission to set the default format if (is_numeric($form_values['default'])) { drupal_set_message(t('Default format updated.')); @@ -352,7 +352,7 @@ function filter_admin_delete() { /** * Process filter delete form submission. */ -function filter_admin_delete_submit($form_id, $form_values) { +function filter_admin_delete_submit($form_values, $form, &$form_state) { db_query("DELETE FROM {filter_formats} WHERE format = %d", $form_values['format']); db_query("DELETE FROM {filters} WHERE format = %d", $form_values['format']); @@ -365,7 +365,8 @@ function filter_admin_delete_submit($for cache_clear_all($form_values['format'] .':', 'cache_filter', TRUE); drupal_set_message(t('Deleted input format %format.', array('%format' => $form_values['name']))); - return 'admin/settings/filters'; + $form_state['redirect'] = 'admin/settings/filters'; + return; } /** @@ -441,7 +442,7 @@ function filter_admin_format_form($forma /** * Validate filter format form submissions. */ -function filter_admin_format_form_validate($form_id, $form_values) { +function filter_admin_format_form_validate($form_values, $form, &$form_state) { if (!isset($form_values['format'])) { $name = trim($form_values['name']); $result = db_fetch_object(db_query("SELECT format FROM {filter_formats} WHERE name='%s'", $name)); @@ -454,7 +455,7 @@ function filter_admin_format_form_valida /** * Process filter format form submissions. */ -function filter_admin_format_form_submit($form_id, $form_values) { +function filter_admin_format_form_submit($form_values, $form, &$form_state) { $format = isset($form_values['format']) ? $form_values['format'] : NULL; $current = filter_list_format($format); $name = trim($form_values['name']); @@ -506,7 +507,8 @@ function filter_admin_format_form_submit if (!empty($new)) { $return .= '/'. $format; } - return $return; + $form_state['redirect'] = $return; + return; } /** @@ -549,7 +551,7 @@ function theme_filter_admin_order($form) /** * Process filter order configuration form submission. */ -function filter_admin_order_submit($form_id, $form_values) { +function filter_admin_order_submit($form_values, $form, &$form_state) { foreach ($form_values['weights'] as $id => $weight) { list($module, $delta) = explode('/', $id); db_query("UPDATE {filters} SET weight = %d WHERE format = %d AND module = '%s' AND delta = %d", $weight, $form_values['format'], $module, $delta); @@ -784,7 +786,7 @@ function filter_form($value = FILTER_FOR '#collapsible' => TRUE, '#collapsed' => TRUE, '#weight' => $weight, - '#validate' => array('filter_form_validate' => array()), + '#element_validate' => array('filter_form_validate'), ); // Multiple formats available: display radio buttons with tips. foreach ($formats as $format) { Index: modules/forum/forum.module =================================================================== RCS file: /cvs/drupal/drupal/modules/forum/forum.module,v retrieving revision 1.396 diff -u -F^f -r1.396 forum.module --- modules/forum/forum.module 7 May 2007 17:02:54 -0000 1.396 +++ modules/forum/forum.module 9 May 2007 19:49:57 -0000 @@ -348,11 +348,11 @@ function forum_view(&$node, $teaser = FA * Check in particular that only a "leaf" term in the associated taxonomy * vocabulary is selected, not a "container" term. */ -function forum_submit(&$node) { +function forum_submit(&$form_values) { // Make sure all fields are set properly: - $node->icon = !empty($node->icon) ? $node->icon : ''; + $form_values['icon'] = $form_values['icon'] ? $form_values['icon'] : ''; - if ($node->taxonomy) { + if ($form_values['taxonomy']) { // Get the forum terms from the (cached) tree $tree = taxonomy_get_tree(_forum_get_vid()); if ($tree) { @@ -360,16 +360,16 @@ function forum_submit(&$node) { $forum_terms[] = $term->tid; } } - foreach ($node->taxonomy as $term) { + foreach ($form_values['taxonomy'] as $term) { if (in_array($term, $forum_terms)) { - $node->tid = $term; + $form_values['tid'] = $term; } } - $old_tid = db_result(db_query_range("SELECT tid FROM {forum} WHERE nid = %d ORDER BY vid DESC", $node->nid, 0, 1)); + $old_tid = db_result(db_query_range("SELECT tid FROM {forum} WHERE nid = %d ORDER BY vid DESC", $form_values['nid'], 0, 1)); if ($old_tid) { - if (($node->tid != $old_tid) && $node->shadow) { + if (($form_values['tid'] != $old_tid) && $form_values['shadow']) { // A shadow copy needs to be created. Retain new term and add old term. - $node->taxonomy[] = $old_tid; + $form_values['taxonomy'][] = $old_tid; } } } @@ -499,8 +499,8 @@ function forum_form_container($edit = ar $form['delete'] = array('#type' => 'submit', '#value' => t('Delete')); $form['tid'] = array('#type' => 'value', '#value' => $edit['tid']); } - $form['#submit']['forum_form_submit'] = array(); - $form['#validate']['forum_form_validate'] = array(); + $form['#submit'][] = 'forum_form_submit'; + $form['#validate'][] = 'forum_form_validate'; $form['#theme'] = 'forum_form'; return $form; @@ -558,8 +558,8 @@ function forum_form_forum($edit = array( $form['delete'] = array('#type' => 'submit', '#value' => t('Delete')); $form['tid'] = array('#type' => 'hidden', '#value' => $edit['tid']); } - $form['#submit']['forum_form_submit'] = array(); - $form['#validate']['forum_form_validate'] = array(); + $form['#submit'][] = 'forum_form_submit'; + $form['#validate'][] = 'forum_form_validate'; $form['#theme'] = 'forum_form'; return $form; @@ -568,8 +568,8 @@ function forum_form_forum($edit = array( /** * Process forum form and container form submissions. */ -function forum_form_submit($form_id, $form_values) { - if ($form_id == 'forum_form_container') { +function forum_form_submit($form_values, $form, &$form_state) { + if ($form['form_id'] == 'forum_form_container') { $container = TRUE; $type = t('forum container'); } @@ -592,7 +592,8 @@ function forum_form_submit($form_id, $fo drupal_set_message(t('The @type %term has been updated.', array('%term' => $form_values['name'], '@type' => $type))); break; } - return 'admin/content/forum'; + $form_state['redirect'] = 'admin/content/forum'; + return; } /** @@ -612,12 +613,13 @@ function forum_confirm_delete($tid) { /** * Implementation of forms api _submit call. Deletes a forum after confirmation. */ -function forum_confirm_delete_submit($form_id, $form_values) { +function forum_confirm_delete_submit($form_values, $form, &$form_state) { taxonomy_del_term($form_values['tid']); drupal_set_message(t('The forum %term and all sub-forums and associated posts have been deleted.', array('%term' => $form_values['name']))); watchdog('content', 'forum: deleted %term and all its sub-forums and associated posts.', array('%term' => $form_values['name'])); - return 'admin/content/forum'; + $form_state['redirect'] = 'admin/content/forum'; + return; } /** Index: modules/menu/menu.module =================================================================== RCS file: /cvs/drupal/drupal/modules/menu/menu.module,v retrieving revision 1.109 diff -u -F^f -r1.109 menu.module --- modules/menu/menu.module 30 Apr 2007 17:03:25 -0000 1.109 +++ modules/menu/menu.module 9 May 2007 19:49:57 -0000 @@ -321,7 +321,7 @@ function menu_edit_item_form($type, $mid return $form; } -function menu_edit_item_form_validate($form_id, $form_values) { +function menu_edit_item_form_validate($form_values, $form, &$form_state) { if (isset($form_values['path'])) { $path = $form_values['path']; // Skip external links. @@ -341,9 +341,10 @@ function menu_edit_item_form_validate($f /** * Process menu and menu item add/edit form submissions. */ -function menu_edit_item_form_submit($form_id, $form_values) { +function menu_edit_item_form_submit($form_values, $form, &$form_state) { menu_edit_item_save($form_values); - return 'admin/build/menu'; + $form_state['redirect'] = 'admin/build/menu'; + return; } /** @@ -461,8 +462,8 @@ function menu_edit_menu_form($type, $mid $form['type'] = array('#type' => 'value', '#value' => $item['type']); $form['submit'] = array('#type' => 'submit', '#value' => t('Submit')); // Reuse the submit function of menu_edit_item_form. - $form['#submit']['menu_edit_item_form_submit'] = array(); - $form['#validate']['menu_edit_item_form_validate'] = array(); + $form['#submit'][] = 'menu_edit_item_form_submit'; + $form['#validate'][] = 'menu_edit_item_form_validate'; $form['#theme'] = 'menu_edit_item_form'; return $form; @@ -494,7 +495,7 @@ function menu_item_delete_form($mid) { /** * Process menu delete form submissions. */ -function menu_item_delete_form_submit($form_id, $form_values) { +function menu_item_delete_form_submit($form_values, $form, &$form_state) { menu_delete_item($form_values['path']); $t_args = array('%title' => $form_values['title']); @@ -507,7 +508,8 @@ function menu_item_delete_form_submit($f watchdog('menu', 'Deleted menu item %title.', $t_args, WATCHDOG_NOTICE); } - return 'admin/build/menu'; + $form_state['redirect'] = 'admin/build/menu'; + return; } /** @@ -526,11 +528,12 @@ function menu_reset_item($mid) { /** * Process menu reset item form submissions. */ -function menu_reset_item_submit($form_id, $form_values) { +function menu_reset_item_submit($form_values, $form, &$form_state) { menu_delete_item($form_values['mid']); drupal_set_message(t('The menu item was reset to its default settings.')); - return 'admin/build/menu'; + $form_state['redirect'] = 'admin/build/menu'; + return; } /** Index: modules/node/content_types.inc =================================================================== RCS file: /cvs/drupal/drupal/modules/node/content_types.inc,v retrieving revision 1.30 diff -u -F^f -r1.30 content_types.inc --- modules/node/content_types.inc 7 May 2007 12:32:55 -0000 1.30 +++ modules/node/content_types.inc 9 May 2007 19:49:57 -0000 @@ -216,7 +216,7 @@ function node_type_form($type = NULL) { /** * Implementation of hook_form_validate(). */ -function node_type_form_validate($form_id, $form_values) { +function node_type_form_validate($form_values, $form, &$form_state) { $type = new stdClass(); $type->type = trim($form_values['type']); $type->name = trim($form_values['name']); @@ -252,7 +252,7 @@ function node_type_form_validate($form_i /** * Implementation of hook_form_submit(). */ -function node_type_form_submit($form_id, $form_values) { +function node_type_form_submit($form_values, $form, &$form_state) { $op = isset($form_values['op']) ? $form_values['op'] : ''; $type = new stdClass(); @@ -282,7 +282,8 @@ function node_type_form_submit($form_id, node_type_reset($type); } elseif ($op == t('Delete content type')) { - return 'admin/content/types/'. str_replace('_', '-', $type->old_type) .'/delete'; + $form_state['redirect'] = 'admin/content/types/'. str_replace('_', '-', $type->old_type) .'/delete'; + return; } $status = node_type_save($type); @@ -336,7 +337,8 @@ function node_type_form_submit($form_id, watchdog('node', 'Added content type %name.', $t_args, WATCHDOG_NOTICE, l(t('view'), 'admin/content/types')); } - return 'admin/content/types'; + $form_state['redirect'] = 'admin/content/types'; + return; } /** @@ -396,7 +398,7 @@ function node_type_delete_confirm($type) /** * Process content type delete confirm submissions. */ -function node_type_delete_confirm_submit($form_id, $form_values) { +function node_type_delete_confirm_submit($form_values, $form, &$form_state) { node_type_delete($form_values['type']); $t_args = array('%name' => $form_values['name']); @@ -406,5 +408,6 @@ function node_type_delete_confirm_submit node_types_rebuild(); menu_rebuild(); - return 'admin/content/types'; + $form_state['redirect'] = 'admin/content/types'; + return; } Index: modules/node/node.module =================================================================== RCS file: /cvs/drupal/drupal/modules/node/node.module,v retrieving revision 1.807 diff -u -F^f -r1.807 node.module --- modules/node/node.module 8 May 2007 17:08:14 -0000 1.807 +++ modules/node/node.module 9 May 2007 19:49:58 -0000 @@ -173,7 +173,7 @@ function node_mark($nid, $timestamp) { /** * See if the user used JS to submit a teaser. */ -function node_teaser_js(&$form, $form_values) { +function node_teaser_js(&$form, $form_values, &$form_state) { // Glue the teaser to the body. if (isset($form['#post']['teaser_js'])) { if (trim($form_values['teaser_js'])) { @@ -185,7 +185,7 @@ function node_teaser_js(&$form, $form_va $body = ''. $form_values['body']; } // Pass value onto preview/submit - form_set_value($form['body'], $body); + form_set_value($form['body'], $body, $form_state); // Pass value back onto form $form['body']['#value'] = $body; } @@ -1066,7 +1066,7 @@ function node_configure() { /** * Form validate callback. */ -function node_configure_validate($form_id, $form_values) { +function node_configure_validate($form_values, $form, &$form_state) { if ($form_values['op'] == t('Rebuild permissions')) { drupal_goto('admin/content/node-settings/rebuild'); } @@ -1083,10 +1083,11 @@ function node_configure_rebuild_confirm( /** * Handler for wipe confirmation */ -function node_configure_rebuild_confirm_submit($form_id, &$form) { +function node_configure_rebuild_confirm_submit(&$form, $form, &$form_state) { node_access_rebuild(); drupal_set_message(t('The node access table has been rebuilt.')); - return 'admin/content/node-settings'; + $form_state['redirect'] = 'admin/content/node-settings'; + return; } /** @@ -1514,7 +1515,7 @@ function theme_node_filters($form) { /** * Process result from node administration filter form. */ -function node_filter_form_submit($form_id, $form_values) { +function node_filter_form_submit($form_values, $form, &$form_state) { $filters = node_filters(); switch ($form_values['op']) { case t('Filter'): @@ -1542,7 +1543,7 @@ function node_filter_form_submit($form_i /** * Submit the node administration update form. */ -function node_admin_nodes_submit($form_id, $form_values) { +function node_admin_nodes_submit($form_values, $form, &$form_state) { $operations = module_invoke_all('node_operations'); $operation = $operations[$form_values['operation']]; // Filter out unchecked nodes @@ -1562,7 +1563,7 @@ function node_admin_nodes_submit($form_i } } -function node_admin_nodes_validate($form_id, $form_values) { +function node_admin_nodes_validate($form_values, $form, &$form_state) { $nodes = array_filter($form_values['nodes']); if (count($nodes) == 0) { form_set_error('', t('No items selected.')); @@ -1683,14 +1684,15 @@ function node_multiple_delete_confirm() t('Delete all'), t('Cancel')); } -function node_multiple_delete_confirm_submit($form_id, $form_values) { +function node_multiple_delete_confirm_submit($form_values, $form, &$form_state) { if ($form_values['confirm']) { foreach ($form_values['nodes'] as $nid => $value) { node_delete($nid); } drupal_set_message(t('The items have been deleted.')); } - return 'admin/content/node'; + $form_state['redirect'] = 'admin/content/node'; + return; } /** @@ -1956,10 +1958,6 @@ function node_submit($node) { $node->created = $node->date ? strtotime($node->date) : NULL; } - // Do node-type-specific validation checks. - node_invoke($node, 'submit'); - node_invoke_nodeapi($node, 'submit'); - $node->validated = TRUE; return $node; @@ -2003,7 +2001,7 @@ function node_validate($node, $form = ar node_invoke_nodeapi($node, 'validate', $form); } -function node_form_validate($form_id, $form_values, $form) { +function node_form_validate($form_values, $form, &$form_state) { node_validate($form_values, $form); } @@ -2025,9 +2023,15 @@ function node_object_prepare(&$node) { /** * Generate the node add/edit form array. */ -function node_form($node, $form_values = NULL) { +function node_form($node, $form_state = NULL) { global $user; + if (isset($form_state['node'])) { + $node = $form_state['node'] + (array)$node; + } + if (isset($form_state['node_preview'])) { + $form['#prefix'] = $form_state['node_preview']; + } $node = (object)$node; foreach (array('body', 'title', 'format') as $key) { if (!isset($node->$key)) { @@ -2050,7 +2054,7 @@ function node_form($node, $form_values = // Changed must be sent to the client, for later overwrite error checking. $form['changed'] = array('#type' => 'hidden', '#default_value' => isset($node->changed) ? $node->changed : NULL); // Get the node-specific bits. - if ($extra = node_invoke($node, 'form', $form_values)) { + if ($extra = node_invoke($node, 'form', $form_state)) { $form = array_merge_recursive($form, $extra); } if (!isset($form['title']['#weight'])) { @@ -2118,46 +2122,43 @@ function node_form($node, $form_values = } // Add the buttons. - $form['preview'] = array('#type' => 'button', '#value' => t('Preview'), '#weight' => 40); - $form['submit'] = array('#type' => 'submit', '#value' => t('Submit'), '#weight' => 45); + $form['preview'] = array( + '#type' => 'submit', + '#value' => t('Preview'), + '#weight' => 40, + '#submit' => array('node_form_build_preview'), + ); + $form['submit'] = array( + '#type' => 'submit', + '#value' => t('Submit'), + '#weight' => 45, + '#submit' => array('node_form_submit'), + ); if (!empty($node->nid) && node_access('delete', $node)) { $form['delete'] = array('#type' => 'button', '#value' => t('Delete'), '#weight' => 50); } - $form['#after_build'] = array('node_form_add_preview'); - $form['#submit']['node_form_submit'] = array(); - $form['#validate']['node_form_validate'] = array(); + $form['#validate'][] = 'node_form_validate'; $form['#theme'] = 'node_form'; return $form; } -function node_form_add_preview($form) { - global $form_values; - - $op = isset($form_values['op']) ? $form_values['op'] : ''; - if ($op == t('Preview')) { - // Invoke full validation for the form, to protect against cross site - // request forgeries (CSRF) and setting arbitrary values for fields such as - // the input format. Preview the node only when form validation does not - // set any errors. - drupal_validate_form($form['form_id']['#value'], $form); - if (!form_get_errors()) { - // Because the node preview may display a form, we must render it - // outside the node submission form tags using the #prefix property - // (i.e. to prevent illegally nested forms). - // If the node form already has a #prefix, we must preserve it. - // In this case, we put the preview before the #prefix so we keep - // the #prefix as "close" to the rest of the form as possible, - // for example, to keep a'. t('The following modules will be completely uninstalled from your site, and all data from these modules will be lost!') .'
'. theme('item_list', $uninstall)); $form = confirm_form( $form, @@ -1836,7 +1838,7 @@ function theme_system_modules_uninstall( * @param * $form_values Submitted form values. */ -function system_modules_uninstall_validate($form_id, $form_values) { +function system_modules_uninstall_validate($form_values, $form, &$form_state) { // Form submitted, but no modules selected. if (!count(array_filter($form_values['uninstall']))) { drupal_set_message(t('No modules selected.'), 'error'); @@ -1852,16 +1854,23 @@ function system_modules_uninstall_valida * @param * $form_values Submitted form values. */ -function system_modules_uninstall_submit($form_id, $form_values) { +function system_modules_uninstall_submit($form_values, $form, &$form_state) { // Make sure the install API is available. include_once './includes/install.inc'; - // Call the uninstall routine for each selected module. - foreach (array_filter($form_values['uninstall']) as $module => $value) { - drupal_uninstall_module($module); + if (!empty($form['#confirmed'])) { + // Call the uninstall routine for each selected module. + foreach (array_filter($form_values['uninstall']) as $module => $value) { + drupal_uninstall_module($module); + } + drupal_set_message(t('The selected modules have been uninstalled.')); + + unset($form_state['storage']); + $form_state['redirect'] = 'admin/build/modules/uninstall'; + } + else { + $form_state['storage'] = $form_values; } - drupal_set_message(t('The selected modules have been uninstalled.')); - drupal_goto('admin/build/modules/uninstall'); } /** Index: modules/taxonomy/taxonomy.module =================================================================== RCS file: /cvs/drupal/drupal/modules/taxonomy/taxonomy.module,v retrieving revision 1.354 diff -u -F^f -r1.354 taxonomy.module --- modules/taxonomy/taxonomy.module 4 May 2007 08:38:34 -0000 1.354 +++ modules/taxonomy/taxonomy.module 9 May 2007 19:49:59 -0000 @@ -304,7 +304,7 @@ function taxonomy_form_vocabulary($edit /** * Accept the form submission for a vocabulary and save the results. */ -function taxonomy_form_vocabulary_submit($form_id, $form_values) { +function taxonomy_form_vocabulary_submit($form_values, $form, &$form_state) { // Fix up the nodes array to remove unchecked nodes. $form_values['nodes'] = array_filter($form_values['nodes']); switch (taxonomy_save_vocabulary($form_values)) { @@ -318,7 +318,9 @@ function taxonomy_form_vocabulary_submit break; } - return 'admin/content/taxonomy'; + $form_state['vid'] = $form_values['vid']; + $form_state['redirect'] = 'admin/content/taxonomy'; + return; } function taxonomy_save_vocabulary(&$edit) { @@ -391,11 +393,12 @@ function taxonomy_vocabulary_confirm_del t('Cancel')); } -function taxonomy_vocabulary_confirm_delete_submit($form_id, $form_values) { +function taxonomy_vocabulary_confirm_delete_submit($form_values, $form, &$form_state) { $status = taxonomy_del_vocabulary($form_values['vid']); drupal_set_message(t('Deleted vocabulary %name.', array('%name' => $form_values['name']))); watchdog('taxonomy', 'Deleted vocabulary %name.', array('%name' => $form_values['name']), WATCHDOG_NOTICE); - return 'admin/content/taxonomy'; + $form_state['redirect'] = 'admin/content/taxonomy'; + return; } function taxonomy_form_term($vocabulary, $edit = array()) { @@ -476,7 +479,7 @@ function taxonomy_form_term($vocabulary, /** * Accept the form submission for a taxonomy term and save the result. */ -function taxonomy_form_term_submit($form_id, $form_values) { +function taxonomy_form_term_submit($form_values, $form, &$form_state) { switch (taxonomy_save_term($form_values)) { case SAVED_NEW: drupal_set_message(t('Created new term %term.', array('%term' => $form_values['name']))); @@ -487,7 +490,10 @@ function taxonomy_form_term_submit($form watchdog('taxonomy', 'Updated term %term.', array('%term' => $form_values['name']), WATCHDOG_NOTICE, l(t('edit'), 'admin/content/taxonomy/edit/term/'. $form_values['tid'])); break; } - return 'admin/content/taxonomy'; + + $form_state['tid'] = $form_values['tid']; + $form_state['redirect'] = 'admin/content/taxonomy'; + return; } /** @@ -623,11 +629,12 @@ function taxonomy_term_confirm_delete($t t('Cancel')); } -function taxonomy_term_confirm_delete_submit($form_id, $form_values) { +function taxonomy_term_confirm_delete_submit($form_values, $form, &$form_state) { taxonomy_del_term($form_values['tid']); drupal_set_message(t('Deleted term %name.', array('%name' => $form_values['name']))); watchdog('taxonomy', 'Deleted term %name.', array('%name' => $form_values['name']), WATCHDOG_NOTICE); - return 'admin/content/taxonomy'; + $form_state['redirect'] = 'admin/content/taxonomy'; + return; } /** Index: modules/throttle/throttle.module =================================================================== RCS file: /cvs/drupal/drupal/modules/throttle/throttle.module,v retrieving revision 1.75 diff -u -F^f -r1.75 throttle.module --- modules/throttle/throttle.module 30 Apr 2007 17:03:29 -0000 1.75 +++ modules/throttle/throttle.module 9 May 2007 19:49:59 -0000 @@ -156,7 +156,7 @@ function throttle_admin_settings() { return system_settings_form($form); } -function throttle_admin_settings_validate($form_id, $form_values) { +function throttle_admin_settings_validate($form_values, $form, &$form_state) { if (!is_numeric($form_values['throttle_anonymous']) || $form_values['throttle_anonymous'] < 0) { form_set_error('throttle_anonymous', t("%value is not a valid auto-throttle setting. Please enter a positive numeric value.", array('%value' => $form_values['throttle_anonymous']))); } Index: modules/upload/upload.module =================================================================== RCS file: /cvs/drupal/drupal/modules/upload/upload.module,v retrieving revision 1.159 diff -u -F^f -r1.159 upload.module --- modules/upload/upload.module 30 Apr 2007 17:03:29 -0000 1.159 +++ modules/upload/upload.module 9 May 2007 19:49:59 -0000 @@ -119,7 +119,7 @@ function upload_init() { /** * Form API callback to validate the upload settings form. */ -function upload_admin_settings_validate($form_id, $form_values) { +function upload_admin_settings_validate($form_values, $form, &$form_state) { if (($form_values['upload_max_resolution'] != '0')) { if (!preg_match('/^[0-9]+x[0-9]+$/', $form_values['upload_max_resolution'])) { form_set_error('upload_max_resolution', t('The maximum allowed image size expressed as WIDTHxHEIGHT (e.g. 640x480). Set to 0 for no restriction.')); @@ -326,7 +326,7 @@ function _upload_prepare(&$node) { // Scale image uploads. $file = _upload_image($file); - $key = 'upload_'. (isset($_SESSION['file_previews']) ? 0 : count($_SESSION['file_previews'])); + $key = 'upload_'. (!isset($_SESSION['file_previews']) ? 0 : count($_SESSION['file_previews'])); $file->fid = $key; $file->source = $key; $file->list = variable_get('upload_list_default', 1); @@ -813,7 +813,13 @@ function _upload_form($node) { '#suffix' => 'Welcome to Drupal. You are user #1, which gives you full and immediate access. All future registrants will receive their passwords via e-mail, so please make sure your website e-mail address is set properly under the general settings on the site information settings page.
Your password is %pass. You may change your password below.
', array('%pass' => $pass, '@settings' => url('admin/settings/site-information')))); user_authenticate($account->name, trim($pass)); - return 'user/1/edit'; + $form_state['redirect'] = 'user/1/edit'; + return; } else { if ($admin && !$notify) { @@ -1390,7 +1396,8 @@ function user_register_submit($form_id, $body = _user_mail_text('welcome_body', $variables); drupal_mail('user-register-welcome', $mail, $subject, $body, $from); user_authenticate($account->name, trim($pass)); - return ''; + $form_state['redirect'] = ''; + return; } else if ($account->status || $notify) { // Create new user account, no administrator approval required. @@ -1404,7 +1411,8 @@ function user_register_submit($form_id, } else { drupal_set_message(t('Your password and further instructions have been sent to your e-mail address.')); - return ''; + $form_state['redirect'] = ''; + return; } } else { @@ -1496,7 +1504,9 @@ function user_edit_form($uid, $edit, $re $form['picture']['picture_delete'] = array('#type' => 'hidden'); } $form['picture']['picture_upload'] = array('#type' => 'file', '#title' => t('Upload picture'), '#size' => 48, '#description' => t('Your virtual face or picture. Maximum dimensions are %dimensions and the maximum size is %size kB.', array('%dimensions' => variable_get('user_picture_dimensions', '85x85'), '%size' => variable_get('user_picture_file_size', '30'))) .' '. variable_get('user_picture_guidelines', '')); + $form['#validate'][] = 'user_validate_picture'; } + $form['#uid'] = $uid; return $form; } @@ -1526,11 +1536,6 @@ function _user_edit_validate($uid, &$edi else if (drupal_is_denied('mail', $edit['mail'])) { form_set_error('mail', t('The e-mail address %email has been denied access.', array('%email' => $edit['mail']))); } - - // If required, validate the uploaded picture. - if ($file = file_check_upload('picture_upload')) { - user_validate_picture($file, $edit, $user); - } } function _user_edit_submit($uid, &$edit) { @@ -1584,6 +1589,7 @@ function user_edit($category = 'account' $form['delete'] = array('#type' => 'submit', '#value' => t('Delete'), '#weight' => 31); } $form['#attributes']['enctype'] = 'multipart/form-data'; + $form['#validate'][] = 'user_edit_validate'; drupal_set_title(check_plain($account->name)); return $form; @@ -1615,7 +1621,7 @@ function user_delete($edit, $uid) { module_invoke_all('user', 'delete', $edit, $account); } -function user_edit_validate($form_id, $form_values) { +function user_edit_validate($form_values, $form, &$form_state) { user_module_invoke('validate', $form_values, $form_values['_account'], $form_values['_category']); // Validate input to ensure that non-privileged users can't alter protected data. if ((!user_access('administer users') && array_intersect(array_keys($form_values), array('uid', 'init', 'session'))) || (!user_access('administer access control') && isset($form_values['roles']))) { @@ -1625,7 +1631,7 @@ function user_edit_validate($form_id, $f } } -function user_edit_submit($form_id, $form_values) { +function user_edit_submit($form_values, $form, &$form_state) { $account = $form_values['_account']; $category = $form_values['_category']; unset($form_values['_account'], $form_values['op'], $form_values['submit'], $form_values['delete'], $form_values['form_token'], $form_values['form_id'], $form_values['_category']); @@ -1636,7 +1642,8 @@ function user_edit_submit($form_id, $for cache_clear_all(); drupal_set_message(t('The changes have been saved.')); - return 'user/'. $account->uid; + $form_state['redirect'] = 'user/'. $account->uid; + return; } function user_view($account) { @@ -1698,8 +1705,8 @@ function user_admin_check_user() { $form['user']['test'] = array('#type' => 'textfield', '#title' => '', '#description' => t('Enter a username to check if it will be denied or allowed.'), '#size' => 30, '#maxlength' => USERNAME_MAX_LENGTH); $form['user']['type'] = array('#type' => 'hidden', '#value' => 'user'); $form['user']['submit'] = array('#type' => 'submit', '#value' => t('Check username')); - $form['#submit']['user_admin_access_check_submit'] = array(); - $form['#validate']['user_admin_access_check_validate'] = array(); + $form['#submit'][] = 'user_admin_access_check_submit'; + $form['#validate'][] = 'user_admin_access_check_validate'; $form['#theme'] = 'user_admin_access_check'; return $form; } @@ -1709,8 +1716,8 @@ function user_admin_check_mail() { $form['mail']['test'] = array('#type' => 'textfield', '#title' => '', '#description' => t('Enter an e-mail address to check if it will be denied or allowed.'), '#size' => 30, '#maxlength' => EMAIL_MAX_LENGTH); $form['mail']['type'] = array('#type' => 'hidden', '#value' => 'mail'); $form['mail']['submit'] = array('#type' => 'submit', '#value' => t('Check e-mail')); - $form['#submit']['user_admin_access_check_submit'] = array(); - $form['#validate']['user_admin_access_check_validate'] = array(); + $form['#submit'][] = 'user_admin_access_check_submit'; + $form['#validate'][] = 'user_admin_access_check_validate'; $form['#theme'] = 'user_admin_access_check'; return $form; } @@ -1720,8 +1727,8 @@ function user_admin_check_host() { $form['host']['test'] = array('#type' => 'textfield', '#title' => '', '#description' => t('Enter a hostname or IP address to check if it will be denied or allowed.'), '#size' => 30, '#maxlength' => 64); $form['host']['type'] = array('#type' => 'hidden', '#value' => 'host'); $form['host']['submit'] = array('#type' => 'submit', '#value' => t('Check hostname')); - $form['#submit']['user_admin_access_check_submit'] = array(); - $form['#validate']['user_admin_access_check_validate'] = array(); + $form['#submit'][] = 'user_admin_access_check_submit'; + $form['#validate'][] = 'user_admin_access_check_validate'; $form['#theme'] = 'user_admin_access_check'; return $form; } @@ -1736,13 +1743,13 @@ function user_admin_access_check() { return $output; } -function user_admin_access_check_validate($form_id, $form_values) { +function user_admin_access_check_validate($form_values, $form, &$form_state) { if (empty($form_values['test'])) { form_set_error($form_values['type'], t('No value entered. Please enter a test string and try again.')); } } -function user_admin_access_check_submit($form_id, $form_values) { +function user_admin_access_check_submit($form_values, $form, &$form_state) { switch ($form_values['type']) { case 'user': if (drupal_is_denied('user', $form_values['test'])) { @@ -1813,10 +1820,11 @@ function user_admin_access_delete_confir return $output; } -function user_admin_access_delete_confirm_submit($form_id, $form_values) { +function user_admin_access_delete_confirm_submit($form_values, $form, &$form_state) { db_query('DELETE FROM {access} WHERE aid = %d', $form_values['aid']); drupal_set_message(t('The access rule has been deleted.')); - return 'admin/user/rules'; + $form_state['redirect'] = 'admin/user/rules'; + return; } /** @@ -2005,7 +2013,7 @@ function theme_user_admin_perm($form) { return $output; } -function user_admin_perm_submit($form_id, $form_values) { +function user_admin_perm_submit($form_values, $form, &$form_state) { // Save permissions: $result = db_query('SELECT * FROM {role}'); while ($role = db_fetch_object($result)) { @@ -2070,13 +2078,13 @@ function user_admin_role() { '#type' => 'submit', '#value' => t('Add role'), ); - $form['#submit']['user_admin_role_submit'] = array(); - $form['#validate']['user_admin_role_validate'] = array(); + $form['#submit'][] = 'user_admin_role_submit'; + $form['#validate'][] = 'user_admin_role_validate'; } return $form; } -function user_admin_role_validate($form_id, $form_values) { +function user_admin_role_validate($form_values, $form, &$form_state) { if ($form_values['name']) { if ($form_values['op'] == t('Save role')) { if (db_result(db_query("SELECT COUNT(*) FROM {role} WHERE name = '%s' AND rid != %d", $form_values['name'], $form_values['rid']))) { @@ -2094,7 +2102,7 @@ function user_admin_role_validate($form_ } } -function user_admin_role_submit($form_id, $form_values) { +function user_admin_role_submit($form_values, $form, &$form_state) { if ($form_values['op'] == t('Save role')) { db_query("UPDATE {role} SET name = '%s' WHERE rid = %d", $form_values['name'], $form_values['rid']); drupal_set_message(t('The role has been renamed.')); @@ -2111,7 +2119,8 @@ function user_admin_role_submit($form_id db_query("INSERT INTO {role} (name) VALUES ('%s')", $form_values['name']); drupal_set_message(t('The role has been added.')); } - return 'admin/user/roles'; + $form_state['redirect'] = 'admin/user/roles'; + return; } function theme_user_admin_new_role($form) { @@ -2245,7 +2254,7 @@ function theme_user_admin_account($form) /** * Submit the user administration update form. */ -function user_admin_account_submit($form_id, $form_values) { +function user_admin_account_submit($form_values, $form, &$form_state) { $operations = module_invoke_all('user_operations'); $operation = $operations[$form_values['operation']]; // Filter out unchecked accounts. @@ -2264,7 +2273,7 @@ function user_admin_account_submit($form } } -function user_admin_account_validate($form_id, $form_values) { +function user_admin_account_validate($form_values, $form, &$form_state) { $form_values['accounts'] = array_filter($form_values['accounts']); if (count($form_values['accounts']) == 0) { form_set_error('', t('No users selected.')); @@ -2416,14 +2425,15 @@ function user_multiple_delete_confirm() t('Delete all'), t('Cancel')); } -function user_multiple_delete_confirm_submit($form_id, $form_values) { +function user_multiple_delete_confirm_submit($form_values, $form, &$form_state) { if ($form_values['confirm']) { foreach ($form_values['accounts'] as $uid => $value) { user_delete($form_values, $uid); } drupal_set_message(t('The users have been deleted.')); } - return 'admin/user/user'; + $form_state['redirect'] = 'admin/user/user'; + return; } function user_admin_settings() { @@ -2784,7 +2794,7 @@ function theme_user_filters($form) { /** * Process result from user administration filter form. */ -function user_filter_form_submit($form_id, $form_values) { +function user_filter_form_submit($form_values, $form, &$form_state) { $op = $form_values['op']; $filters = user_filters(); switch ($op) { @@ -2808,7 +2818,8 @@ function user_filter_form_submit($form_i return; } - return 'admin/user/user'; + $form_state['redirect'] = 'admin/user/user'; + return; }