/[cvs]/nfo/php/libs/com.newsblob.phphtmllib/widgets/data_list/DataList.inc
ViewVC logotype

Contents of /nfo/php/libs/com.newsblob.phphtmllib/widgets/data_list/DataList.inc

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.6 - (show annotations)
Sun Feb 23 23:39:44 2003 UTC (21 years, 6 months ago) by jonen
Branch: MAIN
Changes since 1.5: +7 -15 lines
+ repatched previous updated to v2.2.1
+ removed still duplicated functions

1 <?php
2 /**
3 * This is the base class for managing a list
4 * of data points.
5 *
6 * @author Walter A. Boring IV <waboring@buildabetterweb.com>
7 * @package phpHtmlLib
8 */
9
10 /**
11 * Some global defines used
12 */
13 define("SORTABLE", TRUE);
14 define("NOT_SORTABLE", FALSE);
15 define("SEARCHABLE", TRUE);
16 define("NOT_SEARCHABLE", FALSE);
17
18 //Some defines for setting up the search
19 //modifier fields.
20 define("SEARCH_BEGINS_WITH", 1);
21 define("SEARCH_CONTAINS", 2);
22 define("SEARCH_EXACT", 4);
23 define("SEARCH_ENDS_WITH", 8);
24 define("SEARCH_ALL", 15);
25
26
27 /**
28 * This object is the base class that can be
29 * used to build a widget that shows lists of
30 * data from any source via the DataListSource
31 * object. It fetches/builds/gets its data
32 * from the DataListSource object, which can
33 * be written to support any data source
34 * (MySQL, Oracle, comma delimited file, xml, etc.)
35 *
36 * This base class MUST be extended by a child to
37 * actually render the list. The job of the DataList
38 * class is to provide the basic API and abstraction
39 * mechanism to handling searching, showing, sorting
40 * lists of data.
41 *
42 * Each column of data is associated with a title and a
43 * name. The title is what is shown to the user for that
44 * column. The name is the mapping between the column and
45 * the DataListSource. Each column can be marked
46 * as sortable and searchable. If a column is sortable,
47 * the title is a link that can be clicked on to sort.
48 * The sorting is done in the DataListSource object (
49 * via the sql query, or sort() functions depending on the
50 * data source itself)
51 *
52 * The DataList object will build the title, the search block
53 * (if any), the datalist controls (the links/imges for
54 * first, prev, next, last, all). Then the data columns/labels.
55 * Then it will fetch each of the rows of data to display
56 * from the DataListSource.
57 *
58 * The logic of the output calls follows in the order:
59 *
60 * title
61 * search table/block
62 * datalist controls (first, prev, next, last, all)
63 * data columns/labels
64 * data rows x through y
65 *
66 *
67 * REQUIREMENTS:
68 * You must use/define a DataListSource object.
69 * You MUST override/extend the following methods:
70 *
71 * * get_data_source() - used to set the DataListSource
72 * by this class.
73 * * user_setup() - used to set the columns to show and any
74 * options used by the DataList class and
75 * DataListSource object.
76 *
77 *
78 * UI ABSTRACTION METHODS
79 * These methods allow for some level of abstraction for
80 * the layout/look/feel of the actual list of data.
81 *
82 *
83 * * gui_init() - the function gives the child class a chance
84 * to do any building of the objects that will
85 * hold the search area, column headers and the
86 * rows of data.
87 *
88 * * child_build_column_header() - This method is responsible
89 * for building and inserting
90 * the column header title into
91 * the UI object.
92 *
93 * * child_add_row_cell() - This function is responsible for adding
94 * the cell in the current row. The method
95 * is responsible for keeping track of the
96 * location in its UI object for the current
97 * row.
98 *
99 * * child_get_gui() - This method returns the entire UI in 1 object
100 * or container. At this point the entire UI
101 * has been constructed, the entire list of data
102 * has been walked and inserted.
103 *
104 *
105 * @author Walter A. Boring IV <waboring@buildabetterweb.com>
106 * @package phpHtmlLib
107 */
108 class DataList extends BaseWidget {
109
110 /**
111 * This value holds the number
112 * of pages of data we have
113 * to display.
114 *
115 */
116 var $_num_pages=1;
117
118 /**
119 * The number of rows of data
120 * to show per "page".
121 * The default is 20.
122 *
123 */
124 var $_default_rows_per_page = 10;
125
126 /**
127 * The max number of rows to
128 * show when the user does the
129 * "EXPAND" command.
130 */
131 var $_max_rows = 200;
132
133
134 /**
135 * Do we want to alternate the row colors?
136 * This helps to see each row easier.
137 */
138 var $alternating_row_colors = TRUE;
139
140 /**
141 * prefix for all list variable
142 * names, so we can potentially
143 * have more then 1 list per page.
144 */
145 var $_global_prefix = '';
146
147
148 /**
149 * Holds an array of all the
150 * form vars we need for this
151 * class to work.
152 */
153 var $_vars = array("offsetVar" => "offset",
154 "orderbyVar" => "orderby",
155 "reverseorderVar" => "reverseorder",
156 "numrowsVar" => "numrows",
157 "showallVar" => "showall",
158 "search_fieldVar" => "search_field",
159 "search_valueVar" => "search_value",
160 "search_typeVar" => "search_type",
161 "simple_search_modifierVar" => "simple_search_modifier");
162
163 /**
164 * Holds the db column name that
165 * we want to order by default.
166 */
167 var $_default_orderby = '';
168
169 /**
170 * Holds a flag to let us know to
171 * reverse order the column by default
172 */
173 var $_default_reverseorder = "false";
174
175 /**
176 * Flag to let us know that search
177 * is enabled.
178 *
179 */
180 var $_search_flag = FALSE;
181
182 /**
183 * Flag to let us know that
184 * advanced search is enabled
185 *
186 */
187 var $_advanced_search_flag = FALSE;
188
189 /**
190 * Flag to enable simple search modifyer.
191 * IF enabled it will add a select that adds
192 * the "beings with", "contains" options for
193 * a simple search.
194 */
195 var $_simple_search_modifier = FALSE;
196
197
198 /**
199 * Holds the object block that is the
200 * search UI
201 */
202 var $_search_table = NULL;
203
204 /**
205 * This holds a list of
206 * name=>value vars that the
207 * caller/child wants to propogate
208 * automatically.
209 *
210 */
211 var $_save_vars = array();
212
213
214 /**
215 * The column descriptions
216 * for the data we are working on
217 *
218 * @var array
219 */
220 var $_columns = array();
221
222 /**
223 * Keeps track of the # of columns we have
224 */
225 var $_num_columns = 0;
226
227
228 /**
229 * This holds the form attributes
230 *
231 */
232 var $_form_attributes = array("method" => "GET",
233 "target" => "",
234 "action" => "",
235 "name" => "");
236
237 /**
238 * Build everything inside a form?
239 *
240 */
241 var $_form_render_flag = FALSE;
242
243
244 /**
245 * flag to let us know if we want to show
246 * the results or not.
247 */
248 var $_show_results_flag = TRUE;
249
250
251 /**
252 * Holds our reference/copy of the
253 * DataListSource object which is used to
254 * access the data that this object uses
255 *
256 * @var DataListSource object
257 */
258 var $_datasource = NULL;
259
260 /**
261 * This stores the base path to where the
262 * tool link images live. This lets you
263 * specify a new path to where your images
264 * live.
265 */
266 var $_image_path = "/phphtmllib/images/widgets";
267
268
269 /**
270 * The constructor
271 *
272 * @param string - the title of the data list
273 * @param string - the overall width
274 * @param string - the column to use as the default sorting order
275 * @param boolean - sort the default column in reverse order?
276 */
277 function DataList($title, $width = "100%", $default_orderby='',
278 $default_reverseorder=FALSE) {
279 $this->set_title( $title );
280 $this->set_form_name( str_replace(' ', '_', strtolower($title)) );
281 $this->set_width( $width );
282
283
284 $this->_default_orderby = $default_orderby;
285 if ( $default_reverseorder === TRUE ) {
286 $default_reverseorder = "true";
287 }if ( $default_reverse_order === FALSE ) {
288 $default_reverseorder = "false";
289 }
290 $this->_default_reverseorder = $default_reverseorder;
291
292
293 //Set the global prefix for our variables.
294 //want to make sure we can have multiple
295 //item lists per html page.
296 $this->set_global_prefix('');
297
298 //child class MUST override this
299 //method to automatically set
300 //the DataListSource object.
301 //This class doesn't work without it.
302 $this->get_data_source();
303
304 //Call the subclass setup function.
305 //This is a way to get around having
306 //to override the constructor and
307 //pass in the same params.
308 $this->user_setup();
309 }
310
311 /**
312 * This function renders the final
313 * widget
314 *
315 */
316 function render($indent_level, $output_debug) {
317
318 //setup the columns in their sorts
319 $this->setup_columns();
320
321 //do any data prefetch work
322 //which may be child specific
323 if ( $this->_show_results() ) {
324 $this->data_prefetch();
325 }
326
327 //This function gives the child class
328 //a chance to build the tables/divs/containers
329 //that will be responsible for the look/feel
330 //of the DataList
331 $this->gui_init();
332
333 //see if we need to build the search area.
334 if ( $this->is_search_enabled() || $this->is_advanced_search_enabled() ) {
335 $this->_search_table = $this->child_build_search_table();
336 if ( $this->_search_table ) {
337 $this->set_form_render(TRUE);
338 }
339 }
340
341
342 if ( $this->get_form_render() ) {
343 $form = new FORMtag( array("method" => $this->get_form_method(),
344 "action" => $this->build_base_url(),
345 "name" => $this->get_form_name(),
346 "style" => "margin-top: 0px;margin-bottom:0px;") );
347
348 $target = $this->get_form_target();
349 if ( $target != NULL )
350 $form->set_tag_attribute("target",$target);
351
352 $action = $this->get_form_action();
353 if ( $action != NULL )
354 $form->set_tag_attribute("action",$action);
355
356 //now build the UI and return it
357 $form->add( $this->build_gui() );
358
359 } else {
360 $form = container();
361
362 //now build the UI and return it
363 $form->add( $this->build_gui() );
364 }
365
366 //add the hidden vars if we are a POST
367 if ($this->get_form_method() == "POST") {
368 $form->add( $this->_build_default_vars() );
369 }
370
371 //add the save vars the user wants.
372 $form->add( $this->_build_save_vars() );
373
374 //add any javascript required
375 $container = container( $this->_javascript(), $form );
376 return $container->render( $indent_level, $output_debug );
377 }
378
379 /**
380 * This function is responsible for calling the child
381 * class's methods for building the GUI container.
382 * This function builds the search area, the
383 * title, page controls, the column headers,
384 * and walks the rows of data and adds them
385 *
386 * A child class can override this method to
387 * move the placement of the search box
388 * relative to the data list. By default
389 * the search area comes above the table
390 * for the data list and page controls
391 *
392 * @return Container
393 */
394 function build_gui() {
395 $container = container();
396
397 //if we have a search area to show
398 //add it to the ui.
399 if ( $this->_search_table ) {
400 $container->add( $this->_search_table );
401 }
402
403 if ( $this->_show_results() ) {
404 //walk the list of columns and call the child
405 //method to add it
406 $column_count = count($this->_columns);
407 foreach( $this->_columns as $name => $col ) {
408 $this->child_build_column_header( $name, $col, $column_count);
409 }
410
411 //now walk the list of rows and build and add the
412 //cells of data
413 $col_count = count($this->_columns);
414 while ( $row = $this->_datasource->get_next_data_row() ) {
415 $cnt = 1;
416 foreach( $this->_columns as $col_name => $data ) {
417 $obj = $this->build_column_item($row, $col_name);
418 if ( !is_object($obj) ) {
419 $obj = $this->_clean_string($obj, $col_name);
420 }
421 //
422 $this->child_add_row_cell($obj, $col_name,
423 (($cnt == $col_count) ? TRUE : FALSE),
424 $row);
425 $cnt++;
426 }
427 }
428 $container->add( $this->child_get_gui() );
429 }
430
431
432 return $container;
433 }
434
435 /**
436 * This function is called automatically by
437 * the DataList constructor. It must be
438 * extended by the child class to actually
439 * set the DataListSource object.
440 *
441 *
442 */
443 function get_data_source() {
444 user_error("DataList::get_data_source() - ".
445 "child class must override this to ".
446 "set the the DataListSource object.");
447 }
448
449 /**
450 * A subclass can override this function
451 * to setup the class variables after
452 * the constructor. The constructor
453 * automatically calls this function.
454 *
455 */
456 function user_setup() {
457 user_error("DataList::user_setup() - ".
458 "child class must override this method ".
459 "to set the columns, and any options for ".
460 "the DataListSource.");
461 }
462
463 /**
464 * A subclass can override this function
465 * to setup the class variables after
466 * the constructor. The constructor
467 * automatically calls this function.
468 *
469 */
470 function gui_init() {
471 user_error("DataList::gui_init() - ".
472 "child class must override this method ".
473 "to set up the containers/objects that will ".
474 "hold the search area, page controls, ".
475 "column headers and the data cells");
476 }
477
478 /**
479 * This method is supposed to be written by
480 * the child class to build and add the column
481 * title to the UI
482 *
483 * @param string - the title of the column
484 * @param array - the column data ( from $this->_columns )
485 * @param int - the column #
486 *
487 */
488 function child_build_column_header($title, $col_data, $col_count) {
489 user_error("DataList::child_build_column_header() - ".
490 "child class must override this method ".
491 "to build the object that will be the ".
492 "individual column header/itle");
493 }
494
495 /**
496 * This method is supposed to be written by
497 * the child class to add the cell data to the
498 * current row in the UI
499 *
500 * @param mixed - the object/string/entity that
501 * should get put into the column row cell.
502 * @param string - the name/title of the column that the
503 * object will live in
504 * @param boolean - flag that tells the function if this is
505 * is the last cell for the current row.
506 *
507 */
508 function child_add_row_cell($obj, $col_name, $last_in_row_flag) {
509 user_error("DataList::child_add_row_cell() - ".
510 "child class must override this method ".
511 "to build the object that will be the ".
512 "individual column data cell");
513 }
514
515 /**
516 * This function is called after all of the data has
517 * been added to the UI object. It just returns the
518 * container that is the entire UI for the DataList
519 *
520 * @return Container
521 */
522 function child_get_gui() {
523 user_error("DataList::child_get_gui() - ".
524 "child class must override this method ".
525 "to return the wrapper that contains ".
526 "the entire UI.");
527 }
528
529 /**
530 * This function builds the search
531 * block that lives above the results
532 *
533 * @return Container
534 */
535 function child_build_search_table() {
536 user_error("DataList::child_build_search_table() - ".
537 "child class must override this");
538 return NULL;
539 }
540
541 /**
542 * This function provides a way to automatically
543 * add javascript to this object.
544 * This function is meant to be extended by the
545 * child class.
546 *
547 * @return SCRIPTtag object
548 */
549 function _javascript() {
550 return NULL;
551 }
552
553 /**
554 * This function adds a header item to the column headers
555 * from a list of parameters.
556 *
557 * @param string - $label - the label to use for
558 * the column header.
559 * @param int - $size - the size for the table column.
560 * @param string - $dbfield - the db field associated
561 * with this label from the query.
562 * @param boolean - $sortable - flag to make this column sortable.
563 * @param boolean - $searchable - flag to make this column searchable.
564 * @param string - header align value.
565 * @param string - the maximum # of characters to allow in the cell.
566 *
567 * @return array a single header array
568 */
569 function add_header_item( $label, $size=100, $data_name=NULL,
570 $sortable=FALSE, $searchable=FALSE,
571 $align="left", $sortorder="",
572 $max_text_length=NULL) {
573
574 $this->_columns[$label] = array("size" => $size,
575 "data_name" => $data_name,
576 "sortable" => $sortable,
577 "searchable" => $searchable,
578 "align" => $align,
579 "sortorder" => $sortorder,
580 "maxtextlength" => $max_text_length);
581 $this->_num_headers++;
582
583 $this->_check_datasource("add_header_item");
584 $this->_datasource->add_column($label, $data_name, $sortable,
585 $searchable, $sortorder);
586 }
587
588
589 /**
590 * This function sets a prefix for all
591 * variables that are used in the item list
592 * table on a page. This allows you to have
593 * multiple itemlists on a single html page.
594 *
595 * @param string $prefix - the prefix for all vars.
596 */
597 function set_global_prefix($prefix) {
598 $this->_global_prefix = $prefix;
599 //update all the vars used
600 foreach ($this->_vars as $name => $value ) {
601 $this->_vars[$name] = $prefix.$value;
602 }
603 }
604
605 /**
606 * returns the current variable prefix
607 * string being used.
608 *
609 * @return string - current global prefix
610 */
611 function get_global_prefix() {
612 return $this->_global_prefix;
613 }
614
615 /**
616 * This function is used to set the
617 * DataListSource object for this instance
618 *
619 * @param DataListSource object
620 */
621 function set_data_source( $datasource ) {
622 $this->_datasource = &$datasource;
623 }
624
625 /**
626 * Enable the search ability.
627 *
628 * @param boolean
629 */
630 function search_enable( ) {
631 $this->_search_flag = TRUE;
632 if ( !$this->is_advanced_search_enabled() ) {
633 $this->set_search_type("simple");
634 }
635 }
636
637 /**
638 * Disable the search ability.
639 *
640 * @param boolean
641 */
642 function search_disable( ) {
643 $this->_search_flag = FALSE;
644 }
645
646 /**
647 * get the status of the search
648 * ability.
649 *
650 * @return boolean
651 */
652 function is_search_enabled() {
653 return $this->_search_flag;
654 }
655
656
657 /**
658 * Enable the advanced search
659 * capability
660 * NOTE: Child class MUST
661 * extend the
662 * _build_advanced_search_table
663 */
664 function advanced_search_enable() {
665 $this->_advanced_search_flag = TRUE;
666 if ( !$this->is_search_enabled() ) {
667 $this->set_search_type("advanced");
668 }
669 }
670
671 /**
672 * Disable the advanced search
673 * capability
674 *
675 */
676 function advanced_search_disable() {
677 $this->_advanced_search_flag = FALSE;
678 }
679
680 /**
681 * This returns the status of the
682 * advanced search flag.
683 *
684 * @return boolean
685 */
686 function is_advanced_search_enabled() {
687 return $this->_advanced_search_flag;
688 }
689
690 /**
691 * Set the simple search modifyer
692 * flag.
693 * NOTE: by default all the modifiers
694 * are enabled. You can limit the
695 * modifiers by passing in the
696 * string of defines of which ones
697 * you want enabled.
698 *
699 * MODIFIERS:
700 * SEARCH_BEGINS_WITH
701 * SEARCH_CONTAINS
702 * SEARCH_EXACT
703 * SEARCH_ENDS_WITH
704 *
705 * ie. SEARCH_BEGINS_WITH.SEARCH_EXACT
706 * will enable ONLY the
707 * "begins with" and "exact" modifiers.
708 *
709 * @param string
710 */
711 function set_simple_search_modifier( $modifier = SEARCH_ALL ) {
712 if ( $modifier == 0 ) {
713 $this->_simple_search_modifier = SEARCH_BEGINS_WITH |
714 SEARCH_CONTAINS |
715 SEARCH_EXACT |
716 SEARCH_ENDS_WITH;
717 } else {
718 $this->_simple_search_modifier = $modifier;
719 }
720 }
721
722 /**
723 * gets the value of the search modifier
724 * flag.
725 */
726 function get_simple_search_modifier() {
727 return $this->_simple_search_modifier;
728 }
729
730 /**
731 * This function sets the default # of rows
732 * per page to display. By default its 10.
733 * This lets the user override this value.
734 *
735 * @param int - the # of rows to use.
736 */
737 function set_default_num_rows( $num_rows ) {
738 $this->default_rows_per_page = $num_rows;
739 }
740
741 /**
742 * This function gets the current default
743 * number of rows to display setting.
744 *
745 * @return int
746 */
747 function get_default_num_rows( ) {
748 return $this->_default_rows_per_page;
749 }
750
751 /**
752 * This returns the Maximum # of rows to
753 * display when in expand mode
754 *
755 * @return int
756 */
757 function get_max_rows() {
758 return $this->_max_rows;
759 }
760
761 /**
762 * This sets the maximum # of rows to
763 * display when in expand mode
764 *
765 * @param int - new # of maximum rows
766 * to display when in 'expand' mode
767 *
768 */
769 function set_max_rows( $max ) {
770 $this->_max_rows = $max;
771 }
772
773
774
775 /**
776 * This function is used to set up any
777 * data that needs to be munged before the
778 * data is fetched from the DataListSource
779 *
780 */
781 function data_prefetch() {
782 $this->_check_datasource("data_prefetch");
783
784 if ( $this->showall() ) {
785 $this->set_default_num_rows( $this->get_max_rows() );
786 $this->set_numrows( $this->get_max_rows() );
787 }
788
789 $limit = $this->numrows();
790 $this->_datasource->query($this->offset(), $limit,
791 $this->orderby(), $this->reverseorder(),
792 $this->search_field(), $this->search_value(),
793 $this->simple_search_modifier_value(),
794 $this->search_type() );
795 }
796
797
798
799 /*
800 * Takes an array of (name, sortable, db_field, alignment,
801 * size), with one element corresponding to each column.
802 */
803 function setup_columns() {
804 $temp_headers = array();
805
806 foreach( $this->_columns as $col_name => $data ) {
807 if ( $data["sortorder"] == "reverse" ) {
808 $data["reverseorder"] = "true";
809 } else {
810 $data["reverseorder"] = "false";
811 }
812 $temp_headers[$col_name] = $data;
813 }
814 $this->_columns = $temp_headers;
815 }
816
817
818
819 /**
820 * general DataListSource object checker.
821 *
822 */
823 function _check_datasource($function_name) {
824 if ( !is_object($this->_datasource) ) {
825 user_error("DataList::".$function_name."() - DataListSource object is not set");
826 exit;
827 }
828 }
829
830
831 /*********************************************/
832 /* REQUEST VARIABLE SECTION */
833 /*********************************************/
834
835
836
837 /**
838 * Function used to get the current
839 * value of one of the control vars
840 * for this class
841 *
842 * @param string - the name we want to get
843 * @param mixed - the default value if not set
844 * @return the current value or default if not set
845 */
846 function _get($name, $default_value=NULL) {
847 if ( !$_REQUEST[$this->_vars[$name]] ) {
848 $this->_set($name, $default_value);
849 }
850 //ddd( $name . " : ". $_REQUEST[$this->_vars[$name]] );
851 return $_REQUEST[$this->_vars[$name]];
852 }
853
854 /**
855 * This function is used to set the
856 * value of the control var
857 *
858 * @param string - the name we want to get
859 * @param mixed - the new value for it.
860 */
861 function _set($name, $value) {
862 $_REQUEST[$this->_vars[$name]] = $value;
863 }
864
865 /**
866 * This function returns the current value
867 * of the offset variable. This is an offset
868 * into the query return data set.
869 *
870 * @return int - the current value.
871 */
872 function offset() {
873 return(int)$this->_get("offsetVar", 0);
874 }
875
876 /**
877 * This function is used to set/change
878 * the offset for this list.
879 *
880 * @param int - the new offset.
881 */
882 function set_offset($new_offset) {
883 $this->_set("offsetVar", $new_offset);
884 }
885
886 /**
887 * This function returns the value of the
888 * current orderby variable.
889 *
890 * @return string.
891 */
892 function orderby() {
893 return $this->_get("orderbyVar", $this->_default_orderby);
894 }
895
896 /**
897 * This builds a query string var for the
898 * orderby value.
899 *
900 * @return string - "orderby=(thevalue)"
901 */
902 function build_orderby_querystring() {
903 $str = $this->_vars["orderbyVar"]."=".urlencode($this->orderby());
904 return $str;
905 }
906
907 /**
908 * This function returns the current value of
909 * the reverse order member variable.
910 *
911 * @return string.
912 */
913 function reverseorder() {
914 return $this->_get("reverseorderVar", $this->_default_reverseorder);
915 }
916
917 /**
918 * This function sets the reverse order flag
919 * to a new value.
920 *
921 * @param string - the new value.
922 */
923 function set_reverseorder($new_value) {
924 $this->_set("reverseorderVar", $new_value);
925 }
926
927 /**
928 * This builds a query string var for the
929 * reverseorder value.
930 *
931 * @return string - "orderby=(thevalue)"
932 */
933 function build_reverseorder_querystring() {
934 $str = $this->_vars["reverseorderVar"]."=".urlencode($this->reverseorder());
935 return $str;
936 }
937
938 /**
939 * This function returns the number of rows
940 * that the query found.
941 *
942 * @return int - the number of rows
943 */
944 function numrows() {
945 return(int)$this->_get("numrowsVar", $this->_default_rows_per_page);
946 }
947
948 /**
949 * This function sets the # of rows to display
950 * per page.
951 *
952 * @param int - the # of rows
953 */
954 function set_numrows($new_numrows) {
955 $this->_set("numrowsVar", $new_numrows);
956 }
957
958 /**
959 * returns the current value of
960 * the search field name
961 *
962 * @return string
963 */
964 function search_field() {
965 return $this->_get("search_fieldVar", '');
966 }
967
968 /**
969 * This builds a query string var for the
970 * searchfield value.
971 *
972 * @return string - "orderby=(thevalue)"
973 */
974 function build_searchfield_querystring() {
975 $str = $this->_vars["search_fieldVar"]."=".urlencode($this->searchfield());
976 return $str;
977 }
978
979 /**
980 * returns the current value of
981 * te search field value.
982 *
983 * @return string
984 */
985 function search_value() {
986 return $this->_get("search_valueVar", '');
987 }
988
989 /**
990 * This builds a query string var for the
991 * searchfield value.
992 *
993 * @return string - "orderby=(thevalue)"
994 */
995 function build_searchvalue_querystring() {
996 $str = $this->_vars["search_valueVar"]."=".urlencode($this->search_value());
997 return $str;
998 }
999
1000 /**
1001 * returns the current value of the
1002 * simple search modifier
1003 *
1004 * @return string
1005 */
1006 function simple_search_modifier_value() {
1007 return $this->_get("simple_search_modifierVar", '');
1008 }
1009
1010
1011 /**
1012 * returns the type of search being used
1013 *
1014 * @return string
1015 */
1016 function search_type() {
1017 return $this->_get("search_typeVar", "simple");
1018 }
1019
1020 /**
1021 * This function sets the search type
1022 *
1023 * @param string - the search type
1024 * "simple" or "advanced"
1025 */
1026 function set_search_type($type) {
1027 $this->_set("search_typeVar", $type);
1028 }
1029
1030
1031 /**
1032 * returns the current value of the showall
1033 * flag. This tells us if they want the entire
1034 * list of data back from the DB.
1035 *
1036 * @return string - the current value
1037 */
1038 function showall() {
1039 return(int)$this->_get("showallVar", 0);
1040 }
1041
1042 /**
1043 * This is the basic function for letting us
1044 * do a mapping between the column name in
1045 * the header, to the value found in the DB.
1046 *
1047 * NOTE: this function is meant to be overridden
1048 * so that you can push whatever you want.
1049 *
1050 * @param array - $row_data - the entire data for the row
1051 * @param string - $col_name - the name of the column header
1052 * for this row to render.
1053 * @return mixed - either a HTMLTag object, or raw text.
1054 */
1055 function build_column_item($row_data, $col_name) {
1056 $key = $this->_columns[$col_name]["data_name"];
1057
1058 if ( $row_data[$key] == '' ) {
1059 return "&nbsp;";
1060 } else {
1061 return $this->_filter_column_string($row_data[$key]);
1062 }
1063 }
1064
1065
1066 /**
1067 * This does some magic filtering on the data
1068 * that we display in a column. This helps
1069 * to prevent nast data that may have html
1070 * tags in it.
1071 *
1072 * @param string - the column data u want to filter
1073 * @return string the cleaned/filtered data
1074 */
1075 function _filter_column_string($data) {
1076 // WAS: return htmlspecialchars(trim($data));
1077
1078 // NEW: require 'flib/Application/i18n/TextEncode.php'
1079 // this will do a 'htmlentities' RECURSIVE on each item
1080 $encoder = new Data_Encode($data);
1081 $encoder->toHTML();
1082 return $data;
1083 }
1084
1085
1086 /*******************************************/
1087 /* FORM VARIABLES SECTION */
1088 /*******************************************/
1089
1090 /**
1091 * This function is used to set the
1092 * form name
1093 *
1094 * @param string
1095 */
1096 function set_form_name($name) {
1097 $this->_form_attributes["name"] = $name;
1098 }
1099
1100 /**
1101 * This function is used to get
1102 * the form name
1103 *
1104 * @return string
1105 */
1106 function get_form_name() {
1107 return $this->_form_attributes["name"];
1108 }
1109
1110 /**
1111 * This function is used to set the
1112 * form target
1113 *
1114 * @param string
1115 */
1116 function set_form_target($target) {
1117 $this->_form_attributes["target"] = $target;
1118 }
1119
1120 /**
1121 * This function is used to get
1122 * the form target
1123 *
1124 * @return string
1125 */
1126 function get_form_target() {
1127 return $this->_form_attributes["target"];
1128 }
1129
1130 /**
1131 * This function is used to set the
1132 * form method
1133 *
1134 * @param string (POST or GET)
1135 */
1136 function set_form_method($method) {
1137 if ( $method != "GET" && $method != "POST" ) {
1138 user_error("DataList::set_form_method() - INVALID Form method ".$method);
1139 } else {
1140 $this->_form_attributes["method"] = $method;
1141 }
1142 }
1143
1144 /**
1145 * This function is used to get
1146 * the form method
1147 *
1148 * @return string (POST or GET)
1149 */
1150 function get_form_method() {
1151 return $this->_form_attributes["method"];
1152 }
1153
1154 /**
1155 * Sets the form action
1156 *
1157 * @param string
1158 */
1159 function set_form_action($action) {
1160 $this->_form_attributes["action"] = $action;
1161 }
1162
1163 /**
1164 * This function is used to get
1165 * the form action
1166 *
1167 * @return string (POST or GET)
1168 */
1169 function get_form_action() {
1170 return $this->_form_attributes["action"];
1171 }
1172
1173 /**
1174 * Sets whether to the output into a form
1175 *
1176 * @param bool
1177 */
1178 function set_form_render($flag) {
1179 $this->_form_render_flag = $flag;
1180 }
1181
1182 /**
1183 * Return the state of the form render
1184 *
1185 * @return bool
1186 */
1187 function get_form_render() {
1188 return $this->_form_render_flag;
1189 }
1190
1191 /**
1192 * This function is used to set the
1193 * message displayed when no data is found
1194 *
1195 * @param string
1196 */
1197 function set_not_found_message($mesg) {
1198 $this->_check_datasource("set_not_found_message");
1199 $this->_datasource->set_not_found_message($mesg);
1200 }
1201
1202
1203 /**
1204 * This function is used to set the value
1205 * of the _show_results_flag
1206 *
1207 * @param boolean - TRUE to show the results
1208 */
1209 function set_show_results( $flag=TRUE ) {
1210 $this->_show_results_flag = $flag;
1211 }
1212
1213
1214 /**
1215 * This function is used to let render() know
1216 * that we should show the results or not.
1217 *
1218 * @return boolean
1219 */
1220 function _show_results() {
1221 return $this->_show_results_flag;
1222 }
1223
1224 /**
1225 * this method builds some hidden
1226 * form fields to automatically
1227 * be placed inside the form.
1228 *
1229 * This method returns a list of
1230 * hidden form fields if we are a POST.
1231 * It returns a portion of a query string
1232 * If we are a GET.
1233 *
1234 * @return mixed depending on form method
1235 */
1236 function _build_save_vars() {
1237 $container = container();
1238 foreach($this->_save_vars as $name => $value) {
1239 $container->add(form_hidden($name, $value));
1240 }
1241 return $container;
1242 }
1243
1244 /**
1245 * This function sets the save variables
1246 * that the user/child wants to automatically
1247 * propogate
1248 *
1249 * @param array - name=>value pairs of the data
1250 * that they want to propogate
1251 */
1252 function set_save_vars($vars) {
1253 $this->_save_vars = $vars;
1254 }
1255
1256 /**
1257 * This function builds the list of
1258 * default hidden form vars for when
1259 * the datalist is being rendered
1260 * as a POST
1261 *
1262 * @return Container
1263 */
1264 function _build_default_vars() {
1265 // the navigation links will set the offset anyway
1266 $container = container(form_hidden($this->_vars["offsetVar"], $this->offset()),
1267 form_hidden($this->_vars["orderbyVar"], $this->orderby()),
1268 form_hidden($this->_vars["reverseorderVar"], $this->reverseorder()),
1269 form_hidden($this->_vars["showallVar"], $this->showall()));
1270 return $container;
1271 }
1272
1273
1274
1275 /**
1276 * This builds the base url used
1277 * by the column headers as well
1278 * as the page tool links.
1279 *
1280 * it basically builds:
1281 * $_SELF?$_GET
1282 *
1283 * @return string
1284 */
1285 function build_base_url() {
1286
1287 $url = $_SERVER["PHP_SELF"]."?";
1288
1289 if ( $this->get_form_method() == "POST" ) {
1290 return $url;
1291 }
1292
1293 $vars = array_merge($_POST, $_GET);
1294 //request method independant access to
1295 //browser variables
1296 if ( count($vars) ) {
1297 //walk through all of the get vars
1298 //and add them to the url to save them.
1299 foreach($vars as $name => $value) {
1300
1301 if ( $name != $this->_vars["offsetVar"] &&
1302 $name != $this->_vars["orderbyVar"] &&
1303 $name != $this->_vars["reverseorderVar"] &&
1304 $name != $this->_vars["search_valueVar"]
1305 ) {
1306 if ( is_array($value) ) {
1307 $url .= $name."[]=".implode("&".$name."[]=",$value)."&";
1308 } else {
1309 $url .= $name."=".urlencode(stripslashes($value))."&";
1310 }
1311 }
1312 }
1313 }
1314
1315 return htmlentities($url);
1316 }
1317
1318 /**
1319 * This function builds the 'tool' images that
1320 * allow you to walk through the data list itself.
1321 * It provides image links for
1322 * first - go to the first page in the data list
1323 * prev - go to the previous page in the data list
1324 * next - go to the next page in the data list
1325 * last - go to the last page in the data list
1326 * all - show the rest of the list from the current offset
1327 *
1328 * @param string - which tool image to build
1329 * @return Object
1330 */
1331 function build_tool_link( $which ) {
1332 $num_pages = $this->get_num_pages();
1333 $cur_page = $this->get_current_page();
1334 $last_page = $this->get_last_page();
1335
1336 $image_path = $this->get_image_path();
1337 switch ( $which ) {
1338
1339 case "first":
1340 $rows_string = "First ".$this->get_default_num_rows()." Rows";
1341 if ( $this->offset() <= 0 ) {
1342 $obj = html_img($image_path."/first_group_button_inactive.gif",
1343 '','',0,$rows_string, NULL, $rows_string);
1344 } else {
1345 $url = $this->_build_tool_url(0);
1346 $obj = html_img_href($url, $image_path."/first_group_button.gif",
1347 '','',0, $rows_string, NULL, NULL, $rows_string);
1348 }
1349 break;
1350
1351 case "prev":
1352 $rows_string = "Previous ".$this->get_default_num_rows()." Rows";
1353 if ( $this->offset() <= 0 ) {
1354 $obj = html_img($image_path."/prev_group_button_inactive.gif",
1355 '','',0,$rows_string, NULL, $rows_string);
1356 } else {
1357 $offset = $this->offset() - $this->numrows();
1358 if ( $offset < 0 ) {
1359 $offset = 0;
1360 }
1361 $url = $this->_build_tool_url($offset);
1362 $obj = html_img_href($url, $image_path."/prev_group_button.gif",
1363 '','',0, $rows_string, NULL, NULL, $rows_string);
1364 }
1365 break;
1366
1367 case "next":
1368 $rows_string = "Next ".$this->get_default_num_rows()." Rows";
1369 if ( ($num_pages == 1) || ($cur_page == $last_page) ) {
1370 $obj = html_img($image_path."/next_group_button_inactive.gif",
1371 '','',0, $rows_string, NULL, $rows_string);
1372 } else {
1373 $offset = $this->offset() + $this->numrows();
1374 $url = $this->_build_tool_url($offset);
1375 $obj = html_img_href($url, $image_path."/next_group_button.gif",
1376 '','',0, $rows_string, NULL, NULL, $rows_string);
1377 }
1378 break;
1379
1380 case "last":
1381 $rows_string = "Last ".$this->get_default_num_rows()." Rows";
1382 if ( ($num_pages == 1) || ($cur_page == $last_page) ) {
1383 $obj = html_img($image_path."/last_group_button_inactive.gif",
1384 '','',0, $rows_string, NULL, $rows_string);
1385 } else {
1386 $offset = (int)(($num_pages - 1) * $this->numrows());
1387 $url = $this->_build_tool_url($offset);
1388 $obj = html_img_href($url, $image_path."/last_group_button.gif",
1389 '','',0, $rows_string, NULL, NULL, $rows_string);
1390 }
1391 break;
1392
1393 case "all":
1394 $offset = $this->offset();
1395 if ( $this->showall() ) {
1396 $url = $this->_build_tool_url($offset, TRUE, 0);
1397 $obj = html_img_href($url, $image_path."/close_group_button.gif",
1398 '','',0,"Collapse Rows", NULL, NULL, "Collapse Rows");
1399 } else {
1400 if ( ($num_pages == 1) ) {
1401 $obj = html_img($image_path."/expand_group_button_inactive.gif",
1402 '','',0, "Expand Rows", NULL, "Expand Rows");
1403 } else {
1404 $url = $this->_build_tool_url($offset, TRUE, 1);
1405 $obj = html_img_href($url, $image_path."/expand_group_button.gif",
1406 '','',0,"Expand Rows", NULL, NULL, "Expand Rows");
1407 }
1408 }
1409 //so we don't save it into the mozilla navigation bar links
1410 unset($url);
1411 break;
1412 }
1413
1414 if ( $url ) {
1415 $this->_save_mozilla_nav_link($which, $url);
1416 }
1417
1418 return $obj;
1419 }
1420
1421 /**
1422 * This function is used to build the url
1423 * for a tool link.
1424 * (first, prev, next, last, all)
1425 *
1426 * @param int - the offset for the link
1427 * @param boolean - add the showall value to the url
1428 * @param int - the showall value to use if the flag is on
1429 *
1430 * @return string
1431 */
1432 function _build_tool_url($offset, $showall_flag=FALSE, $showall_value=0) {
1433 if ( $this->get_form_method() == "POST" ) {
1434 $form_name = $this->get_form_name();
1435 $url = "javascript: document.".$form_name;
1436 $url .= ".".$this->_vars["offsetVar"].".value='".$offset."';";
1437
1438 //add the showall variable to the post
1439 if ( $showall_flag ) {
1440 $form_field = $this->_vars["showallVar"];
1441 $url .= "document.".$form_name.".";
1442 $url .= $form_field.".value='".$showall_value."';";
1443 }
1444
1445 $url .= "document.".$form_name.".submit();";
1446 } else {
1447 $url = $this->build_base_url();
1448 $url .= $this->build_state_vars_query_string($offset, $showall_flag,
1449 $showall_value);
1450 }
1451 return $url;
1452 }
1453
1454 /**
1455 * this function is used to build a sub query string
1456 * of all of the query string vars to save the
1457 * state of the DBItemList. This is used for pages
1458 * that want to come back to the list at the same state
1459 *
1460 * @return string - name=value& pairs
1461 */
1462 function build_state_vars_query_string($offset, $showall_flag=FALSE,
1463 $showall_value=0) {
1464 $str = "";
1465
1466 $str .= $this->_vars["offsetVar"]."=".urlencode($offset);
1467 $str .= "&".$this->_vars["orderbyVar"]."=".urlencode($this->orderby());
1468 $str .= "&".$this->_vars["reverseorderVar"]."=".urlencode($this->reverseorder());
1469 $str .= "&".$this->_vars["search_fieldVar"]."=".urlencode($this->search_field());
1470 $str .= "&".$this->_vars["search_valueVar"]."=".urlencode($this->search_value());
1471 $str .= "&".$this->_vars["simple_search_modifierVar"]."=".urlencode($this->simple_search_modifier_value());
1472 $str .= "&".$this->_vars["search_typeVar"]."=".urlencode($this->search_type());
1473 if ( $showall_flag ) {
1474 $str .= "&".$this->_vars["showallVar"]."=".urlencode($showall_value);
1475 }
1476
1477 return htmlentities($str);
1478 }
1479
1480 /**
1481 * This function stores the url for each of the tool
1482 * urls, so we can push these out for mozilla.
1483 * Mozilla has a nice navigation bar feature that
1484 * lets you program first, prev, next, last links
1485 *
1486 * @param string - which tool link
1487 * @param string - the url for that link
1488 */
1489 function _save_mozilla_nav_link($which, $url) {
1490 $this->_mozilla_nav_links[$which] = $url;
1491 }
1492
1493
1494 /**
1495 * This function returns the path to the
1496 * images used in this class
1497 *
1498 * @return string
1499 */
1500 function get_image_path() {
1501 return $this->_image_path;
1502 }
1503
1504 /**
1505 * This function returns the path to the
1506 * images used in this class
1507 *
1508 * @return string
1509 */
1510 function set_image_path($path) {
1511 return $this->_image_path = $path;
1512 }
1513
1514 /**
1515 * This function returns the current
1516 * page that the item list is on.
1517 *
1518 * @return int
1519 */
1520 function get_current_page() {
1521 return((int) ($this->offset() / $this->numrows())) + 1;
1522 }
1523
1524 /**
1525 * This function returns the #
1526 * of pages that are available
1527 * for this list of items.
1528 *
1529 * @return int
1530 */
1531 function get_num_pages() {
1532 $this->_check_datasource("get_num_pages");
1533 $total_rows = $this->_datasource->get_total_rows();
1534
1535 $cnt = (int)($total_rows / $this->numrows());
1536 if ( (($total_rows % $this->numrows()) != 0) || ($total_rows == 0) ) {
1537 $cnt++;
1538 }
1539 return $cnt;
1540 }
1541
1542 /**
1543 * This calculates the last page #
1544 * for this list of items
1545 *
1546 * @return int
1547 */
1548 function get_last_page() {
1549 return $this->get_num_pages();
1550 }
1551
1552 /**
1553 * This function builds the string
1554 * that describes the current page
1555 * out of n pages the list is showing
1556 *
1557 * @return string (ie. 1 to 10 of 25)
1558 */
1559 function get_page_info() {
1560 $cur_page = $this->get_current_page();
1561 $low_range = $this->offset() + 1;
1562 $num_pages = $this->get_num_pages();
1563 $num_rows_per_page = $this->numrows();
1564
1565 $this->_check_datasource("get_page_info");
1566 $total_rows = $this->_datasource->get_total_rows();
1567
1568 $high_range = $low_range + ($num_rows_per_page - 1);
1569 if ( $high_range > $total_rows ) {
1570 $high_range = $total_rows;
1571 }
1572
1573 if ( $total_rows == 0 ) {
1574 $str = "0 of 0";
1575 } else {
1576 $str = $low_range . " to ". $high_range;
1577 $str .= " of ".$total_rows;
1578 }
1579
1580 return $str;
1581 }
1582
1583
1584
1585 /**
1586 * This builds a url for a particular
1587 * column header.
1588 *
1589 * @param string - $col_name
1590 * @return Atag object;
1591 */
1592 function build_column_url($col_name) {
1593 $orderby = $this->orderby();
1594 $reverseorder = $this->reverseorder();
1595 $search_value = $this->search_value();
1596
1597 $order_value = $this->_columns[$col_name]["data_name"];
1598 $reverse_value = "false";
1599 if ( !$reverseorder ) {
1600 $reverseorder = 'false';
1601 }
1602
1603 if ( $orderby == $order_value && $reverseorder === 'false' ) {
1604 $reverse_value = "true";
1605 }
1606
1607 if ( $this->get_form_method() == "POST" ) {
1608 //we have to construct this url
1609 //specially.
1610 $form_name = $this->get_form_name();
1611
1612 $url = "javascript: ";
1613 //set the offset correctly
1614 $url .= "document.".$form_name.".".$this->_vars["offsetVar"].".value='".$this->offset()."';";
1615 //set the orderby correctly.
1616 $url .= "document.".$form_name.".".$this->_vars["orderbyVar"].".value='".$order_value."';";
1617 //set the reverseorder
1618 $url .= "document.".$form_name.".".$this->_vars["reverseorderVar"].".value='".$reverse_value."';";
1619
1620 $url .= "document.".$form_name.".submit();";
1621 } else {
1622 //handle the normal get.
1623 $url = $this->build_base_url();
1624 //Now add the orderby, reverseorder and offset vars
1625 $url .= $this->_vars["offsetVar"] ."=0&";
1626 //set the orderbyvar
1627 $url .= $this->_vars["orderbyVar"] ."=".$order_value."&";
1628 //set the reverseorder
1629 $url .= $this->_vars["reverseorderVar"] ."=".$reverse_value."&";
1630 //set the search value
1631 $url .= $this->_vars["search_valueVar"] ."=".$search_value;
1632 }
1633
1634 return $url;
1635 }
1636
1637
1638 /**
1639 * This function is used to make sure that the string we are
1640 * placing in a cell has been "cleaned"
1641 *
1642 * @param mixed - the cell object. It can be a string.
1643 * @param string - the name of the column this object/string
1644 * will live
1645 *
1646 * @return mixed - the cleaned string or object
1647 */
1648 function _clean_string($obj, $col_name) {
1649 if ( is_string($obj) ) {
1650 if ( $this->_columns[$col_name]["maxtextlength"] ) {
1651 //looks like we need to make sure we
1652 //truncate the string to a max length
1653 if ( strlen($obj) > $this->_columns[$col_name]["maxtextlength"] ) {
1654 //we need to truncate it.
1655 $obj = substr($obj, 0, $this->_columns[$col_name]["maxtextlength"]);
1656 $obj .= "...";
1657 }
1658 }
1659 }
1660 return $obj;
1661 }
1662
1663 /********************************/
1664 /* SEARCH RELATED */
1665 /********************************/
1666
1667 /**
1668 * This method gets the array of
1669 * searchable header fields (columns)
1670 *
1671 * @return array
1672 */
1673 function _get_searchable_fields() {
1674 $fields = array();
1675 foreach($this->_columns as $name => $header) {
1676 if ( $header["searchable"] == TRUE ) {
1677 $fields[$name] = $header["data_name"];
1678 }
1679 }
1680 return $fields;
1681 }
1682
1683 /**
1684 * This builds the simple search modifier
1685 * select box.
1686 *
1687 * @return INPUTtag object.
1688 */
1689 function _build_simple_search_modifier() {
1690
1691 $options = array();
1692
1693 $modifier = $this->get_simple_search_modifier();
1694
1695 if ( $modifier & SEARCH_BEGINS_WITH ) {
1696 $options["beginning with"] = "BEGINS";
1697 }
1698 if ( $modifier & SEARCH_CONTAINS ) {
1699 $options["containing"] = "CONTAINS";
1700 }
1701 if ( $modifier & SEARCH_EXACT ) {
1702 $options["matching"] = "EXACT";
1703 }
1704 if ( $modifier & SEARCH_ENDS_WITH ) {
1705 $options["ending with"] = "ENDS";
1706 }
1707
1708 $selected = $this->simple_search_modifier_value();
1709 //make the default Begins with
1710 if ( !$selected ) {
1711 $selected = "BEGINS";
1712 }
1713
1714 return form_select($this->_vars["simple_search_modifierVar"], $options, $selected);
1715 }
1716
1717 /**
1718 * This function is used to make safe
1719 * any query string value that is used
1720 *
1721 * @param string
1722 * @return string
1723 */
1724 function search_value_filter( $value ) {
1725 return stripslashes( trim($value) );
1726 }
1727 }
1728 ?>

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