| // | Bertrand Mansion | // +----------------------------------------------------------------------+ // // $Id: Table.php,v 1.14 2002/01/31 13:01:52 mansion Exp $ require_once "PEAR.php"; require_once "HTML/Common.php"; /** * Builds an HTML table * * @author Adam Daniel * @author Bertrand Mansion * @version 1.6 * @since PHP 4.0.3pl1 */ class HTML_Table extends HTML_Common { /** * Automatically adds a new row or column if a given row or column index does not exist * * @var bool * @access private */ var $_autoGrow = true; /** * Value to insert into empty cells * * @var string * @access private */ var $_autoFill = " "; /** * Array containing the table structure * * @var array * @access private */ var $_structure = array(); /** * Number of rows composing in the table * * @var int * @access private */ var $_rows = 0; /** * Number of column composing the table * * @var int * @access private */ var $_cols = 0; /** * Tracks the level of nested tables * * @var int * @since 1.5 * @access private */ var $_nestLevel = 0; /** * Class constructor * * @param array $attributes Associative array of table tag attributes * @param int $tabOffset * @access public */ function HTML_Table($attributes = null, $tabOffset = 0) { $commonVersion = 1.3; if (HTML_Common::apiVersion() < $commonVersion) { return new PEAR_Error("HTML_Table version " . $this->apiVersion() . " requires " . "HTML_Common version $commonVersion or greater.", 0, PEAR_ERROR_TRIGGER); } HTML_Common::HTML_Common($attributes, $tabOffset); } // end constructor /** * Returns the API version * * @access public * @return double */ function apiVersion() { return 1.6; } // end func apiVersion /** * Sets the table caption * * @param string $caption * @param mixed $attributes Associative array or string of table row attributes * @access public */ function setCaption($caption, $attributes = null) { $attributes = $this->_parseAttributes($attributes); $this->_structure["caption"] = array("attr" => $attributes, "contents" => $caption); } // end func setCaption /** * Sets the autoFill value * * @param mixed $fill * @access public */ function setAutoFill($fill) { $this->_autoFill = $fill; } // end func setAutoFill /** * Returns the autoFill value * * @access public * @return mixed */ function getAutoFill() { return $this->_autoFill; } // end func getAutoFill /** * Sets the autoGrow value * * @param bool $fill * @access public */ function setAutoGrow($grow) { $this->_autoGrow = $grow; } // end func setAutoGrow /** * Returns the autoGrow value * * @access public * @return mixed */ function getAutoGrow() { return $this->_autoGrow; } // end func getAutoGrow /** * Sets the number of rows in the table * * @param int $rows * @access public */ function setRowCount($rows) { $this->_rows = $rows; } // end func setRowCount /** * Sets the number of columns in the table * * @param int $cols * @access public */ function setColCount($cols) { $this->_cols = $cols; } // end func setColCount /** * Returns the number of rows in the table * * @access public * @return int */ function getRowCount() { return $this->_rows; } // end func getRowCount /** * Sets the number of columns in the table * * @access public * @return int */ function getColCount() { return $this->_cols; } // end func getColCount /** * Sets a rows type 'TH' or 'TD' * * @param int $row Row index * @param string $type 'TH' or 'TD' * @access public */ function setRowType($row, $type) { for ($counter = 0; $counter < $this->_cols; $counter++) { $this->_structure[$row][$counter]["type"] = $type; } } // end func setRowType /** * Sets a columns type 'TH' or 'TD' * * @param int $col Column index * @param string $type 'TH' or 'TD' * @access public */ function setColType($col, $type) { for ($counter = 0; $counter < $this->_rows; $counter++) { $this->_structure[$counter][$col]["type"] = $type; } } // end func setColType /** * Sets the cell attributes for an existing cell. * * If the given indices do not exist and autoGrow is true then the given * row and/or col is automatically added. If autoGrow is false then an * error is returned. * * @param int $row Row index * @param int $col Column index * @param mixed $attributes Associative array or string of table row attributes * @access public * @throws PEAR_Error */ function setCellAttributes($row, $col, $attributes) { if (isset($this->_structure[$row][$col]) && $this->_structure[$row][$col] == "__SPANNED__") return; $attributes = $this->_parseAttributes($attributes); $err = $this->_adjustEnds($row, $col, 'setCellAttributes', $attributes); if (PEAR::isError($err)) { return $err; } $this->_structure[$row][$col]["attr"] = $attributes; $this->_updateSpanGrid($row, $col); } // end func setCellAttributes /** * Updates the cell attributes passed but leaves other existing attributes in tact * * @param int $row Row index * @param int $col Column index * @param mixed $attributes Associative array or string of table row attributes * @access public */ function updateCellAttributes($row, $col, $attributes) { if (isset($this->_structure[$row][$col]) && $this->_structure[$row][$col] == "__SPANNED__") return; $attributes = $this->_parseAttributes($attributes); $err = $this->_adjustEnds($row, $col, 'updateCellAttributes', $attributes); if (PEAR::isError($err)) { return $err; } $this->_updateAttrArray($this->_structure[$row][$col]["attr"], $attributes); $this->_updateSpanGrid($row, $col); } // end func updateCellAttributes /** * Sets the cell contents for an existing cell * * If the given indices do not exist and autoGrow is true then the given * row and/or col is automatically added. If autoGrow is false then an * error is returned. * * @param int $row Row index * @param int $col Column index * @param mixed $contents May contain html or any object with a toHTML method * @param string $type (optional) Cell type either 'TH' or 'TD' * @access public * @throws PEAR_Error */ function setCellContents($row, $col, $contents, $type = 'TD') { if(isset($this->_structure[$row][$col]) && $this->_structure[$row][$col] == "__SPANNED__") return; $err = $this->_adjustEnds($row, $col, 'setCellContents'); if (PEAR::isError($err)) { return $err; } $this->_structure[$row][$col]["contents"] = $contents; $this->_structure[$row][$col]["type"] = $type; } // end func setCellContents /** * Returns the cell contents for an existing cell * * @param int $row Row index * @param int $col Column index * @access public * @return mixed */ function getCellContents($row, $col) { if (isset($this->_structure[$row][$col]) && $this->_structure[$row][$col] == "__SPANNED__") return; return $this->_structure[$row][$col]["contents"]; } // end func getCellContents /** * Sets the contents of a header cell * * @param int $row * @param int $col * @param mixed $contents * @access public */ function setHeaderContents($row, $col, $contents) { $this->setCellContents($row, $col, $contents, 'TH'); } // end func setHeaderContents /** * Adds a table row and returns the row identifier * * @param array $contents (optional) Must be a indexed array of valid cell contents * @param mixed $attributes (optional) Associative array or string of table row attributes * @param string $type (optional) Cell type either 'TH' or 'TD' * @return int * @access public */ function addRow($contents = null, $attributes = null, $type = 'TD') { if (isset($contents) && !is_array($contents)) { return new PEAR_Error("First parameter to HTML_Table::addRow must be an array"); } $row = $this->_rows++; for ($counter = 0; $counter < count($contents); $counter++) { if ($type == 'TD') { $this->setCellContents($row, $counter, $contents[$counter]); } elseif ($type == 'TH') { $this->setHeaderContents($row, $counter, $contents[$counter]); } } $this->setRowAttributes($row, $attributes); return $row; } // end func addRow /** * Sets the row attributes for an existing row * * @param int $row Row index * @param mixed $attributes Associative array or string of table row attributes * @access public */ function setRowAttributes($row, $attributes) { for ($i = 0; $i < $this->_cols; $i++) { $this->setCellAttributes($row, $i, $attributes); } } // end func setRowAttributes /** * Updates the row attributes for an existing row * * @param int $row Row index * @param mixed $attributes Associative array or string of table row attributes * @access public */ function updateRowAttributes($row, $attributes = null) { for ($i = 0; $i < $this->_cols; $i++) { $this->updateCellAttributes($row, $i, $attributes); } } // end func updateRowAttributes /** * Alternates the row attributes starting at $start * * @param int $start Row index of row in which alternating begins * @param mixed $attributes1 Associative array or string of table row attributes * @param mixed $attribute2 Associative array or string of table row attributes * @access public */ function altRowAttributes($start, $attributes1, $attributes2) { for ($row = $start ; $row < $this->_rows ; $row++) { $attributes = ( ($row+$start)%2 == 0 ) ? $attributes1 : $attributes2; $this->updateRowAttributes($row, $attributes); } } // end func altRowAttributes /** * Adds a table column and returns the column identifier * * @param array $contents (optional) Must be a indexed array of valid cell contents * @param mixed $attributes (optional) Associative array or string of table row attributes * @param string $type (optional) Cell type either 'TH' or 'TD' * @return int * @access public */ function addCol($contents = null, $attributes = null, $type = 'TD') { if (isset($contents) && !is_array($contents)) { return new PEAR_Error("First parameter to HTML_Table::addCol must be an array"); } $col = $this->_cols++; for ($counter = 0; $counter < count($contents); $counter++) { $this->setCellContents($counter, $col, $contents[$counter], $type); } $this->setColAttributes($col, $attributes); return $col; } // end func addCol /** * Sets the column attributes for an existing column * * @param int $col Column index * @param mixed $attributes (optional) Associative array or string of table row attributes * @access public */ function setColAttributes($col, $attributes = null) { for ($i = 0; $i < $this->_rows; $i++) { $this->setCellAttributes($i,$col,$attributes); } } // end func setColAttributes /** * Updates the column attributes for an existing column * * @param int $col Column index * @param mixed $attributes (optional) Associative array or string of table row attributes * @access public */ function updateColAttributes($col, $attributes = null) { for ($i = 0; $i < $this->_rows; $i++) { $this->updateCellAttributes($i, $col, $attributes); } } // end func updateColAttributes /** * Sets the attributes for all cells * * @param mixed $attributes (optional) Associative array or string of table row attributes * @since 1.6 * @access public */ function setAllAttributes($attributes = null) { for ($i = 0; $i < $this->_rows; $i++) { $this->setRowAttributes($i, $attributes); } } // end func setAllAttributes /** * Updates the attributes for all cells * * @param mixed $attributes (optional) Associative array or string of table row attributes * @since 1.6 * @access public */ function updateAllAttributes($attributes = null) { for ($i = 0; $i < $this->_rows; $i++) { $this->updateRowAttributes($i, $attributes); } } // end func updateAllAttributes /** * Returns the table structure as HTML * * @access public * @return string */ function toHtml() { $tabs = $this->_getTabs(); $strHtml = "\n" . $tabs . "\n"; if ($this->_comment) { $strHtml .= $tabs . "\n"; } $strHtml .= $tabs . "_getAttrString($this->_attributes) . ">\n"; if (!empty($this->_structure["caption"])) { $attr = $this->_structure["caption"]["attr"]; $contents = $this->_structure["caption"]["contents"]; $strHtml .= $tabs . "\t_getAttrString($attr) . ">"; if (is_array($contents)) $contents = implode(", ", $contents); $strHtml .= $contents; $strHtml .= "\n"; } for ($i = 0 ; $i < $this->_rows ; $i++) { $strHtml .= $tabs ."\t\n"; for ($j = 0 ; $j < $this->_cols ; $j++) { if (isset($this -> _structure[$i][$j]) && $this->_structure[$i][$j] == "__SPANNED__") { $strHtml .= $tabs ."\t\t\n"; continue; } if (isset($this->_structure[$i][$j]["type"])) { $type = (strtoupper($this->_structure[$i][$j]["type"]) == "TH" ? "th" : "td"); } else { $type = "td"; } if (isset($this->_structure[$i][$j]["attr"])) { $attr = $this->_structure[$i][$j]["attr"]; } else { $attr = ""; } if (isset($this->_structure[$i][$j]["contents"])) { $contents = $this->_structure[$i][$j]["contents"]; } else { $contents = ""; } $flagCloseTable = false; $strHtml .= $tabs . "\t\t<$type" . $this->_getAttrString($attr) . ">"; if (is_object($contents)) { if (is_subclass_of($contents, "html_common")) { $contents->setTabOffset($this->_tabOffset + 3); $contents->_nestLevel = $this->_nestLevel + 1; $flagCloseTable = true; } if (method_exists($contents, "toHtml")) { $contents = $contents->toHtml(); } elseif (method_exists($contents, "toString")) { $contents = $contents->toString(); } } if (is_array($contents)) $contents = implode(", ",$contents); if (isset($this->_autoFill) && $contents == "") $contents = $this->_autoFill; $strHtml .= $contents; $strHtml .= (isset($flagCloseTable)) ? "\t\t" : ''; $strHtml .= "\n"; } $strHtml .= $tabs ."\t\n"; } $strHtml .= $tabs . "\n". $tabs . "\n"; return $strHtml; } // end func toHtml /** * Checks if rows or columns are spanned * * @param int $row Row index * @param int $col Column index * @access private */ function _updateSpanGrid($row, $col) { if (isset($this->_structure[$row][$col]["attr"]["colspan"])) { $colspan = $this->_structure[$row][$col]["attr"]["colspan"]; } if (isset($this->_structure[$row][$col]["attr"]["rowspan"])) { $rowspan = $this->_structure[$row][$col]["attr"]["rowspan"]; } if (isset($colspan)) { for ($j = $col+1; (($j < $this->_cols) && ($j <= ($col + $colspan - 1))); $j++) { $this->_structure[$row][$j] = "__SPANNED__"; } } if (isset($rowspan)) { for ($i = $row+1; (($i < $this->_rows) && ($i <= ($row + $rowspan - 1))); $i++) { $this->_structure[$i][$col] = "__SPANNED__"; } } if (isset($colspan) && isset($rowspan)) { for ($i = $row+1; (($i < $this->_rows) && ($i <= ($row + $rowspan - 1))); $i++) { for ($j = $col+1; (($j <= $this->_cols) && ($j <= ($col + $colspan - 1))); $j++) { $this->_structure[$i][$j] = "__SPANNED__"; } } } } // end func _updateSpanGrid /** * Adjusts ends (total number of rows and columns) * * @param int $row Row index * @param int $col Column index * @param string $method Method name of caller * Used to populate PEAR_Error if thrown. * @param array $attributes Assoc array of attributes * Default is an empty array. * @access private * @throws PEAR_Error */ function _adjustEnds($row, $col, $method, $attributes = array()) { $colspan = isset($attributes['colspan']) ? $attributes['colspan'] : 1; $rowspan = isset($attributes['rowspan']) ? $attributes['rowspan'] : 1; if (($row + $rowspan - 1) >= $this->_rows) { if ($this->_autoGrow) { $this->_rows = $row + $rowspan; } else { return new PEAR_Error('Invalid table row reference[' . $row . '] in HTML_Table::' . $method); } } if (($col + $colspan - 1) >= $this->_cols) { if ($this->_autoGrow) { $this->_cols = $col + $colspan; } else { return new PEAR_Error('Invalid table column reference[' . $col . '] in HTML_Table::' . $method); } } } } // end class HTML_Table ?>