Commit 69b484f6 authored by Dries's avatar Dries

- Patch #74660 by Eaton: make drupal_get_form() more granular and improved the code comments.

parent 0c05ae7a
......@@ -69,6 +69,39 @@ function drupal_get_form($form_id, &$form, $callback = NULL) {
$form_submitted = FALSE;
$form_button_counter = array(0, 0);
$form = drupal_build_form($form_id, $form, $callback);
if (!empty($_POST['edit']) && (($_POST['edit']['form_id'] == $form_id) || ($_POST['edit']['form_id'] == $callback))) {
drupal_validate_form($form_id, $form, $callback);
// 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_submitted || (!$form_button_counter[0] && $form_button_counter[1])) && !form_get_errors()) {
$redirect = drupal_submit_form($form_id, $form, $callback);
drupal_redirect_form($form, $redirect);
}
}
$output = drupal_render_form($form_id, $form, $callback);
list($form_values, $form_submitted, $form_button_counter) = array_pop($saved_globals);
return $output;
}
/**
* Prepares a structured form array by adding required elements,
* executing any hook_form_alter functions, and optionally inserting
* a validation token to prevent tampering.
*
* @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 $callback
* An optional callback that will be used in addition to the form_id.
*
*/
function drupal_build_form($form_id, &$form, $callback = NULL) {
$form['#type'] = 'form';
if (isset($form['#token'])) {
// If the page cache is on and an anonymous user issues a GET request,
......@@ -86,6 +119,7 @@ function drupal_get_form($form_id, &$form, $callback = NULL) {
$form['form_token'] = array('#type' => 'hidden', '#default_value' => md5(session_id() . $form['#token'] . variable_get('drupal_private_key', '')));
}
}
if (isset($form_id)) {
$form['form_id'] = array('#type' => 'hidden', '#value' => $form_id, '#id' => str_replace('_', '-', "edit-$form_id"));
}
......@@ -121,57 +155,24 @@ function drupal_get_form($form_id, &$form, $callback = NULL) {
}
$form = form_builder($form_id, $form);
if (!empty($_POST['edit']) && (($_POST['edit']['form_id'] == $form_id) || ($_POST['edit']['form_id'] == $callback))) {
drupal_validate_form($form_id, $form, $callback);
// 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_submitted || (!$form_button_counter[0] && $form_button_counter[1])) && !form_get_errors()) {
$redirect = drupal_submit_form($form_id, $form, $callback);
if (isset($redirect)) {
$goto = $redirect;
}
if (isset($form['#redirect'])) {
$goto = $form['#redirect'];
}
if ($goto !== FALSE) {
if (is_array($goto)) {
call_user_func_array('drupal_goto', $goto);
}
elseif (!isset($goto)) {
drupal_goto($_GET['q']);
}
else {
drupal_goto($goto);
}
}
}
}
// Don't override #theme if someone already set it.
if (!isset($form['#theme'])) {
if (theme_get_function($form_id)) {
$form['#theme'] = $form_id;
}
elseif (theme_get_function($callback)) {
$form['#theme'] = $callback;
}
}
if (isset($form['#pre_render'])) {
foreach ($form['#pre_render'] as $function) {
if (function_exists($function)) {
$function($form_id, $form);
}
}
}
$output = form_render($form);
// Restore globals
list($form_values, $form_submitted, $form_button_counter) = array_pop($saved_globals);
return $output;
return $form;
}
/**
* Validates user-submitted form data from a global variable using
* the validate 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.
* @param $callback
* An optional callback that will be used in addition to the form_id.
*
*/
function drupal_validate_form($form_id, $form, $callback = NULL) {
global $form_values;
static $validated_forms = array();
......@@ -180,6 +181,8 @@ function drupal_validate_form($form_id, $form, $callback = NULL) {
return;
}
// If the session token was set by drupal_build_form(), ensure that it
// matches the current user's session
if (isset($form['#token'])) {
if ($form_values['form_token'] != md5(session_id() . $form['#token'] . variable_get('drupal_private_key', ''))) {
// setting this error will cause the form to fail validation
......@@ -191,6 +194,22 @@ function drupal_validate_form($form_id, $form, $callback = NULL) {
$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.
* @param $callback
* An optional callback that will be used in addition to the form_id.
* @return
* A string containing the path of the page to display when processing
* is complete.
*
*/
function drupal_submit_form($form_id, $form, $callback = NULL) {
global $form_values;
$default_args = array($form_id, &$form_values);
......@@ -210,6 +229,74 @@ function drupal_submit_form($form_id, $form, $callback = NULL) {
return $goto;
}
/**
* Renders a structured form array into themed HTML.
*
* @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 $callback
* An optional callback that will be used in addition to the form_id.
* @return
* A string containing the path of the page to display when processing
* is complete.
*
*/
function drupal_render_form($form_id, &$form, $callback = NULL) {
// Don't override #theme if someone already set it.
if (!isset($form['#theme'])) {
if (theme_get_function($form_id)) {
$form['#theme'] = $form_id;
}
elseif (theme_get_function($callback)) {
$form['#theme'] = $callback;
}
}
if (isset($form['#pre_render'])) {
foreach ($form['#pre_render'] as $function) {
if (function_exists($function)) {
$function($form_id, $form);
}
}
}
$output = form_render($form);
return $output;
}
/**
* Redirect the user to a URL after a form has been processed.
*
* @param $form
* An associative array containing the structure of the form.
* @param $redirect
* An optional string containing the destination path to redirect
* to if none is specified by the form.
*
*/
function drupal_redirect_form($form, $redirect = NULL) {
if (isset($redirect)) {
$goto = $redirect;
}
if (isset($form['#redirect'])) {
$goto = $form['#redirect'];
}
if ($goto !== FALSE) {
if (is_array($goto)) {
call_user_func_array('drupal_goto', $goto);
}
elseif (!isset($goto)) {
drupal_goto($_GET['q']);
}
else {
drupal_goto($goto);
}
}
}
function _form_validate($elements, $form_id = NULL) {
// Recurse through all children.
foreach (element_children($elements) as $key) {
......@@ -324,7 +411,8 @@ function form_error(&$element, $message = '') {
* already have an assigned value.
*
* @param $form_id
* A unique string identifying the form. Allows each form to be themed.
* 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.
*/
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment