Note:

If you want to create a new page for developers, you should create it on the Moodle Developer Resource site.

lib/tablelib.php

From MoodleDocs

Status of this doc

This doc is a description of proposed additions to the api for using tablelib. It has not yet been agreed on. Seemed a good idea to create it at this url rather than some development notes page for instance so that the history of this page will include the changes made to the original proposal.

What changes in the new api?

  • Currently the code for creating table often involves a lot of duplication of code. New api can improve things.
  • New API handles downloads
    • download export formats are seperated into classes and it is simple to add more formats. Added two more formats. Unpaged XHTML format and comma seperated values format.
  • No longer have to make sure that column data is added to the table in the same order as columns are declared. Can have the logic for choosing what columns to include in the table in one place.
  • New mechanism in table_sql allows appropriate code to be automatically called to format data before putting it into the table.

Skeleton Usage

In order to check your sql query is working as expected when developing a page it can be useful just to output all the data from the query in the table before going on to work out how you want to format data. The code below will output all the data from your query in a collapsible, sortable table. It automatically displays all columns returned from the db.

You should go on to :

  • specify what columns to include in the table and what names to display for the columns using define_columms and define_headers
  • use your own child class of easy_table and define methods col_{columnname} to add hyperlinks etc to the table. You can also use method other_cols.

See below for examples of typical usage.

<?php  // $Id$
/**
 * Simple file test.php to drop into root of Moodle installation.
 * This is the skeleton code to print a downloadable, paged, sorted table of
 * data from a sql query.
 */
require "config.php";
require "$CFG->libdir/tablelib.php";

$download = optional_param('download', '', PARAM_ALPHA);

$table = new table_sql('uniqueid');
$table->is_downloading($download, 'test',
                    'testing123');
if (!$table->is_downloading()) {
    // Only print headers if not asked to download data
    /// Print the page header
    $navigation = build_navigation('Testing table class');
    
    print_header_simple('Testing ', 'Testing table class', $navigation);

}

//work out the sql for the table.
$table->set_sql('*', "{$CFG->prefix}user", '1');

$table->define_baseurl("$CFG->wwwroot/test.php");

$table->out(40, true);

if (!$table->is_downloading()) {
    print_footer();
}
?>

The Next Step : Typical Usage

Define table

Define table class in file somethingsomthing_table.php

In the file define a child class of 'sql_table'. Mostly this child class will just contain methods to format data for display.

Format data for display

Define methods col_{colmname} to process data from db and to add it to table. Eg. Here is an example from table class quiz_report_overview_table

    function col_timefinish($attempt){
        if ($attempt->attempt) {
            if ($attempt->timefinish) {
                $timefinish = userdate($attempt->timefinish, $this->strtimeformat);
                if (!$this->is_downloading()) {
                    return '<a href="review.php?q='.$this->quiz->id.'&attempt='.$attempt->attempt.'">'.$timefinish.'</a>';
                } else {
                    return $timefinish;
                }
            } else {
                return  '-';
            }
        } else {
            return  '-';
        }
    }

Where you do not know the names of the columns at the time of writing the class definition then you can use other_cols method. Eg.

    function other_cols($colname, $attempt){
        if (preg_match('/^qsgrade([0-9]+)$/', $colname, $matches)){
            $questionid = $matches[1];
            $question = $this->questions[$questionid];
            $state = new object();
            $state->event = $attempt->{'qsevent'.$questionid};
            if (question_state_is_graded($state)) {
                $grade = quiz_rescale_grade($attempt->{'qsgrade'.$questionid}, $this->quiz);
            } else {
                $grade = '--';
            }
            if (!$this->is_downloading()) {
                $grade = $grade.'/'.quiz_rescale_grade($question->grade, $this->quiz);
                return link_to_popup_window('/mod/quiz/reviewquestion.php?state='.
                        $attempt->{'qsid'.$questionid}.'&number='.$question->number,
                        'reviewquestion', $grade, 450, 650, get_string('reviewresponse', 'quiz'),
                        'none', true);
            } else {
                return $grade;
            }     
        } else {
            return NULL;
        }
    }

If there is no method col_{column name} and other_cols returns NULL then the column data is put straight in the table unprocessed.

Use your table class

        //start page
        $download = optional_param('download', '', PARAM_ALPHA);

        $table = new name_of_your_table('uniqueid');
        $table->is_downloading($download, $filenamefordownload, $sheettitle);
        if (!$table->is_downloading()) {
            // Only print headers if not asked to download data
            $this->print_header_and_tabs($cm, $course, $quiz, "overview");
        }
        //various page set up stuff
        if (!$table->is_downloading()) { //do not print notices when downloading
            //wrap output of html in these if conditions
        }
        
        //work out the sql for the table.

        //use this method only if you want to specify some sql with less joins for 
        //counting the total records
        $table->set_count_sql("SELECT COUNT(1) FROM $from WHERE $where");

        if ($something) {
            // Add some more joins
        }
        
        $table->set_sql($fields, $from, $where);
        // Define table columns
        $columns = array();
        $headers = array();
        

        if (!$table->is_downloading() && $candelete) {
            $columns[]= 'checkbox';
            $headers[]= NULL;
        }
        
        if (!$table->is_downloading() && $CFG->grade_report_showuserimage) {
            $columns[]= 'picture';
            $headers[]= '';
        }
        if (!$table->is_downloading()){
            $columns[]= 'fullname';
            $headers[]= get_string('name');
        } else {
            $columns[]= 'lastname';
            $headers[]= get_string('lastname');
            $columns[]= 'firstname';
            $headers[]= get_string('firstname');
        }

        if ($CFG->grade_report_showuseridnumber) {
            $columns[]= 'idnumber';
            $headers[]= get_string('idnumber');
        }
        
        $columns[]= 'timestart';
        $headers[]= get_string('startedon', 'quiz');

        $columns[]= 'timefinish';
        $headers[]= get_string('timecompleted','quiz');

        $columns[]= 'duration';
        $headers[]= get_string('attemptduration', 'quiz');

        if ($detailedmarks) {
            foreach ($questions as $id => $question) {
                // Ignore questions of zero length
                $columns[] = 'qsgrade'.$id;
                $headers[] = '#'.$question->number;
            }
        }

        if ($showgrades) {
            $columns[] = 'sumgrades';
            $headers[] = get_string('grade', 'quiz').'/'.$quiz->grade;
        }

        if ($hasfeedback) {
            $columns[] = 'feedbacktext';
            $headers[] = get_string('feedback', 'quiz');
        }
        
        $table->define_columns($columns);
        $table->define_headers($headers);
        $table->sortable(true, 'uniqueid');
        
        // Set up the table some of these settings will be ignored for downloads
        $table->define_baseurl($reporturl->out(false, $displayoptions));


        $table->column_suppress('picture');
        $table->column_suppress('fullname');
        $table->column_suppress('idnumber');
        
        $table->no_sorting('feedbacktext');

        $table->column_class('picture', 'picture');
        $table->column_class('fullname', 'bold');
        $table->column_class('sumgrades', 'bold');

        $table->set_attribute('id', 'attempts');

        $table->out($pagesize, $useinitialsbar);
        
        if (!$table->is_downloading()) {
            //footer and other html stuff to display
        }

See also