#193191 by chx: allow form elements to enable form caching - allows custom form elements to leverage the AHAH framework
							parent
							
								
									c1555f33bc
								
							
						
					
					
						commit
						4615c96d59
					
				| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			@ -144,6 +130,75 @@ function drupal_get_form($form_id) {
 | 
			
		|||
  return drupal_render_form($form_id, $form);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 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.
 | 
			
		||||
 */
 | 
			
		||||
| 
						 | 
				
			
			@ -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;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue