Source for file Table.php
Documentation is available at Table.php
* Utility for printing tables from commandline scripts.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* o Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* o Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* o The names of the authors may not be used to endorse or promote products
* derived from this software without specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
* @author Richard Heyes <richard@phpguru.org>
* @author Jan Schneider <jan@horde.org>
* @copyright 2002-2005 Richard Heyes
* @copyright 2006-2008 Jan Schneider
* @license http://www.debian.org/misc/bsd.license BSD License (3 Clause)
* @link http://pear.php.net/package/Console_Table
define('CONSOLE_TABLE_HORIZONTAL_RULE', 1 );
define('CONSOLE_TABLE_ALIGN_LEFT', -1 );
define('CONSOLE_TABLE_ALIGN_CENTER', 0 );
define('CONSOLE_TABLE_ALIGN_RIGHT', 1 );
define('CONSOLE_TABLE_BORDER_ASCII', -1 );
* @author Jan Schneider <jan@horde.org>
* @license http://www.debian.org/misc/bsd.license BSD License (3 Clause)
* @link http://pear.php.net/package/Console_Table
* The maximum number of columns in a row.
* The maximum number of rows in the table.
* Lengths of the columns, calculated when rows are added to the table.
var $_cell_lengths = array ();
var $_row_heights = array ();
* How many spaces to use to pad the table.
* Columns to calculate totals for.
* Alignment of the columns.
var $_col_align = array ();
* Default alignment of columns.
* Character set of the data.
var $_border = CONSOLE_TABLE_BORDER_ASCII;
* Whether the data has ANSI colors.
* @param integer $align Default alignment. One of
* CONSOLE_TABLE_ALIGN_LEFT,
* CONSOLE_TABLE_ALIGN_CENTER or
* CONSOLE_TABLE_ALIGN_RIGHT.
* @param string $border The character used for table borders or
* CONSOLE_TABLE_BORDER_ASCII.
* @param integer $padding How many spaces to use to pad the table.
* @param string $charset A charset supported by the mbstring PHP
* @param boolean $color Whether the data contains ansi color codes.
$border = CONSOLE_TABLE_BORDER_ASCII , $padding = 1 ,
$charset = null , $color = false )
$this->_defaultAlign = $align;
$this->_border = $border;
$this->_padding = $padding;
$this->_ansiColor = $color;
include_once 'Console/Color.php';
* Converts an array to a table.
* @param array $headers Headers for the table.
* @param array $data A two dimensional array with the table
* @param boolean $returnObject Whether to return the Console_Table object
* instead of the rendered table.
* @return Console_Table|string A Console_Table object or the generated
function fromArray($headers, $data, $returnObject = false )
$table->setHeaders ($headers);
foreach ($data as $row) {
return $returnObject ? $table : $table->getTable ();
* Adds a filter to a column.
* Filters are standard PHP callbacks which are run on the data before
* table generation is performed. Filters are applied in the order they
* are added. The callback function must accept a single argument, which
* is a single table cell.
* @param integer $col Column to apply filter to.
* @param mixed &$callback PHP callback to apply.
$this->_filters[] = array ($col, &$callback);
* Sets the charset of the provided table data.
* @param string $charset A charset supported by the mbstring PHP
* Sets the alignment for the columns.
* @param integer $col_id The column number.
* @param integer $align Alignment to set for this column. One of
* CONSOLE_TABLE_ALIGN_LEFT
* CONSOLE_TABLE_ALIGN_CENTER
* CONSOLE_TABLE_ALIGN_RIGHT.
function setAlign($col_id, $align = CONSOLE_TABLE_ALIGN_LEFT )
$this->_col_align[$col_id] = $pad;
* Specifies which columns are to have totals calculated for them and
* added as a new row at the bottom.
* @param array $cols Array of column numbers (starting with 0).
$this->_calculateTotals = $cols;
* Sets the headers for the columns.
* @param array $headers The column headers.
$this->_updateRowsCols ($headers);
* Adds a row to the table.
* @param array $row The row data to add.
* @param boolean $append Whether to append or prepend the row.
function addRow($row, $append = true )
$this->_updateRowsCols ($row);
* Inserts a row after a given row number in the table.
* If $row_id is not given it will prepend the row.
* @param array $row The data to insert.
* @param integer $row_id Row number to insert before.
$this->_updateRowsCols ($row);
* Adds a column to the table.
* @param array $col_data The data of the column.
* @param integer $col_id The column index to populate.
* @param integer $row_id If starting row is not zero, specify it here.
function addCol($col_data, $col_id = 0 , $row_id = 0 )
foreach ($col_data as $col_cell) {
$this->_data[$row_id++ ][$col_id] = $col_cell;
$this->_updateRowsCols ();
$this->_max_cols = max($this->_max_cols, $col_id + 1 );
* Adds data to the table.
* @param array $data A two dimensional array with the table data.
* @param integer $col_id Starting column number.
* @param integer $row_id Starting row number.
function addData($data, $col_id = 0 , $row_id = 0 )
foreach ($data as $row) {
foreach ($row as $cell) {
$this->_data[$row_id][$starting_col++ ] = $cell;
$this->_updateRowsCols ();
$this->_max_cols = max($this->_max_cols, $starting_col);
* Adds a horizontal seperator to the table.
* Returns the generated table.
* @return string The generated table.
$this->_calculateTotals ();
return $this->_buildTable ();
* Calculates totals for columns.
function _calculateTotals ()
if (empty ($this->_calculateTotals)) {
foreach ($this->_data as $row) {
foreach ($this->_calculateTotals as $columnID) {
$totals[$columnID] += $row[$columnID];
$this->_data[] = $totals;
$this->_updateRowsCols ();
* Applies any column filters to the data.
if (empty ($this->_filters)) {
foreach ($this->_filters as $filter) {
foreach ($this->_data as $row_id => $row_data) {
$this->_data[$row_id][$column] =
* Ensures that column and row counts are correct.
function _validateTable ()
if (!empty ($this->_headers)) {
$this->_calculateRowHeight (-1 , $this->_headers[0 ]);
for ($i = 0; $i < $this->_max_rows; $i++ ) {
for ($j = 0; $j < $this->_max_cols; $j++ ) {
if (!isset ($this->_data[$i][$j]) &&
(!isset ($this->_data[$i]) ||
$this->_data[$i][$j] = '';
$this->_calculateRowHeight ($i, $this->_data[$i]);
$this->_splitMultilineRows ();
for ($i = 0; $i < count($this->_headers); $i++ ) {
$this->_calculateCellLengths ($this->_headers[$i]);
for ($i = 0; $i < $this->_max_rows; $i++ ) {
$this->_calculateCellLengths ($this->_data[$i]);
* Splits multiline rows into many smaller one-line rows.
function _splitMultilineRows ()
$sections = array (&$this->_headers, &$this->_data);
$max_rows = array (count($this->_headers), $this->_max_rows);
$row_height_offset = array (-1 , 0 );
for ($s = 0; $s <= 1; $s++ ) {
$new_data = $sections[$s];
for ($i = 0; $i < $max_rows[$s]; $i++ ) {
// Process only rows that have many lines.
$height = $this->_row_heights[$i + $row_height_offset[$s]];
// Split column data into one-liners.
for ($j = 0; $j < $this->_max_cols; $j++ ) {
// Construct new 'virtual' rows - insert empty strings for
// columns that have less lines that the highest one.
for ($i2 = 0; $i2 < $height; $i2++ ) {
for ($j = 0; $j < $this->_max_cols; $j++ ) {
$new_rows[$i2][$j] = !isset ($split[$j][$i2])
// Replace current row with smaller rows. $inserted is
// used to take account of bigger array because of already
$inserted += count($new_rows) - 1;
// Has the data been modified?
$sections[$s] = $new_data;
$this->_updateRowsCols ();
* @return string The generated table string.
if (!count($this->_data)) {
$separator = $this->_getSeparator ();
for ($i = 0; $i < count($this->_data); $i++ ) {
for ($j = 0; $j < count($this->_data[$i]); $j++ ) {
$this->_strlen ($this->_data[$i][$j]) <
$this->_cell_lengths[$j]) {
$this->_data[$i][$j] = $this->_strpad ($this->_data[$i][$j],
$this->_cell_lengths[$j],
$row_begin = $rule . str_repeat(' ', $this->_padding);
$row_end = str_repeat(' ', $this->_padding) . $rule;
$implode_char = str_repeat(' ', $this->_padding) . $rule
. implode($implode_char, $this->_data[$i]) . $row_end;
} elseif (!empty ($separator)) {
$return = implode("\r\n", $return);
if (!empty ($separator)) {
$return = $separator . "\r\n" . $return . "\r\n" . $separator;
if (!empty ($this->_headers)) {
$return = $this->_getHeaderLine () . "\r\n" . $return;
* Creates a horizontal separator for header separation and table
* @return string The horizontal separator.
$rule = $sect = $this->_border;
foreach ($this->_cell_lengths as $cl) {
$row_begin = $sect . str_repeat($rule, $this->_padding);
$row_end = str_repeat($rule, $this->_padding) . $sect;
$implode_char = str_repeat($rule, $this->_padding) . $sect
return $row_begin . implode($implode_char, $return) . $row_end;
* Returns the header line for the table.
* @return string The header line of the table.
function _getHeaderLine ()
// Make sure column count is correct
for ($j = 0; $j < count($this->_headers); $j++ ) {
for ($i = 0; $i < $this->_max_cols; $i++ ) {
if (!isset ($this->_headers[$j][$i])) {
$this->_headers[$j][$i] = '';
for ($j = 0; $j < count($this->_headers); $j++ ) {
for ($i = 0; $i < count($this->_headers[$j]); $i++ ) {
if ($this->_strlen ($this->_headers[$j][$i]) <
$this->_cell_lengths[$i]) {
$this->_headers[$j][$i] =
$this->_strpad ($this->_headers[$j][$i],
$this->_cell_lengths[$i],
$row_begin = $rule . str_repeat(' ', $this->_padding);
$row_end = str_repeat(' ', $this->_padding) . $rule;
$implode_char = str_repeat(' ', $this->_padding) . $rule
$separator = $this->_getSeparator ();
if (!empty ($separator)) {
for ($j = 0; $j < count($this->_headers); $j++ ) {
. implode($implode_char, $this->_headers[$j]) . $row_end;
* Updates values for maximum columns and rows.
* @param array $rowdata Data array of a single row.
function _updateRowsCols ($rowdata = null )
// Update maximum columns.
$this->_max_cols = max($this->_max_cols, count($rowdata));
$this->_max_rows = end($keys) + 1;
switch ($this->_defaultAlign) {
// Set default column alignments
for ($i = count($this->_col_align); $i < $this->_max_cols; $i++ ) {
$this->_col_align[$i] = $pad;
* Calculates the maximum length for each column of a row.
* @param array $row The row data.
function _calculateCellLengths ($row)
for ($i = 0; $i < count($row); $i++ ) {
if (!isset ($this->_cell_lengths[$i])) {
$this->_cell_lengths[$i] = 0;
$this->_cell_lengths[$i] = max($this->_cell_lengths[$i],
$this->_strlen ($row[$i]));
* Calculates the maximum height for all columns of a row.
* @param integer $row_number The row number.
* @param array $row The row data.
function _calculateRowHeight ($row_number, $row)
if (!isset ($this->_row_heights[$row_number])) {
$this->_row_heights[$row_number] = 1;
// Do not process horizontal rule rows.
for ($i = 0 , $c = count($row); $i < $c; ++ $i) {
$this->_row_heights[$row_number] = max($this->_row_heights[$row_number],
* Returns the character length of a string.
* @param string $str A multibyte or singlebyte string.
* @return integer The string length.
// Strip ANSI color codes if requested.
$str = Console_Color ::strip ($str);
// Cache expensive function_exists() calls.
* Returns part of a string.
* @param string $string The string to be converted.
* @param integer $start The part's start position, zero based.
* @param integer $length The part's length.
* @return string The string's part.
function _substr ($string, $start, $length = null )
// Cache expensive function_exists() calls.
$length = $this->_strlen ($string);
$ret = @mb_substr($string, $start, $length, $this->_charset);
return substr($string, $start, $length);
* Returns a string padded to a certain length with another string.
* This method behaves exactly like str_pad but is multibyte safe.
* @param string $input The string to be padded.
* @param integer $length The length of the resulting string.
* @param string $pad The string to pad the input string with. Must
* be in the same charset like the input string.
* @param const $type The padding type. One of STR_PAD_LEFT,
* STR_PAD_RIGHT, or STR_PAD_BOTH.
* @return string The padded string.
function _strpad ($input, $length, $pad = ' ', $type = STR_PAD_RIGHT )
$mb_length = $this->_strlen ($input);
$pad_length = $this->_strlen ($pad);
/* Return if we already have the length. */
if ($mb_length >= $length) {
/* Shortcut for single byte strings. */
if ($mb_length == $sb_length && $pad_length == strlen($pad)) {
return str_pad($input, $length, $pad, $type);
$left = $length - $mb_length;
0 , $left, $this->_charset) . $input;
$left = floor(($length - $mb_length) / 2 );
$right = ceil(($length - $mb_length) / 2 );
0 , $left, $this->_charset) .
0 , $right, $this->_charset);
$right = $length - $mb_length;
0 , $right, $this->_charset);
Documentation generated on Fri, 07 Dec 2012 15:00:03 +0000 by phpDocumentor 1.4.3. PEAR Logo Copyright © PHP Group 2004.
|