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

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

Parent Directory Parent Directory | Revision Log Revision Log


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

1 <?php
2 /**
3 * This file contains the FormWizard class.
4 *
5 * $Id: FormWizard.inc,v 1.4 2003/08/19 00:48:57 hemna Exp $
6 *
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 //user_error(__CLASS__."::".__FUNCTION__." - this class isn't done yet.");
51 $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 debug( "have we visited?" ,null,4);
97 //debug( $_REQUEST );
98 if (isset($_REQUEST[FORM_VISITED]) && $_REQUEST[FORM_VISITED] == 1) {
99 //looks like the form has been processed?
100 debug( "confirmed = ".$this->_confirmed );
101 debug( "curr step = ".$this->_current_step() );
102 if (!$this->_confirmed && $this->_vars["on_confirm"]) {
103 debug("FINAL DUDE!");
104 $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 debug("DO ACTION!");
109 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 debug("PROCESS STEP ".$this->_current_step());
149 $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 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 }
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 $current_step = $this->_current_step();
179 debug( "CURRENT STEP ".$current_step);
180
181 switch ($_REQUEST[WIZARD_ACTION]) {
182 case WIZARD_NEXT:
183 debug("NEXT");
184 if ($current_step == $this->_vars["num_steps"]) {
185 debug("SHOW CONFIRMATION");
186 //we need to show the confirmation
187 //don't process
188 $this->_vars["on_confirm"] = TRUE;
189 $this->_step_visited( $current_step );
190 $this->_set_current_step($current_step+1);
191 } else {
192 $this->_step_visited( $current_step );
193 $this->_set_current_step($current_step+1);
194 unset($_REQUEST[FORM_VISITED]);
195 $this->_form_content = &$this->_steps[$this->_current_step()-1]["form"];
196 //$this->_process_form();
197 }
198 break;
199
200 case WIZARD_PREV:
201 debug("PREV");
202 $this->_set_current_step($current_step-1);
203 unset($_REQUEST[FORM_VISITED]);
204 $this->_form_content = &$this->_steps[$this->_current_step()-1]["form"];
205 //$this->_process_form();
206 break;
207 }
208 }
209 }
210 }
211 }
212 debug("bail");
213 }
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 debug("BUILD CONFIRM");
231 //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 //debug( $this->_vars );
298
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 //debug( $_SESSION );
313
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 xxx("current step ".$current_step);
401 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 xxx($step_num);
428 $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
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
460 $c->add( _HTML_SPACE, _HTML_SPACE, $link);
461 } else {
462 $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 //if ($this->_vars["on_confirm"]) {
487 //$current_step++;
488 //}
489
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 } else if ($this->_is_step_visited($step_num) ||
496 $current_step == $this->_vars["num_steps"]+1) {
497 $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 debug( "SET STEP ".$step);
551 $_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