/[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.1 - (show annotations)
Thu Jan 30 03:29:45 2003 UTC (21 years, 6 months ago) by jonen
Branch: MAIN
Branch point for: no_vendor_tag
Initial revision

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

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