<?php
namespace PHPFUI;
class Table extends \PHPFUI\HTML5Element
{
protected bool $alwaysOutput = false;
protected string $caption = '';
protected array $colspans = [];
protected array $columnAttributes = [];
protected bool $displayHeaders = true;
protected array $footerAttributes = [];
protected array $footers = [];
protected array $headers = [];
protected array $nextRowAttributes = [];
protected ?\PHPFUI\Interfaces\Page $page = null;
protected string $recordId = '';
protected array $rowAttributes = [];
protected array $rows = [];
protected string $sortableBodyClass = '';
protected string $sortableTrClass = '';
protected bool $strict = false;
protected array $widths = [];
public function __construct()
{
parent::__construct('table');
}
public function addArrowNavigation(\PHPFUI\Interfaces\Page $page) : static
{
$page->addTailScript('jquery.arrow_nav.js');
$this->addClass('arrow-nav');
return $this;
}
public function addColumnAttribute(string $column, array $attributePairs) : static
{
if (! isset($this->columnAttributes[$column]))
{
$this->columnAttributes[$column] = [];
}
foreach ($attributePairs as $class => $value)
{
if (! isset($this->columnAttributes[$column][$class]))
{
$this->columnAttributes[$column][$class] = '';
}
$this->columnAttributes[$column][$class] .= ' ' . $value;
}
return $this;
}
public function addFooter(string $field, string $footer) : static
{
$this->footers[$field] = $footer;
return $this;
}
public function addFooterAttribute(string $key, array $values) : static
{
$this->footerAttributes[$key] = $values;
return $this;
}
public function addHeader(string $field, string $header) : static
{
$this->headers[$field] = $header;
return $this;
}
public function addNextRowAttribute(string $attribute, string $value) : static
{
$this->nextRowAttributes[$attribute][] = $value;
return $this;
}
public function addRow(array $row, array $colspans = []) : static
{
$this->rows[] = $row;
$this->colspans[] = $colspans;
$this->rowAttributes[] = $this->nextRowAttributes;
$this->nextRowAttributes = [];
return $this;
}
public function count() : int
{
return \count($this->rows);
}
public function deleteHeader(string $field) : static
{
unset($this->headers[$field]);
return $this;
}
public function displayHeaders(bool $display = true) : static
{
$this->displayHeaders = $display;
return $this;
}
public function getRecordId() : string
{
return $this->recordId;
}
public function getRows() : array
{
return $this->rows;
}
public function outputBodyRows() : string
{
$output = '';
\reset($this->colspans);
\reset($this->rowAttributes);
foreach ($this->rows as $row)
{
$output .= $this->outputRow('td', $row, '', \current($this->rowAttributes), \current($this->colspans));
\next($this->colspans);
\next($this->rowAttributes);
}
return $output;
}
public function outputFooter() : string
{
return $this->outputRow('td', $this->footers, 'tfoot', $this->footerAttributes);
}
public function outputHeader() : string
{
if (! $this->displayHeaders)
{
return '';
}
return $this->outputRow('th', $this->headers, 'thead', [], $this->widths, 'width');
}
public function setAlwaysOutput(bool $alwaysOutput = true) : static
{
$this->alwaysOutput = $alwaysOutput;
return $this;
}
public function setCaption(string $caption) : static
{
$this->caption = $caption;
return $this;
}
public function setFooters(array $footers) : static
{
$this->footers = $footers;
return $this;
}
public function setHeaders(array $headers) : static
{
$this->headers = [];
foreach ($headers as $key => $header)
{
if (\is_string($key))
{
$this->headers[$key] = $header;
}
else
{
$this->headers[$header] = $header;
}
}
return $this;
}
public function setRecordId(string $key) : static
{
$this->recordId = $key;
return $this;
}
public function setRows(array $rows) : static
{
$this->rows = $rows;
return $this;
}
public function setStrict(bool $strict = true) : static
{
$this->strict = $strict;
return $this;
}
public function setWidths(array $widths) : static
{
$this->widths = $widths;
return $this;
}
protected function getBody() : string
{
$output = '';
if (\count($this->rows) || $this->alwaysOutput)
{
if ($this->caption)
{
$output .= "<caption>{$this->caption}</caption>";
}
$output .= $this->outputHeader();
$output .= "<tbody{$this->sortableBodyClass}>";
$output .= $this->outputBodyRows();
$output .= '</tbody>';
$output .= $this->outputFooter();
}
return $output;
}
protected function getEnd() : string
{
return parent::getEnd() . '</div>';
}
protected function getSortHeader(string $field, string $title) : string
{
return $title;
}
protected function getStart() : string
{
if ($this->page && $this->sortableBodyClass)
{
$spanCount = \count($this->headers);
if (! $spanCount)
{
$spanCount = \count($this->rows[0] ?? []);
}
$placeholder = "<tr><td colspan='{$spanCount}'><span class='center'>" . \PHPFUI\Language::$dropRowHere . '</span></td></tr>';
$this->page->addJavaScript('sortable(".table-sortable",{items:"tr.row-sortable",forcePlaceholderSize:true,placeholder:"' . $placeholder . '",handle:"td.handle"})');
}
return '<div style="overflow-x:auto;">' . parent::getStart();
}
protected function outputRow(string $td, array $row, string $type = '', array $rowAttributes = [], array $attribute = [], string $attributeName = 'colspan') : string
{
if (! \count($row))
{
return '';
}
$output = '';
if ($type)
{
$output .= "<{$type}>";
}
$recordId = 0;
$id = '';
if (isset($row[$this->recordId]) && \is_scalar($row[$this->recordId]))
{
$recordId = $row[$this->recordId];
$id = " id='{$this->recordId}-{$recordId}'";
}
$rowAttributeString = '';
foreach ($rowAttributes as $rowAttribute => $value)
{
$rowAttributeString .= " {$rowAttribute}='" . \implode(' ', $value) . "' ";
}
$output .= "<tr{$id}{$rowAttributeString}{$this->sortableTrClass}>";
if (\count($this->headers))
{
\reset($attribute);
$inSpan = 0;
foreach (\array_keys($this->headers) as $field)
{
$tdclass = $td;
if (isset($this->columnAttributes[$field]))
{
foreach ($this->columnAttributes[$field] as $key => $class)
{
$tdclass .= " {$key}='{$class}'";
}
}
$final = '';
if (isset($row[$field]))
{
$final = (string)$row[$field];
}
elseif ($this->strict)
{
$final = "missing {$field}";
}
if ('th' == $td)
{
$final = $this->getSortHeader($field, $final);
}
$id = '';
if ($recordId)
{
$id = " id='{$field}-{$recordId}'";
}
if ($span = \current($attribute))
{
$inSpan = $span;
$output .= "<{$tdclass} {$attributeName}='{$span}'{$id}>{$final}</{$td}>";
}
else
{
--$inSpan;
}
if ($inSpan <= 0)
{
$output .= "<{$tdclass}{$id}>{$final}</{$td}>";
}
\next($attribute);
}
}
else
{
foreach ($row as $value)
{
$output .= "<{$td}>{$value}</{$td}>";
}
}
$output .= '</tr>';
if ($type)
{
$output .= "</{$type}>";
}
return $output;
}
}