package.xml0000664000175000017500000003031512650201765011305 0ustar janjan Console_Table pear.php.net Library that makes it easy to build console style tables Provides a Console_Table class with methods such as addRow(), insertRow(), addCol() etc. to build console tables with or without headers and with user defined table rules, padding, and alignment. Jan Schneider yunosh jan@horde.org yes Richard Heyes richard richard@phpguru.org no Tal Peer tal tal@php.net no Xavier Noguer xnoguer xnoguer@php.net no 2016-01-21 1.3.0 1.3.0 stable stable BSD * Fix warning with PHP 7 and bump required PHP version to 5.2.0 (Pieter Frenssen PR #13). 5.2.0 1.4.0b1 Console_Color2 pear.php.net 0.1.2 0.8 0.8 beta beta 2002-09-02 BSD * Initial release. 1.0 1.0.0 stable stable 2003-01-24 BSD * Removed a few options and added addData() method. 1.0.1 1.0.0 stable stable 2003-03-03 BSD * Fixed a caching bug. 1.0.2 1.0.0 stable stable 2005-07-16 BSD * Added support for column alignment (Michael Richter). 1.0.3 1.0.0 stable stable 2006-03-13 BSD * Fix cell width calculation if setting header with associative array (Bug #4299). * Fix fatal reference error with some PHP versions (Bug #5309). * Fix notice if no data has been provided (Bug #5851). * Added multibyte support (Requests #2934, Request #7014). 1.0.4 1.0.0 stable stable 2006-04-08 BSD * Add support for multi-line cells (koto at webworkers dot pl, Request #7017). 1.0.5 1.0.0 stable stable 2006-08-28 BSD * Allow to specify separator rules in addData(). * Fix warnings when combining separator rules and callback filters (Bug #8566). 1.0.6 1.0.0 stable stable 2007-01-19 BSD * Add support for multi-line headers (Request #8615). 2007-05-17 1.0.7 1.0.0 stable stable BSD * Fix header height if first data row has more than one line (Bug #11064). * Fix notice if header is not set. 2008-01-09 1.0.8 1.0.0 stable stable BSD * Fix cell padding with multibyte strings under certain circumstances (Bug #12853). 2008-03-28 1.1.0 1.1.0 stable stable BSD * Add option to set table border character. * Extend constructor to set table borders, padding, and charset on instantiation. 2008-04-09 1.1.1 1.1.0 stable stable BSD * Fix rendering of multiline rows with cells that contain zeros (Bug #13629). 2008-07-27 1.1.2 1.1.0 stable stable BSD * Don't render anything if no data has been provided (Bug #14405). 2008-10-20 1.1.3 1.1.1 stable stable BSD * Add option to render data with ANSI color codes (Igor Feghali, Request #14835). 1.1.4 1.1.1 stable stable 2010-10-25 BSD * Automatically built QA release. * Add Console_Color support (Request #14835). * Improve documentation (Christian Weiske, Bug #15006). 2012-12-07 1.1.5 1.1.1 stable stable BSD * Use mb_strwidth() instead of mb_strlen() to determine lengths of multi-byte strings (Bug #19423). 2013-10-12 1.1.6 1.1.1 stable stable BSD * Use line breaks dependent on the current operating system (Bug #20092). 2014-02-17 1.2.0 1.2.0 stable stable BSD * Make border visibility configurable (Christian Weiske, Request #20186). * Allow to customize all border characters (Christian Weiske, Request #20182). * Fix notice when using setAlign() on other than first column (Christian Weiske, Bug #20181). * Use Console_Color2 to avoid notices from PHP 4 code (Christian Weiske, Bug #20188) 2014-10-27 1.2.1 1.2.0 stable stable BSD * Add travis configuration (Christian Weiske). * Try to autoload Console_Color2 first (Jurgen Rutten, PR #11). * Fix Composer definition syntax (Rob Loach, PR #9). 2016-01-21 1.3.0 1.3.0 stable stable BSD * Fix warning with PHP 7 and bump required PHP version to 5.2.0 (Pieter Frenssen PR #13). Console_Table-1.3.0/tests/assoziative_arrays.phpt0000664000175000017500000000103212650201765020311 0ustar janjan--TEST-- Header and data as associative arrays. --FILE-- 'foo', 'two' => 'bar' ); $data = array( array( 'x' => 'baz', ) ); $table = new Console_Table(); $table->setHeaders($headers); $table->addData($data); echo $table->getTable(); ?> --EXPECT-- +-----+-----+ | foo | bar | +-----+-----+ | baz | | +-----+-----+ Console_Table-1.3.0/tests/border-ascii.phpt0000664000175000017500000000122712650201765016740 0ustar janjan--TEST-- Border: default ASCII mode --FILE-- setHeaders(array('City', 'Mayor')); $table->addRow(array('Leipzig', 'Major Tom')); $table->addRow(array('New York', 'Towerhouse')); echo $table->getTable(); ?> --EXPECT-- +----------+------------+ | City | Mayor | +----------+------------+ | Leipzig | Major Tom | | New York | Towerhouse | +----------+------------+ Console_Table-1.3.0/tests/border-custom.phpt0000664000175000017500000000131012650201765017153 0ustar janjan--TEST-- Border: new custom mode --FILE-- '=', 'vertical' => ':', 'intersection' => '*') ); $table->setHeaders(array('City', 'Mayor')); $table->addRow(array('Leipzig', 'Major Tom')); $table->addRow(array('New York', 'Towerhouse')); echo $table->getTable(); ?> --EXPECT-- *==========*============* : City : Mayor : *==========*============* : Leipzig : Major Tom : : New York : Towerhouse : *==========*============* Console_Table-1.3.0/tests/border-custom2.phpt0000664000175000017500000000130712650201765017243 0ustar janjan--TEST-- Border: new custom mode, alternative style --FILE-- '=', 'vertical' => '', 'intersection' => '') ); $table->setHeaders(array('City', 'Mayor')); $table->addRow(array('Leipzig', 'Major Tom')); $table->addRow(array('New York', 'Towerhouse')); echo $table->getTable(); ?> --EXPECT-- ====================== City Mayor ====================== Leipzig Major Tom New York Towerhouse ====================== Console_Table-1.3.0/tests/border-disable.phpt0000664000175000017500000000264512650201765017260 0ustar janjan--TEST-- Border: disable it --FILE-- setHeaders(array('City', 'Mayor')); $table->addRow(array('Leipzig', 'Major Tom')); $table->addRow(array('New York', 'Towerhouse')); $table->setBorderVisibility( array( 'left' => false, 'right' => false, ) ); echo "Horizontal borders only:\n"; echo $table->getTable() . "\n"; $table->setBorderVisibility( array( 'top' => false, 'right' => false, 'bottom' => false, 'left' => false, 'inner' => false, ) ); echo "No borders:\n"; echo $table->getTable() . "\n"; $table->setBorderVisibility( array( 'top' => false, 'right' => true, 'bottom' => false, 'left' => true, 'inner' => true, ) ); echo "Vertical and inner only:\n"; echo $table->getTable() . "\n"; ?> --EXPECT-- Horizontal borders only: ---------+----------- City | Mayor ---------+----------- Leipzig | Major Tom New York | Towerhouse ---------+----------- No borders: City | Mayor Leipzig | Major Tom New York | Towerhouse Vertical and inner only: | City | Mayor | +----------+------------+ | Leipzig | Major Tom | | New York | Towerhouse | Console_Table-1.3.0/tests/border-dot.phpt0000664000175000017500000000120512650201765016432 0ustar janjan--TEST-- Border: custom border character --FILE-- setHeaders(array('City', 'Mayor')); $table->addRow(array('Leipzig', 'Major Tom')); $table->addRow(array('New York', 'Towerhouse')); echo $table->getTable(); ?> --EXPECT-- ......................... . City . Mayor . ......................... . Leipzig . Major Tom . . New York . Towerhouse . ......................... Console_Table-1.3.0/tests/border-empty.phpt0000664000175000017500000000105412650201765017004 0ustar janjan--TEST-- Border: empty character --FILE-- setHeaders(array('City', 'Mayor')); $table->addRow(array('Leipzig', 'Major Tom')); $table->addRow(array('New York', 'Towerhouse')); echo $table->getTable() . "\n"; ?> --EXPECT-- City Mayor Leipzig Major Tom New York Towerhouse Console_Table-1.3.0/tests/bug20181.phpt0000664000175000017500000000101212650201765015536 0ustar janjan--TEST-- Bug #20181: setAlign() on non-zero column --FILE-- setAlign(1, CONSOLE_TABLE_ALIGN_RIGHT); $table->setHeaders(array('f', 'bar')); $table->addRow(array('baz', 'b')); echo $table->getTable(); ?> --EXPECT-- +-----+-----+ | f | bar | +-----+-----+ | baz | b | +-----+-----+ Console_Table-1.3.0/tests/colors.phpt0000664000175000017500000000127012650201765015674 0ustar janjan--TEST-- Data with ANSI color codes --SKIPIF-- --FILE-- setHeaders(array('foo', 'bar')); $table->addRow(array('baz', $cc->convert("%bblue%n"))); echo $table->getTable(); ?> --EXPECT-- +-----+------+ | foo | bar | +-----+------+ | baz | blue | +-----+------+ Console_Table-1.3.0/tests/filters.phpt0000664000175000017500000000131512650201765016043 0ustar janjan--TEST-- Callback filters --FILE-- setHeaders(array('foo', 'bar')); $table->addData($data); $table->addFilter(0, $filter); echo $table->getTable(); ?> --EXPECT-- +-------+-------+ | foo | bar | +-------+-------+ | ONE | two | | THREE | four | +-------+-------+ | FIVE | six | | SEVEN | eight | +-------+-------+ Console_Table-1.3.0/tests/multibyte.phpt0000664000175000017500000000143212650201765016411 0ustar janjan--TEST-- Multibyte strings --FILE-- setHeaders(array('Schön', 'Häßlich')); $table->addData(array(array('Ich', 'Du'), array('Ä', 'Ü'))); echo $table->getTable(); $table = new Console_Table(); $table->addRow(array("I'm from 中国")); $table->addRow(array("我是中国人")); $table->addRow(array("I'm from China")); echo $table->getTable(); ?> --EXPECT-- +-------+---------+ | Schön | Häßlich | +-------+---------+ | Ich | Du | | Ä | Ü | +-------+---------+ +----------------+ | I'm from 中国 | | 我是中国人 | | I'm from China | +----------------+ Console_Table-1.3.0/tests/multiline.phpt0000664000175000017500000000310312650201765016372 0ustar janjan--TEST-- Multiline table cells --FILE-- setHeaders(array("h1\nmultiline", 'h2', "h3", 'h4')); $table->addData($data); echo $table->getTable(); echo Console_Table::fromArray(array('one line header'), array(array("multiple\nlines"), array('one line'))); ?> --EXPECT-- +-----------+--------+-----------+--------+ | h1 | h2 | h3 | h4 | | multiline | | | | +-----------+--------+-----------+--------+ | col1 | 0 | col3 | col4 | | | | multiline | | | r2col1 | r2col2 | r2col3 | r2col4 | | | | multiline | | | r3col1 | r3col2 | r3col3 | r3col4 | | | | multiline | | | | | verymuch | | | r4col1 | r4col2 | r4col3 | r4col4 | | r5col1 | r5col2 | r5col3 | r5col4 | +-----------+--------+-----------+--------+ +-----------------+ | one line header | +-----------------+ | multiple | | lines | | one line | +-----------------+ Console_Table-1.3.0/tests/no_header.phpt0000664000175000017500000000055412650201765016323 0ustar janjan--TEST-- Table without header --FILE-- addData(array(array('foo', 'bar'))); echo $table->getTable(); ?> --EXPECT-- +-----+-----+ | foo | bar | +-----+-----+ Console_Table-1.3.0/tests/no_rows.phpt0000664000175000017500000000067112650201765016065 0ustar janjan--TEST-- Table without data --FILE-- setHeaders(array('foo', 'bar')); echo $table->getTable(); $table = new Console_Table(); echo $table->getTable(); ?> --EXPECT-- +-----+-----+ | foo | bar | +-----+-----+ | | | +-----+-----+ Console_Table-1.3.0/tests/rules.phpt0000664000175000017500000000276612650201765015540 0ustar janjan--TEST-- Horizontal rules --FILE-- setHeaders(array('foo', 'bar')); $table->addData($data); $table->addSeparator(); echo $table->getTable(); echo "=========================\n"; $table = new Console_Table(CONSOLE_TABLE_ALIGN_LEFT, ''); $table->setHeaders(array('foo', 'bar')); $table->addData($data); $table->addSeparator(); echo $table->getTable(); echo "=========================\n"; $table = new Console_Table(CONSOLE_TABLE_ALIGN_LEFT, '#', 0); $table->setHeaders(array('foo', 'bar')); $table->addData($data); $table->addSeparator(); echo $table->getTable(); ?> --EXPECT-- +-------+-------+ | foo | bar | +-------+-------+ | one | two | +-------+-------+ | three | four | +-------+-------+ +-------+-------+ | five | six | | seven | eight | +-------+-------+ +-------+-------+ ========================= foo bar one two three four five six seven eight ========================= ############# #foo #bar # ############# #one #two # ############# #three#four # ############# ############# #five #six # #seven#eight# ############# ############# Console_Table-1.3.0/Table.php0000775000175000017500000007053012650201765014104 0ustar janjan * @author Jan Schneider * @copyright 2002-2005 Richard Heyes * @copyright 2006-2008 Jan Schneider * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * @version CVS: $Id$ * @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); /** * The main class. * * @category Console * @package Console_Table * @author Jan Schneider * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * @link http://pear.php.net/package/Console_Table */ class Console_Table { /** * The table headers. * * @var array */ var $_headers = array(); /** * The data of the table. * * @var array */ var $_data = array(); /** * The maximum number of columns in a row. * * @var integer */ var $_max_cols = 0; /** * The maximum number of rows in the table. * * @var integer */ var $_max_rows = 0; /** * Lengths of the columns, calculated when rows are added to the table. * * @var array */ var $_cell_lengths = array(); /** * Heights of the rows. * * @var array */ var $_row_heights = array(); /** * How many spaces to use to pad the table. * * @var integer */ var $_padding = 1; /** * Column filters. * * @var array */ var $_filters = array(); /** * Columns to calculate totals for. * * @var array */ var $_calculateTotals; /** * Alignment of the columns. * * @var array */ var $_col_align = array(); /** * Default alignment of columns. * * @var integer */ var $_defaultAlign; /** * Character set of the data. * * @var string */ var $_charset = 'utf-8'; /** * Border characters. * Allowed keys: * - intersection - intersection ("+") * - horizontal - horizontal rule character ("-") * - vertical - vertical rule character ("|") * * @var array */ var $_border = array( 'intersection' => '+', 'horizontal' => '-', 'vertical' => '|', ); /** * If borders are shown or not * Allowed keys: top, right, bottom, left, inner: true and false * * @var array */ var $_borderVisibility = array( 'top' => true, 'right' => true, 'bottom' => true, 'left' => true, 'inner' => true ); /** * Whether the data has ANSI colors. * * @var Console_Color2 */ var $_ansiColor = false; /** * Constructor. * * @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 * extension. * @param boolean $color Whether the data contains ansi color codes. */ function __construct($align = CONSOLE_TABLE_ALIGN_LEFT, $border = CONSOLE_TABLE_BORDER_ASCII, $padding = 1, $charset = null, $color = false) { $this->_defaultAlign = $align; $this->setBorder($border); $this->_padding = $padding; if ($color) { if (!class_exists('Console_Color2')) { include_once 'Console/Color2.php'; } $this->_ansiColor = new Console_Color2(); } if (!empty($charset)) { $this->setCharset($charset); } } /** * Converts an array to a table. * * @param array $headers Headers for the table. * @param array $data A two dimensional array with the table * data. * @param boolean $returnObject Whether to return the Console_Table object * instead of the rendered table. * * @static * * @return Console_Table|string A Console_Table object or the generated * table. */ function fromArray($headers, $data, $returnObject = false) { if (!is_array($headers) || !is_array($data)) { return false; } $table = new Console_Table(); $table->setHeaders($headers); foreach ($data as $row) { $table->addRow($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. * * @return void */ function addFilter($col, &$callback) { $this->_filters[] = array($col, &$callback); } /** * Sets the charset of the provided table data. * * @param string $charset A charset supported by the mbstring PHP * extension. * * @return void */ function setCharset($charset) { $locale = setlocale(LC_CTYPE, 0); setlocale(LC_CTYPE, 'en_US'); $this->_charset = strtolower($charset); setlocale(LC_CTYPE, $locale); } /** * Set the table border settings * * Border definition modes: * - CONSOLE_TABLE_BORDER_ASCII: Default border with +, - and | * - array with keys "intersection", "horizontal" and "vertical" * - single character string that sets all three of the array keys * * @param mixed $border Border definition * * @return void * @see $_border */ function setBorder($border) { if ($border === CONSOLE_TABLE_BORDER_ASCII) { $intersection = '+'; $horizontal = '-'; $vertical = '|'; } else if (is_string($border)) { $intersection = $horizontal = $vertical = $border; } else if ($border == '') { $intersection = $horizontal = $vertical = ''; } else { extract($border); } $this->_border = array( 'intersection' => $intersection, 'horizontal' => $horizontal, 'vertical' => $vertical, ); } /** * Set which borders shall be shown. * * @param array $visibility Visibility settings. * Allowed keys: left, right, top, bottom, inner * * @return void * @see $_borderVisibility */ function setBorderVisibility($visibility) { $this->_borderVisibility = array_merge( $this->_borderVisibility, array_intersect_key( $visibility, $this->_borderVisibility ) ); } /** * 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. * * @return void */ function setAlign($col_id, $align = CONSOLE_TABLE_ALIGN_LEFT) { switch ($align) { case CONSOLE_TABLE_ALIGN_CENTER: $pad = STR_PAD_BOTH; break; case CONSOLE_TABLE_ALIGN_RIGHT: $pad = STR_PAD_LEFT; break; default: $pad = STR_PAD_RIGHT; break; } $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). * * @return void */ function calculateTotalsFor($cols) { $this->_calculateTotals = $cols; } /** * Sets the headers for the columns. * * @param array $headers The column headers. * * @return void */ function setHeaders($headers) { $this->_headers = array(array_values($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. * * @return void */ function addRow($row, $append = true) { if ($append) { $this->_data[] = array_values($row); } else { array_unshift($this->_data, array_values($row)); } $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. * * @return void */ function insertRow($row, $row_id = 0) { array_splice($this->_data, $row_id, 0, array($row)); $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. * * @return void */ 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. * * @return void */ function addData($data, $col_id = 0, $row_id = 0) { foreach ($data as $row) { if ($row === CONSOLE_TABLE_HORIZONTAL_RULE) { $this->_data[$row_id] = CONSOLE_TABLE_HORIZONTAL_RULE; $row_id++; continue; } $starting_col = $col_id; foreach ($row as $cell) { $this->_data[$row_id][$starting_col++] = $cell; } $this->_updateRowsCols(); $this->_max_cols = max($this->_max_cols, $starting_col); $row_id++; } } /** * Adds a horizontal seperator to the table. * * @return void */ function addSeparator() { $this->_data[] = CONSOLE_TABLE_HORIZONTAL_RULE; } /** * Returns the generated table. * * @return string The generated table. */ function getTable() { $this->_applyFilters(); $this->_calculateTotals(); $this->_validateTable(); return $this->_buildTable(); } /** * Calculates totals for columns. * * @return void */ function _calculateTotals() { if (empty($this->_calculateTotals)) { return; } $this->addSeparator(); $totals = array(); foreach ($this->_data as $row) { if (is_array($row)) { foreach ($this->_calculateTotals as $columnID) { $totals[$columnID] += $row[$columnID]; } } } $this->_data[] = $totals; $this->_updateRowsCols(); } /** * Applies any column filters to the data. * * @return void */ function _applyFilters() { if (empty($this->_filters)) { return; } foreach ($this->_filters as $filter) { $column = $filter[0]; $callback = $filter[1]; foreach ($this->_data as $row_id => $row_data) { if ($row_data !== CONSOLE_TABLE_HORIZONTAL_RULE) { $this->_data[$row_id][$column] = call_user_func($callback, $row_data[$column]); } } } } /** * Ensures that column and row counts are correct. * * @return void */ 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] !== CONSOLE_TABLE_HORIZONTAL_RULE)) { $this->_data[$i][$j] = ''; } } $this->_calculateRowHeight($i, $this->_data[$i]); if ($this->_data[$i] !== CONSOLE_TABLE_HORIZONTAL_RULE) { ksort($this->_data[$i]); } } $this->_splitMultilineRows(); // Update cell lengths. 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]); } ksort($this->_data); } /** * Splits multiline rows into many smaller one-line rows. * * @return void */ function _splitMultilineRows() { ksort($this->_data); $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++) { $inserted = 0; $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]]; if ($height > 1) { // Split column data into one-liners. $split = array(); for ($j = 0; $j < $this->_max_cols; $j++) { $split[$j] = preg_split('/\r?\n|\r/', $sections[$s][$i][$j]); } $new_rows = array(); // 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]) ? '' : $split[$j][$i2]; } } // Replace current row with smaller rows. $inserted is // used to take account of bigger array because of already // inserted rows. array_splice($new_data, $i + $inserted, 1, $new_rows); $inserted += count($new_rows) - 1; } } // Has the data been modified? if ($inserted > 0) { $sections[$s] = $new_data; $this->_updateRowsCols(); } } } /** * Builds the table. * * @return string The generated table string. */ function _buildTable() { if (!count($this->_data)) { return ''; } $vertical = $this->_border['vertical']; $separator = $this->_getSeparator(); $return = array(); for ($i = 0; $i < count($this->_data); $i++) { for ($j = 0; $j < count($this->_data[$i]); $j++) { if ($this->_data[$i] !== CONSOLE_TABLE_HORIZONTAL_RULE && $this->_strlen($this->_data[$i][$j]) < $this->_cell_lengths[$j]) { $this->_data[$i][$j] = $this->_strpad($this->_data[$i][$j], $this->_cell_lengths[$j], ' ', $this->_col_align[$j]); } } if ($this->_data[$i] !== CONSOLE_TABLE_HORIZONTAL_RULE) { $row_begin = $this->_borderVisibility['left'] ? $vertical . str_repeat(' ', $this->_padding) : ''; $row_end = $this->_borderVisibility['right'] ? str_repeat(' ', $this->_padding) . $vertical : ''; $implode_char = str_repeat(' ', $this->_padding) . $vertical . str_repeat(' ', $this->_padding); $return[] = $row_begin . implode($implode_char, $this->_data[$i]) . $row_end; } elseif (!empty($separator)) { $return[] = $separator; } } $return = implode(PHP_EOL, $return); if (!empty($separator)) { if ($this->_borderVisibility['inner']) { $return = $separator . PHP_EOL . $return; } if ($this->_borderVisibility['bottom']) { $return .= PHP_EOL . $separator; } } $return .= PHP_EOL; if (!empty($this->_headers)) { $return = $this->_getHeaderLine() . PHP_EOL . $return; } return $return; } /** * Creates a horizontal separator for header separation and table * start/end etc. * * @return string The horizontal separator. */ function _getSeparator() { if (!$this->_border) { return; } $horizontal = $this->_border['horizontal']; $intersection = $this->_border['intersection']; $return = array(); foreach ($this->_cell_lengths as $cl) { $return[] = str_repeat($horizontal, $cl); } $row_begin = $this->_borderVisibility['left'] ? $intersection . str_repeat($horizontal, $this->_padding) : ''; $row_end = $this->_borderVisibility['right'] ? str_repeat($horizontal, $this->_padding) . $intersection : ''; $implode_char = str_repeat($horizontal, $this->_padding) . $intersection . str_repeat($horizontal, $this->_padding); 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], ' ', $this->_col_align[$i]); } } } $vertical = $this->_border['vertical']; $row_begin = $this->_borderVisibility['left'] ? $vertical . str_repeat(' ', $this->_padding) : ''; $row_end = $this->_borderVisibility['right'] ? str_repeat(' ', $this->_padding) . $vertical : ''; $implode_char = str_repeat(' ', $this->_padding) . $vertical . str_repeat(' ', $this->_padding); $separator = $this->_getSeparator(); if (!empty($separator) && $this->_borderVisibility['top']) { $return[] = $separator; } for ($j = 0; $j < count($this->_headers); $j++) { $return[] = $row_begin . implode($implode_char, $this->_headers[$j]) . $row_end; } return implode(PHP_EOL, $return); } /** * Updates values for maximum columns and rows. * * @param array $rowdata Data array of a single row. * * @return void */ function _updateRowsCols($rowdata = null) { // Update maximum columns. $this->_max_cols = max($this->_max_cols, count($rowdata)); // Update maximum rows. ksort($this->_data); $keys = array_keys($this->_data); $this->_max_rows = end($keys) + 1; switch ($this->_defaultAlign) { case CONSOLE_TABLE_ALIGN_CENTER: $pad = STR_PAD_BOTH; break; case CONSOLE_TABLE_ALIGN_RIGHT: $pad = STR_PAD_LEFT; break; default: $pad = STR_PAD_RIGHT; break; } // Set default column alignments for ($i = 0; $i < $this->_max_cols; $i++) { if (!isset($this->_col_align[$i])) { $this->_col_align[$i] = $pad; } } } /** * Calculates the maximum length for each column of a row. * * @param array $row The row data. * * @return void */ 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. * * @return void */ function _calculateRowHeight($row_number, $row) { if (!isset($this->_row_heights[$row_number])) { $this->_row_heights[$row_number] = 1; } // Do not process horizontal rule rows. if ($row === CONSOLE_TABLE_HORIZONTAL_RULE) { return; } for ($i = 0, $c = count($row); $i < $c; ++$i) { $lines = preg_split('/\r?\n|\r/', $row[$i]); $this->_row_heights[$row_number] = max($this->_row_heights[$row_number], count($lines)); } } /** * Returns the character length of a string. * * @param string $str A multibyte or singlebyte string. * * @return integer The string length. */ function _strlen($str) { static $mbstring; // Strip ANSI color codes if requested. if ($this->_ansiColor) { $str = $this->_ansiColor->strip($str); } // Cache expensive function_exists() calls. if (!isset($mbstring)) { $mbstring = function_exists('mb_strwidth'); } if ($mbstring) { return mb_strwidth($str, $this->_charset); } return strlen($str); } /** * 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) { static $mbstring; // Cache expensive function_exists() calls. if (!isset($mbstring)) { $mbstring = function_exists('mb_substr'); } if (is_null($length)) { $length = $this->_strlen($string); } if ($mbstring) { $ret = @mb_substr($string, $start, $length, $this->_charset); if (!empty($ret)) { return $ret; } } 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); $sb_length = strlen($input); $pad_length = $this->_strlen($pad); /* Return if we already have the length. */ if ($mb_length >= $length) { return $input; } /* Shortcut for single byte strings. */ if ($mb_length == $sb_length && $pad_length == strlen($pad)) { return str_pad($input, $length, $pad, $type); } switch ($type) { case STR_PAD_LEFT: $left = $length - $mb_length; $output = $this->_substr(str_repeat($pad, ceil($left / $pad_length)), 0, $left, $this->_charset) . $input; break; case STR_PAD_BOTH: $left = floor(($length - $mb_length) / 2); $right = ceil(($length - $mb_length) / 2); $output = $this->_substr(str_repeat($pad, ceil($left / $pad_length)), 0, $left, $this->_charset) . $input . $this->_substr(str_repeat($pad, ceil($right / $pad_length)), 0, $right, $this->_charset); break; case STR_PAD_RIGHT: $right = $length - $mb_length; $output = $input . $this->_substr(str_repeat($pad, ceil($right / $pad_length)), 0, $right, $this->_charset); break; } return $output; } }