/[cvs]/nfo/php/libs/com.newsblob.phphtmllib/form/FormWizard.inc
ViewVC logotype

Annotation of /nfo/php/libs/com.newsblob.phphtmllib/form/FormWizard.inc

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.2 - (hide annotations)
Thu May 6 16:27:23 2004 UTC (20 years, 3 months ago) by jonen
Branch: MAIN
Changes since 1.1: +45 -36 lines
 updated all to v2.4.1 - Apr 01, 2004

1 jonen 1.1 <?php
2     /**
3     * This file contains the FormWizard class.
4     *
5 jonen 1.2 * $Id: FormWizard.inc,v 1.4 2003/08/19 00:48:57 hemna Exp $
6 jonen 1.1 *
7     * @author Walter A. Boring IV <waboring@buildabetterweb.com>
8     * @package phpHtmlLib
9     * @subpackage FormProcessing
10     *
11     * @copyright LGPL - See LICENCE
12     *
13     */
14    
15     define("WIZARD_VISITED", "_wizard_visited");
16     define("WIZARD_STEP", "_wizard_step");
17     define("WIZARD_TO_STEP", "_wizard_to_step");
18     define("WIZARD_ID", "_wizard_id");
19     define("WIZARD_ACTION", "_wizard_action");
20    
21     define("WIZARD_NEXT", "NEXT");
22     define("WIZARD_PREV", "PREV");
23     define("WIZARD_JUMP", "JUMP");
24     define("WIZARD_FINAL", "FINAL");
25    
26     class FormWizard extends FormProcessor {
27    
28     /**
29     * This holds the array of
30     * step objects for the
31     * wizard
32     */
33     var $_steps = array();
34    
35    
36     /**
37     * Holds a bunch of state
38     * variables
39     */
40     var $_vars = array("to_step" => 0,
41     "num_steps" => 0,
42     "on_confirm" => FALSE,
43     WIZARD_ID => NULL );
44    
45     /**
46     * The constructor
47     *
48     */
49     function FormWizard() {
50 jonen 1.2 //user_error(__CLASS__."::".__FUNCTION__." - this class isn't done yet.");
51 jonen 1.1 $this->_session_test();
52     $this->set_form_name( "form_wizard" );
53     $this->set_form_action( $_SERVER["PHP_SELF"] );
54    
55     //let the child class add the steps
56     $this->user_setup();
57    
58     //init our vars
59     $this->_init();
60    
61     //Set up the Validation object
62     //and the FormErrors object to
63     //be used by this form.
64     $this->setup_validation();
65    
66     //set the current step
67     $this->_set_step();
68    
69     //now process the form
70     $this->_process_form();
71    
72     //now we need to process the current step.
73     }
74    
75    
76     /**
77     * This function renders the
78     * FormWizard
79     *
80     */
81     function render($indent_level=0, $output_debug=0) {
82     $container = container();
83    
84     //add the JS
85     $container->add( $this->_build_js() );
86    
87     $container->add( $this->_build_toolbar(),
88     html_br(2) );
89    
90     if ($this->_has_errors) {
91     //we need to render the form errors
92     //and then the form
93     $container->add( $this->render_error($indent_level, $output_debug) );
94     } else {
95     //there are no errors!
96 jonen 1.2 debug( "have we visited?" ,null,4);
97     //debug( $_REQUEST );
98     if (isset($_REQUEST[FORM_VISITED]) && $_REQUEST[FORM_VISITED] == 1) {
99 jonen 1.1 //looks like the form has been processed?
100 jonen 1.2 debug( "confirmed = ".$this->_confirmed );
101     debug( "curr step = ".$this->_current_step() );
102 jonen 1.1 if (!$this->_confirmed && $this->_vars["on_confirm"]) {
103 jonen 1.2 debug("FINAL DUDE!");
104 jonen 1.1 $container->add( $this->render_confirm($indent_level, $output_debug) );
105     } else {
106     //Looks like the action worked
107     $success = $this->_form_content->form_success();
108 jonen 1.2 debug("DO ACTION!");
109 jonen 1.1 if ($this->_form_success_render) {
110     $container->add( $this->render_form($indent_level, $output_debug, $success) );
111     } else {
112     if (method_exists($success,"render")) {
113     //looks like this is an object.
114     //we'll assume it has a render function.
115     $container->add( $success->render($indent_level, $output_debug) );
116     } else {
117     //since its not an object,
118     //lets just display it.
119     $container->add( $success );
120     }
121     }
122     }
123     } else {
124     $container->add( $this->render_form($indent_level, $output_debug) );
125     }
126     }
127    
128     return $container->render($indent_level, $output_debug);
129     }
130    
131    
132     /**
133     * This method does the logic of
134     * doing the form processing
135     */
136     function _process_form() {
137     //Has this step been visited yet?
138    
139     if (!$this->_is_step_visited($this->_current_step()) &&
140     $this->_current_step() <= $this->_vars["num_steps"]) {
141     $this->_form_content->form_init_data();
142     }
143    
144     //we only need to process the form
145     //if it has been visited. Otherwise
146     //it just gets rendered.
147     if (@$_REQUEST[FORM_VISITED] == 1) {
148 jonen 1.2 debug("PROCESS STEP ".$this->_current_step());
149 jonen 1.1 $this->_form_content->set_action($_REQUEST[FORM_ACTION]);
150    
151     //let see if this was a confirmation page.
152     if ( @$_REQUEST[WIZARD_ACTION] == WIZARD_FINAL ) {
153     //looks like this was a submit on a
154     //confirmation page. we don't need
155     //to do form field validation.
156     $this->_confirmed = TRUE;
157     for ($i=0; $i<=$this->_vars["num_steps"]-1; $i++) {
158     $this->_has_errors = !$this->_steps[$i]["form"]->form_action();
159     }
160     } else {
161     //we haven't been confirmed, so we
162     //need to validate the form.
163     if ($this->can_validate()) {
164     //looks like we should do validation
165 jonen 1.2 if ($_REQUEST[WIZARD_ACTION] != WIZARD_PREV) {
166     //we don't need to validate if we haven't
167     //finished this step yet.
168     $this->do_validation();
169     }
170 jonen 1.1 }
171     if (!$this->_has_errors) {
172     //no errors were found
173     //make sure we don't have any backend errors
174     $this->_has_errors = !$this->_form_content->form_backend_validation();
175     if (!$this->_has_errors) {
176     //ok this step validated. lets display the next.
177     //mark this step as visited
178 jonen 1.2 $current_step = $this->_current_step();
179     debug( "CURRENT STEP ".$current_step);
180 jonen 1.1
181     switch ($_REQUEST[WIZARD_ACTION]) {
182     case WIZARD_NEXT:
183 jonen 1.2 debug("NEXT");
184 jonen 1.1 if ($current_step == $this->_vars["num_steps"]) {
185 jonen 1.2 debug("SHOW CONFIRMATION");
186 jonen 1.1 //we need to show the confirmation
187     //don't process
188     $this->_vars["on_confirm"] = TRUE;
189 jonen 1.2 $this->_step_visited( $current_step );
190     $this->_set_current_step($current_step+1);
191 jonen 1.1 } else {
192 jonen 1.2 $this->_step_visited( $current_step );
193 jonen 1.1 $this->_set_current_step($current_step+1);
194     unset($_REQUEST[FORM_VISITED]);
195     $this->_form_content = &$this->_steps[$this->_current_step()-1]["form"];
196 jonen 1.2 //$this->_process_form();
197     }
198 jonen 1.1 break;
199    
200     case WIZARD_PREV:
201 jonen 1.2 debug("PREV");
202 jonen 1.1 $this->_set_current_step($current_step-1);
203     unset($_REQUEST[FORM_VISITED]);
204 jonen 1.2 $this->_form_content = &$this->_steps[$this->_current_step()-1]["form"];
205     //$this->_process_form();
206 jonen 1.1 break;
207     }
208     }
209     }
210     }
211     }
212 jonen 1.2 debug("bail");
213 jonen 1.1 }
214    
215    
216     /**
217     * This function renders the confirmation
218     * page. This page sits in between the
219     * front end form, and the action handler.
220     * This only gets called after a form
221     * and its data has been successfully
222     * validated.
223     *
224     * @param int - $indent_level
225     * @param int - $output_debug
226     *
227     * @return string - the raw html
228     */
229     function render_confirm( $indent_level, $output_debug ) {
230 jonen 1.2 debug("BUILD CONFIRM");
231 jonen 1.1 //build the $this->_form object.
232     $this->_build_form_tag();
233    
234     //add the confirm object/html
235     for($i=0; $i<=$this->_vars["num_steps"]-1; $i++) {
236     $title = "Step ".($i+1)." : ".$this->_steps[$i]["title"];
237     $this->_form->add( $this->_steps[$i]["form"]->form_confirm($title, FALSE),
238     html_br(2));
239     }
240     //$confirm = &$this->_form_content->form_confirm( $this->data );
241     //$this->_form->add_reference( $confirm );
242    
243     //ok add all of the submitted data as hidden form fields
244     $this->_add_confirm_data();
245    
246     //Ok lets add our hidden vars
247     $this->__hidden_fields();
248    
249     return $this->_form->render($indent_level, $output_debug);
250     }
251    
252     /**
253     * A subclass can override this function
254     * to setup the class variables after
255     * the constructor. The constructor
256     * automatically calls this function.
257     *
258     */
259     function user_setup() {
260     trigger_error("FormWizard::user_setup() - ".
261     "child class must override this method ".
262     "to add the wizard steps");
263     }
264    
265    
266     /**
267     * This adds a step to the wizard
268     *
269     * @param string - the title for the step
270     * @param string - the description for the step
271     * @param string - the help url for the step (if any)
272     * @param FormContent - the form content object
273     * that is the step.
274     */
275     function add_step( $title, $desc, $help, &$step ) {
276     $this->_steps[] = array("title" => $title,
277     "desc" => $desc,
278     "help" => $help,
279     "form" => &$step);
280     $this->_vars["num_steps"]++;
281     }
282    
283    
284     /**
285     * This function initializes all of the fields we
286     * need to keep track of for the internal state
287     * of the wizard. It also walks each of the
288     * step FormContent objects and initializes them.
289     *
290     * We save some of the state of the wizard in
291     * the session.
292     */
293     function _init() {
294     if (!isset($_REQUEST[WIZARD_VISITED])) {
295    
296     $this->_vars[WIZARD_ID] = uniqid("wizard_");
297 jonen 1.2 //debug( $this->_vars );
298 jonen 1.1
299     $this->_init_session();
300     $this->_vars["to_step"] = 2;
301     } else {
302     $this->_vars[WIZARD_ID] = $_REQUEST[WIZARD_ID];
303     $current_step = $this->_current_step();
304     $this->_vars["to_step"] = $current_step++;
305    
306     //if ($this->_vars["current_step"] == count($this->_steps)) {
307     // $this->_vars["to_step"] = WIZARD_FINAL;
308     //} else {
309     // $this->_vars["to_step"] = WIZARD_NEXT;
310     //}
311     }
312 jonen 1.2 //debug( $_SESSION );
313 jonen 1.1
314     //initialize all of the Forms
315     //so they retain their data.
316     for ($i=0; $i<=$this->_vars["num_steps"]-1; $i++) {
317     $this->_steps[$i]["form"]->form_init_elements();
318     }
319    
320     }
321    
322     /**
323     * This function sets the _form_content
324     * object for the current step we are operating on.
325     * The parent FormProcessor needs this object set
326     * in order to process the step correctly.
327     *
328     */
329     function _set_step() {
330     $this->_form_content = &$this->_steps[$this->_current_step()-1]["form"];
331     }
332    
333     function __hidden_fields() {
334    
335     //add all of the other steps fields
336     //we need to add all the previous visted steps
337     //fields so we save em.
338     $step_count = 1;
339     foreach( $this->_steps as $step ) {
340     if ($step_count != $this->_current_step()) {
341     $this->_form_content = &$step["form"];
342     $this->_add_confirm_data();
343     }
344     $step_count++;
345     }
346    
347     if (isset($_REQUEST[WIZARD_ACTION]) &&
348     $_REQUEST[WIZARD_ACTION] == WIZARD_FINAL) {
349     $this->_set_step();
350     }
351    
352     parent::__hidden_fields();
353    
354     //$this->_form->add( form_hidden(WIZARD_STEP, $this->_vars["current_step"]) );
355     $this->_form->add( form_hidden(WIZARD_TO_STEP, $this->_vars["to_step"]) );
356     $this->_form->add( form_hidden(WIZARD_ID, $this->_vars[WIZARD_ID]) );
357     $this->_form->add( form_hidden(WIZARD_ACTION, WIZARD_NEXT) );
358     $this->_form->add( form_hidden(WIZARD_VISITED, 1) );
359     }
360    
361    
362     /**
363     * This builds the javascript needed for the
364     * navigation of the wizard
365     *
366     * @return string
367     */
368     function _build_js() {
369     $name = $this->_form_attributes["name"];
370     $js = "
371     function wizard_cancel_confirm(butname, txt) {
372     if (confirm(txt)){
373     document.$name.".WIZARD_ACTION.".value = butname;
374     document.$name.submit();
375     }
376     }
377     function wizard_submit(txt) {
378     document.$name.".WIZARD_ACTION.".value = txt;
379     document.$name.submit();
380     }
381     function wizard_submit2(txt, step) {
382     document.$name.".WIZARD_ACTION.".value = txt;
383     document.$name.".WIZARD_TO_STEP.".value = step;
384     document.$name.submit();
385     }";
386    
387     $script = html_script();
388     $script->add( $js );
389     return $script;
390     }
391    
392    
393    
394     /**
395     * This renders the toolbar/step table
396     * for the navigation of the wizard
397     */
398     function _build_toolbar() {
399     $current_step = $this->_current_step();
400 jonen 1.2 xxx("current step ".$current_step);
401 jonen 1.1 if ($this->_vars["on_confirm"]) {
402     $current_step++;
403     $step_title = "Confirmation";
404     } else {
405     $step_title = $this->_steps[$current_step - 1]["title"];
406     }
407    
408     $title = "Step ".$current_step." : ". $step_title;
409     $table = new InfoTable($title, 500);
410    
411     //build the table of steps.
412     $c = container();
413     $step_num = 1;
414     foreach( $this->_steps as $step ) {
415     $c->add( $this->_build_step_image( $step_num, $step["title"] ) );
416    
417     if ($step_num != $this->_vars["num_steps"]) {
418     $arrow = html_img("/phphtmllib/images/wizard/arrow.png");
419     $arrow->set_style("vertical-align:super");
420     $c->add( $arrow );
421     }
422    
423     $step_num++;
424     }
425    
426     //add the confirmation step
427 jonen 1.2 xxx($step_num);
428 jonen 1.1 $c->add( $arrow );
429     $c->add( $this->_build_step_image( $step_num, "Confirmation" ) );
430    
431    
432     $tr = html_tr("", $c );
433     $tr->set_style("text-align: center");
434     $table->add_row( $tr );
435    
436     //now show the description
437     if ($this->_vars["on_confirm"] == true) {
438     $desc = "Confirmation";
439     } else {
440     $desc = $this->_steps[$current_step - 1]["desc"];
441     }
442     $tr = html_tr("", $desc );
443     $tr->set_style("text-align: center");
444     $table->add_row( $tr );
445    
446     //now add the controls
447     $c = html_div();
448     $c->set_style("padding-top: 5px;");
449    
450     if ($current_step != 1) {
451     $link = html_a("javascript:wizard_submit2('".WIZARD_PREV."',".($current_step-1).");",
452     html_img("/phphtmllib/images/wizard/previous_step.png"));
453     $c->add( $link );
454     }
455 jonen 1.2
456     if ($current_step == $this->_vars["num_steps"]+1) {
457     $link = html_a("javascript:wizard_submit2('".WIZARD_FINAL."',".($current_step).");",
458     html_img("/phphtmllib/images/wizard/finish_steps.png") );
459 jonen 1.1
460 jonen 1.2 $c->add( _HTML_SPACE, _HTML_SPACE, $link);
461     } else {
462 jonen 1.1 $link = html_a("javascript:wizard_submit2('".WIZARD_NEXT."',".($current_step+1).");",
463     html_img("/phphtmllib/images/wizard/next_step.png") );
464     $c->add( $link );
465     }
466    
467    
468     $tr = html_tr("", $c );
469     $tr->set_style("text-align: center;");
470     $table->add_row( $tr );
471    
472     return $table;
473     }
474    
475    
476     /**
477     * This function builds an image for a step #
478     *
479     * @param string - the step # to build
480     * @return Atag object
481     */
482     function &_build_step_image( $step_num, $step_title ) {
483     $title = "Step ".$step_num." ";
484    
485     $current_step = $this->_current_step();
486 jonen 1.2 //if ($this->_vars["on_confirm"]) {
487     //$current_step++;
488     //}
489 jonen 1.1
490     if ($step_num == $current_step) {
491     $title .= " (Current) : ".$step_title;
492     $img = html_img("/phphtmllib/images/wizard/".$step_num."_red.png", 30, 30, 0,
493     $title, NULL, $title);
494    
495 jonen 1.2 } else if ($this->_is_step_visited($step_num) ||
496     $current_step == $this->_vars["num_steps"]+1) {
497 jonen 1.1 $title .= " (Completed) : ".$step_title;
498     $img = html_img("/phphtmllib/images/wizard/".$step_num."_black.png", 30, 30 ,0,
499     $title, NULL, $title);
500    
501     } else {
502     $title .= " (Not Completed) : ".$step_title;
503     $img = html_img("/phphtmllib/images/wizard/".$step_num."_gray.png", 30,30,0,
504     $title, NULL, $title);
505     }
506    
507     return $img;
508     }
509    
510    
511    
512     /*****************************************/
513     /* SESSION RELATED METHODS */
514     /*****************************************/
515    
516     /**
517     * This method initializes the session
518     * variable that we use
519     *
520     */
521     function _init_session() {
522     //create a unique id for this wizard
523     //so we can have multple wizards
524     //running per session.
525     $_SESSION[$this->_vars[WIZARD_ID]] = array();
526     $_SESSION[$this->_vars[WIZARD_ID]];
527     $this->_set_current_step(1);
528    
529     //mark all steps as NOT visited
530     for ($i=0; $i<=$this->_vars["num_steps"]-1; $i++) {
531     $this->_step_visited($i, FALSE);
532     }
533     }
534    
535     /**
536     * This returns the current step id
537     * from the session
538     *
539     */
540     function _current_step() {
541     return $_SESSION[$this->_vars[WIZARD_ID]]["current_step"];
542     }
543    
544     /**
545     * This sets the current step id
546     *
547     * @param int - the new step #
548     */
549     function _set_current_step($step) {
550 jonen 1.2 debug( "SET STEP ".$step);
551 jonen 1.1 $_SESSION[$this->_vars[WIZARD_ID]]["current_step"] = $step;
552     }
553    
554    
555     /**
556     * This sets the state variable for the
557     * step to let us know it has been visited or not
558     *
559     * @param int - the step to mark
560     * @param boolean - TRUE = visited
561     */
562     function _step_visited($step_num, $visited=TRUE) {
563     $_SESSION[$this->_vars[WIZARD_ID]]["visited_steps"][$step_num] = $visited;
564     }
565    
566     /**
567     * This tests to see if the step has been visited or not.
568     *
569     * @param int - the step to mark
570     * @return boolean - TRUE = visited
571     */
572     function _is_step_visited($step_num) {
573     if (isset($_SESSION[$this->_vars[WIZARD_ID]]["visited_steps"][$step_num])) {
574     return $_SESSION[$this->_vars[WIZARD_ID]]["visited_steps"][$step_num];
575     } else {
576     return FALSE;
577     }
578     }
579    
580     /**
581     * This function cleans up the saved Session state
582     * for the wizard. This gets called when we have
583     * completed the wizard w/o errors.
584     *
585     */
586     function _clean() {
587     unset($_SESSION[$this->_vars[WIZARD_ID]]);
588     }
589    
590     /**
591     * This ensures that we have sessions started
592     *
593     */
594     function _session_test() {
595     if (!session_id()) {
596     //we have to have sessions started.
597     session_start();
598     }
599     }
600     }
601     ?>

MailToCvsAdmin">MailToCvsAdmin
ViewVC Help
Powered by ViewVC 1.1.26 RSS 2.0 feed