|
Moodle
2.2.1
http://www.collinsharper.com
|
00001 <?php 00002 00003 // This file is part of Moodle - http://moodle.org/ 00004 // 00005 // Moodle is free software: you can redistribute it and/or modify 00006 // it under the terms of the GNU General Public License as published by 00007 // the Free Software Foundation, either version 3 of the License, or 00008 // (at your option) any later version. 00009 // 00010 // Moodle is distributed in the hope that it will be useful, 00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00013 // GNU General Public License for more details. 00014 // 00015 // You should have received a copy of the GNU General Public License 00016 // along with Moodle. If not, see <http://www.gnu.org/licenses/>. 00017 00026 defined('MOODLE_INTERNAL') || die(); 00027 00031 define('TABLE_VAR_SORT', 1); 00032 define('TABLE_VAR_HIDE', 2); 00033 define('TABLE_VAR_SHOW', 3); 00034 define('TABLE_VAR_IFIRST', 4); 00035 define('TABLE_VAR_ILAST', 5); 00036 define('TABLE_VAR_PAGE', 6); 00043 define('TABLE_P_TOP', 1); 00044 define('TABLE_P_BOTTOM', 2); 00053 class flexible_table { 00054 00055 var $uniqueid = NULL; 00056 var $attributes = array(); 00057 var $headers = array(); 00058 var $columns = array(); 00059 var $column_style = array(); 00060 var $column_class = array(); 00061 var $column_suppress = array(); 00062 var $column_nosort = array('userpic'); 00063 var $setup = false; 00064 var $sess = NULL; 00065 var $baseurl = NULL; 00066 var $request = array(); 00067 00068 var $is_collapsible = false; 00069 var $is_sortable = false; 00070 var $use_pages = false; 00071 var $use_initials = false; 00072 00073 var $maxsortkeys = 2; 00074 var $pagesize = 30; 00075 var $currpage = 0; 00076 var $totalrows = 0; 00077 var $sort_default_column = NULL; 00078 var $sort_default_order = SORT_ASC; 00079 00083 var $showdownloadbuttonsat= array(TABLE_P_TOP); 00084 00089 public $useridfield = 'id'; 00090 00096 var $download = ''; 00097 00102 var $downloadable = false; 00103 00108 var $defaultdownloadformat = 'csv'; 00109 00113 var $started_output = false; 00114 00115 var $exportclass = null; 00116 00122 function __construct($uniqueid) { 00123 $this->uniqueid = $uniqueid; 00124 $this->request = array( 00125 TABLE_VAR_SORT => 'tsort', 00126 TABLE_VAR_HIDE => 'thide', 00127 TABLE_VAR_SHOW => 'tshow', 00128 TABLE_VAR_IFIRST => 'tifirst', 00129 TABLE_VAR_ILAST => 'tilast', 00130 TABLE_VAR_PAGE => 'page', 00131 ); 00132 } 00133 00139 function flexible_table($uniqueid) { 00140 debugging('Please update your code to user PHP5-style parent::__construct(...), ' . 00141 'not parent::flexible_table(...).'); 00142 $this->__construct($uniqueid); 00143 } 00144 00158 function is_downloading($download = null, $filename='', $sheettitle='') { 00159 if ($download!==null) { 00160 $this->sheettitle = $sheettitle; 00161 $this->is_downloadable(true); 00162 $this->download = $download; 00163 $this->filename = clean_filename($filename); 00164 $this->export_class_instance(); 00165 } 00166 return $this->download; 00167 } 00168 00174 function export_class_instance($exportclass = null) { 00175 if (!is_null($exportclass)) { 00176 $this->started_output = true; 00177 $this->exportclass = $exportclass; 00178 $this->exportclass->table = $this; 00179 } else if (is_null($this->exportclass) && !empty($this->download)) { 00180 $classname = 'table_'.$this->download.'_export_format'; 00181 $this->exportclass = new $classname($this); 00182 if (!$this->exportclass->document_started()) { 00183 $this->exportclass->start_document($this->filename); 00184 } 00185 } 00186 return $this->exportclass; 00187 } 00188 00198 function is_downloadable($downloadable = null) { 00199 if ($downloadable !== null) { 00200 $this->downloadable = $downloadable; 00201 } 00202 return $this->downloadable; 00203 } 00204 00210 function show_download_buttons_at($showat) { 00211 $this->showdownloadbuttonsat = $showat; 00212 } 00213 00222 function sortable($bool, $defaultcolumn = NULL, $defaultorder = SORT_ASC) { 00223 $this->is_sortable = $bool; 00224 $this->sort_default_column = $defaultcolumn; 00225 $this->sort_default_order = $defaultorder; 00226 } 00227 00232 function no_sorting($column) { 00233 $this->column_nosort[] = $column; 00234 } 00235 00241 function is_sortable($column = null) { 00242 if (empty($column)) { 00243 return $this->is_sortable; 00244 } 00245 if (!$this->is_sortable) { 00246 return false; 00247 } 00248 return !in_array($column, $this->column_nosort); 00249 } 00250 00256 function collapsible($bool) { 00257 $this->is_collapsible = $bool; 00258 } 00259 00265 function pageable($bool) { 00266 $this->use_pages = $bool; 00267 } 00268 00274 function initialbars($bool) { 00275 $this->use_initials = $bool; 00276 } 00277 00285 function pagesize($perpage, $total) { 00286 $this->pagesize = $perpage; 00287 $this->totalrows = $total; 00288 $this->use_pages = true; 00289 } 00290 00297 function set_control_variables($variables) { 00298 foreach ($variables as $what => $variable) { 00299 if (isset($this->request[$what])) { 00300 $this->request[$what] = $variable; 00301 } 00302 } 00303 } 00304 00311 function set_attribute($attribute, $value) { 00312 $this->attributes[$attribute] = $value; 00313 } 00314 00324 function column_suppress($column) { 00325 if (isset($this->column_suppress[$column])) { 00326 $this->column_suppress[$column] = true; 00327 } 00328 } 00329 00336 function column_class($column, $classname) { 00337 if (isset($this->column_class[$column])) { 00338 $this->column_class[$column] = ' '.$classname; // This space needed so that classnames don't run together in the HTML 00339 } 00340 } 00341 00349 function column_style($column, $property, $value) { 00350 if (isset($this->column_style[$column])) { 00351 $this->column_style[$column][$property] = $value; 00352 } 00353 } 00354 00361 function column_style_all($property, $value) { 00362 foreach (array_keys($this->columns) as $column) { 00363 $this->column_style[$column][$property] = $value; 00364 } 00365 } 00366 00371 function define_baseurl($url) { 00372 $this->baseurl = new moodle_url($url); 00373 } 00374 00379 function define_columns($columns) { 00380 $this->columns = array(); 00381 $this->column_style = array(); 00382 $this->column_class = array(); 00383 $colnum = 0; 00384 00385 foreach ($columns as $column) { 00386 $this->columns[$column] = $colnum++; 00387 $this->column_style[$column] = array(); 00388 $this->column_class[$column] = ''; 00389 $this->column_suppress[$column] = false; 00390 } 00391 } 00392 00397 function define_headers($headers) { 00398 $this->headers = $headers; 00399 } 00400 00406 function setup() { 00407 global $SESSION, $CFG; 00408 00409 if (empty($this->columns) || empty($this->uniqueid)) { 00410 return false; 00411 } 00412 00413 if (!isset($SESSION->flextable)) { 00414 $SESSION->flextable = array(); 00415 } 00416 00417 if (!isset($SESSION->flextable[$this->uniqueid])) { 00418 $SESSION->flextable[$this->uniqueid] = new stdClass; 00419 $SESSION->flextable[$this->uniqueid]->uniqueid = $this->uniqueid; 00420 $SESSION->flextable[$this->uniqueid]->collapse = array(); 00421 $SESSION->flextable[$this->uniqueid]->sortby = array(); 00422 $SESSION->flextable[$this->uniqueid]->i_first = ''; 00423 $SESSION->flextable[$this->uniqueid]->i_last = ''; 00424 } 00425 00426 $this->sess = &$SESSION->flextable[$this->uniqueid]; 00427 00428 if (($showcol = optional_param($this->request[TABLE_VAR_SHOW], '', PARAM_ALPHANUMEXT)) && 00429 isset($this->columns[$showcol])) { 00430 $this->sess->collapse[$showcol] = false; 00431 00432 } else if (($hidecol = optional_param($this->request[TABLE_VAR_HIDE], '', PARAM_ALPHANUMEXT)) && 00433 isset($this->columns[$hidecol])) { 00434 $this->sess->collapse[$hidecol] = true; 00435 if (array_key_exists($hidecol, $this->sess->sortby)) { 00436 unset($this->sess->sortby[$hidecol]); 00437 } 00438 } 00439 00440 // Now, update the column attributes for collapsed columns 00441 foreach (array_keys($this->columns) as $column) { 00442 if (!empty($this->sess->collapse[$column])) { 00443 $this->column_style[$column]['width'] = '10px'; 00444 } 00445 } 00446 00447 if (($sortcol = optional_param($this->request[TABLE_VAR_SORT], '', PARAM_ALPHANUMEXT)) && 00448 $this->is_sortable($sortcol) && empty($this->sess->collapse[$sortcol]) && 00449 (isset($this->columns[$sortcol]) || in_array($sortcol, array('firstname', 'lastname')) && isset($this->columns['fullname']))) { 00450 00451 if (array_key_exists($sortcol, $this->sess->sortby)) { 00452 // This key already exists somewhere. Change its sortorder and bring it to the top. 00453 $sortorder = $this->sess->sortby[$sortcol] == SORT_ASC ? SORT_DESC : SORT_ASC; 00454 unset($this->sess->sortby[$sortcol]); 00455 $this->sess->sortby = array_merge(array($sortcol => $sortorder), $this->sess->sortby); 00456 } else { 00457 // Key doesn't exist, so just add it to the beginning of the array, ascending order 00458 $this->sess->sortby = array_merge(array($sortcol => SORT_ASC), $this->sess->sortby); 00459 } 00460 00461 // Finally, make sure that no more than $this->maxsortkeys are present into the array 00462 $this->sess->sortby = array_slice($this->sess->sortby, 0, $this->maxsortkeys); 00463 } 00464 00465 // If we didn't sort just now, then use the default sort order if one is defined and the column exists 00466 if (empty($this->sess->sortby) && !empty($this->sort_default_column)) { 00467 $this->sess->sortby = array ($this->sort_default_column => ($this->sort_default_order == SORT_DESC ? SORT_DESC : SORT_ASC)); 00468 } 00469 00470 $ilast = optional_param($this->request[TABLE_VAR_ILAST], null, PARAM_RAW); 00471 if (!is_null($ilast) && ($ilast ==='' || strpos(get_string('alphabet', 'langconfig'), $ilast) !== false)) { 00472 $this->sess->i_last = $ilast; 00473 } 00474 00475 $ifirst = optional_param($this->request[TABLE_VAR_IFIRST], null, PARAM_RAW); 00476 if (!is_null($ifirst) && ($ifirst === '' || strpos(get_string('alphabet', 'langconfig'), $ifirst) !== false)) { 00477 $this->sess->i_first = $ifirst; 00478 } 00479 00480 if (empty($this->baseurl)) { 00481 debugging('You should set baseurl when using flexible_table.'); 00482 global $PAGE; 00483 $this->baseurl = $PAGE->url; 00484 } 00485 00486 $this->currpage = optional_param($this->request[TABLE_VAR_PAGE], 0, PARAM_INT); 00487 $this->setup = true; 00488 00489 // Always introduce the "flexible" class for the table if not specified 00490 if (empty($this->attributes)) { 00491 $this->attributes['class'] = 'flexible'; 00492 } else if (!isset($this->attributes['class'])) { 00493 $this->attributes['class'] = 'flexible'; 00494 } else if (!in_array('flexible', explode(' ', $this->attributes['class']))) { 00495 $this->attributes['class'] = trim('flexible ' . $this->attributes['class']); 00496 } 00497 } 00498 00504 public static function get_sort_for_table($uniqueid) { 00505 global $SESSION; 00506 if (empty($SESSION->flextable[$uniqueid])) { 00507 return ''; 00508 } 00509 00510 $sess = &$SESSION->flextable[$uniqueid]; 00511 if (empty($sess->sortby)) { 00512 return ''; 00513 } 00514 00515 return self::construct_order_by($sess->sortby); 00516 } 00517 00523 public static function construct_order_by($cols) { 00524 $bits = array(); 00525 00526 foreach ($cols as $column => $order) { 00527 if ($order == SORT_ASC) { 00528 $bits[] = $column . ' ASC'; 00529 } else { 00530 $bits[] = $column . ' DESC'; 00531 } 00532 } 00533 00534 return implode(', ', $bits); 00535 } 00536 00540 public function get_sql_sort() { 00541 return self::construct_order_by($this->get_sort_columns()); 00542 } 00543 00548 public function get_sort_columns() { 00549 if (!$this->setup) { 00550 throw new coding_exception('Cannot call get_sort_columns until you have called setup.'); 00551 } 00552 00553 if (empty($this->sess->sortby)) { 00554 return array(); 00555 } 00556 00557 foreach ($this->sess->sortby as $column => $notused) { 00558 if (isset($this->columns[$column])) { 00559 continue; // This column is OK. 00560 } 00561 if (in_array($column, array('firstname', 'lastname')) && 00562 isset($this->columns['fullname'])) { 00563 continue; // This column is OK. 00564 } 00565 // This column is not OK. 00566 unset($this->sess->sortby[$column]); 00567 } 00568 00569 return $this->sess->sortby; 00570 } 00571 00575 function get_page_start() { 00576 if (!$this->use_pages) { 00577 return ''; 00578 } 00579 return $this->currpage * $this->pagesize; 00580 } 00581 00585 function get_page_size() { 00586 if (!$this->use_pages) { 00587 return ''; 00588 } 00589 return $this->pagesize; 00590 } 00591 00595 function get_sql_where() { 00596 global $DB; 00597 00598 $conditions = array(); 00599 $params = array(); 00600 00601 if (isset($this->columns['fullname'])) { 00602 static $i = 0; 00603 $i++; 00604 00605 if (!empty($this->sess->i_first)) { 00606 $conditions[] = $DB->sql_like('firstname', ':ifirstc'.$i, false, false); 00607 $params['ifirstc'.$i] = $this->sess->i_first.'%'; 00608 } 00609 if (!empty($this->sess->i_last)) { 00610 $conditions[] = $DB->sql_like('lastname', ':ilastc'.$i, false, false); 00611 $params['ilastc'.$i] = $this->sess->i_last.'%'; 00612 } 00613 } 00614 00615 return array(implode(" AND ", $conditions), $params); 00616 } 00617 00628 function add_data_keyed($rowwithkeys, $classname = '') { 00629 $this->add_data($this->get_row_from_keyed($rowwithkeys), $classname); 00630 } 00631 00635 function add_separator() { 00636 if (!$this->setup) { 00637 return false; 00638 } 00639 $this->add_data(NULL); 00640 } 00641 00653 function add_data($row, $classname = '') { 00654 if (!$this->setup) { 00655 return false; 00656 } 00657 if (!$this->started_output) { 00658 $this->start_output(); 00659 } 00660 if ($this->exportclass!==null) { 00661 if ($row === null) { 00662 $this->exportclass->add_seperator(); 00663 } else { 00664 $this->exportclass->add_data($row); 00665 } 00666 } else { 00667 $this->print_row($row, $classname); 00668 } 00669 return true; 00670 } 00671 00677 function finish_output($closeexportclassdoc = true) { 00678 if ($this->exportclass!==null) { 00679 $this->exportclass->finish_table(); 00680 if ($closeexportclassdoc) { 00681 $this->exportclass->finish_document(); 00682 } 00683 } else { 00684 $this->finish_html(); 00685 } 00686 } 00687 00693 function wrap_html_start() { 00694 } 00695 00701 function wrap_html_finish() { 00702 } 00703 00709 function format_row($row) { 00710 $formattedrow = array(); 00711 foreach (array_keys($this->columns) as $column) { 00712 $colmethodname = 'col_'.$column; 00713 if (method_exists($this, $colmethodname)) { 00714 $formattedcolumn = $this->$colmethodname($row); 00715 } else { 00716 $formattedcolumn = $this->other_cols($column, $row); 00717 if ($formattedcolumn===NULL) { 00718 $formattedcolumn = $row->$column; 00719 } 00720 } 00721 $formattedrow[$column] = $formattedcolumn; 00722 } 00723 return $formattedrow; 00724 } 00725 00734 function col_fullname($row) { 00735 global $COURSE, $CFG; 00736 00737 if (!$this->download) { 00738 $profileurl = new moodle_url('/user/profile.php', array('id' => $row->{$this->useridfield})); 00739 if ($COURSE->id != SITEID) { 00740 $profileurl->param('course', $COURSE->id); 00741 } 00742 return html_writer::link($profileurl, fullname($row)); 00743 00744 } else { 00745 return fullname($row); 00746 } 00747 } 00748 00753 function other_cols($column, $row) { 00754 return NULL; 00755 } 00756 00764 function format_text($text, $format=FORMAT_MOODLE, $options=NULL, $courseid=NULL) { 00765 if (!$this->is_downloading()) { 00766 if (is_null($options)) { 00767 $options = new stdClass; 00768 } 00769 //some sensible defaults 00770 if (!isset($options->para)) { 00771 $options->para = false; 00772 } 00773 if (!isset($options->newlines)) { 00774 $options->newlines = false; 00775 } 00776 if (!isset($options->smiley)) { 00777 $options->smiley = false; 00778 } 00779 if (!isset($options->filter)) { 00780 $options->filter = false; 00781 } 00782 return format_text($text, $format, $options); 00783 } else { 00784 $eci =& $this->export_class_instance(); 00785 return $eci->format_text($text, $format, $options, $courseid); 00786 } 00787 } 00792 function print_html() { 00793 if (!$this->setup) { 00794 return false; 00795 } 00796 $this->finish_html(); 00797 } 00798 00803 function get_initial_first() { 00804 if (!$this->use_initials) { 00805 return NULL; 00806 } 00807 00808 return $this->sess->i_first; 00809 } 00810 00815 function get_initial_last() { 00816 if (!$this->use_initials) { 00817 return NULL; 00818 } 00819 00820 return $this->sess->i_last; 00821 } 00822 00831 protected function print_one_initials_bar($alpha, $current, $class, $title, $urlvar) { 00832 echo html_writer::start_tag('div', array('class' => 'initialbar ' . $class)) . 00833 $title . ' : '; 00834 if ($current) { 00835 echo html_writer::link($this->baseurl->out(false, array($urlvar => '')), get_string('all')); 00836 } else { 00837 echo html_writer::tag('strong', get_string('all')); 00838 } 00839 00840 foreach ($alpha as $letter) { 00841 if ($letter === $current) { 00842 echo html_writer::tag('strong', $letter); 00843 } else { 00844 echo html_writer::link($this->baseurl->out(false, array($urlvar => $letter)), $letter); 00845 } 00846 } 00847 00848 echo html_writer::end_tag('div'); 00849 } 00850 00854 function print_initials_bar() { 00855 if ((!empty($this->sess->i_last) || !empty($this->sess->i_first) ||$this->use_initials) 00856 && isset($this->columns['fullname'])) { 00857 00858 $alpha = explode(',', get_string('alphabet', 'langconfig')); 00859 00860 // Bar of first initials 00861 if (!empty($this->sess->i_first)) { 00862 $ifirst = $this->sess->i_first; 00863 } else { 00864 $ifirst = ''; 00865 } 00866 $this->print_one_initials_bar($alpha, $ifirst, 'firstinitial', 00867 get_string('firstname'), $this->request[TABLE_VAR_IFIRST]); 00868 00869 // Bar of last initials 00870 if (!empty($this->sess->i_last)) { 00871 $ilast = $this->sess->i_last; 00872 } else { 00873 $ilast = ''; 00874 } 00875 $this->print_one_initials_bar($alpha, $ilast, 'lastinitial', 00876 get_string('lastname'), $this->request[TABLE_VAR_ILAST]); 00877 } 00878 } 00879 00883 function print_nothing_to_display() { 00884 global $OUTPUT; 00885 $this->print_initials_bar(); 00886 00887 echo $OUTPUT->heading(get_string('nothingtodisplay')); 00888 } 00889 00893 function get_row_from_keyed($rowwithkeys) { 00894 if (is_object($rowwithkeys)) { 00895 $rowwithkeys = (array)$rowwithkeys; 00896 } 00897 $row = array(); 00898 foreach (array_keys($this->columns) as $column) { 00899 if (isset($rowwithkeys[$column])) { 00900 $row [] = $rowwithkeys[$column]; 00901 } else { 00902 $row[] =''; 00903 } 00904 } 00905 return $row; 00906 } 00910 function get_download_menu() { 00911 $allclasses= get_declared_classes(); 00912 $exportclasses = array(); 00913 foreach ($allclasses as $class) { 00914 $matches = array(); 00915 if (preg_match('/^table\_([a-z]+)\_export\_format$/', $class, $matches)) { 00916 $type = $matches[1]; 00917 $exportclasses[$type]= get_string("download$type", 'table'); 00918 } 00919 } 00920 return $exportclasses; 00921 } 00922 00926 function download_buttons() { 00927 if ($this->is_downloadable() && !$this->is_downloading()) { 00928 $downloadoptions = $this->get_download_menu(); 00929 $html = '<form action="'. $this->baseurl .'" method="post">'; 00930 $html .= '<div class="mdl-align">'; 00931 $html .= '<input type="submit" value="'.get_string('downloadas', 'table').'"/>'; 00932 $html .= html_writer::select($downloadoptions, 'download', $this->defaultdownloadformat, false); 00933 $html .= '</div></form>'; 00934 00935 return $html; 00936 } else { 00937 return ''; 00938 } 00939 } 00946 function start_output() { 00947 $this->started_output = true; 00948 if ($this->exportclass!==null) { 00949 $this->exportclass->start_table($this->sheettitle); 00950 $this->exportclass->output_headers($this->headers); 00951 } else { 00952 $this->start_html(); 00953 $this->print_headers(); 00954 } 00955 } 00956 00960 function print_row($row, $classname = '') { 00961 static $suppress_lastrow = NULL; 00962 static $oddeven = 1; 00963 $rowclasses = array('r' . $oddeven); 00964 $oddeven = $oddeven ? 0 : 1; 00965 00966 if ($classname) { 00967 $rowclasses[] = $classname; 00968 } 00969 00970 echo html_writer::start_tag('tr', array('class' => implode(' ', $rowclasses))); 00971 00972 // If we have a separator, print it 00973 if ($row === NULL) { 00974 $colcount = count($this->columns); 00975 echo html_writer::tag('td', html_writer::tag('div', '', 00976 array('class' => 'tabledivider')), array('colspan' => $colcount)); 00977 00978 } else { 00979 $colbyindex = array_flip($this->columns); 00980 foreach ($row as $index => $data) { 00981 $column = $colbyindex[$index]; 00982 00983 if (empty($this->sess->collapse[$column])) { 00984 if ($this->column_suppress[$column] && $suppress_lastrow !== NULL && $suppress_lastrow[$index] === $data) { 00985 $content = ' '; 00986 } else { 00987 $content = $data; 00988 } 00989 } else { 00990 $content = ' '; 00991 } 00992 00993 echo html_writer::tag('td', $content, array( 00994 'class' => 'cell c' . $index . $this->column_class[$column], 00995 'style' => $this->make_styles_string($this->column_style[$column]))); 00996 } 00997 } 00998 00999 echo html_writer::end_tag('tr'); 01000 01001 $suppress_enabled = array_sum($this->column_suppress); 01002 if ($suppress_enabled) { 01003 $suppress_lastrow = $row; 01004 } 01005 } 01006 01010 function finish_html() { 01011 global $OUTPUT; 01012 if (!$this->started_output) { 01013 //no data has been added to the table. 01014 $this->print_nothing_to_display(); 01015 01016 } else { 01017 echo html_writer::end_tag('table'); 01018 echo html_writer::end_tag('div'); 01019 $this->wrap_html_finish(); 01020 01021 // Paging bar 01022 if(in_array(TABLE_P_BOTTOM, $this->showdownloadbuttonsat)) { 01023 echo $this->download_buttons(); 01024 } 01025 01026 if($this->use_pages) { 01027 $pagingbar = new paging_bar($this->totalrows, $this->currpage, $this->pagesize, $this->baseurl); 01028 $pagingbar->pagevar = $this->request[TABLE_VAR_PAGE]; 01029 echo $OUTPUT->render($pagingbar); 01030 } 01031 } 01032 } 01033 01041 protected function show_hide_link($column, $index) { 01042 global $OUTPUT; 01043 // Some headers contain <br /> tags, do not include in title, hence the 01044 // strip tags. 01045 01046 if (!empty($this->sess->collapse[$column])) { 01047 return html_writer::link($this->baseurl->out(false, array($this->request[TABLE_VAR_SHOW] => $column)), 01048 html_writer::empty_tag('img', array('src' => $OUTPUT->pix_url('t/switch_plus'), 'alt' => get_string('show'))), 01049 array('title' => get_string('show') . ' ' . strip_tags($this->headers[$index]))); 01050 01051 } else if ($this->headers[$index] !== NULL) { 01052 return html_writer::link($this->baseurl->out(false, array($this->request[TABLE_VAR_HIDE] => $column)), 01053 html_writer::empty_tag('img', array('src' => $OUTPUT->pix_url('t/switch_minus'), 'alt' => get_string('hide'))), 01054 array('title' => get_string('hide') . ' ' . strip_tags($this->headers[$index]))); 01055 } 01056 } 01057 01061 function print_headers() { 01062 global $CFG, $OUTPUT; 01063 01064 echo html_writer::start_tag('tr'); 01065 foreach ($this->columns as $column => $index) { 01066 01067 $icon_hide = ''; 01068 if ($this->is_collapsible) { 01069 $icon_hide = $this->show_hide_link($column, $index); 01070 } 01071 01072 $primary_sort_column = ''; 01073 $primary_sort_order = ''; 01074 if (reset($this->sess->sortby)) { 01075 $primary_sort_column = key($this->sess->sortby); 01076 $primary_sort_order = current($this->sess->sortby); 01077 } 01078 01079 switch ($column) { 01080 01081 case 'fullname': 01082 if ($this->is_sortable($column)) { 01083 $firstnamesortlink = $this->sort_link(get_string('firstname'), 01084 'firstname', $primary_sort_column === 'firstname', $primary_sort_order); 01085 01086 $lastnamesortlink = $this->sort_link(get_string('lastname'), 01087 'lastname', $primary_sort_column === 'lastname', $primary_sort_order); 01088 01089 $override = new stdClass(); 01090 $override->firstname = 'firstname'; 01091 $override->lastname = 'lastname'; 01092 $fullnamelanguage = get_string('fullnamedisplay', '', $override); 01093 01094 if (($CFG->fullnamedisplay == 'firstname lastname') or 01095 ($CFG->fullnamedisplay == 'firstname') or 01096 ($CFG->fullnamedisplay == 'language' and $fullnamelanguage == 'firstname lastname' )) { 01097 $this->headers[$index] = $firstnamesortlink . ' / ' . $lastnamesortlink; 01098 } else { 01099 $this->headers[$index] = $lastnamesortlink . ' / ' . $firstnamesortlink; 01100 } 01101 } 01102 break; 01103 01104 case 'userpic': 01105 // do nothing, do not display sortable links 01106 break; 01107 01108 default: 01109 if ($this->is_sortable($column)) { 01110 $this->headers[$index] = $this->sort_link($this->headers[$index], 01111 $column, $primary_sort_column == $column, $primary_sort_order); 01112 } 01113 } 01114 01115 $attributes = array( 01116 'class' => 'header c' . $index . $this->column_class[$column], 01117 'scope' => 'col', 01118 ); 01119 if ($this->headers[$index] === NULL) { 01120 $content = ' '; 01121 } else if (!empty($this->sess->collapse[$column])) { 01122 $content = $icon_hide; 01123 } else { 01124 if (is_array($this->column_style[$column])) { 01125 $attributes['style'] = $this->make_styles_string($this->column_style[$column]); 01126 } 01127 $content = $this->headers[$index] . html_writer::tag('div', 01128 $icon_hide, array('class' => 'commands')); 01129 } 01130 echo html_writer::tag('th', $content, $attributes); 01131 } 01132 01133 echo html_writer::end_tag('tr'); 01134 } 01135 01142 protected function sort_icon($isprimary, $order) { 01143 global $OUTPUT; 01144 01145 if (!$isprimary) { 01146 return ''; 01147 } 01148 01149 if ($order == SORT_ASC) { 01150 return html_writer::empty_tag('img', 01151 array('src' => $OUTPUT->pix_url('t/down'), 'alt' => get_string('asc'))); 01152 } else { 01153 return html_writer::empty_tag('img', 01154 array('src' => $OUTPUT->pix_url('t/up'), 'alt' => get_string('desc'))); 01155 } 01156 } 01157 01165 protected function sort_order_name($isprimary, $order) { 01166 if ($isprimary && $order != SORT_ASC) { 01167 return get_string('desc'); 01168 } else { 01169 return get_string('asc'); 01170 } 01171 } 01172 01181 protected function sort_link($text, $column, $isprimary, $order) { 01182 return html_writer::link($this->baseurl->out(false, 01183 array($this->request[TABLE_VAR_SORT] => $column)), 01184 $text . get_accesshide(get_string('sortby') . ' ' . 01185 $text . ' ' . $this->sort_order_name($isprimary, $order))) . ' ' . 01186 $this->sort_icon($isprimary, $order); 01187 } 01188 01192 function start_html() { 01193 global $OUTPUT; 01194 // Do we need to print initial bars? 01195 $this->print_initials_bar(); 01196 01197 // Paging bar 01198 if ($this->use_pages) { 01199 $pagingbar = new paging_bar($this->totalrows, $this->currpage, $this->pagesize, $this->baseurl); 01200 $pagingbar->pagevar = $this->request[TABLE_VAR_PAGE]; 01201 echo $OUTPUT->render($pagingbar); 01202 } 01203 01204 if (in_array(TABLE_P_TOP, $this->showdownloadbuttonsat)) { 01205 echo $this->download_buttons(); 01206 } 01207 01208 $this->wrap_html_start(); 01209 // Start of main data table 01210 01211 echo html_writer::start_tag('div', array('class' => 'no-overflow')); 01212 echo html_writer::start_tag('table', $this->attributes); 01213 01214 } 01215 01221 function make_styles_string($styles) { 01222 if (empty($styles)) { 01223 return null; 01224 } 01225 01226 $string = ''; 01227 foreach($styles as $property => $value) { 01228 $string .= $property . ':' . $value . ';'; 01229 } 01230 return $string; 01231 } 01232 } 01233 01234 01240 class table_sql extends flexible_table { 01241 01242 public $countsql = NULL; 01243 public $countparams = NULL; 01247 public $sql = NULL; 01251 public $rawdata = NULL; 01252 01256 public $is_sortable = true; 01260 public $is_collapsible = true; 01261 01266 function __construct($uniqueid) { 01267 parent::__construct($uniqueid); 01268 // some sensible defaults 01269 $this->set_attribute('cellspacing', '0'); 01270 $this->set_attribute('class', 'generaltable generalbox'); 01271 } 01272 01278 function table_sql($uniqueid) { 01279 debugging('Please update your code to user PHP5-style parent::__construct(...), ' . 01280 'not parent::table_sql(...).'); 01281 $this->__construct($uniqueid); 01282 } 01283 01290 function build_table() { 01291 if ($this->rawdata) { 01292 foreach ($this->rawdata as $row) { 01293 $formattedrow = $this->format_row($row); 01294 $this->add_data_keyed($formattedrow, 01295 $this->get_row_class($row)); 01296 } 01297 } 01298 } 01299 01305 function get_row_class($row) { 01306 return ''; 01307 } 01308 01318 function set_count_sql($sql, array $params = NULL) { 01319 $this->countsql = $sql; 01320 $this->countparams = $params; 01321 } 01322 01329 function set_sql($fields, $from, $where, array $params = NULL) { 01330 $this->sql = new stdClass(); 01331 $this->sql->fields = $fields; 01332 $this->sql->from = $from; 01333 $this->sql->where = $where; 01334 $this->sql->params = $params; 01335 } 01336 01344 function query_db($pagesize, $useinitialsbar=true) { 01345 global $DB; 01346 if (!$this->is_downloading()) { 01347 if ($this->countsql === NULL) { 01348 $this->countsql = 'SELECT COUNT(1) FROM '.$this->sql->from.' WHERE '.$this->sql->where; 01349 $this->countparams = $this->sql->params; 01350 } 01351 $grandtotal = $DB->count_records_sql($this->countsql, $this->countparams); 01352 if ($useinitialsbar && !$this->is_downloading()) { 01353 $this->initialbars($grandtotal > $pagesize); 01354 } 01355 01356 list($wsql, $wparams) = $this->get_sql_where(); 01357 if ($wsql) { 01358 $this->countsql .= ' AND '.$wsql; 01359 $this->countparams = array_merge($this->countparams, $wparams); 01360 01361 $this->sql->where .= ' AND '.$wsql; 01362 $this->sql->params = array_merge($this->sql->params, $wparams); 01363 01364 $total = $DB->count_records_sql($this->countsql, $this->countparams); 01365 } else { 01366 $total = $grandtotal; 01367 } 01368 01369 $this->pagesize($pagesize, $total); 01370 } 01371 01372 // Fetch the attempts 01373 $sort = $this->get_sql_sort(); 01374 if ($sort) { 01375 $sort = "ORDER BY $sort"; 01376 } 01377 $sql = "SELECT 01378 {$this->sql->fields} 01379 FROM {$this->sql->from} 01380 WHERE {$this->sql->where} 01381 {$sort}"; 01382 01383 if (!$this->is_downloading()) { 01384 $this->rawdata = $DB->get_records_sql($sql, $this->sql->params, $this->get_page_start(), $this->get_page_size()); 01385 } else { 01386 $this->rawdata = $DB->get_records_sql($sql, $this->sql->params); 01387 } 01388 } 01389 01394 function out($pagesize, $useinitialsbar, $downloadhelpbutton='') { 01395 global $DB; 01396 if (!$this->columns) { 01397 $onerow = $DB->get_record_sql("SELECT {$this->sql->fields} FROM {$this->sql->from} WHERE {$this->sql->where}", $this->sql->params); 01398 //if columns is not set then define columns as the keys of the rows returned 01399 //from the db. 01400 $this->define_columns(array_keys((array)$onerow)); 01401 $this->define_headers(array_keys((array)$onerow)); 01402 } 01403 $this->setup(); 01404 $this->query_db($pagesize, $useinitialsbar); 01405 $this->build_table(); 01406 $this->finish_output(); 01407 } 01408 } 01409 01410 01416 class table_default_export_format_parent { 01421 var $table; 01422 01427 var $documentstarted = false; 01428 function table_default_export_format_parent(&$table) { 01429 $this->table =& $table; 01430 } 01431 01432 function set_table(&$table) { 01433 $this->table =& $table; 01434 } 01435 01436 function add_data($row) { 01437 return false; 01438 } 01439 01440 function add_seperator() { 01441 return false; 01442 } 01443 01444 function document_started() { 01445 return $this->documentstarted; 01446 } 01452 function format_text($text, $format=FORMAT_MOODLE, $options=NULL, $courseid=NULL) { 01453 //use some whitespace to indicate where there was some line spacing. 01454 $text = str_replace(array('</p>', "\n", "\r"), ' ', $text); 01455 return strip_tags($text); 01456 } 01457 } 01458 01459 01465 class table_spreadsheet_export_format_parent extends table_default_export_format_parent { 01466 var $rownum; 01467 var $workbook; 01468 var $worksheet; 01472 var $formatnormal; 01476 var $formatheaders; 01477 01481 var $fileextension; 01482 01486 function define_workbook() { 01487 } 01488 01489 function start_document($filename) { 01490 $filename = $filename.'.'.$this->fileextension; 01491 $this->define_workbook(); 01492 // format types 01493 $this->formatnormal =& $this->workbook->add_format(); 01494 $this->formatnormal->set_bold(0); 01495 $this->formatheaders =& $this->workbook->add_format(); 01496 $this->formatheaders->set_bold(1); 01497 $this->formatheaders->set_align('center'); 01498 // Sending HTTP headers 01499 $this->workbook->send($filename); 01500 $this->documentstarted = true; 01501 } 01502 01503 function start_table($sheettitle) { 01504 $this->worksheet =& $this->workbook->add_worksheet($sheettitle); 01505 $this->rownum=0; 01506 } 01507 01508 function output_headers($headers) { 01509 $colnum = 0; 01510 foreach ($headers as $item) { 01511 $this->worksheet->write($this->rownum,$colnum,$item,$this->formatheaders); 01512 $colnum++; 01513 } 01514 $this->rownum++; 01515 } 01516 01517 function add_data($row) { 01518 $colnum = 0; 01519 foreach ($row as $item) { 01520 $this->worksheet->write($this->rownum,$colnum,$item,$this->formatnormal); 01521 $colnum++; 01522 } 01523 $this->rownum++; 01524 return true; 01525 } 01526 01527 function add_seperator() { 01528 $this->rownum++; 01529 return true; 01530 } 01531 01532 function finish_table() { 01533 } 01534 01535 function finish_document() { 01536 $this->workbook->close(); 01537 exit; 01538 } 01539 } 01540 01541 01547 class table_excel_export_format extends table_spreadsheet_export_format_parent { 01548 var $fileextension = 'xls'; 01549 01550 function define_workbook() { 01551 global $CFG; 01552 require_once("$CFG->libdir/excellib.class.php"); 01553 // Creating a workbook 01554 $this->workbook = new MoodleExcelWorkbook("-"); 01555 } 01556 01557 } 01558 01559 01565 class table_ods_export_format extends table_spreadsheet_export_format_parent { 01566 var $fileextension = 'ods'; 01567 function define_workbook() { 01568 global $CFG; 01569 require_once("$CFG->libdir/odslib.class.php"); 01570 // Creating a workbook 01571 $this->workbook = new MoodleODSWorkbook("-"); 01572 } 01573 } 01574 01575 01581 class table_text_export_format_parent extends table_default_export_format_parent { 01582 protected $seperator = "\t"; 01583 protected $mimetype = 'text/tab-separated-values'; 01584 protected $ext = '.txt'; 01585 01586 public function start_document($filename) { 01587 $this->filename = $filename . $this->ext; 01588 header('Content-Type: ' . $this->mimetype . '; charset=UTF-8'); 01589 header('Content-Disposition: attachment; filename="' . $this->filename . '"'); 01590 header('Expires: 0'); 01591 header('Cache-Control: must-revalidate,post-check=0,pre-check=0'); 01592 header('Pragma: public'); 01593 $this->documentstarted = true; 01594 } 01595 01596 public function start_table($sheettitle) { 01597 //nothing to do here 01598 } 01599 01600 public function output_headers($headers) { 01601 echo $this->format_row($headers); 01602 } 01603 01604 public function add_data($row) { 01605 echo $this->format_row($row); 01606 return true; 01607 } 01608 01609 public function finish_table() { 01610 echo "\n\n"; 01611 } 01612 01613 public function finish_document() { 01614 exit; 01615 } 01616 01621 protected function format_row($data) { 01622 $escapeddata = array(); 01623 foreach ($data as $value) { 01624 $escapeddata[] = '"' . str_replace('"', '""', $value) . '"'; 01625 } 01626 return implode($this->seperator, $escapeddata) . "\n"; 01627 } 01628 } 01629 01630 01636 class table_tsv_export_format extends table_text_export_format_parent { 01637 protected $seperator = "\t"; 01638 protected $mimetype = 'text/tab-separated-values'; 01639 protected $ext = '.txt'; 01640 } 01641 01642 01648 class table_csv_export_format extends table_text_export_format_parent { 01649 protected $seperator = ","; 01650 protected $mimetype = 'text/csv'; 01651 protected $ext = '.csv'; 01652 } 01653 01654 01660 class table_xhtml_export_format extends table_default_export_format_parent { 01661 function start_document($filename) { 01662 header("Content-Type: application/download\n"); 01663 header("Content-Disposition: attachment; filename=\"$filename.html\""); 01664 header("Expires: 0"); 01665 header("Cache-Control: must-revalidate,post-check=0,pre-check=0"); 01666 header("Pragma: public"); 01667 //html headers 01668 echo <<<EOF 01669 <?xml version="1.0" encoding="UTF-8"?> 01670 <!DOCTYPE html 01671 PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 01672 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 01673 01674 <html xmlns="http://www.w3.org/1999/xhtml" 01675 xml:lang="en" lang="en"> 01676 <head> 01677 <style type="text/css">/*<![CDATA[*/ 01678 01679 .flexible th { 01680 white-space:normal; 01681 } 01682 th.header, td.header, div.header { 01683 border-color:#DDDDDD; 01684 background-color:lightGrey; 01685 } 01686 .flexible th { 01687 white-space:nowrap; 01688 } 01689 th { 01690 font-weight:bold; 01691 } 01692 01693 .generaltable { 01694 border-style:solid; 01695 } 01696 .generalbox { 01697 border-style:solid; 01698 } 01699 body, table, td, th { 01700 font-family:Arial,Verdana,Helvetica,sans-serif; 01701 font-size:100%; 01702 } 01703 td { 01704 border-style:solid; 01705 border-width:1pt; 01706 } 01707 table { 01708 border-collapse:collapse; 01709 border-spacing:0pt; 01710 width:80%; 01711 margin:auto; 01712 } 01713 01714 h1, h2 { 01715 text-align:center; 01716 } 01717 .bold { 01718 font-weight:bold; 01719 } 01720 .mdl-align { 01721 text-align:center; 01722 } 01723 /*]]>*/</style> 01724 <title>$filename</title> 01725 </head> 01726 <body> 01727 EOF; 01728 $this->documentstarted = true; 01729 } 01730 01731 function start_table($sheettitle) { 01732 $this->table->sortable(false); 01733 $this->table->collapsible(false); 01734 echo "<h2>{$sheettitle}</h2>"; 01735 $this->table->start_html(); 01736 } 01737 01738 function output_headers($headers) { 01739 $this->table->print_headers(); 01740 } 01741 01742 function add_data($row) { 01743 $this->table->print_row($row); 01744 return true; 01745 } 01746 01747 function add_seperator() { 01748 $this->table->print_row(NULL); 01749 return true; 01750 } 01751 01752 function finish_table() { 01753 $this->table->finish_html(); 01754 } 01755 01756 function finish_document() { 01757 echo "</body>\n</html>"; 01758 exit; 01759 } 01760 01761 function format_text($text, $format=FORMAT_MOODLE, $options=NULL, $courseid=NULL) { 01762 if (is_null($options)) { 01763 $options = new stdClass; 01764 } 01765 //some sensible defaults 01766 if (!isset($options->para)) { 01767 $options->para = false; 01768 } 01769 if (!isset($options->newlines)) { 01770 $options->newlines = false; 01771 } 01772 if (!isset($options->smiley)) { 01773 $options->smiley = false; 01774 } 01775 if (!isset($options->filter)) { 01776 $options->filter = false; 01777 } 01778 return format_text($text, $format, $options); 01779 } 01780 }