/[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.3 - (show annotations)
Mon Feb 3 16:21:09 2003 UTC (21 years, 6 months ago) by jonen
Branch: MAIN
Changes since 1.2: +12 -42 lines
- removed doubled functions 'build_column_item()' and '_filter_column_string()'
+ replaced 'htmlspecialchars(trim($data))' at 'filter_column_string($data)'
   with '$encoder->toHTML()' which do a deep 'htmlentities(trim($data))
   (nfo/php/libs/flib/Application/i18n/TextEncode.php is required)

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 = "img/widgets";
299
300
301
302 /**
303 * The constructor
304 *
305 * @param string - the title of the data list
306 * @param string - the overall width
307 * @param string - the column to use as the default sorting order
308 * @param boolean - sort the default column in reverse order?
309 */
310 function DataList($title, $width = "100%", $default_orderby='',
311 $default_reverseorder=FALSE ) {
312 $this->set_title( $title );
313 $this->set_form_name( str_replace(' ', '_', strtolower($title)) );
314 $this->set_width( $width );
315
316 $this->_default_orderby = $default_orderby;
317 if ($default_reverseorder === TRUE) {
318 $default_reverseorder = "true";
319 } if ($default_reverse_order === FALSE) {
320 $default_reverseorder = "false";
321 }
322 $this->_default_reverseorder = $default_reverseorder;
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
1084 /*******************************************/
1085 /* FORM VARIABLES SECTION */
1086 /*******************************************/
1087
1088 /**
1089 * This function is used to set the
1090 * form name
1091 *
1092 * @param string
1093 */
1094 function set_form_name($name) {
1095 $this->_form_attributes["name"] = $name;
1096 }
1097
1098 /**
1099 * This function is used to get
1100 * the form name
1101 *
1102 * @return string
1103 */
1104 function get_form_name() {
1105 return $this->_form_attributes["name"];
1106 }
1107
1108 /**
1109 * This function is used to set the
1110 * form target
1111 *
1112 * @param string
1113 */
1114 function set_form_target($target) {
1115 $this->_form_attributes["target"] = $target;
1116 }
1117
1118 /**
1119 * This function is used to get
1120 * the form target
1121 *
1122 * @return string
1123 */
1124 function get_form_target() {
1125 return $this->_form_attributes["target"];
1126 }
1127
1128 /**
1129 * This function is used to set the
1130 * form method
1131 *
1132 * @param string (POST or GET)
1133 */
1134 function set_form_method($method) {
1135 if ($method != "GET" && $method != "POST") {
1136 user_error("DataList::set_form_method() - INVALID Form method ".$method);
1137 } else {
1138 $this->_form_attributes["method"] = $method;
1139 }
1140 }
1141
1142 /**
1143 * This function is used to get
1144 * the form method
1145 *
1146 * @return string (POST or GET)
1147 */
1148 function get_form_method() {
1149 return $this->_form_attributes["method"];
1150 }
1151
1152 /**
1153 * Sets the form action
1154 *
1155 * @param string
1156 */
1157 function set_form_action($action) {
1158 $this->_form_attributes["action"] = $action;
1159 }
1160
1161 /**
1162 * This function is used to get
1163 * the form action
1164 *
1165 * @return string (POST or GET)
1166 */
1167 function get_form_action() {
1168 return $this->_form_attributes["action"];
1169 }
1170
1171 /**
1172 * Sets whether to the output into a form
1173 *
1174 * @param bool
1175 */
1176 function set_form_render($flag) {
1177 $this->_form_render_flag = $flag;
1178 }
1179
1180 /**
1181 * Return the state of the form render
1182 *
1183 * @return bool
1184 */
1185 function get_form_render() {
1186 return $this->_form_render_flag;
1187 }
1188
1189 /**
1190 * This function is used to set the
1191 * message displayed when no data is found
1192 *
1193 * @param string
1194 */
1195 function set_not_found_message($mesg) {
1196 $this->_check_datasource("set_not_found_message");
1197 $this->_datasource->set_not_found_message($mesg);
1198 }
1199
1200
1201 /**
1202 * This function is used to set the value
1203 * of the _show_results_flag
1204 *
1205 * @param boolean - TRUE to show the results
1206 */
1207 function set_show_results( $flag=TRUE ) {
1208 $this->_show_results_flag = $flag;
1209 }
1210
1211
1212 /**
1213 * This function is used to let render() know
1214 * that we should show the results or not.
1215 *
1216 * @return boolean
1217 */
1218 function _show_results() {
1219 return $this->_show_results_flag;
1220 }
1221
1222 /**
1223 * this method builds some hidden
1224 * form fields to automatically
1225 * be placed inside the form.
1226 *
1227 * @return ContainerWidget object.
1228 */
1229 function _build_save_vars() {
1230 $container = container();
1231 foreach($this->_save_vars as $name => $value) {
1232 $container->add(form_hidden($name, $value));
1233 }
1234 return $container;
1235 }
1236
1237 /**
1238 * This function sets the save variables
1239 * that the user/child wants to automatically
1240 * propogate
1241 *
1242 * @param array - name=>value pairs of the data
1243 * that they want to propogate
1244 */
1245 function set_save_vars($vars) {
1246 $this->_save_vars = $vars;
1247 }
1248
1249 /**
1250 * This builds the base url used
1251 * by the column headers as well
1252 * as the page tool links.
1253 *
1254 * it basically builds:
1255 * $_SELF?$_GET
1256 *
1257 * @return string
1258 */
1259 function build_base_url() {
1260
1261 $url = $_SERVER["PHP_SELF"]."?";
1262
1263 if ($this->get_form_method() == "POST") {
1264 return $url;
1265 }
1266
1267 $vars = array_merge($_POST, $_GET);
1268 //request method independant access to
1269 //browser variables
1270 if (count($vars)) {
1271 //walk through all of the get vars
1272 //and add them to the url to save them.
1273 foreach($vars as $name => $value) {
1274
1275 if ($name != $this->_offsetVar &&
1276 $name != $this->_orderbyVar &&
1277 $name != $this->_reverseorderVar &&
1278 $name != $this->_search_valueVar
1279 ) {
1280 if (is_array($value)) {
1281 $url .= $name."[]=".implode("&".$name."[]=",$value)."&";
1282 } else {
1283 $url .= $name."=".urlencode(stripslashes($value))."&";
1284 }
1285 }
1286 }
1287 }
1288
1289 return $url;
1290 }
1291
1292 /**
1293 * This function builds the 'tool' images that
1294 * allow you to walk through the data list itself.
1295 * It provides image links for
1296 * first - go to the first page in the data list
1297 * prev - go to the previous page in the data list
1298 * next - go to the next page in the data list
1299 * last - go to the last page in the data list
1300 * all - show the rest of the list from the current offset
1301 *
1302 * @param string - which tool image to build
1303 * @return Object
1304 */
1305 function build_tool_link( $which ) {
1306 $num_pages = $this->get_num_pages();
1307 $cur_page = $this->get_current_page();
1308 $last_page = $this->get_last_page();
1309
1310 $image_path = $this->get_image_path();
1311 switch ($which) {
1312
1313 case "first":
1314 $rows_string = "First ".$this->get_default_num_rows()." Rows";
1315 if ($this->offset() <= 0) {
1316 $obj = html_img($image_path."/first_group_button_inactive.gif",
1317 '','',0,$rows_string, NULL, $rows_string);
1318 } else {
1319 $url = $this->_build_tool_url(0);
1320 $obj = html_img_href($url, $image_path."/first_group_button.gif",
1321 '','',0, $rows_string, NULL, NULL, $rows_string);
1322 }
1323 break;
1324
1325 case "prev":
1326 $rows_string = "Previous ".$this->get_default_num_rows()." Rows";
1327 if ($this->offset() <= 0) {
1328 $obj = html_img($image_path."/prev_group_button_inactive.gif",
1329 '','',0,$rows_string, NULL, $rows_string);
1330 } else {
1331 $offset = $this->offset() - $this->numrows();
1332 if ($offset < 0) {
1333 $offset = 0;
1334 }
1335 $url = $this->_build_tool_url($offset);
1336 $obj = html_img_href($url, $image_path."/prev_group_button.gif",
1337 '','',0, $rows_string, NULL, NULL, $rows_string);
1338 }
1339 break;
1340
1341 case "next":
1342 $rows_string = "Next ".$this->get_default_num_rows()." Rows";
1343 if (($num_pages == 1) || ($cur_page == $last_page)) {
1344 $obj = html_img($image_path."/next_group_button_inactive.gif",
1345 '','',0, $rows_string, NULL, $rows_string);
1346 } else {
1347 $offset = $this->offset() + $this->numrows();
1348 $url = $this->_build_tool_url($offset);
1349 $obj = html_img_href($url, $image_path."/next_group_button.gif",
1350 '','',0, $rows_string, NULL, NULL, $rows_string);
1351 }
1352 break;
1353
1354 case "last":
1355 $rows_string = "Last ".$this->get_default_num_rows()." Rows";
1356 if (($num_pages == 1) || ($cur_page == $last_page)) {
1357 $obj = html_img($image_path."/last_group_button_inactive.gif",
1358 '','',0, $rows_string, NULL, $rows_string);
1359 } else {
1360 $offset = (int)(($num_pages - 1) * $this->numrows());
1361 $url = $this->_build_tool_url($offset);
1362 $obj = html_img_href($url, $image_path."/last_group_button.gif",
1363 '','',0, $rows_string, NULL, NULL, $rows_string);
1364 }
1365 break;
1366
1367 case "all":
1368 $offset = $this->offset();
1369 if ($this->showall()) {
1370 $url = $this->_build_tool_url($offset, TRUE, 0);
1371 $obj = html_img_href($url, $image_path."/close_group_button.gif",
1372 '','',0,"Collapse Rows", NULL, NULL, "Collapse Rows");
1373 } else {
1374 if (($num_pages == 1)) {
1375 $obj = html_img($image_path."/expand_group_button_inactive.gif",
1376 '','',0, "Expand Rows", NULL, "Expand Rows");
1377 } else {
1378 $url = $this->_build_tool_url($offset, TRUE, 1);
1379 $obj = html_img_href($url, $image_path."/expand_group_button.gif",
1380 '','',0,"Expand Rows", NULL, NULL, "Expand Rows");
1381 }
1382 }
1383 //so we don't save it into the mozilla navigation bar links
1384 unset($url);
1385 break;
1386 }
1387
1388 if ($url) {
1389 $this->_save_mozilla_nav_link($which, $url);
1390 }
1391
1392 return $obj;
1393 }
1394
1395 /**
1396 * This function is used to build the url
1397 * for a tool link.
1398 * (first, prev, next, last, all)
1399 *
1400 * @param int - the offset for the link
1401 * @param boolean - add the showall value to the url
1402 * @param int - the showall value to use if the flag is on
1403 *
1404 * @return string
1405 */
1406 function _build_tool_url($offset, $showall_flag=FALSE, $showall_value=0) {
1407 if ($this->get_form_method() == "POST") {
1408 $form_name = $this->get_form_name();
1409 $url = "javascript: document.".$form_name;
1410 $url .= ".".$this->_offsetVar.".value='".$offset."';";
1411
1412 //add the showall variable to the post
1413 if ($showall_flag) {
1414 $form_field = $this->_showallVar;
1415 $url .= "document.".$form_name.".";
1416 $url .= $form_field.".value='".$showall_value."';";
1417 }
1418
1419 $url .= "document.".$form_name.".submit();";
1420 } else {
1421 $url = $this->build_base_url();
1422 $url .= $this->build_state_vars_query_string($offset, $showall_flag,
1423 $showall_value);
1424 }
1425 return $url;
1426 }
1427
1428 /**
1429 * this function is used to build a sub query string
1430 * of all of the query string vars to save the
1431 * state of the DBItemList. This is used for pages
1432 * that want to come back to the list at the same state
1433 *
1434 * @return string - name=value& pairs
1435 */
1436 function build_state_vars_query_string($offset, $showall_flag=FALSE,
1437 $showall_value=0) {
1438 $str = "";
1439
1440 $str .= $this->_offsetVar."=".urlencode($offset);
1441 $str .= "&".$this->_orderbyVar."=".urlencode($this->orderby());
1442 $str .= "&".$this->_reverseorderVar."=".urlencode($this->reverseorder());
1443 $str .= "&".$this->_search_fieldVar."=".urlencode($this->search_field());
1444 $str .= "&".$this->_search_valueVar."=".urlencode($this->search_value());
1445 $str .= "&".$this->_simple_search_modifierVar."=".urlencode($this->simple_search_modifier_value());
1446 $str .= "&".$this->_search_typeVar."=".urlencode($this->search_type());
1447 if ($showall_flag) {
1448 $str .= "&".$this->_showallVar."=".urlencode($showall_value);
1449 }
1450
1451 return $str;
1452 }
1453
1454 /**
1455 * This function stores the url for each of the tool
1456 * urls, so we can push these out for mozilla.
1457 * Mozilla has a nice navigation bar feature that
1458 * lets you program first, prev, next, last links
1459 *
1460 * @param string - which tool link
1461 * @param string - the url for that link
1462 */
1463 function _save_mozilla_nav_link($which, $url) {
1464 $this->_mozilla_nav_links[$which] = $url;
1465 }
1466
1467
1468 /**
1469 * This function returns the path to the
1470 * images used in this class
1471 *
1472 * @return string
1473 */
1474 function get_image_path() {
1475 return $this->_image_path;
1476 }
1477
1478 /**
1479 * This function returns the path to the
1480 * images used in this class
1481 *
1482 * @return string
1483 */
1484 function set_image_path($path) {
1485 return $this->_image_path = $path;
1486 }
1487
1488 /**
1489 * This function returns the current
1490 * page that the item list is on.
1491 *
1492 * @return int
1493 */
1494 function get_current_page() {
1495 return((int) ($this->offset() / $this->numrows())) + 1;
1496 }
1497
1498 /**
1499 * This function returns the #
1500 * of pages that are available
1501 * for this list of items.
1502 *
1503 * @return int
1504 */
1505 function get_num_pages() {
1506 $this->_check_datasource("get_num_pages");
1507 $total_rows = $this->_datasource->get_total_rows();
1508
1509 $cnt = (int)($total_rows / $this->numrows());
1510 if ((($total_rows % $this->numrows()) != 0) || ($total_rows == 0)) {
1511 $cnt++;
1512 }
1513 return $cnt;
1514 }
1515
1516 /**
1517 * This calculates the last page #
1518 * for this list of items
1519 *
1520 * @return int
1521 */
1522 function get_last_page() {
1523 return $this->get_num_pages();
1524 }
1525
1526 /**
1527 * This function builds the string
1528 * that describes the current page
1529 * out of n pages the list is showing
1530 *
1531 * @return string (ie. 1 to 10 of 25)
1532 */
1533 function get_page_info() {
1534 $cur_page = $this->get_current_page();
1535 $low_range = $this->offset() + 1;
1536 $num_pages = $this->get_num_pages();
1537 $num_rows_per_page = $this->numrows();
1538
1539 $this->_check_datasource("get_page_info");
1540 $total_rows = $this->_datasource->get_total_rows();
1541
1542 $high_range = $low_range + ($num_rows_per_page - 1);
1543 if ($high_range > $total_rows) {
1544 $high_range = $total_rows;
1545 }
1546
1547 if ($total_rows == 0) {
1548 $str = "0 of 0";
1549 } else {
1550 $str = $low_range . " to ". $high_range;
1551 $str .= " of ".$total_rows;
1552 }
1553
1554 return $str;
1555 }
1556
1557
1558
1559 /**
1560 * This builds a url for a particular
1561 * column header.
1562 *
1563 * @param string - $col_name
1564 * @return Atag object;
1565 */
1566 function build_column_url($col_name) {
1567 $orderby = $this->orderby();
1568 $reverseorder = $this->reverseorder();
1569 $search_value = $this->search_value();
1570
1571 $order_value = $this->_columns[$col_name]["data_name"];
1572 $reverse_value = "false";
1573 if (!$reverseorder) {
1574 $reverseorder = 'false';
1575 }
1576
1577 if ($orderby == $order_value && $reverseorder === 'false') {
1578 $reverse_value = "true";
1579 }
1580
1581 if ($this->form_method == "POST") {
1582 //we have to construct this url
1583 //specially.
1584 $form_name = $this->get_form_name();
1585
1586 $url = "javascript: ";
1587 //set the offset correctly
1588 $url .= "document.".$form_name.".".$this->_offsetVar.".value='".$this->offset()."';";
1589 //set the orderby correctly.
1590 $url .= "document.".$form_name.".".$this->_orderbyVar.".value='".$order_value."';";
1591 //set the reverseorder
1592 $url .= "document.".$form_name.".".$this->_reverseorderVar.".value='".$reverse_value."';";
1593
1594 $url .= "document.".$form_name.".submit();";
1595 } else {
1596 //handle the normal get.
1597 $url = $this->build_base_url();
1598 //Now add the orderby, reverseorder and offset vars
1599 $url .= $this->_offsetVar ."=0&";
1600 //set the orderbyvar
1601 $url .= $this->_orderbyVar ."=".$order_value."&";
1602 //set the reverseorder
1603 $url .= $this->_reverseorderVar ."=".$reverse_value."&";
1604 //set the search value
1605 $url .= $this->_search_valueVar ."=".$search_value;
1606 }
1607
1608 return $url;
1609 }
1610
1611 /**
1612 * This is the basic function for letting us
1613 * do a mapping between the column name in
1614 * the header, to the value found in the DB.
1615 *
1616 * NOTE: this function is meant to be overridden
1617 * so that you can push whatever you want.
1618 *
1619 * @param array - $row_data - the entire data for the row
1620 * @param string - $col_name - the name of the column header
1621 * for this row to render.
1622 * @return mixed - either a HTMLTag object, or raw text.
1623 */
1624 function build_column_item($row_data, $col_name) {
1625 $key = $this->_columns[$col_name]["data_name"];
1626
1627 if ($row_data[$key] == '') {
1628 return "&nbsp;";
1629 } else {
1630 return $this->filter_column_string($row_data[$key]);
1631 }
1632 }
1633
1634
1635 /**
1636 * This does some magic filtering on the data
1637 * that we display in a column. This helps
1638 * to prevent nast data that may have html
1639 * tags in it.
1640 *
1641 * @param string - the column data u want to filter
1642 * @return string the cleaned/filtered data
1643 */
1644 function filter_column_string($data) {
1645 // WAS: return htmlspecialchars(trim($data));
1646
1647 // NEW: require 'flib/Application/i18n/TextEncode.php'
1648 // this will do a 'htmlentities' RECURSIVE on each item
1649 $encoder = new TextEncode($data);
1650 $encoder->toHTML();
1651 return $data;
1652 }
1653
1654
1655
1656 /**
1657 * This function is used to make sure that the string we are
1658 * placing in a cell has been "cleaned"
1659 *
1660 * @param mixed - the cell object. It can be a string.
1661 * @param string - the name of the column this object/string
1662 * will live
1663 *
1664 * @return mixed - the cleaned string or object
1665 */
1666 function _clean_string($obj, $col_name){
1667 if (is_string($obj)) {
1668 if ($this->_columns[$col_name]["maxtextlength"]) {
1669 //looks like we need to make sure we
1670 //truncate the string to a max length
1671 if (strlen($obj) > $this->_columns[$col_name]["maxtextlength"]) {
1672 //we need to truncate it.
1673 $obj = substr($obj, 0, $this->_columns[$col_name]["maxtextlength"]);
1674 $obj .= "...";
1675 }
1676 }
1677 }
1678 return $obj;
1679 }
1680
1681 /********************************/
1682 /* SEARCH RELATED */
1683 /********************************/
1684
1685 /**
1686 * This method gets the array of
1687 * searchable header fields (columns)
1688 *
1689 * @return array
1690 */
1691 function _get_searchable_fields() {
1692 $fields = array();
1693 foreach($this->_columns as $name => $header) {
1694 if ($header["searchable"] == TRUE) {
1695 $fields[$name] = $header["data_name"];
1696 }
1697 }
1698 return $fields;
1699 }
1700
1701 /**
1702 * This builds the simple search modifier
1703 * select box.
1704 *
1705 * @return INPUTtag object.
1706 */
1707 function _build_simple_search_modifier() {
1708
1709 $options = array();
1710
1711 $modifier = $this->get_simple_search_modifier();
1712
1713 if ($modifier & SEARCH_BEGINS_WITH) {
1714 $options["beginning with"] = "BEGINS";
1715 }
1716 if ($modifier & SEARCH_CONTAINS) {
1717 $options["containing"] = "CONTAINS";
1718 }
1719 if ($modifier & SEARCH_EXACT) {
1720 $options["matching"] = "EXACT";
1721 }
1722 if ($modifier & SEARCH_ENDS_WITH) {
1723 $options["ending with"] = "ENDS";
1724 }
1725
1726 $selected = $this->simple_search_modifier_value();
1727 //make the default Begins with
1728 if (!$selected) {
1729 $selected = "BEGINS";
1730 }
1731
1732 return form_select($this->_simple_search_modifierVar, $options, $selected);
1733 }
1734
1735 /**
1736 * This function is used to make safe
1737 * any query string value that is used
1738 *
1739 * @param string
1740 * @return string
1741 */
1742 function search_value_filter( $value ) {
1743 return stripslashes( trim($value) );
1744 }
1745 }
1746 ?>

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