summaryrefslogtreecommitdiff
path: root/includes
diff options
context:
space:
mode:
authorGábor Hojtsy <gabor@hojtsy.hu>2007-11-19 19:23:28 +0000
committerGábor Hojtsy <gabor@hojtsy.hu>2007-11-19 19:23:28 +0000
commit4615c96d59927845ebcfdabe3882cc17cd60fa5d (patch)
treec9cc3053bc101cfa40a67c2b8442d81dcbc6e80c /includes
parentc1555f33bcc33b5bba9756c3b2e8fcb197cf5da7 (diff)
downloadbrdo-4615c96d59927845ebcfdabe3882cc17cd60fa5d.tar.gz
brdo-4615c96d59927845ebcfdabe3882cc17cd60fa5d.tar.bz2
#193191 by chx: allow form elements to enable form caching - allows custom form elements to leverage the AHAH framework
Diffstat (limited to 'includes')
-rw-r--r--includes/form.inc125
1 files changed, 96 insertions, 29 deletions
diff --git a/includes/form.inc b/includes/form.inc
index f32184fc2..994045dfa 100644
--- a/includes/form.inc
+++ b/includes/form.inc
@@ -51,6 +51,7 @@ function drupal_get_form($form_id) {
$form_state = array('storage' => NULL, 'submitted' => FALSE);
$args = func_get_args();
+ $cacheable = FALSE;
if (isset($_SESSION['batch_form_state'])) {
// We've been redirected here after a batch processing : the form has
@@ -84,11 +85,10 @@ function drupal_get_form($form_id) {
$form_build_id = 'form-'. md5(mt_rand());
$form['#build_id'] = $form_build_id;
drupal_prepare_form($form_id, $form, $form_state);
- if (!empty($form['#cache'])) {
- // By not sending the form state, we avoid storing the storage which
- // won't have been touched yet.
- form_set_cache($form_build_id, $form, NULL);
- }
+ // Store a copy of the unprocessed form for caching and indicate that it
+ // is cacheable if #cache will be set.
+ $original_form = $form;
+ $cacheable = TRUE;
unset($form_state['post']);
}
$form['#post'] = $_POST;
@@ -99,6 +99,12 @@ function drupal_get_form($form_id) {
// altering the $form_state variable, which is passed into them by
// reference.
drupal_process_form($form_id, $form, $form_state);
+ if ($cacheable && !empty($form['#cache'])) {
+ // Caching is done past drupal_process_form so #process callbacks can
+ // set #cache. By not sending the form state, we avoid storing
+ // $form_state['storage'].
+ form_set_cache($form_build_id, $original_form, NULL);
+ }
}
// Most simple, single-step forms will be finished by this point --
@@ -116,27 +122,7 @@ function drupal_get_form($form_id) {
// other variables passed into drupal_get_form().
if (!empty($form_state['rebuild']) || !empty($form_state['storage'])) {
- array_shift($args);
- array_unshift($args, $form_state);
- array_unshift($args, $form_id);
- $form = call_user_func_array('drupal_retrieve_form', $args);
-
- // We need a new build_id for the new version of the form.
- $form_build_id = 'form-'. 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.
- form_set_cache($form_build_id, $form, $form_state);
-
- // 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);
+ $form = drupal_rebuild_form($form_id, $form_state, $args);
}
// If we haven't redirected to a new location by now, we want to
@@ -145,6 +131,75 @@ function drupal_get_form($form_id) {
}
/**
+ * Retrieves a form, caches it and processes it with an empty $_POST.
+ *
+ * This function clears $_POST and passes the empty $_POST to the form_builder.
+ * To preserve some parts from $_POST, pass them in $form_state.
+ *
+ * If your AHAH callback simulates the pressing of a button, then your AHAH
+ * callback will need to do the same as what drupal_get_form would do when the
+ * button is pressed: get the form from the cache, run drupal_process_form over
+ * it and then if it needs rebuild, run drupal_rebuild_form over it. Then send
+ * back a part of the returned form.
+ * $form_state['clicked_button']['#array_parents'] will help you to find which
+ * part.
+ *
+ * @param $form_id
+ * The unique string identifying the desired form. If a function
+ * with that name exists, it is called to build the form array.
+ * 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 constructor function. Examples
+ * may be found in node_forms(), search_forms(), and user_forms().
+ * @param $form_state
+ * A keyed array containing the current state of the form. Most
+ * important is the $form_state['storage'] collection.
+ * @param $args
+ * Any additional arguments are passed on to the functions called by
+ * drupal_get_form(), plus the original form_state in the beginning. If you
+ * are getting a form from the cache, use $form['#parameters'] to shift off
+ * the $form_id from its beginning then the resulting array can be used as
+ * $arg here.
+ * @param $form_build_id
+ * If the AHAH callback calling this function only alters part of the form,
+ * then pass in the existing form_build_id so we can re-cache with the same
+ * csid.
+ * @return
+ * The newly built form.
+ */
+function drupal_rebuild_form($form_id, &$form_state, $args, $form_build_id = NULL) {
+ // Remove the first argument. This is $form_id.when called from
+ // drupal_get_form and the original $form_state when called from some AHAH
+ // callback. Neither is needed.
+ array_shift($args);
+ // Put in the current state.
+ array_unshift($args, $form_state);
+ // And the form_id.
+ array_unshift($args, $form_id);
+ $form = call_user_func_array('drupal_retrieve_form', $args);
+
+ if (!isset($form_build_id)) {
+ // We need a new build_id for the new version of the form.
+ $form_build_id = 'form-'. 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.
+ form_set_cache($form_build_id, $form, $form_state);
+
+ // 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);
+ return $form;
+}
+
+/**
* Fetch a form from cache.
*/
function form_get_cache($form_build_id, &$form_state) {
@@ -738,7 +793,7 @@ function form_error(&$element, $message = '') {
* $_POST data.
*/
function form_builder($form_id, $form, &$form_state) {
- static $complete_form;
+ static $complete_form, $cache;
// Initialize as unprocessed.
$form['#processed'] = FALSE;
@@ -784,6 +839,9 @@ function form_builder($form_id, $form, &$form_state) {
// Check to see if a tree of child elements is present. If so,
// continue down the tree if required.
$form[$key]['#parents'] = $form[$key]['#tree'] && $form['#tree'] ? array_merge($form['#parents'], array($key)) : array($key);
+ $array_parents = isset($form['#array_parents']) ? $form['#array_parents'] : array();
+ $array_parents[] = $key;
+ $form[$key]['#array_parents'] = $array_parents;
}
// Assign a decimal placeholder weight to preserve original array order.
@@ -815,6 +873,15 @@ function form_builder($form_id, $form, &$form_state) {
// After handling the special IE case, we no longer need the buttons collection.
unset($form_state['buttons']);
+ // If some callback set #cache, we need to flip a static flag so later it
+ // can be found.
+ if (isset($form['#cache'])) {
+ $cache = $form['#cache'];
+ }
+ // We are on the top form, we can copy back #cache if it's set.
+ if (isset($form['#type']) && $form['#type'] == 'form' && isset($cache)) {
+ $form['#cache'] = TRUE;
+ }
return $form;
}
@@ -913,8 +980,7 @@ function _form_builder_handle_input_element($form_id, &$form, &$form_state, $com
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), array($complete_form));
- $form = call_user_func_array($process, $args);
+ $form = $process($form, isset($edit) ? $edit : NULL, $form_state, $complete_form);
}
}
$form['#processed'] = TRUE;
@@ -1669,6 +1735,7 @@ function form_expand_ahah($element) {
drupal_add_js(array('ahah' => array($element['#id'] => $ahah_binding)), 'setting');
$js_added[$element['#id']] = TRUE;
+ $element['#cache'] = TRUE;
}
return $element;
}