* @copyright 2001-2007 VIKO team and contributors * @license http://www.gnu.org/licenses/gpl.html GPL 2.0 */ /** * This class simplifies the usage of PEAR class HTML_Table */ require_once 'HTML/Table.php'; /** * This class uses HTML class for creating abbrevation elements */ require_once 'HTML.php'; /** * Footer type EMPTY */ define('CONTENT_TABLE_EMPTY', 0); /** * Footer type SUM */ define('CONTENT_TABLE_SUM', 1); /** * Cell type NORMAL */ define('CONTENT_TABLE_NORMAL', 0); /** * Cell type NUMERIC */ define('CONTENT_TABLE_NUMERIC', 1); /** * Cell type DELETE */ define('CONTENT_TABLE_FILESIZE', 2); /** * Cell type DELETE */ define('CONTENT_TABLE_DELETE', 3); /** * Manages creation of HTML data tables for VIKO environment */ class ContentTable { /** * Reference to the table object * * @access private */ var $_table; /** * Reference to the table header object * * @access private */ var $_thead; /** * Reference to the table body object * * @access private */ var $_tbody; /** * Reference to the table footer object * * @access private */ var $_tfoot; /** * The schema (columns description) of the table * * @access private */ var $_schema; /** * The content of the table (list of rows) * * @access private */ var $_data; /** * Constructs new ContentTable instance * * The $schema must be an array consisting of column name * and column description pairs. Column name is simply a unique * value identifying the column. Column description is an * array consisting of attributes, that describe that column. * * In each description-array, the "title" attribute is required, * all others are optional. Here are all the possible attributes: * *
* $schema = array( * "name" => array( * "title" => _("School name"), * "footer" => _("Total"), * ), * "courses" => array( * "title" => _("Nr of Courses"), * "type" => CONTENT_TABLE_NUMERIC, * "footer" => CONTENT_TABLE_SUM, * ), * "filesize" => array( * "title" => _("Size of files"), * "type" => CONTENT_TABLE_NUMERIC, * "footer" => CONTENT_TABLE_FILESIZE, * ), * "delete" => array( * "title" => _("Delete school"), * "type" => CONTENT_TABLE_DELETE, * ), * ); ** * @access public * @param array $schema an array describing the columns in this table */ function ContentTable( $schema ) { $this->_schema = $schema; // initialize the encapsulated table object $this->_table =& new HTML_Table(); $this->_thead =& $this->_table->getHeader(); $this->_tbody =& $this->_table->getBody(); $this->_tfoot =& $this->_table->getFooter(); } /** * Loads the table with data * * $data must contain two-dimensional array with the following structure: * *
* $data = array( * array("first column content", "second column content", ...), // first row * array("first column content", "second column content", ...), // second row * array("first column content", "second column content", ...), // third row * ... * ) ** * Alternatively the fields in a row might also be given explicit * association with columns by giving the column name as an index. * In that way, the ordering of fields doesn't matter and empty * fields may just be skipped, like in the following example: * *
* $row = array( * "first_column_name" => "first column content", * "third_column_name" => "third column content", * ... * ) ** * @access public * @param array $data all the rows of a table */ function PopulateWithData( $data ) { $this->_data = $data; } /** * Converts the table into HTML * * @access public * @return string HTML table element */ function toHTML() { $this->createTableHead(); $this->createTableBody(); $this->createTableFoot(); $this->setTableAttributes(); return $this->_table->toHTML(); } function createTableHead() { // create table head $col_index=0; foreach ( $this->_schema as $col_name => $column ) { $this->_thead->setHeaderContents( 0, $col_index, $column['title'] ); $col_index++; } } function createTableBody() { // fill table body with data for ( $row_index=0; $row_index < count($this->_data); $row_index++ ) { $row = $this->_data[$row_index]; for ( $col_index=0; $col_index < count($row); $col_index++ ) { $cell = $this->createCellContents( $row[$col_index] ); $this->_tbody->setCellContents( $row_index, $col_index, $cell ); } } } function createCellContents($content) { if ( is_array($content) ) { return HTML::a( $content[0], $content[1] ); } else { return $content; } } function createTextualCellContent($content) { if ( is_array($content) ) { return $content[1]; } else { return $content; } } function createTableFoot() { $col_index=0; foreach ( $this->_schema as $col_name => $column ) { // when the footer type is defined, set the footer if ( isset($column['footer']) && $column['footer'] !== CONTENT_TABLE_EMPTY ) { $footer_cell = $this->createFooterCell( $column['footer'], $col_index ); $this->_tfoot->setCellContents( 0, $col_index, $footer_cell ); } $col_index++; } } /** * Creates a footer cell value for a particular type of footer */ function createFooterCell($footer_type, $col_index) { if ( $footer_type === CONTENT_TABLE_SUM ) { return $this->columnSum($col_index); } else { // anything else is considered a literal text of footer return $footer_type; } } /** * Calculates the sum of values in a column with specified index. * * If the data doesn't consist entirely of numbers, the sum * will result in "not a number". */ function columnSum($col_index) { $sum = 0; foreach ( $this->_data as $row ) { if ( !is_numeric($row[$col_index]) ) { return 'not a number'; } $sum+= $row[$col_index]; } return $sum; } /** * Sets all kinds of table attributes, like column types and * marking odd and even rows. */ function setTableAttributes() { $this->createStripes($this->_tbody); // set attributes for columns $col_index=0; foreach ( $this->_schema as $column ) { if ( isset($column['type']) && $column['type'] !== CONTENT_TABLE_NORMAL ) { $this->setColumnType($column['type'], $col_index); } $col_index++; } } function setColumnType($column_type, $col_index) { if ( $column_type === CONTENT_TABLE_NUMERIC ) { // numeric type applies class "nr" only to the body and footer $attr = array('class' => 'nr'); $this->_tfoot->setColAttributes($col_index, $attr); $this->_tbody->setColAttributes($col_index, $attr); } elseif ( $column_type === CONTENT_TABLE_FILESIZE ) { // filesize type applies class "nr" only to the body and footer $attr = array('class' => 'nr'); $this->_tfoot->setColAttributes($col_index, $attr); $this->_tbody->setColAttributes($col_index, $attr); // the fields themselves also have to be converted for ( $i = 0; $i < count($this->_data); $i++ ) { $size = $this->_data[$i][$col_index]; $formatted_size = $this->makeHumanReadableFilesize($size); $this->_tbody->setCellContents($i, $col_index, $formatted_size); } // and the footer too $size = $this->_tfoot->getCellContents(0, $col_index); $formatted_size = $this->makeHumanReadableFilesize($size); $this->_tfoot->setCellContents(0, $col_index, $formatted_size); } elseif ( $column_type === CONTENT_TABLE_DELETE ) { // delete type applies class 'delete' only to the body and header $attr = array('class' => 'delete'); $this->_thead->setColAttributes($col_index, $attr); $this->_tbody->setColAttributes($col_index, $attr); // the header must be converted into abbrevation element $title = $this->_thead->getCellContents(0, $col_index); $abbr = HTML::abbr('X', $title); $this->_thead->setHeaderContents(0, $col_index, $abbr); // the data cells containing URI's have to be converted to links. for ( $i = 0; $i < count($this->_data); $i++ ) { // delete-cells contain URI's $uri = $this->_data[$i][$col_index]; // contents of first column will be contained inside title $first_cell = $this->createTextualCellContent( $this->_data[$i][0] ); $title = sprintf( _('delete %s'), $first_cell ); $link = HTML::a($uri, 'X', $title); $this->_tbody->setCellContents($i, $col_index, $link); } } else { // anything else is considered a literal CSS class name $attr = array('class' => $column_type ); // CSS class is applied to all parts of the table $this->_thead->setColAttributes($col_index, $attr); $this->_tfoot->setColAttributes($col_index, $attr); $this->_tbody->setColAttributes($col_index, $attr); } } function createStripes(&$table_section) { $odd_row = array('class' => 'odd'); $even_row = array('class' => 'even'); $table_section->altRowAttributes(0, $odd_row, $even_row, true); } /** * Returns the size of the file in human-readable format * * Mutch like the -h option in many UNIX utilities. * If the size is >= 1024 bytes, it is represented in KB, * if size is >= 1024 KB, it's given in MB. * * The unit B, KB, MB or GB is appended to the returned string. * If the value is a fraction, only one place after the comma is shown. * * @static * @param int $size file size in bytes * @return string file size */ function makeHumanReadableFilesize( $size ) { if ( $size < 1024 ) { return $size . " B"; } elseif ( $size < 1024*1024 ) { return round($size/1024, 1) . " KB"; } elseif ( $size < 1024*1024*1024 ) { return round($size/1024/1024, 1) . " MB"; } else { return round($size/1024/1024/1024, 1) . " GB"; } } } ?>