258 lines
6.4 KiB
PHP
258 lines
6.4 KiB
PHP
<?php
|
|
/**
|
|
* PHP Command Line Tools
|
|
*
|
|
* This source file is subject to the MIT license that is bundled
|
|
* with this package in the file LICENSE.
|
|
*
|
|
* @author James Logsdon <dwarf@girsbrain.org>
|
|
* @copyright 2010 James Logsdom (http://girsbrain.org)
|
|
* @license http://www.opensource.org/licenses/mit-license.php The MIT License
|
|
*/
|
|
|
|
namespace cli;
|
|
|
|
use cli\Shell;
|
|
use cli\Streams;
|
|
use cli\table\Ascii;
|
|
use cli\table\Renderer;
|
|
use cli\table\Tabular;
|
|
|
|
/**
|
|
* The `Table` class is used to display data in a tabular format.
|
|
*/
|
|
class Table {
|
|
protected $_renderer;
|
|
protected $_headers = array();
|
|
protected $_footers = array();
|
|
protected $_width = array();
|
|
protected $_rows = array();
|
|
|
|
/**
|
|
* Initializes the `Table` class.
|
|
*
|
|
* There are 3 ways to instantiate this class:
|
|
*
|
|
* 1. Pass an array of strings as the first parameter for the column headers
|
|
* and a 2-dimensional array as the second parameter for the data rows.
|
|
* 2. Pass an array of hash tables (string indexes instead of numerical)
|
|
* where each hash table is a row and the indexes of the *first* hash
|
|
* table are used as the header values.
|
|
* 3. Pass nothing and use `setHeaders()` and `addRow()` or `setRows()`.
|
|
*
|
|
* @param array $headers Headers used in this table. Optional.
|
|
* @param array $rows The rows of data for this table. Optional.
|
|
* @param array $footers Footers used in this table. Optional.
|
|
*/
|
|
public function __construct(array $headers = null, array $rows = null, array $footers = null) {
|
|
if (!empty($headers)) {
|
|
// If all the rows is given in $headers we use the keys from the
|
|
// first row for the header values
|
|
if ($rows === null) {
|
|
$rows = $headers;
|
|
$keys = array_keys(array_shift($headers));
|
|
$headers = array();
|
|
|
|
foreach ($keys as $header) {
|
|
$headers[$header] = $header;
|
|
}
|
|
}
|
|
|
|
$this->setHeaders($headers);
|
|
$this->setRows($rows);
|
|
}
|
|
|
|
if (!empty($footers)) {
|
|
$this->setFooters($footers);
|
|
}
|
|
|
|
if (Shell::isPiped()) {
|
|
$this->setRenderer(new Tabular());
|
|
} else {
|
|
$this->setRenderer(new Ascii());
|
|
}
|
|
}
|
|
|
|
public function resetTable()
|
|
{
|
|
$this->_headers = array();
|
|
$this->_width = array();
|
|
$this->_rows = array();
|
|
$this->_footers = array();
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* Sets the renderer used by this table.
|
|
*
|
|
* @param table\Renderer $renderer The renderer to use for output.
|
|
* @see table\Renderer
|
|
* @see table\Ascii
|
|
* @see table\Tabular
|
|
*/
|
|
public function setRenderer(Renderer $renderer) {
|
|
$this->_renderer = $renderer;
|
|
}
|
|
|
|
/**
|
|
* Loops through the row and sets the maximum width for each column.
|
|
*
|
|
* @param array $row The table row.
|
|
* @return array $row
|
|
*/
|
|
protected function checkRow(array $row) {
|
|
foreach ($row as $column => $str) {
|
|
$width = Colors::width( $str, $this->isAsciiPreColorized( $column ) );
|
|
if (!isset($this->_width[$column]) || $width > $this->_width[$column]) {
|
|
$this->_width[$column] = $width;
|
|
}
|
|
}
|
|
|
|
return $row;
|
|
}
|
|
|
|
/**
|
|
* Output the table to `STDOUT` using `cli\line()`.
|
|
*
|
|
* If STDOUT is a pipe or redirected to a file, should output simple
|
|
* tab-separated text. Otherwise, renders table with ASCII table borders
|
|
*
|
|
* @uses cli\Shell::isPiped() Determine what format to output
|
|
*
|
|
* @see cli\Table::renderRow()
|
|
*/
|
|
public function display() {
|
|
foreach( $this->getDisplayLines() as $line ) {
|
|
Streams::line( $line );
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get the table lines to output.
|
|
*
|
|
* @see cli\Table::display()
|
|
* @see cli\Table::renderRow()
|
|
*
|
|
* @return array
|
|
*/
|
|
public function getDisplayLines() {
|
|
$this->_renderer->setWidths($this->_width, $fallback = true);
|
|
$border = $this->_renderer->border();
|
|
|
|
$out = array();
|
|
if (isset($border)) {
|
|
$out[] = $border;
|
|
}
|
|
$out[] = $this->_renderer->row($this->_headers);
|
|
if (isset($border)) {
|
|
$out[] = $border;
|
|
}
|
|
|
|
foreach ($this->_rows as $row) {
|
|
$row = $this->_renderer->row($row);
|
|
$row = explode( PHP_EOL, $row );
|
|
$out = array_merge( $out, $row );
|
|
}
|
|
|
|
if (isset($border)) {
|
|
$out[] = $border;
|
|
}
|
|
|
|
if ($this->_footers) {
|
|
$out[] = $this->_renderer->row($this->_footers);
|
|
if (isset($border)) {
|
|
$out[] = $border;
|
|
}
|
|
}
|
|
return $out;
|
|
}
|
|
|
|
/**
|
|
* Sort the table by a column. Must be called before `cli\Table::display()`.
|
|
*
|
|
* @param int $column The index of the column to sort by.
|
|
*/
|
|
public function sort($column) {
|
|
if (!isset($this->_headers[$column])) {
|
|
trigger_error('No column with index ' . $column, E_USER_NOTICE);
|
|
return;
|
|
}
|
|
|
|
usort($this->_rows, function($a, $b) use ($column) {
|
|
return strcmp($a[$column], $b[$column]);
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Set the headers of the table.
|
|
*
|
|
* @param array $headers An array of strings containing column header names.
|
|
*/
|
|
public function setHeaders(array $headers) {
|
|
$this->_headers = $this->checkRow($headers);
|
|
}
|
|
|
|
/**
|
|
* Set the footers of the table.
|
|
*
|
|
* @param array $footers An array of strings containing column footers names.
|
|
*/
|
|
public function setFooters(array $footers) {
|
|
$this->_footers = $this->checkRow($footers);
|
|
}
|
|
|
|
|
|
/**
|
|
* Add a row to the table.
|
|
*
|
|
* @param array $row The row data.
|
|
* @see cli\Table::checkRow()
|
|
*/
|
|
public function addRow(array $row) {
|
|
$this->_rows[] = $this->checkRow($row);
|
|
}
|
|
|
|
/**
|
|
* Clears all previous rows and adds the given rows.
|
|
*
|
|
* @param array $rows A 2-dimensional array of row data.
|
|
* @see cli\Table::addRow()
|
|
*/
|
|
public function setRows(array $rows) {
|
|
$this->_rows = array();
|
|
foreach ($rows as $row) {
|
|
$this->addRow($row);
|
|
}
|
|
}
|
|
|
|
public function countRows() {
|
|
return count($this->_rows);
|
|
}
|
|
|
|
/**
|
|
* Set whether items in an Ascii table are pre-colorized.
|
|
*
|
|
* @param bool|array $precolorized A boolean to set all columns in the table as pre-colorized, or an array of booleans keyed by column index (number) to set individual columns as pre-colorized.
|
|
* @see cli\Ascii::setPreColorized()
|
|
*/
|
|
public function setAsciiPreColorized( $pre_colorized ) {
|
|
if ( $this->_renderer instanceof Ascii ) {
|
|
$this->_renderer->setPreColorized( $pre_colorized );
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Is a column in an Ascii table pre-colorized?
|
|
*
|
|
* @param int $column Column index to check.
|
|
* @return bool True if whole Ascii table is marked as pre-colorized, or if the individual column is pre-colorized; else false.
|
|
* @see cli\Ascii::isPreColorized()
|
|
*/
|
|
private function isAsciiPreColorized( $column ) {
|
|
if ( $this->_renderer instanceof Ascii ) {
|
|
return $this->_renderer->isPreColorized( $column );
|
|
}
|
|
return false;
|
|
}
|
|
}
|