After my previous question I made several changes and came up with this. Remember: I wrote this for PHP 7.0.33. I'm aware I should upgrade, save the advice :)
class Table
{
private $orientation = "hz"; // "vt" not implemented yet
private $table_title = "";
private $headers = array();
private $data = array();
private $footers = array();
private $tabs = 0;
/**
* Holds default HTML classes
* @var array
*
* Should be private but PHP 7 blah blah... save the advice, I'm aware
*/
const HTML_TABLE_CLASSES = [
"table" => "table",
"title" => "table-title",
"header_row" => "table-header",
"header_cell" => "table-header-cell",
"body" => "table-body",
"row" => "table-row",
"cell" => "table-row-cell",
"footer_row" => "table-footer",
"footer_cell" => "table-footer-cell"
];
/**
* Holds user defined attributes for HTML elements
* @var array
*/
private $html_attributes = [
"table" => [],
"title" => [],
"header_row" => [],
"header_cell" => [],
"body" => [],
"row" => [],
"cell" => [],
"footer_row" => [],
"footer_cell" => []
];
public function __construct(
string $orientation = "hz",
int $tabs = 0,
array $tableAttrs = []
) {
$this->setOrientation($orientation);
$this->setTabs($tabs);
$this->setTableAttributes($tableAttrs);
}
public function setOrientation(string $orientation = "hz"): bool
{
if ($orientation === "vt") {
$this->orientation = "vt";
}
return true;
}
public function setTabs(int $tabs = 0): bool
{
$this->tabs = ($tabs > 0) ? $tabs : 0;
return true;
}
public function setTableAttributes(array $attrs = []): bool
{
$this->html_attributes["table"] = $attrs;
return true;
}
public function setTitle(string $table_title, array $attributes = []): bool
{
$this->table_title = $table_title;
$this->html_attributes['title'] = $attributes;
return true;
}
private function getTitle(): string
{
if (strlen($this->table_title) === 0) {
return "";
}
return $this->getHtmlDiv(
$this->table_title,
$this->getHtmlAttributes("title"),
1
);
}
public function setHeaders(
array $headers,
array $row_attributes = [],
array $cell_attributes = []
): bool {
if (
(count($headers) > 0) &&
(count($headers) !== count($headers, COUNT_RECURSIVE))
) {
// throw new Exception("Headers array should be a simple array");
trigger_error("Headers array should be a simple array. Headers will be dismissed.", E_USER_WARNING);
return false;
}
$this->headers = $headers;
$this->html_attributes['header_row'] = $row_attributes;
$this->html_attributes['header_cell'] = $cell_attributes;
return true;
}
private function getHeaders(): string
{
$output = "";
$cell_counter = 0;
if (count($this->headers) !== 0) {
foreach($this->headers as $cell_data) {
$output .= $this->getHtmlDiv(
$cell_data,
$this->getHtmlAttributes("header_cell", $cell_counter),
2
);
$cell_counter++;
}
$output = $this->getHtmlDiv(
$output,
$this->getHtmlAttributes("header_row"),
1,
true
);
}
return $output;
}
public function setData(
array $data,
array $row_attributes = [],
array $cell_attributes = []
): bool {
$this->checkData($data);
$this->data = $data;
$this->html_attributes['row'] = $row_attributes;
$this->html_attributes['cell'] = $cell_attributes;
return true;
}
private function checkData(array $data = []): bool
{
/*
if (count($data) < 1) {
throw new Exception("With no data there is no table to render");
}
*/
if (
(count($data) > 1) &&
count($data) === count($data, COUNT_RECURSIVE)
) {
// throw new Exception("Table data array has the wrong format: it must be a multidimensional array");
trigger_error(
"Table data array has the wrong format: it must be a multidimensional array. Set to empty array.",
E_USER_WARNING
);
$this->data = [];
}
return true;
}
private function getData(): string
{
$this->checkData($this->data);
$body_build = "";
$row_build = "";
$output = "";
$col_count = 0;
if (count($this->headers) > 0) {
$col_count = count($this->headers);
} else {
$col_count = count($this->data[array_keys($this->data)[0]]);
}
$row_counter = 0;
foreach ($this->data as $data) { // row
$row_build = "";
$cell_counter = 0;
foreach ($data as $cell_data) { // cell
if ($cell_counter < $col_count) {
$row_build .= $this->getHtmlDiv(
$cell_data ?? "",
$this->getHtmlAttributes("cell", $row_counter, $cell_counter),
3
);
$cell_counter++;
}
}
$row_build .= $this->getEmptyCells("footer_cell", $cell_counter, 2);
$body_build .= $this->getHtmlDiv(
$row_build,
$this->getHtmlAttributes("row", $row_counter, 0),
2,
true
);
$row_counter++;
}
$output .= $this->getHtmlDiv(
$body_build,
$this->getHtmlAttributes("body"),
1,
true
);
return $output;
}
public function setBodyAttributes(array $attrs = []): bool
{
$this->html_attributes["body"] = $attrs;
return true;
}
public function setFooters(
array $footers = [],
array $row_attributes = [],
array $cell_attributes = []
): bool {
if (count($footers) > 0) {
if (
(count($footers) > 0) &&
(count($footers) !== count($footers, COUNT_RECURSIVE))
) {
// throw new Exception("Footers should be a simple array");
trigger_error("Footers should be a simple array. Footers will be dismissed", E_USER_WARNING);
return false;
}
$this->footers = $footers;
$this->html_attributes['footer_row'] = $row_attributes;
$this->html_attributes['footer_cell'] = $cell_attributes;
}
return true;
}
private function getFooters(int $col_count): string
{
$output = "";
$cell_counter = 0;
if (count($this->footers) > 0) {
foreach($this->footers as $cell_data) {
if ($cell_counter < $col_count) {
$output .= $this->getHtmlDiv(
$cell_data,
$this->getHtmlAttributes("footer_cell", $cell_counter),
2
);
$cell_counter++;
}
}
$output .= $this->getEmptyCells("footer_cell", $cell_counter, 2);
$output = $this->getHtmlDiv(
$output,
$this->getHtmlAttributes("footer_row"),
1,
true
);
}
return $output;
}
public function get(): string
{
$this->checkData($this->data);
$output = "";
$output .= $this->getTitle();
if ($this->orientation === "hz") {
/**
* column count: Anything beyond $col_count will be dismissed.
* A warning will be added.
*/
if (count($this->headers) > 0) {
$col_count = count($this->headers);
} else {
$col_count = count($this->data[array_keys($this->data)[0]]);
}
$output .= $this->getHeaders();
$output .= $this->getData($col_count);
$output .= $this->getFooters($col_count);
}
// get table and return
return $this->getHtmlDiv(
$output,
$this->getHtmlAttributes("table"),
0,
true
);
}
private function getHtmlAttributes(string $section, int $row = 0, int $column = 0): array
{
$output = [];
if (strpos($section, "cell") !== false) {
if (
array_key_exists($row, $this->html_attributes[$section]) &&
array_key_exists($column, $this->html_attributes[$section][$row])
) {
$output = $this->html_attributes[$section][$row][$column];
}
} else { // table, title, header, body, row, footer
$output = $this->html_attributes[$section];
}
if ( // set default. trigger user warning?
!array_key_exists("class", $output) ||
(strlen($output["class"]) === 0)
) {
$output["class"] = self::HTML_TABLE_CLASSES[$section];
}
return $output;
}
private function getHtmlDiv(
string $content = "",
array $attrs = [],
int $tabcount = 0,
bool $add_newline = false
): string {
$output = "\n" . str_repeat(" ", $this->tabs + $tabcount) . "<div";
foreach ($attrs as $attr => $value) {
$output .= " $attr='$value'";
}
$output .= ">";
$output .= $content;
if ($add_newline) {
$output .= "\n" . str_repeat(" ", $this->tabs + $tabcount);
}
$output .= "</div>";
return $output;
}
private function getEmptyCells(
string $section,
int $cell_counter,
int $tabs
): string {
$output = "";
while ($cell_counter < count($this->headers)) {
$output .= $this->getHtmlDiv(
"",
$this->getHtmlAttributes($section, $cell_counter),
$tabs
);
$cell_counter++;
}
return $output;
}
}
[reviewed]
in it? That doesn't uniquely describe what your script does. A title should endeavor to uniquely describe the script and nothing more. \$\endgroup\$[closed]
at a quick glance... \$\endgroup\$