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

1 <?php
2 /**
3 * This file contains the FormWizard class.
4 *
5 * $Id: FormWizard.inc,v 1.5.2.1 2005/05/12 01:24:02 hemna Exp $
6 *
7 * @author Walter A. Boring IV <waboring@newsblob.com>
8 * @package phpHtmlLib
9 * @subpackage FormProcessing
10 *
11 * @copyright LGPL - See LICENCE
12 * @todo Finish this. It doesn't work now.
13 *
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
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 class FormWizard extends FormProcessor {
39
40 /**
41 * This holds the array of
42 * step objects for the
43 * 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 //user_error(__CLASS__."::".__FUNCTION__." - this class isn't done yet.");
63 $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 * This function renders the
90 * 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 debug( "have we visited?" ,null,4);
109 //debug( $_REQUEST );
110 if (isset($_REQUEST[FORM_VISITED]) && $_REQUEST[FORM_VISITED] == 1) {
111 //looks like the form has been processed?
112 debug( "confirmed = ".$this->_confirmed );
113 debug( "curr step = ".$this->_current_step() );
114 if (!$this->_confirmed && $this->_vars["on_confirm"]) {
115 debug("FINAL DUDE!");
116 $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 debug("DO ACTION!");
121 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 debug("PROCESS STEP ".$this->_current_step());
161 $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 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 }
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 $current_step = $this->_current_step();
191 debug( "CURRENT STEP ".$current_step);
192
193 switch ($_REQUEST[WIZARD_ACTION]) {
194 case WIZARD_NEXT:
195 debug("NEXT");
196 if ($current_step == $this->_vars["num_steps"]) {
197 debug("SHOW CONFIRMATION");
198 //we need to show the confirmation
199 //don't process
200 $this->_vars["on_confirm"] = TRUE;
201 $this->_step_visited( $current_step );
202 $this->_set_current_step($current_step+1);
203 } else {
204 $this->_step_visited( $current_step );
205 $this->_set_current_step($current_step+1);
206 unset($_REQUEST[FORM_VISITED]);
207 $this->_form_content = &$this->_steps[$this->_current_step()-1]["form"];
208 //$this->_process_form();
209 }
210 break;
211
212 case WIZARD_PREV:
213 debug("PREV");
214 $this->_set_current_step($current_step-1);
215 unset($_REQUEST[FORM_VISITED]);
216 $this->_form_content = &$this->_steps[$this->_current_step()-1]["form"];
217 //$this->_process_form();
218 break;
219 }
220 }
221 }
222 }
223 }
224 debug("bail");
225 }
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 debug("BUILD CONFIRM");
243 //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 * This function initializes all of the fields we
298 * 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 *
302 * We save some of the state of the wizard in
303 * the session.
304 */
305 function _init() {
306 if (!isset($_REQUEST[WIZARD_VISITED])) {
307
308 $this->_vars[WIZARD_ID] = uniqid("wizard_");
309 //debug( $this->_vars );
310
311 $this->_init_session();
312 $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 //}
323 }
324 //debug( $_SESSION );
325
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 * The parent FormProcessor needs this object set
338 * 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 xxx("current step ".$current_step);
413 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
429 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
435 $step_num++;
436 }
437
438 //add the confirmation step
439 xxx($step_num);
440 $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 $link = html_a("javascript:wizard_submit2('".WIZARD_PREV."',".($current_step-1).");",
464 html_img("/phphtmllib/images/wizard/previous_step.png"));
465 $c->add( $link );
466 }
467
468 if ($current_step == $this->_vars["num_steps"]+1) {
469 $link = html_a("javascript:wizard_submit2('".WIZARD_FINAL."',".($current_step).");",
470 html_img("/phphtmllib/images/wizard/finish_steps.png") );
471
472 $c->add( _HTML_SPACE, _HTML_SPACE, $link);
473 } else {
474 $link = html_a("javascript:wizard_submit2('".WIZARD_NEXT."',".($current_step+1).");",
475 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 //if ($this->_vars["on_confirm"]) {
499 //$current_step++;
500 //}
501
502 if ($step_num == $current_step) {
503 $title .= " (Current) : ".$step_title;
504 $img = html_img("/phphtmllib/images/wizard/".$step_num."_red.png", 30, 30, 0,
505 $title, NULL, $title);
506
507 } else if ($this->_is_step_visited($step_num) ||
508 $current_step == $this->_vars["num_steps"]+1) {
509 $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
519 return $img;
520 }
521
522
523
524 /*****************************************/
525 /* SESSION RELATED METHODS */
526 /*****************************************/
527
528 /**
529 * This method initializes the session
530 * variable that we use
531 *
532 */
533 function _init_session() {
534 //create a unique id for this wizard
535 //so we can have multple wizards
536 //running per session.
537 $_SESSION[$this->_vars[WIZARD_ID]] = array();
538 $_SESSION[$this->_vars[WIZARD_ID]];
539 $this->_set_current_step(1);
540
541 //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 debug( "SET STEP ".$step);
563 $_SESSION[$this->_vars[WIZARD_ID]]["current_step"] = $step;
564 }
565
566
567 /**
568 * This sets the state variable for the
569 * 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 }
590 }
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 *
605 */
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