From 69b484f634d861e401d520c17a253f8c4d13a790 Mon Sep 17 00:00:00 2001
From: Dries Buytaert <dries@buytaert.net>
Date: Sat, 22 Jul 2006 19:26:58 +0000
Subject: [PATCH] - Patch #74660 by Eaton: make drupal_get_form() more granular
 and improved the code comments.

---
 includes/form.inc | 186 ++++++++++++++++++++++++++++++++++------------
 1 file changed, 137 insertions(+), 49 deletions(-)

diff --git a/includes/form.inc b/includes/form.inc
index bf027bca33d9..9aae8e49a0bc 100644
--- a/includes/form.inc
+++ b/includes/form.inc
@@ -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.
  */
-- 
GitLab