Skip to content
Snippets Groups Projects
Commit 9a5cd170 authored by Neil Drumm's avatar Neil Drumm :wave:
Browse files

#79937 by Eaton and chx. Provide a convenient framework for multi-step forms.

parent f5d7375c
No related branches found
No related tags found
2 merge requests!7452Issue #1797438. HTML5 validation is preventing form submit and not fully...,!789Issue #3210310: Adjust Database API to remove deprecated Drupal 9 code in Drupal 10
......@@ -39,7 +39,9 @@
/**
* Retrieves a form from a builder function, passes it on for
* processing, and renders the form or redirects to its destination
* as appropriate.
* as appropriate. In multi-step form scenerios, it handles properly
* processing the values using the previous step's form definition,
* then rendering the requested step for display.
*
* @param $form_id
* The unique string identifying the desired form. If a function
......@@ -54,12 +56,61 @@
* The rendered form.
*/
function drupal_get_form($form_id) {
$args = func_get_args();
$form = call_user_func_array('drupal_retrieve_form', $args);
drupal_process_form($form_id, $form);
return drupal_render_form($form_id, $form);
// In multi-step form scenerios, the incoming $_POST values are not
// necessarily intended for the current form. We need to build
// a copy of the previously built form for validation and processing,
// then go on to the one that was requested if everything works.
$form_build_id = md5(mt_rand());
if (isset($_POST['form_build_id']) && isset($_SESSION['form'][$_POST['form_build_id']])) {
// There's a previously stored multi-step form. We should handle
// IT first.
$stored = TRUE;
$args = $_SESSION['form'][$_POST['form_build_id']];
$form = call_user_func_array('drupal_retrieve_form', $args);
}
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']) {
$_SESSION['form'][$form_build_id] = $args;
$form['#build_id'] = $form_build_id;
}
$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['edit'];
$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] = $args;
$form['#build_id'] = $form_build_id;
}
// If we're in this part of the code, $_POST['edit'] always contains
// values from the previously submitted form. Unset it to avoid
// any accidental submission of doubled data, then process the form
// to prep it for rendering.
unset($_POST['edit']);
drupal_process_form($args[0], $form);
}
return drupal_render_form($args[0], $form);
}
/**
* Retrieves the structured array that defines a given form.
*
......@@ -158,6 +209,17 @@ function drupal_prepare_form($form_id, &$form) {
$form['#programmed'] = TRUE;
}
// In multi-step form scenerios, 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',
'#value' => $form['#build_id'],
'#id' => $form['#build_id'],
'#name' => 'form_build_id',
);
}
// If $base is set, it is used in place of $form_id when constructing validation,
// submission, and theming functions. Useful for mapping many similar or duplicate
// forms with different $form_ids to the same processing functions.
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment