- <?php
- /*
- * Lokorin.com
- * Copyright 2004-2006
- * Licensed under the GNU LGPL. See COPYING for full terms.
- */
- /**
- * A library that contains everything that is connected to table elements.
- * @author Andreas Launila
- * @version $Revision: 1.7 $
- * @package com.lokorin.lokorin.lib
- * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
- */
-
- /**
- * For access to common constants and functions.
- */
- require_once('common.php');
-
- CssHandler::getInstance()->includeCss('tables');
-
- /**
- * Describes a Table.
- * @author Andreas Launila
- * @package com.lokorin.lokorin.lib
- */
- class Table {
- /**
- * Contains the header (if any) for the Table.
- * @var Header
- */
- private $tableHeader;
- /**
- * Contains an array which maps ints onto other ints. The mapping can
- * rearange the order in which the row entries are displayed.
- * @var access
- */
- private $entryMap;
- /**
- * Contains an array which contains an array for each row. The key of the
- * rows should be numeric, the value should be the value that should be
- * displayed.
- * @var array
- */
- private $rows;
- /**
- * The CSS class to use for the header when displaying.
- * @var string
- */
- private $cssClass;
-
- /**
- * Constructor for Table.
- */
- public function __construct() {
- $this->tableHeader = null;
- $this->rows = array();
- $this->entryMap = '';
- }
-
- /**
- * Sets a specified header as the new header that should be used by the
- * table.
- * @param Header $newHeader The new header that should be used for the
- * table.
- */
- public function setHeader(Header $newHeader) {
- $this->tableHeader = $newHeader;
- }
-
- /**
- * Gets the header of the table.
- * @return Header The Header instance for the table.
- */
- public function getHeader() {
- return $this->tableHeader;
- }
-
- /**
- * Adds a new row to the table.
- * @param array $row The row that should be added. The values of the array
- * is the ones that should be added.
- */
- public function addRow($row) {
- if(!is_array($row)) {
- return;
- }
- $this->rows[] = $row;
- }
-
- /**
- * Gets the table in HTML format.
- * @return string The describes table in HTML format.
- */
- public function getTable() {
- if($this->cssClass != '') {
- $class = ' class="'.$this->cssClass.'"';
- } else {
- $class = '';
- }
- $output = '<table'.$class.'>';
- if(isset($this->tableHeader)) {
- $header = $this->tableHeader;
- $output .= $header->getAsHTML()."\n";
- $this->rows = $header->performSort($this->rows);
- }
- if(is_array($this->entryMap)) {
- $arr = array_flip($this->entryMap);
- $rows = array();
- foreach($this->rows as $k => $row) {
- if(isset($arr[$k])) {
- $rows[$arr[$k]] = $row;
- } else {
- $rows[$k] = $row;
- }
- }
- } else {
- $rows = $this->rows;
- }
- foreach($rows as $k => $row) {
- if($k % 2 == 1) {
- //So that one can alternate colors
- $output .= '<tr class="odd">';
- } else {
- $output .= '<tr>';
- }
- foreach($row as $value) {
- $output .= '<td>'.$value.'</td>'."\n";
- }
- $output .= '</tr>';
- }
- $output .= '</table>';
- return $output;
- }
-
- /**
- * Sets a row mapping for the table to use. The row map rearranges the
- * values of a row into a different order.
- * @param array $map The map should define value for all keys corresponding
- * to the columns that it want changed in each row. The value should
- * be the column to which the value should be moved. For instance the
- * array (1 => 4, 4 => 1) will rearrange the values so that the second
- * columns' values are moved to the fifth column and vice versa.
- * Observe that the first column has index 0 and so on.
- */
- public function setRowMapping($map) {
- $this->entryMap = $map;
- }
-
- /**
- * Sets the CSS class that the table should use.
- * @param string $class The name of the CSS class to use.
- */
- public function setCssClass($class) {
- $this->cssClass = $class;
- }
- }
-
- /**
- * Descibes an Header.
- * @author Andreas Launila
- * @package com.lokorin.lokorin.lib
- */
- class Header {
- /**
- * Contains the captions for the header.
- * @var array
- */
- private $captions;
-
- /**
- * Constructor for Header.
- * @param array $caption An optional param to define the captions for the
- * header. All captions have to be unique.
- */
- public function __construct($captions = array()) {
- $this->captions = array();
- if(is_array($captions)) {
- foreach($captions as $caption) {
- $this->add($caption);
- }
- }
- }
-
- /**
- * Adds an new caption to the header.
- * @param string $caption The new caption to add. This caption has to be
- * unique, it may not already exist in the table's captions.
- */
- public function add($caption) {
- if(!in_array($caption, $this->captions)) {
- $this->captions[] = $caption;
- }
- }
-
- /**
- * Removes a caption from the header, assuming that the caption exists.
- * @param string $caption The caption to attempt to remove.
- */
- public function remove($caption) {
- if(in_array($caption, $this->captions)) {
- unset($this->captions[$caption]);
- }
- }
-
- /**
- * Gets the header as HTML, including the row tags.
- * I.e. <tr><th>...</th>...</tr>
- * @return string An table header in HTML format.
- */
- public function getAsHtml() {
- doInclude('lib_util');
- $html = '<tr>';
- foreach($this->captions as $caption) {
- if(isset($_GET['tsort']) && ($_GET['tsort'] == 'a'.$caption)) {
- $params = addQueryParams(array('tsort' => 'd'.$caption));
- } else {
- $params = addQueryParams(array('tsort' => 'a'.$caption));
- }
- $html .= '<th><a href="'.htmlspecialchars(SELF.'?'.$params).'">'.
- $caption.'</a></th>';
- }
- return $html.'</tr>';
- }
-
- /**
- * Performs a sort, if the user has requested one, on the specified rows.
- * @param array $rows The rows that should be sorted. The rows should have
- * as many columns as the header has captions.
- * @return The rows, sorted in the specified way.
- */
- public function performSort($rows) {
- if(isset($_GET['tsort'])) {
- /*
- * The parameter is composed of two parts, the first character is
- * either 'a' or 'd' (ascending or descending). The rest of the
- * parameter is the caption for the column that should be sorted.
- */
- if($_GET['tsort']{0} == 'a') {
- $order = SORT_ASC;
- } else if($_GET['tsort']{0} == 'd') {
- $order = SORT_DESC;
- } else {
- //Invalid order type specified.
- return $rows;
- }
- $captionToUse = substr($_GET['tsort'], 1);
- } else {
- //The user has not requested any sorting.
- return $rows;
- }
-
- $columnIndex = -1;
- foreach($this->captions as $key => $caption) {
- if($caption == $captionToUse) {
- $columnIndex = $key;
- break;
- }
- }
- if($columnIndex == -1) {
- //The specified column does not exist.
- return $rows;
- }
-
- //Structure the rows as columns. Take the opportunity to see if the
- //sort column is numeric. If it is then we will want to sort it as one.
- $numeric = true;
- $sortColumn = array();
- foreach($rows as $row) {
- foreach($row as $column => $value) {
- if($column != $columnIndex) {
- continue;
- }
- if($numeric &&
- !$this->isConvertableToNumerical(strip_tags($value))) {
- //The whole column is not numeric.
- $numeric = false;
- }
- $sortColumn[] = $value;
- }
- }
- if($numeric) {
- //Convert the sort column to its numeric form.
- foreach($sortColumn as $key => $value) {
- $sortColumn[$key] = $this->convertToNumerical(
- strip_tags($value));
- }
- }
-
- if($numeric) {
- array_multisort($rows, SORT_NUMERIC, $sortColumn);
- } else {
- array_multisort($rows, SORT_STRING, $sortColumn);
- }
-
- if($order == SORT_DESC) {
- //Because I can't get SORT_DESC along with SORT_STRING in
- //array_multisort to work.
- $rows = array_reverse($rows);
- }
-
- return $rows;
- }
-
- /**
- * Checks if a value could be converted to a numerical value. I.e. if it
- * is a numerical value or possible a formatted numerical value. E.g.
- * '+3,000.50' counts as a convertable value, but '+31 DKP' does not.
- * @param mixed $value The value that should be checked.
- * @return boolean True if the value can be converted to a valid numerical
- * value (one that will make is_numeric true).
- */
- private function isConvertableToNumerical($value) {
- return preg_match('/^(-|\+)?\d[\.,\d]*$/', $value);
- }
-
- /**
- * Converts the value to the corresponding numerical one. The conversion
- * will only be reliable if the value return true with
- * isConvertableToNumerical().
- * @param mixed $value The value that should be converted.
- * @return integer The value in a numerical form.
- */
- private function convertToNumerical($value) {
- return preg_replace('/[^\d-]/', '', $value);
- }
- }
-
- ?>