danielebarchiesi@0: $params) { danielebarchiesi@0: $form_info['order'][$step_id] = $params['title']; danielebarchiesi@0: } danielebarchiesi@0: } danielebarchiesi@0: danielebarchiesi@0: if (!isset($step)) { danielebarchiesi@0: $keys = array_keys($form_info['order']); danielebarchiesi@0: $step = array_shift($keys); danielebarchiesi@0: } danielebarchiesi@0: danielebarchiesi@0: ctools_wizard_defaults($form_info); danielebarchiesi@0: danielebarchiesi@0: // If automated caching is enabled, ensure that everything is as it danielebarchiesi@0: // should be. danielebarchiesi@0: if (!empty($form_info['auto cache'])) { danielebarchiesi@0: // If the cache mechanism hasn't been set, default to the simple danielebarchiesi@0: // mechanism and use the wizard ID to ensure uniqueness so cache danielebarchiesi@0: // objects don't stomp on each other. danielebarchiesi@0: if (!isset($form_info['cache mechanism'])) { danielebarchiesi@0: $form_info['cache mechanism'] = 'simple::wizard::' . $form_info['id']; danielebarchiesi@0: } danielebarchiesi@0: danielebarchiesi@0: // If not set, default the cache key to the wizard ID. This is often danielebarchiesi@0: // a unique ID of the object being edited or similar. danielebarchiesi@0: if (!isset($form_info['cache key'])) { danielebarchiesi@0: $form_info['cache key'] = $form_info['id']; danielebarchiesi@0: } danielebarchiesi@0: danielebarchiesi@0: // If not set, default the cache location to storage. This is often danielebarchiesi@0: // somnething like 'conf'. danielebarchiesi@0: if (!isset($form_info['cache location'])) { danielebarchiesi@0: $form_info['cache location'] = 'storage'; danielebarchiesi@0: } danielebarchiesi@0: danielebarchiesi@0: // If absolutely nothing was set for the cache area to work on danielebarchiesi@0: if (!isset($form_state[$form_info['cache location']])) { danielebarchiesi@0: ctools_include('cache'); danielebarchiesi@0: $form_state[$form_info['cache location']] = ctools_cache_get($form_info['cache mechanism'], $form_info['cache key']); danielebarchiesi@0: } danielebarchiesi@0: } danielebarchiesi@0: danielebarchiesi@0: $form_state['step'] = $step; danielebarchiesi@0: $form_state['form_info'] = $form_info; danielebarchiesi@0: danielebarchiesi@0: // Ensure we have form information for the current step. danielebarchiesi@0: if (!isset($form_info['forms'][$step])) { danielebarchiesi@0: return; danielebarchiesi@0: } danielebarchiesi@0: danielebarchiesi@0: // Ensure that whatever include file(s) were requested by the form info are danielebarchiesi@0: // actually included. danielebarchiesi@0: $info = $form_info['forms'][$step]; danielebarchiesi@0: danielebarchiesi@0: if (!empty($info['include'])) { danielebarchiesi@0: if (is_array($info['include'])) { danielebarchiesi@0: foreach ($info['include'] as $file) { danielebarchiesi@0: ctools_form_include_file($form_state, $file); danielebarchiesi@0: } danielebarchiesi@0: } danielebarchiesi@0: else { danielebarchiesi@0: ctools_form_include_file($form_state, $info['include']); danielebarchiesi@0: } danielebarchiesi@0: } danielebarchiesi@0: danielebarchiesi@0: // This tells drupal_build_form to apply our wrapper to the form. It danielebarchiesi@0: // will give it buttons and the like. danielebarchiesi@0: $form_state['wrapper_callback'] = 'ctools_wizard_wrapper'; danielebarchiesi@0: if (!isset($form_state['rerender'])) { danielebarchiesi@0: $form_state['rerender'] = FALSE; danielebarchiesi@0: } danielebarchiesi@0: danielebarchiesi@0: $form_state['no_redirect'] = TRUE; danielebarchiesi@0: danielebarchiesi@0: $output = drupal_build_form($info['form id'], $form_state); danielebarchiesi@0: danielebarchiesi@0: if (empty($form_state['executed']) || !empty($form_state['rerender'])) { danielebarchiesi@0: if (empty($form_state['title']) && !empty($info['title'])) { danielebarchiesi@0: $form_state['title'] = $info['title']; danielebarchiesi@0: } danielebarchiesi@0: danielebarchiesi@0: if (!empty($form_state['ajax render'])) { danielebarchiesi@0: // Any include files should already be included by this point: danielebarchiesi@0: return $form_state['ajax render']($form_state, $output); danielebarchiesi@0: } danielebarchiesi@0: danielebarchiesi@0: // Automatically use the modal tool if set to true. danielebarchiesi@0: if (!empty($form_state['modal']) && empty($form_state['modal return'])) { danielebarchiesi@0: ctools_include('modal'); danielebarchiesi@0: danielebarchiesi@0: // This overwrites any previous commands. danielebarchiesi@0: $form_state['commands'] = ctools_modal_form_render($form_state, $output); danielebarchiesi@0: } danielebarchiesi@0: } danielebarchiesi@0: danielebarchiesi@0: if (!empty($form_state['executed'])) { danielebarchiesi@0: // We use the plugins get_function format because it's powerful and danielebarchiesi@0: // not limited to just functions. danielebarchiesi@0: ctools_include('plugins'); danielebarchiesi@0: danielebarchiesi@0: if (isset($form_state['clicked_button']['#wizard type'])) { danielebarchiesi@0: $type = $form_state['clicked_button']['#wizard type']; danielebarchiesi@0: // If we have a callback depending upon the type of button that was danielebarchiesi@0: // clicked, call it. danielebarchiesi@0: if ($function = ctools_plugin_get_function($form_info, "$type callback")) { danielebarchiesi@0: $function($form_state); danielebarchiesi@0: } danielebarchiesi@0: danielebarchiesi@0: // If auto-caching is on, we need to write the cache on next and danielebarchiesi@0: // clear the cache on finish. danielebarchiesi@0: if (!empty($form_info['auto cache'])) { danielebarchiesi@0: if ($type == 'next') { danielebarchiesi@0: ctools_include('cache'); danielebarchiesi@0: ctools_cache_set($form_info['cache mechanism'], $form_info['cache key'], $form_state[$form_info['cache location']]); danielebarchiesi@0: } danielebarchiesi@0: elseif ($type == 'finish') { danielebarchiesi@0: ctools_include('cache'); danielebarchiesi@0: ctools_cache_clear($form_info['cache mechanism'], $form_info['cache key']); danielebarchiesi@0: } danielebarchiesi@0: } danielebarchiesi@0: danielebarchiesi@0: // Set a couple of niceties: danielebarchiesi@0: if ($type == 'finish') { danielebarchiesi@0: $form_state['complete'] = TRUE; danielebarchiesi@0: } danielebarchiesi@0: danielebarchiesi@0: if ($type == 'cancel') { danielebarchiesi@0: $form_state['cancel'] = TRUE; danielebarchiesi@0: } danielebarchiesi@0: danielebarchiesi@0: // If the modal is in use, some special code for it: danielebarchiesi@0: if (!empty($form_state['modal']) && empty($form_state['modal return'])) { danielebarchiesi@0: if ($type != 'next') { danielebarchiesi@0: // Automatically dismiss the modal if we're not going to another form. danielebarchiesi@0: ctools_include('modal'); danielebarchiesi@0: $form_state['commands'][] = ctools_modal_command_dismiss(); danielebarchiesi@0: } danielebarchiesi@0: } danielebarchiesi@0: } danielebarchiesi@0: danielebarchiesi@0: if (empty($form_state['ajax'])) { danielebarchiesi@0: // redirect, if one is set. danielebarchiesi@0: if ($form_state['redirect']) { danielebarchiesi@0: if (is_array($form_state['redirect'])) { danielebarchiesi@0: call_user_func_array('drupal_goto', $form_state['redirect']); danielebarchiesi@0: } danielebarchiesi@0: else { danielebarchiesi@0: drupal_goto($form_state['redirect']); danielebarchiesi@0: } danielebarchiesi@0: } danielebarchiesi@0: } danielebarchiesi@0: else if (isset($form_state['ajax next'])) { danielebarchiesi@0: // Clear a few items off the form state so we don't double post: danielebarchiesi@0: $next = $form_state['ajax next']; danielebarchiesi@0: unset($form_state['ajax next']); danielebarchiesi@0: unset($form_state['executed']); danielebarchiesi@0: unset($form_state['post']); danielebarchiesi@0: unset($form_state['next']); danielebarchiesi@0: return ctools_wizard_multistep_form($form_info, $next, $form_state); danielebarchiesi@0: } danielebarchiesi@0: danielebarchiesi@0: // If the callbacks wanted to do something besides go to the next form, danielebarchiesi@0: // it needs to have set $form_state['commands'] with something that can danielebarchiesi@0: // be rendered. danielebarchiesi@0: } danielebarchiesi@0: danielebarchiesi@0: // Render ajax commands if we have any. danielebarchiesi@0: if (isset($form_state['ajax']) && isset($form_state['commands']) && empty($form_state['modal return'])) { danielebarchiesi@0: return ajax_render($form_state['commands']); danielebarchiesi@0: } danielebarchiesi@0: danielebarchiesi@0: // Otherwise, return the output. danielebarchiesi@0: return $output; danielebarchiesi@0: } danielebarchiesi@0: danielebarchiesi@0: /** danielebarchiesi@0: * Provide a wrapper around another form for adding multi-step information. danielebarchiesi@0: */ danielebarchiesi@0: function ctools_wizard_wrapper($form, &$form_state) { danielebarchiesi@0: $form_info = &$form_state['form_info']; danielebarchiesi@0: $info = $form_info['forms'][$form_state['step']]; danielebarchiesi@0: danielebarchiesi@0: // Determine the next form from this step. danielebarchiesi@0: // Create a form trail if we're supposed to have one. danielebarchiesi@0: $trail = array(); danielebarchiesi@0: $previous = TRUE; danielebarchiesi@0: foreach ($form_info['order'] as $id => $title) { danielebarchiesi@0: if ($id == $form_state['step']) { danielebarchiesi@0: $previous = FALSE; danielebarchiesi@0: $class = 'wizard-trail-current'; danielebarchiesi@0: } danielebarchiesi@0: elseif ($previous) { danielebarchiesi@0: $not_first = TRUE; danielebarchiesi@0: $class = 'wizard-trail-previous'; danielebarchiesi@0: $form_state['previous'] = $id; danielebarchiesi@0: } danielebarchiesi@0: else { danielebarchiesi@0: $class = 'wizard-trail-next'; danielebarchiesi@0: if (!isset($form_state['next'])) { danielebarchiesi@0: $form_state['next'] = $id; danielebarchiesi@0: } danielebarchiesi@0: if (empty($form_info['show trail'])) { danielebarchiesi@0: break; danielebarchiesi@0: } danielebarchiesi@0: } danielebarchiesi@0: danielebarchiesi@0: if (!empty($form_info['show trail'])) { danielebarchiesi@0: if (!empty($form_info['free trail'])) { danielebarchiesi@0: // ctools_wizard_get_path() returns results suitable for danielebarchiesi@0: // $form_state['redirect] which can only be directly used in danielebarchiesi@0: // drupal_goto. We have to futz a bit with it. danielebarchiesi@0: $path = ctools_wizard_get_path($form_info, $id); danielebarchiesi@0: $options = array(); danielebarchiesi@0: if (!empty($path[1])) { danielebarchiesi@0: $options = $path[1]; danielebarchiesi@0: } danielebarchiesi@0: $title = l($title, $path[0], $options); danielebarchiesi@0: } danielebarchiesi@0: $trail[] = '' . $title . ''; danielebarchiesi@0: } danielebarchiesi@0: } danielebarchiesi@0: danielebarchiesi@0: // Display the trail if instructed to do so. danielebarchiesi@0: if (!empty($form_info['show trail'])) { danielebarchiesi@0: ctools_add_css('wizard'); danielebarchiesi@0: $form['ctools_trail'] = array( danielebarchiesi@0: '#markup' => theme(array('ctools_wizard_trail__' . $form_info['id'], 'ctools_wizard_trail'), array('trail' => $trail)), danielebarchiesi@0: '#weight' => -1000, danielebarchiesi@0: ); danielebarchiesi@0: } danielebarchiesi@0: danielebarchiesi@0: if (empty($form_info['no buttons'])) { danielebarchiesi@0: // Ensure buttons stay on the bottom. danielebarchiesi@0: $form['buttons'] = array( danielebarchiesi@0: '#type' => 'actions', danielebarchiesi@0: '#weight' => 1000, danielebarchiesi@0: ); danielebarchiesi@0: danielebarchiesi@0: $button_attributes = array(); danielebarchiesi@0: if (!empty($form_state['ajax']) && empty($form_state['modal'])) { danielebarchiesi@0: $button_attributes = array('class' => array('ctools-use-ajax')); danielebarchiesi@0: } danielebarchiesi@0: danielebarchiesi@0: if (!empty($form_info['show back']) && isset($form_state['previous'])) { danielebarchiesi@0: $form['buttons']['previous'] = array( danielebarchiesi@0: '#type' => 'submit', danielebarchiesi@0: '#value' => $form_info['back text'], danielebarchiesi@0: '#next' => $form_state['previous'], danielebarchiesi@0: '#wizard type' => 'next', danielebarchiesi@0: '#weight' => -2000, danielebarchiesi@0: '#limit_validation_errors' => array(), danielebarchiesi@0: // hardcode the submit so that it doesn't try to save data. danielebarchiesi@0: '#submit' => array('ctools_wizard_submit'), danielebarchiesi@0: '#attributes' => $button_attributes, danielebarchiesi@0: ); danielebarchiesi@0: danielebarchiesi@0: if (isset($form_info['no back validate']) || isset($info['no back validate'])) { danielebarchiesi@0: $form['buttons']['previous']['#validate'] = array(); danielebarchiesi@0: } danielebarchiesi@0: } danielebarchiesi@0: danielebarchiesi@0: // If there is a next form, place the next button. danielebarchiesi@0: if (isset($form_state['next']) || !empty($form_info['free trail'])) { danielebarchiesi@0: $form['buttons']['next'] = array( danielebarchiesi@0: '#type' => 'submit', danielebarchiesi@0: '#value' => $form_info['next text'], danielebarchiesi@0: '#next' => !empty($form_info['free trail']) ? $form_state['step'] : $form_state['next'], danielebarchiesi@0: '#wizard type' => 'next', danielebarchiesi@0: '#weight' => -1000, danielebarchiesi@0: '#attributes' => $button_attributes, danielebarchiesi@0: ); danielebarchiesi@0: } danielebarchiesi@0: danielebarchiesi@0: // There are two ways the return button can appear. If this is not the danielebarchiesi@0: // end of the form list (i.e, there is a next) then it's "update and return" danielebarchiesi@0: // to be clear. If this is the end of the path and there is no next, we danielebarchiesi@0: // call it 'Finish'. danielebarchiesi@0: danielebarchiesi@0: // Even if there is no direct return path (some forms may not want you danielebarchiesi@0: // leaving in the middle) the final button is always a Finish and it does danielebarchiesi@0: // whatever the return action is. danielebarchiesi@0: if (!empty($form_info['show return']) && !empty($form_state['next'])) { danielebarchiesi@0: $form['buttons']['return'] = array( danielebarchiesi@0: '#type' => 'submit', danielebarchiesi@0: '#value' => $form_info['return text'], danielebarchiesi@0: '#wizard type' => 'return', danielebarchiesi@0: '#attributes' => $button_attributes, danielebarchiesi@0: ); danielebarchiesi@0: } danielebarchiesi@0: else if (empty($form_state['next']) || !empty($form_info['free trail'])) { danielebarchiesi@0: $form['buttons']['return'] = array( danielebarchiesi@0: '#type' => 'submit', danielebarchiesi@0: '#value' => $form_info['finish text'], danielebarchiesi@0: '#wizard type' => 'finish', danielebarchiesi@0: '#attributes' => $button_attributes, danielebarchiesi@0: ); danielebarchiesi@0: } danielebarchiesi@0: danielebarchiesi@0: // If we are allowed to cancel, place a cancel button. danielebarchiesi@0: if ((isset($form_info['cancel path']) && !isset($form_info['show cancel'])) || !empty($form_info['show cancel'])) { danielebarchiesi@0: $form['buttons']['cancel'] = array( danielebarchiesi@0: '#type' => 'submit', danielebarchiesi@0: '#value' => $form_info['cancel text'], danielebarchiesi@0: '#wizard type' => 'cancel', danielebarchiesi@0: // hardcode the submit so that it doesn't try to save data. danielebarchiesi@0: '#limit_validation_errors' => array(), danielebarchiesi@0: '#submit' => array('ctools_wizard_submit'), danielebarchiesi@0: '#attributes' => $button_attributes, danielebarchiesi@0: ); danielebarchiesi@0: } danielebarchiesi@0: danielebarchiesi@0: // Set up optional validate handlers. danielebarchiesi@0: $form['#validate'] = array(); danielebarchiesi@0: if (function_exists($info['form id'] . '_validate')) { danielebarchiesi@0: $form['#validate'][] = $info['form id'] . '_validate'; danielebarchiesi@0: } danielebarchiesi@0: if (isset($info['validate']) && function_exists($info['validate'])) { danielebarchiesi@0: $form['#validate'][] = $info['validate']; danielebarchiesi@0: } danielebarchiesi@0: danielebarchiesi@0: // Set up our submit handler after theirs. Since putting something here will danielebarchiesi@0: // skip Drupal's autodetect, we autodetect for it. danielebarchiesi@0: danielebarchiesi@0: // We make sure ours is after theirs so that they get to change #next if danielebarchiesi@0: // the want to. danielebarchiesi@0: $form['#submit'] = array(); danielebarchiesi@0: if (function_exists($info['form id'] . '_submit')) { danielebarchiesi@0: $form['#submit'][] = $info['form id'] . '_submit'; danielebarchiesi@0: } danielebarchiesi@0: if (isset($info['submit']) && function_exists($info['submit'])) { danielebarchiesi@0: $form['#submit'][] = $info['submit']; danielebarchiesi@0: } danielebarchiesi@0: $form['#submit'][] = 'ctools_wizard_submit'; danielebarchiesi@0: } danielebarchiesi@0: danielebarchiesi@0: if (!empty($form_state['ajax'])) { danielebarchiesi@0: $params = ctools_wizard_get_path($form_state['form_info'], $form_state['step']); danielebarchiesi@0: if (count($params) > 1) { danielebarchiesi@0: $url = array_shift($params); danielebarchiesi@0: $options = array(); danielebarchiesi@0: danielebarchiesi@0: $keys = array(0 => 'query', 1 => 'fragment'); danielebarchiesi@0: foreach ($params as $key => $value) { danielebarchiesi@0: if (isset($keys[$key]) && isset($value)) { danielebarchiesi@0: $options[$keys[$key]] = $value; danielebarchiesi@0: } danielebarchiesi@0: } danielebarchiesi@0: danielebarchiesi@0: $params = array($url, $options); danielebarchiesi@0: } danielebarchiesi@0: $form['#action'] = call_user_func_array('url', $params); danielebarchiesi@0: } danielebarchiesi@0: danielebarchiesi@0: if (isset($info['wrapper']) && function_exists($info['wrapper'])) { danielebarchiesi@0: $form = $info['wrapper']($form, $form_state); danielebarchiesi@0: } danielebarchiesi@0: danielebarchiesi@0: if (isset($form_info['wrapper']) && function_exists($form_info['wrapper'])) { danielebarchiesi@0: $form = $form_info['wrapper']($form, $form_state); danielebarchiesi@0: } danielebarchiesi@0: return $form; danielebarchiesi@0: } danielebarchiesi@0: danielebarchiesi@0: /** danielebarchiesi@0: * On a submit, go to the next form. danielebarchiesi@0: */ danielebarchiesi@0: function ctools_wizard_submit(&$form, &$form_state) { danielebarchiesi@0: if (isset($form_state['clicked_button']['#wizard type'])) { danielebarchiesi@0: $type = $form_state['clicked_button']['#wizard type']; danielebarchiesi@0: danielebarchiesi@0: // if AJAX enabled, we proceed slightly differently here. danielebarchiesi@0: if (!empty($form_state['ajax'])) { danielebarchiesi@0: if ($type == 'next') { danielebarchiesi@0: $form_state['ajax next'] = $form_state['clicked_button']['#next']; danielebarchiesi@0: } danielebarchiesi@0: } danielebarchiesi@0: else { danielebarchiesi@0: if ($type == 'cancel' && isset($form_state['form_info']['cancel path'])) { danielebarchiesi@0: $form_state['redirect'] = $form_state['form_info']['cancel path']; danielebarchiesi@0: } danielebarchiesi@0: else if ($type == 'next') { danielebarchiesi@0: $form_state['redirect'] = ctools_wizard_get_path($form_state['form_info'], $form_state['clicked_button']['#next']); danielebarchiesi@0: if (!empty($_GET['destination'])) { danielebarchiesi@0: // We don't want drupal_goto redirect this request danielebarchiesi@0: // back. ctools_wizard_get_path ensures that the destination is danielebarchiesi@0: // carried over on subsequent pages. danielebarchiesi@0: unset($_GET['destination']); danielebarchiesi@0: } danielebarchiesi@0: } danielebarchiesi@0: else if (isset($form_state['form_info']['return path'])) { danielebarchiesi@0: $form_state['redirect'] = $form_state['form_info']['return path']; danielebarchiesi@0: } danielebarchiesi@0: else if ($type == 'finish' && isset($form_state['form_info']['cancel path'])) { danielebarchiesi@0: $form_state['redirect'] = $form_state['form_info']['cancel path']; danielebarchiesi@0: } danielebarchiesi@0: } danielebarchiesi@0: } danielebarchiesi@0: } danielebarchiesi@0: danielebarchiesi@0: /** danielebarchiesi@0: * Create a path from the form info and a given step. danielebarchiesi@0: */ danielebarchiesi@0: function ctools_wizard_get_path($form_info, $step) { danielebarchiesi@0: if (is_array($form_info['path'])) { danielebarchiesi@0: foreach ($form_info['path'] as $id => $part) { danielebarchiesi@0: $form_info['path'][$id] = str_replace('%step', $step, $form_info['path'][$id]); danielebarchiesi@0: } danielebarchiesi@0: $path = $form_info['path']; danielebarchiesi@0: } danielebarchiesi@0: else { danielebarchiesi@0: $path = array(str_replace('%step', $step, $form_info['path'])); danielebarchiesi@0: } danielebarchiesi@0: danielebarchiesi@0: // If destination is set, carry it over so it'll take effect when danielebarchiesi@0: // saving. The submit handler will unset destination to avoid drupal_goto danielebarchiesi@0: // redirecting us. danielebarchiesi@0: if (!empty($_GET['destination'])) { danielebarchiesi@0: // Ensure that options is an array. danielebarchiesi@0: if (!isset($path[1]) || !is_array($path[1])) { danielebarchiesi@0: $path[1] = array(); danielebarchiesi@0: } danielebarchiesi@0: // Ensure that the query part of options is an array. danielebarchiesi@0: $path[1] += array('query' => array()); danielebarchiesi@0: // Add the destination parameter, if not set already. danielebarchiesi@0: $path[1]['query'] += drupal_get_destination(); danielebarchiesi@0: } danielebarchiesi@0: danielebarchiesi@0: return $path; danielebarchiesi@0: } danielebarchiesi@0: danielebarchiesi@0: /** danielebarchiesi@0: * Set default parameters and callbacks if none are given. danielebarchiesi@0: * Callbacks follows pattern: danielebarchiesi@0: * $form_info['id']_$hook danielebarchiesi@0: * $form_info['id']_$form_info['forms'][$step_key]_$hook danielebarchiesi@0: */ danielebarchiesi@0: function ctools_wizard_defaults(&$form_info) { danielebarchiesi@0: $hook = $form_info['id']; danielebarchiesi@0: $defaults = array( danielebarchiesi@0: 'show trail' => FALSE, danielebarchiesi@0: 'free trail' => FALSE, danielebarchiesi@0: 'show back' => FALSE, danielebarchiesi@0: 'show cancel' => FALSE, danielebarchiesi@0: 'show return' => FALSE, danielebarchiesi@0: 'next text' => t('Continue'), danielebarchiesi@0: 'back text' => t('Back'), danielebarchiesi@0: 'return text' => t('Update and return'), danielebarchiesi@0: 'finish text' => t('Finish'), danielebarchiesi@0: 'cancel text' => t('Cancel'), danielebarchiesi@0: ); danielebarchiesi@0: danielebarchiesi@0: if (!empty($form_info['free trail'])) { danielebarchiesi@0: $defaults['next text'] = t('Update'); danielebarchiesi@0: $defaults['finish text'] = t('Save'); danielebarchiesi@0: } danielebarchiesi@0: danielebarchiesi@0: $form_info = $form_info + $defaults; danielebarchiesi@0: // set form callbacks if they aren't defined danielebarchiesi@0: foreach ($form_info['forms'] as $step => $params) { danielebarchiesi@0: if (!$params['form id']) { danielebarchiesi@0: $form_callback = $hook . '_' . $step . '_form'; danielebarchiesi@0: $form_info['forms'][$step]['form id'] = $form_callback; danielebarchiesi@0: } danielebarchiesi@0: } danielebarchiesi@0: danielebarchiesi@0: // set button callbacks danielebarchiesi@0: $callbacks = array( danielebarchiesi@0: 'back callback' => '_back', danielebarchiesi@0: 'next callback' => '_next', danielebarchiesi@0: 'return callback' => '_return', danielebarchiesi@0: 'cancel callback' => '_cancel', danielebarchiesi@0: 'finish callback' => '_finish', danielebarchiesi@0: ); danielebarchiesi@0: danielebarchiesi@0: foreach ($callbacks as $key => $callback) { danielebarchiesi@0: // never overwrite if explicity defined danielebarchiesi@0: if (empty($form_info[$key])) { danielebarchiesi@0: $wizard_callback = $hook . $callback; danielebarchiesi@0: if (function_exists($wizard_callback)) { danielebarchiesi@0: $form_info[$key] = $wizard_callback; danielebarchiesi@0: } danielebarchiesi@0: } danielebarchiesi@0: } danielebarchiesi@0: }