SimpleQueryBasedTable: add new table type...

...and move logic common with ZfQueryBasedTable to a new base class
This commit is contained in:
Thomas Gelf 2017-08-12 12:02:36 +02:00
parent 3b394900c9
commit 4680fa5447
3 changed files with 245 additions and 141 deletions

View File

@ -0,0 +1,202 @@
<?php
namespace ipl\Web\Table;
use Countable;
use Icinga\Application\Benchmark;
use Icinga\Data\Filter\Filter;
use ipl\Data\Paginatable;
use ipl\Db\Zf1\FilterRenderer;
use ipl\Html\Table;
use ipl\Translation\TranslationHelper;
use ipl\Web\Widget\ControlsAndContent;
use ipl\Web\Widget\Paginator;
use ipl\Web\Table\Extension\QuickSearch;
use ipl\Web\Url;
abstract class QueryBasedTable extends Table implements Countable
{
use TranslationHelper;
use QuickSearch;
protected $defaultAttributes = [
'class' => ['common-table', 'table-row-selectable'],
'data-base-target' => '_next',
];
private $fetchedRows;
protected $lastDay;
private $isUsEnglish;
protected $searchColumns = [];
/**
* @return Paginatable
*/
abstract protected function getPaginationAdapter();
abstract public function getQuery();
public function getPaginator(Url $url)
{
return new Paginator(
$this->getPaginationAdapter(),
$url
);
}
public function count()
{
return $this->getPaginationAdapter()->count();
}
public function applyFilter(Filter $filter)
{
FilterRenderer::applyToQuery($filter, $this->getQuery());
return $this;
}
protected function getSearchColumns()
{
return $this->searchColumns;
}
protected function search($search)
{
if (! empty($search)) {
$query = $this->getQuery();
$columns = $this->getSearchColumns();
if (strpos($search, ' ') === false) {
$filter = Filter::matchAny();
foreach ($columns as $column) {
$filter->addFilter(Filter::expression($column, '=', "*$search*"));
}
} else {
$filter = Filter::matchAll();
foreach (explode(' ', $search) as $s) {
$sub = Filter::matchAny();
foreach ($columns as $column) {
$sub->addFilter(Filter::expression($column, '=', "*$s*"));
}
$filter->addFilter($sub);
}
}
FilterRenderer::applyToQuery($filter, $query);
}
return $this;
}
abstract protected function prepareQuery();
public function renderContent()
{
if (count($this->getColumnsToBeRendered())) {
$this->generateHeader();
}
$this->fetchRows();
return parent::renderContent();
}
protected function splitByDay($timestamp)
{
$this->renderDayIfNew((int) $timestamp);
}
protected function fetchRows()
{
foreach ($this->fetch() as $row) {
// Hint: do not fetch the body first, the row might want to replace it
$tr = $this->renderRow($row);
$this->body()->add($tr);
}
}
protected function isUsEnglish()
{
if ($this->isUsEnglish === null) {
$this->isUsEnglish = in_array(setlocale(LC_ALL, 0), array('en_US.UTF-8', 'C'));
}
return $this->isUsEnglish;
}
/**
* @param int $timestamp
*/
protected function renderDayIfNew($timestamp)
{
if ($this->isUsEnglish()) {
$day = date('l, jS F Y', $timestamp);
} else {
$day = strftime('%A, %e. %B, %Y', $timestamp);
}
if ($this->lastDay !== $day) {
$this->nextHeader()->add(
$this::th($day, [
'colspan' => 2,
'class' => 'table-header-day'
])
);
$this->lastDay = $day;
$this->nextBody();
}
}
abstract protected function fetchQueryRows();
public function fetch()
{
$parts = explode('\\', get_class($this));
$name = end($parts);
Benchmark::measure("Fetching data for $name table");
$rows = $this->fetchQueryRows();
$this->fetchedRows = count($rows);
Benchmark::measure("Fetched $this->fetchedRows rows for $name table");
return $rows;
}
protected function initializeOptionalQuickSearch(ControlsAndContent $controller)
{
$columns = $this->getSearchColumns();
if (! empty($columns)) {
$this->search(
$this->getQuickSearch(
$controller->controls(),
$controller->url()
)
);
}
}
/**
* @param ControlsAndContent $controller
* @return $this
*/
public function renderTo(ControlsAndContent $controller)
{
$url = $controller->url();
$c = $controller->content();
$paginator = $this->getPaginator($url);
$this->initializeOptionalQuickSearch($controller);
$controller->actions()->add($paginator);
$c->add($this);
// TODO: move elsewhere
if (method_exists($this, 'dumpSqlQuery')) {
if ($url->getParam('format') === 'sql') {
$c->prepend($this->dumpSqlQuery($url));
}
}
return $this;
}
}

View File

@ -0,0 +1,34 @@
<?php
namespace ipl\Web\Table;
use Icinga\Data\SimpleQuery;
use ipl\Data\SimpleQueryPaginationAdapter;
abstract class SimpleQueryBasedTable extends QueryBasedTable
{
/** @var SimpleQuery */
private $query;
protected function getPaginationAdapter()
{
return new SimpleQueryPaginationAdapter($this->getQuery());
}
protected function fetchQueryRows()
{
return $this->query->fetchAll();
}
/**
* @return SimpleQuery
*/
public function getQuery()
{
if ($this->query === null) {
$this->query = $this->prepareQuery();
}
return $this->query;
}
}

View File

@ -10,23 +10,11 @@ use ipl\Html\Container;
use ipl\Html\DeferredText; use ipl\Html\DeferredText;
use ipl\Html\Html; use ipl\Html\Html;
use ipl\Html\Link; use ipl\Html\Link;
use ipl\Html\Table;
use ipl\Translation\TranslationHelper;
use ipl\Web\Widget\ControlsAndContent; use ipl\Web\Widget\ControlsAndContent;
use ipl\Web\Widget\Paginator;
use ipl\Web\Table\Extension\QuickSearch;
use ipl\Web\Url; use ipl\Web\Url;
abstract class ZfQueryBasedTable extends Table abstract class ZfQueryBasedTable extends QueryBasedTable
{ {
use TranslationHelper;
use QuickSearch;
protected $defaultAttributes = [
'class' => ['common-table', 'table-row-selectable'],
'data-base-target' => '_next',
];
/** @var DbConnection */ /** @var DbConnection */
private $connection; private $connection;
@ -35,20 +23,18 @@ abstract class ZfQueryBasedTable extends Table
private $query; private $query;
private $fetchedRows;
protected $lastDay;
private $isUsEnglish;
protected $searchColumns = [];
public function __construct(DbConnection $connection) public function __construct(DbConnection $connection)
{ {
$this->connection = $connection; $this->connection = $connection;
$this->db = $connection->getDbAdapter(); $this->db = $connection->getDbAdapter();
} }
public static function show(ControlsAndContent $controller, DbConnection $db)
{
$table = new static($db);
$table->renderTo($controller);
}
public function getCountQuery() public function getCountQuery()
{ {
return $this->getPaginationAdapter()->getCountQuery(); return $this->getPaginationAdapter()->getCountQuery();
@ -59,25 +45,12 @@ abstract class ZfQueryBasedTable extends Table
return new SelectPaginationAdapter($this->getQuery()); return new SelectPaginationAdapter($this->getQuery());
} }
public function getPaginator(Url $url)
{
return new Paginator(
$this->getPaginationAdapter(),
$url
);
}
public function applyFilter(Filter $filter) public function applyFilter(Filter $filter)
{ {
FilterRenderer::applyToQuery($filter, $this->getQuery()); FilterRenderer::applyToQuery($filter, $this->getQuery());
return $this; return $this;
} }
protected function getSearchColumns()
{
return $this->searchColumns;
}
protected function search($search) protected function search($search)
{ {
if (! empty($search)) { if (! empty($search)) {
@ -105,75 +78,9 @@ abstract class ZfQueryBasedTable extends Table
return $this; return $this;
} }
abstract protected function prepareQuery(); protected function fetchQueryRows()
public function renderContent()
{ {
if (count($this->getColumnsToBeRendered())) { return $this->db->fetchAll($this->getQuery());
$this->generateHeader();
}
$this->fetchRows();
return parent::renderContent();
}
protected function splitByDay($timestamp)
{
$this->renderDayIfNew((int) $timestamp);
}
protected function fetchRows()
{
foreach ($this->fetch() as $row) {
// Hint: do not fetch the body first, the row might want to replace it
$tr = $this->renderRow($row);
$this->body()->add($tr);
}
}
protected function isUsEnglish()
{
if ($this->isUsEnglish === null) {
$this->isUsEnglish = in_array(setlocale(LC_ALL, 0), array('en_US.UTF-8', 'C'));
}
return $this->isUsEnglish;
}
/**
* @param int $timestamp
*/
protected function renderDayIfNew($timestamp)
{
if ($this->isUsEnglish()) {
$day = date('l, jS F Y', $timestamp);
} else {
$day = strftime('%A, %e. %B, %Y', $timestamp);
}
if ($this->lastDay !== $day) {
$this->nextHeader()->add(
$this::th($day, [
'colspan' => 2,
'class' => 'table-header-day'
])
);
$this->lastDay = $day;
$this->nextBody();
}
}
public function fetch()
{
$rows = $this->db->fetchAll(
$this->getQuery()
);
$this->fetchedRows = count($rows);
return $rows;
} }
public function connection() public function connection()
@ -217,43 +124,4 @@ abstract class ZfQueryBasedTable extends Table
)), )),
]); ]);
} }
public static function show(ControlsAndContent $controller, DbConnection $db)
{
$table = new static($db);
$table->renderTo($controller);
}
protected function initializeOptionalQuickSearch(ControlsAndContent $controller)
{
$columns = $this->getSearchColumns();
if (! empty($columns)) {
$this->search(
$this->getQuickSearch(
$controller->controls(),
$controller->url()
)
);
}
}
/**
* @param ControlsAndContent $controller
* @return $this
*/
public function renderTo(ControlsAndContent $controller)
{
$url = $controller->url();
$c = $controller->content();
$paginator = $this->getPaginator($url);
$this->initializeOptionalQuickSearch($controller);
$controller->actions()->add($paginator);
$c->add($this);
if ($url->getParam('format') === 'sql') {
$c->prepend($this->dumpSqlQuery($url));
}
return $this;
}
} }