<?php

/**
 * THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 *
 * @package fusionLib
 * @copyright Copyright (c) 2012 - 2013 fusionLib. All rights reserved.
 * @link http://fusionlib.com
 */

/**
 * flWidgetTable Class
 *
 * Class to simplify generation of tables from data.
 *
 * @package fusionLib
 */
class flWidgetTable {

	/**
	 * The CSS class to apply to the table.
	 *
	 * @var string
	 */
	protected $css = 'tablewidget';

	/**
	 * The table headings.
	 *
	 * @var array
	 */
	protected $headings = null;

	/**
	 * The column data names.
	 *
	 * @var array
	 */
	protected $dataNames = null;

	/**
	 * Array of column names to skip encoding on.
	 *
	 * @var array
	 */
	protected $skip = array();

	/**
	 * The optional table caption.
	 *
	 * @var string
	 */
	protected $caption = null;

	/**
	 * Storage for row data as it's generated.
	 *
	 * @var array
	 */
	protected $rows = array();

	/**
	 * The content for empty cells.
	 *
	 * @var string
	 */
	protected $empty = '&nbsp;';

	/**
	 * Set the CSS class to use.
	 *
	 * @param string $css The CSS class, default is 'tablewidget'.
	 * @return flWidgetTable This object.
	 */
	function setClass($css) {
		$this->css = $css;
		return $this;
	}

	/**
	 * Set the headings for the columns.
	 *
	 * @param mixed $headings Individual parameters holding the names of each heading or an array of headings.
	 * @return flWidgetTable This object.
	 */
	function setHeadings($headings) {
		if(!is_array($headings)) $headings = func_get_args();
		$this->headings = $headings;
		if($this->dataNames === null)
			$this->dataNames = range(0, count($headings) - 1);
		return $this;
	}

	/**
	 * Set the headings for the columns.
	 *
	 * @param mixed $dataName Individual parameters holding the names of each data item or an array of data item names.
	 * @return flWidgetTable This object.
	 */
	function setColData($dataName) {
		if(!is_array($dataName)) $dataName = func_get_args();
		$this->dataNames = $dataName;
		return $this;
	}

	/**
	 * Set the columns to skip encoding of HTML elements on.
	 *
	 * @param mixed $skip Individual parameters holding the names of the data columns to not encode html entities in or
	 * an array of the column names. If true then all columns are skipped.
	 * @return flWidgetTable This object.
	 */
	function skipEncode($skip) {
		if(!is_array($skip)) $skip = func_get_args();
		$this->skip = $skip;
		return $this;
	}

	/**
	 * The optional caption for the table.
	 *
	 * @param string $caption The caption.
	 * @return flWidgetTable This object.
	 */
	function setCaption($caption) {
		$this->caption = $caption;
		return $this;
	}

	/**
	 * Set the contents to use for empty cells.
	 *
	 * @param string $empty The contents for empty cells or null to throw an exception for missing row data.
	 * @return flWidgetTable This object.
	 */
	function setEmpty($empty) {
		$this->empty = $empty;
		return $this;
	}

	/**
	 * Add a row of data to the table. The current settings for the table are used to extract the row data.
	 *
	 * @param array $data Array of data for the row.
	 * @param string $css Optional CSS class to apply to the row.
	 * @return flWidgetTable This object.
	 * @throws flWidgetException
	 */
	function addRow($data, $css = null) {
		$r = $css === null ? "<tr>\n" : "<tr class=\"$css\">\n";

		foreach($this->dataNames as $n) {
			if(!isset($data[$n])) {
				if($this->empty === null)
					throw new flWidgetException("Data for table column '$n' not supplied.");
				else
					$r .= '<td>' . $this->empty . "</td>\n";
			}
			else
				$r .= '<td>' . ($this->skip === true || in_array($n, $this->skip) ? $data[$n] : fusionLib::htmlChars($data[$n])) . "</td>\n";
		}
		$r .= "</tr>";

		$this->rows[] = $r;

		return $this;
	}

	/**
	 * Render the table.
	 *
	 * @return string The string holding the HTML representation of the table data.
	 * @throws flWidgetException
	 */
	function render() {
		if(count($this->dataNames) != count($this->headings))
			throw new flWidgetException('Unable to render table as number of columns does not match number of headings.');

		$t = "<table class=\"" . $this->css . "\">\n";
		if($this->caption !== null)
			$t .= "<caption>" . $this->caption . "</caption>\n";
		$t .= "<thead>\n<tr>\n";
		foreach($this->headings as $h)
			$t .= "<th>$h</th>";
		$t .= "\n</tr>\n</thead>\n<tbody>\n";
		$t .= join("\n", $this->rows);
		$t .= "</tbody>\n</table>\n";

		return $t;
	}
}
