title: Drupal Ctools Form Wizard in a Block
body: <p>I created a custom module that has a Ctools multi step form. It's basically a copy of <a href="http://www.nicklewis.org/using-chaos-tools-form-wizard-build-multistep-forms-drupal-6" rel="nofollow noreferrer">http://www.nicklewis.org/using-chaos-tools-form-wizard-build-multistep-forms-drupal-6</a>.</p>
  
  <p>The form works. I can see it if I got to the url i made for it.</p>
  
  <p>For the life of me I can't get the multistep form to show up in a block.</p>
  
  <p>Any clues?</p>
  
  <pre><code>/**
  * Implementation of hook_block()
  * */
  
  function mycrazymodule_block($op='list', $delta=0, $edit=array()) {
   switch ($op) {
   case 'list':
    $blocks[0]['info'] = t('SFT Getting Started');
    $blocks[1]['info'] = t('SFT Contact US');
    $blocks[2]['info'] = t('SFT News Letter');
    return $blocks;
   case 'view':
    switch ($delta){
    case '0':
     $block['subject'] = t('SFT Getting Started Subject');
     $block['content'] = mycrazymodule_wizard();
     break;
    case '1':
     $block['subject'] = t('SFT  Contact US Subject');
     $block['content'] =  t('SFT  Contact US content');
     break;
    case '2':
     $block['subject'] = t('SFT  News Letter Subject');
     $block['content'] = t('SFT  News Letter cONTENT');
     break;
    }
    return $block;
   }
  }
  /**
  * Implementation of hook_menu().
  */
  function mycrazymodule_menu() {
   $items['hellocowboy'] = array(
  'title' =&gt; 'Two Step Form',
  'page callback' =&gt; 'mycrazymodule_wizard',
  'access arguments' =&gt; array('access content')
  );
  return $items; 
  }
  
  /**
  * menu callback for the multistep form 
  * step is whatever arg one is -- and will refer to the keys listed in
  * $form_info['order'], and $form_info['forms'] arrays
  */
  function mycrazymodule_wizard() { 
  $step = arg(1);
  // required includes for wizard
  $form_state = array();
  ctools_include('wizard');
  ctools_include('object-cache');
  
  // The array that will hold the two forms and their options
  $form_info = array(
   'id' =&gt; 'getting_started',
   'path' =&gt; "hellocowboy/%step",
   'show trail' =&gt; FALSE,
   'show back' =&gt; FALSE,
   'show cancel' =&gt; false,
   'show return' =&gt;false,
   'next text' =&gt; 'Submit',
   'next callback' =&gt;  'getting_started_add_subtask_next',
   'finish callback' =&gt; 'getting_started_add_subtask_finish',
   'return callback' =&gt; 'getting_started_add_subtask_finish',
   'order' =&gt; array(
     'basic' =&gt; t('Step 1: Basic Info'),
     'lecture' =&gt; t('Step 2: Choose Lecture'),
     ),
   'forms' =&gt; array(
    'basic' =&gt; array(
      'form id' =&gt; 'basic_info_form'
    ),
    'lecture' =&gt; array(
      'form id' =&gt; 'choose_lecture_form'
       ),
      ),
    );  
   $form_state = array(
    'cache name' =&gt; NULL,
   );  
  // no matter the step, you will load your values from the callback page
  $getstart = getting_started_get_page_cache(NULL);
  if (!$getstart) {
  // set form to first step -- we have no data
  $step = current(array_keys($form_info['order']));
  $getstart = new stdClass();
  //create cache
  ctools_object_cache_set('getting_started', $form_state['cache name'], $getstart);
  //print_r($getstart);
  }
   //THIS IS WHERE WILL STORE ALL FORM DATA
   $form_state['getting_started_obj'] = $getstart;  
   // and this is the witchcraft that makes it work
   $output = ctools_wizard_multistep_form($form_info, $step, $form_state);
   return $output;
  }
  
  function basic_info_form(&amp;$form, &amp;$form_state){
   $getstart = &amp;$form_state['getting_started_obj'];
   $form['firstname'] = array(
    '#weight' =&gt; '0',
    '#type' =&gt; 'textfield',
    '#title' =&gt; t('firstname'),
    '#size' =&gt; 60,
    '#maxlength' =&gt; 255,  
    '#required' =&gt; TRUE,  
     );
  
    $form['lastname'] = array(
      '#weight' =&gt; '1',
      '#type' =&gt; 'textfield',
      '#title' =&gt; t('lastname'),
      '#required' =&gt; TRUE,
      '#size' =&gt; 60,
      '#maxlength' =&gt; 255, 
      );
  
      $form['phone'] = array(
      '#weight' =&gt; '2',
      '#type' =&gt; 'textfield',
      '#title' =&gt; t('phone'),
      '#required' =&gt; TRUE,
      '#size' =&gt; 60,
      '#maxlength' =&gt; 255, 
      );
  
      $form['email'] = array(
       '#weight' =&gt; '3',
       '#type' =&gt; 'textfield',
       '#title' =&gt; t('email'),
       '#required' =&gt; TRUE,
       '#size' =&gt; 60,
       '#maxlength' =&gt; 255,
       );
  
      $form['newsletter'] = array(
       '#weight' =&gt; '4',
       '#type' =&gt; 'checkbox',
       '#title' =&gt; t('I would like to receive the newsletter'),
       '#required' =&gt; TRUE,
       '#return_value' =&gt; 1,
       '#default_value' =&gt; 1, 
       );
      $form_state['no buttons'] = TRUE;
      }
      function basic_info_form_validate(&amp;$form, &amp;$form_state){
       $email = $form_state['values']['email'];
       $phone = $form_state['values']['phone'];
        if(valid_email_address($email) != TRUE){
        form_set_error('Dude you have an error', t('Where is your email?'));
       }
      //if (strlen($phone) &gt; 0 &amp;&amp; !ereg('^[0-9]{1,3}-[0-9]{3}-[0-9]{3,4}-[0-9]{3,4}$', 
      $phone)) {
     //form_set_error('Dude the phone', t('Phone number must be in format xxx-xxx-
     nnnn-nnnn.'));
       //}
  
     }
  
  
     function basic_info_form_submit(&amp;$form, &amp;$form_state){
      //Grab the variables
  $firstname =check_plain ($form_state['values']['firstname']);
  $lastname = check_plain ($form_state['values']['lastname']);
  $email = check_plain ($form_state['values']['email']);
  $phone = check_plain ($form_state['values']['phone']);
  $newsletter = $form_state['values']['newsletter'];
  //Send the form and Grab the lead id
  $leadid = send_first_form($lastname, $firstname, $email,$phone, $newsletter);
  //Put into form
  $form_state['getting_started_obj']-&gt;firstname = $firstname;
  $form_state['getting_started_obj']-&gt;lastname = $lastname;
  $form_state['getting_started_obj']-&gt;email = $email;
  $form_state['getting_started_obj']-&gt;phone = $phone;
  $form_state['getting_started_obj']-&gt;newsletter = $newsletter;
  $form_state['getting_started_obj']-&gt;leadid = $leadid;
  }
  
  function choose_lecture_form(&amp;$form, &amp;$form_state){
   $one = 'event 1'
   $two = 'event 2'
   $three = 'event 3' 
   $getstart = &amp;$form_state['getting_started_obj'];
  
  $form['lecture'] = array(
    '#weight' =&gt; '5',
    '#default_value' =&gt; 'two',
    '#options' =&gt; array(
      'one' =&gt; $one,
      'two' =&gt; $two,
      'three' =&gt; $three,
    ),
    '#type' =&gt; 'radios',
    '#title' =&gt; t('Select Workshop'),
    '#required' =&gt; TRUE,
  );
  
  
  $form['attendees'] = array(
    '#weight' =&gt; '6',
    '#default_value' =&gt; 'one',
    '#options' =&gt; array(
      'one' =&gt; t('I will be arriving alone'),
      'two' =&gt;t('I will be arriving with a guest'),
    ),
    '#type' =&gt; 'radios',
    '#title' =&gt; t('Attendees'),
    '#required' =&gt; TRUE,
  );
  
  $form_state['no buttons'] = TRUE;
  }
  
  
  /**
   * Same idea as previous steps submit
   * 
   */
  function choose_lecture_form_submit(&amp;$form, &amp;$form_state) {
   $workshop = $form_state['values']['lecture'];
   $leadid = $form_state['getting_started_obj']-&gt;leadid;
   $attendees = $form_state['values']['attendees'];
  
   $form_state['getting_started_obj']-&gt;lecture =  $workshop;
   $form_state['getting_started_obj']-&gt;attendees = $attendees;
    send_second_form($workshop, $attendees, $leadid);
  }
  
  
  //----PART 3 CTOOLS CALLBACKS -- these usually don't have to be very unique 
  
  /**
   * Callback generated when the add page process is finished.
   * this is where you'd normally save.
   */
  function getting_started_add_subtask_finish(&amp;$form_state) {
    dpm($form_state);
    $getstart = &amp;$form_state['getting_started_obj'];  
      drupal_set_message('mycrazymodule '.$getstart-&gt;name.'  successfully deployed' );
    //Get id
    // Clear the cache
    ctools_object_cache_clear('getting_started', $form_state['cache name']);
    $form_state['redirect'] = 'hellocowboy';
  }
  
  
  /**
   * Callback for the proceed step
   *
   */
  function getting_started_add_subtask_next(&amp;$form_state) {
  
   dpm($form_state);
   $getstart = &amp;$form_state['getting_started_obj'];
   $cache = ctools_object_cache_set('getting_started', $form_state['cache name'],    
   $getstart);
  
  
  }
  
  
  
  
  
  //PART 4 CTOOLS FORM STORAGE HANDLERS -- these usually don't have to be very unique  
  
  /**
   * Remove an item from the object cache.
   */
  function  getting_started_clear_page_cache($name) {
    ctools_object_cache_clear('getting_started', $name);
  }
  
  /**
   * Get the cached changes to a given task handler.
   */
  function getting_started_get_page_cache($name) {
    $cache = ctools_object_cache_get('getting_started', $name);
    return $cache;
  }
  
  
  
  
  //Salesforce Functions
  function send_first_form($lastname, $firstname,$email,$phone, $newsletter){
   $send = array("LastName" =&gt; $lastname , "FirstName" =&gt; $firstname, "Email" =&gt; $email  
  ,"Phone" =&gt; $phone , "Newsletter__c" =&gt;$newsletter );
  $sf = salesforce_api_connect();
  $response = $sf-&gt;client-&gt;create(array($send), 'Lead');
  dpm($response);
  return $response-&gt;id;
  
  }
  
  
  function send_second_form($workshop, $attendees, $leadid){  
  $send = array("Id" =&gt; $leadid ,  "Number_Of_Pepole__c" =&gt; "2"  );
  $sf = salesforce_api_connect();
  $response = $sf-&gt;client-&gt;update(array($send), 'Lead');
  dpm($response, 'the final response');
  return $response-&gt;id;
  
  }
  </code></pre>