Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Class for drawing cool ASCII tables, including data
<?php
class AsciiTable
{
private $rows;
private $columns;
private $headers = array();
private $data = array();
private $separators;
private $headerPadMethod;
public function __construct($rows, $columns, $chars = '-|') {
$this->columns = $columns;
$this->rows = $rows;
$this->separators = str_split($chars);
$this->initData();
}
/**
* @param array $headers
* @param bool $centered
*/
public function addHeaders($headers, $centered = false) {
if (count($headers) == $this->columns) {
$this->headers = array_combine(range(1, count($headers)), $headers);
$this->headerPadMethod = $centered ? STR_PAD_BOTH : STR_PAD_RIGHT;
} else {
throw new LogicException('Header count must match the column count!');
}
}
/**
* @param int $row
* @param int $column
* @param mixed $data
*/
public function addData($row, $column, $data) {
if (isset($this->data[$row][$column])) {
$this->data[$row][$column] = $data;
} else {
trigger_error('Row or column has not been initialized', E_USER_NOTICE);
}
}
/**
* @param int $row
* @param array $data
*/
public function addRowData($row, $data) {
$newData = array_replace(array_values($this->data[$row]), $data);
$this->data[$row] = array_combine(array_keys($this->data[$row]), $newData);
}
public function draw() {
$columnWidths = array();
for ($col = 1; $col <= $this->columns; $col++) {
$columnWidths[$col] = $this->getMaxColumnWidth($col);
}
$gridWidth = array_sum($columnWidths) + ($this->columns * 3) + 1;
for ($row = 0; $row <= $this->rows; $row++) {
if ($row == 0 && empty($this->headers)) {
continue;
}
echo str_repeat($this->separators[0], $gridWidth), PHP_EOL;
for ($col = 1; $col <= $this->columns; $col++) {
if ($row == 0 && !empty($this->headers)) {
$content = $this->headers[$col];
$padMethod = $this->headerPadMethod;
} else {
$content = $this->data[$row][$col];
$padMethod = STR_PAD_RIGHT;
}
$contentLines = explode(PHP_EOL, $content);
//$contentLines = array_replace(array_fill(0, $this->getMaxRowHeight($row), ''), $contentLines);
$contentLines = array_map(function($line) use ($col, $columnWidths, $padMethod) {
return str_pad($line, $columnWidths[$col], ' ', $padMethod);
}, $contentLines);
foreach ($contentLines as $i => $line) {
echo "{$this->separators[1]} $line ";
if ($i < count($contentLines) - 1) {
echo $this->separators[1], PHP_EOL;
}
}
if ($col == $this->columns) {
echo $this->separators[1], PHP_EOL;
}
}
if ($row == $this->rows) {
echo str_repeat($this->separators[0], $gridWidth);
}
}
}
/**
* Creates array structure for $this->data and fills it with empty strings
*/
private function initData() {
for ($row = 1; $row <= $this->rows; $row++) {
$this->data[$row] = array_fill(1, $this->columns, '');
}
}
/**
* @param int $column
* @return int
*/
private function getMaxColumnWidth($column) {
$columns = array_column($this->data, $column);
if (!empty($this->headers)) {
$columns = array_merge([$this->headers[$column]], $columns);
}
$columnLengths = array_map(function($column) {
return max(array_map('strlen', explode(PHP_EOL, $column)));
}, $columns);
return max($columnLengths);
}
/**
* @param int $row
* @return int
*/
private function getMaxRowHeight($row) {
$columnLines = array_map(function($column) {
return count(explode(PHP_EOL, $column));
}, $this->data[$row]);
return max($columnLines);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.