/[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.3 - (hide annotations)
Thu Aug 11 14:09:26 2005 UTC (19 years ago) by jonen
Branch: MAIN
CVS Tags: HEAD
Changes since 1.2: +41 -29 lines
+ updated to version 2.5.3

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

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