http://drupalcontrib.org/api/drupal/contributions!ctools!includes!object-cache.inc/7
The non-volatile object cache is used to store an object while it is being edited, so that we don't have to save until we're completely done. The cache should be 'cleaned' on a regular basis, meaning to remove old objects from the cache, but otherwise the data in this cache must remain stable, as it includes unsaved changes.
Building Multistep forms using the Drupal 7 CTools object cache
multi_step.info
name = MultiStep
description = Custom Multistep form module.
core = 7.x
dependencies[] = ctools
multi_step.install
<?php
/**
* Implements hook_schema().
*/
function multi_step_schema() {
$schema['score'] = array(
'description' => 'Stores all-specific information for Score.',
'fields' => array(
'id' => array(
'type' => 'serial',
'not null' => TRUE,
),
'score' => array(
'type' => 'varchar',
'default' => '',
'length' => 15,
),
'smoke' => array(
'type' => 'varchar',
'default' => '',
'length' => 15,
),
),
'primary key' => array('id'),
);
return $schema;
}
multi_step.module
function multi_step_menu() {
$items = array();
$items['step1'] = array(
'title' => 'Score',
'page callback' => 'drupal_get_form',
'page arguments' => array('multi_step_one'),
'access callback' => TRUE,
'type' => MENU_NORMAL_ITEM,
);
$items['step2'] = array(
'title' => 'Score',
'page callback' => 'drupal_get_form',
'page arguments' => array('multi_step_two'),
'access callback' => TRUE,
'type' => MENU_NORMAL_ITEM,
);
$items['form-results'] = array(
'title' => 'Results',
'page callback' => 'multi_step_display_results',
'access callback' => TRUE,
'type' => MENU_NORMAL_ITEM,
);
return $items;
}
// Step 1
function multi_step_one($form, &$form_state) {
ctools_include('object-cache');
$object = ctools_object_cache_get('submission', 'multi_step_submission');
$form['#prefix'] = '<div id="multistep" class="step1">';
$form['#suffix'] = '</div>';
$form['score'] = array(
'#type' => 'radios',
'#options' => array(1,2,3,4,5,6,7,8,9,10),
'#required' => TRUE,
'#default_value' => isset($object->score) ? $object->score : array(null),
);
$form['multi_step_one_submit'] = array(
'#type' => 'submit',
'#value' => t('Next'),
'#ajax' => array(
'wrapper' => 'multistep',
'callback' => 'multi_step_one_callback',
'progress' => array('type' => 'throbber'),
'prevent' => 'submit click mousedown',
),
);
return $form;
}
// Step 1 Ajax Submit
function multi_step_one_callback($form, &$form_state) {
drupal_validate_form('multi_step_one', $form, $form_state);
if (form_get_errors()) {
$form_state['rebuild'] = TRUE;
return $form;
}
multi_step_one_submit($form, $form_state);
$f = drupal_get_form('multi_step_two');
return drupal_render($f);
}
// Step 1 Submit
function multi_step_one_submit($form, &$form_state) {
ctools_include('object-cache');
$object = ctools_object_cache_get('submission', 'multi_step_submission');
if(isset($object) && $object != '') {
$object->score = $form_state['values']['score'];
}
else {
$object = (object) array(
'score' => $form_state['values']['score'],
);
}
ctools_object_cache_set('submission', 'multi_step_submission', $object);
$form_state['redirect'] = 'step2';
}
// Step 2
function multi_step_two($form, &$form_state) {
global $base_url;
ctools_include('object-cache');
$object = ctools_object_cache_get('submission', 'multi_step_submission');
$form['#prefix'] = '<div id="multistep" class="step2">';
$form['#suffix'] = '</div>';
$smoke_options = array('never' => "Never", 'notnow' => "Not now", 'yes' => 'Yes');
$form['smoke'] = array(
'#type' => 'radios',
'#title' => 'Do you smoke?',
'#options' => $smoke_options,
'#default_value' => isset($object->smoke) ? $object->smoke : '',
'#required' => TRUE,
);
$form['back'] = array(
'#type' => 'submit',
'#value' => t('back'),
'#limit_validation_errors' => array(),
'#ajax' => array(
'wrapper' => 'multistep',
'callback' => 'multistep_two_back_submit',
'progress' => array('type' => 'throbber'),
'prevent' => 'submit click mousedown',
),
'#submit' => array('multistep_two_back_submit'),
);
$form['submit'] = array(
'#type' => 'submit',
'#value' => t('Next'),
'#ajax' => array(
'wrapper' => 'multistep',
'callback' => 'multistep_two_ajax_submit',
'progress' => array('type' => 'throbber'),
'prevent' => 'submit click mousedown',
),
'#submit' => array('multistep_two_submit'),
);
return $form;
}
// Step 2 Back
function multistep_two_back_submit($form, &$form_state) {
$form_state['redirect'] = 'step1';
$f = drupal_get_form('multi_step_one');
return drupal_render($f);
}
// Step 2 Ajax Submit
function multistep_two_ajax_submit($form, &$form_state) {
drupal_validate_form('multi_step_two', $form, $form_state);
if (form_get_errors()) {
$form_state['rebuild'] = TRUE;
return $form;
}
multistep_two_submit($form, $form_state);
return multi_step_display_results();
}
// Step 2 Submit
function multistep_two_submit($form, &$form_state) {
ctools_include('object-cache');
$object = ctools_object_cache_get('submission', 'multi_step_submission');
$object->smoke = $form_state['values']['smoke'];
ctools_object_cache_set('submission', 'multi_step_submission', $object);
$form_state['redirect'] = 'form-results';
}
/******************************Results***********************************/
function multi_step_display_results() {
ctools_include('object-cache');
$object = ctools_object_cache_get('submission', 'multi_step_submission');
//step1
$scorethink = isset($object->score) ? $object->score : '';
//step2
$smoke = isset($object->smoke) ? $object->smoke : '';
db_insert('score')->fields(array(
'score' => $scorethink,
'smoke' => $smoke,
))->execute();
ctools_object_cache_clear('submission', 'multi_step_submission');
if ($object) {
return array(
'#markup' => 'Submitted Values: <br/>Score='.$scorethink.'<br/>Smoke='.$smoke,
);
}
else {
drupal_goto('score');
}
}