Files
r2c/vendor/league/climate/src/TerminalObject/Basic/Table.php
T
2018-06-21 17:59:40 +02:00

226 lines
5.1 KiB
PHP

<?php
namespace League\CLImate\TerminalObject\Basic;
use League\CLImate\TerminalObject\Helper\StringLength;
class Table extends BasicTerminalObject
{
use StringLength;
/**
* The data for the table, an array of (arrays|objects)
*
* @var array $data
*/
protected $data = [];
/**
* An array of the widths of each column in the table
*
* @var array $column_widths
*/
protected $column_widths = [];
/**
* The width of the table
*
* @var integer $table_width
*/
protected $table_width = 0;
/**
* The divider between table cells
*
* @var string $column_divider
*/
protected $column_divider = ' | ';
/**
* The border to divide each row of the table
*
* @var string $border
*/
protected $border;
/**
* The array of rows that will ultimately be returned
*
* @var array $rows
*/
protected $rows = [];
public function __construct(array $data)
{
$this->data = $data;
}
/**
* Return the built rows
*
* @return array
*/
public function result()
{
$this->column_widths = $this->getColumnWidths();
$this->table_width = $this->getWidth();
$this->border = $this->getBorder();
$this->buildHeaderRow();
foreach ($this->data as $key => $columns) {
$this->rows[] = $this->buildRow($columns);
$this->rows[] = $this->border;
}
return $this->rows;
}
/**
* Determine the width of the table
*
* @return integer
*/
protected function getWidth()
{
$first_row = reset($this->data);
$first_row = $this->buildRow($first_row);
return $this->lengthWithoutTags($first_row);
}
/**
* Get the border for each row based on the table width
*/
protected function getBorder()
{
return (new Border())->length($this->table_width)->result();
}
/**
* Check for a header row (if it's an array of associative arrays or objects),
* if there is one, tack it onto the front of the rows array
*/
protected function buildHeaderRow()
{
$header_row = $this->getHeaderRow();
if ($header_row) {
$this->rows[] = $this->border;
$this->rows[] = $this->buildRow($header_row);
$this->rows[] = (new Border())->char('=')->length($this->table_width)->result();
} else {
$this->rows[] = $this->border;
}
}
/**
* Get table row
*
* @param mixed $columns
*
* @return string
*/
protected function buildRow($columns)
{
$row = [];
foreach ($columns as $key => $column) {
$row[] = $this->buildCell($key, $column);
}
$row = implode($this->column_divider, $row);
return trim($this->column_divider . $row . $this->column_divider);
}
/**
* Build the string for this particular table cell
*
* @param mixed $key
* @param string $column
*
* @return string
*/
protected function buildCell($key, $column)
{
return $this->pad($column, $this->column_widths[$key]);
}
/**
* Get the header row for the table if it's an associative array or object
*
* @return mixed
*/
protected function getHeaderRow()
{
$first_item = reset($this->data);
if (is_object($first_item)) {
$first_item = get_object_vars($first_item);
}
$keys = array_keys($first_item);
$first_key = reset($keys);
// We have an associative array (probably), let's have a header row
if (!is_int($first_key)) {
return array_combine($keys, $keys);
}
return false;
}
/**
* Determine the width of each column
*
* @return array
*/
protected function getColumnWidths()
{
$first_row = reset($this->data);
if (is_object($first_row)) {
$first_row = get_object_vars($first_row);
}
// Create an array with the columns as keys and values of zero
$column_widths = $this->getDefaultColumnWidths($first_row);
foreach ($this->data as $columns) {
foreach ($columns as $key => $column) {
$column_widths[$key] = $this->getCellWidth($column_widths[$key], $column);
}
}
return $column_widths;
}
/**
* Set up an array of default column widths
*
* @param array $columns
*
* @return array
*/
protected function getDefaultColumnWidths(array $columns)
{
$widths = $this->arrayOfStrLens(array_keys($columns));
return array_combine(array_keys($columns), $widths);
}
/**
* Determine the width of the columns without tags
*
* @param array $current_width
* @param string $str
*
* @return integer
*/
protected function getCellWidth($current_width, $str)
{
return max($current_width, $this->lengthWithoutTags($str));
}
}