summaryrefslogtreecommitdiffstats
path: root/vendor/gipfl/icingaweb2/src/Table
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-14 13:23:16 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-14 13:23:16 +0000
commit3e97c51418e6d27e9a81906f347fcb7c78e27d4f (patch)
treeee596ce1bc9840661386f96f9b8d1f919a106317 /vendor/gipfl/icingaweb2/src/Table
parentInitial commit. (diff)
downloadicingaweb2-module-incubator-3e97c51418e6d27e9a81906f347fcb7c78e27d4f.tar.xz
icingaweb2-module-incubator-3e97c51418e6d27e9a81906f347fcb7c78e27d4f.zip
Adding upstream version 0.20.0.upstream/0.20.0
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vendor/gipfl/icingaweb2/src/Table')
-rw-r--r--vendor/gipfl/icingaweb2/src/Table/Extension/MultiSelect.php29
-rw-r--r--vendor/gipfl/icingaweb2/src/Table/Extension/QuickSearch.php74
-rw-r--r--vendor/gipfl/icingaweb2/src/Table/Extension/ZfSortablePriority.php263
-rw-r--r--vendor/gipfl/icingaweb2/src/Table/QueryBasedTable.php281
-rw-r--r--vendor/gipfl/icingaweb2/src/Table/SimpleQueryBasedTable.php34
-rw-r--r--vendor/gipfl/icingaweb2/src/Table/ZfQueryBasedTable.php149
6 files changed, 830 insertions, 0 deletions
diff --git a/vendor/gipfl/icingaweb2/src/Table/Extension/MultiSelect.php b/vendor/gipfl/icingaweb2/src/Table/Extension/MultiSelect.php
new file mode 100644
index 0000000..7a5a3ff
--- /dev/null
+++ b/vendor/gipfl/icingaweb2/src/Table/Extension/MultiSelect.php
@@ -0,0 +1,29 @@
+<?php
+
+namespace gipfl\IcingaWeb2\Table\Extension;
+
+use gipfl\IcingaWeb2\Url;
+
+// Could also be a static method, MultiSelect::enable($table)
+trait MultiSelect
+{
+ protected function enableMultiSelect($url, $sourceUrl, array $keys)
+ {
+ /** @var $table \ipl\Html\BaseHtmlElement */
+ $table = $this;
+ $table->addAttributes([
+ 'class' => 'multiselect'
+ ]);
+
+ $prefix = 'data-icinga-multiselect';
+ $multi = [
+ "$prefix-url" => Url::fromPath($url),
+ "$prefix-controllers" => Url::fromPath($sourceUrl),
+ "$prefix-data" => implode(',', $keys),
+ ];
+
+ $table->addAttributes($multi);
+
+ return $this;
+ }
+}
diff --git a/vendor/gipfl/icingaweb2/src/Table/Extension/QuickSearch.php b/vendor/gipfl/icingaweb2/src/Table/Extension/QuickSearch.php
new file mode 100644
index 0000000..0f0cec3
--- /dev/null
+++ b/vendor/gipfl/icingaweb2/src/Table/Extension/QuickSearch.php
@@ -0,0 +1,74 @@
+<?php
+
+namespace gipfl\IcingaWeb2\Table\Extension;
+
+use gipfl\IcingaWeb2\Url;
+use gipfl\IcingaWeb2\Widget\Controls;
+use ipl\Html\BaseHtmlElement;
+use ipl\Html\Html;
+
+trait QuickSearch
+{
+ /** @var BaseHtmlElement */
+ private $quickSearchForm;
+
+ public function getQuickSearch(BaseHtmlElement $parent, Url $url)
+ {
+ $this->requireQuickSearchForm($parent, $url);
+ $search = $url->getParam('q');
+ return $search;
+ }
+
+ private function requireQuickSearchForm(BaseHtmlElement $parent, Url $url)
+ {
+ if ($this->quickSearchForm === null) {
+ $this->quickSearchForm = $this->buildQuickSearchForm($parent, $url);
+ }
+ }
+
+ private function buildQuickSearchForm(BaseHtmlElement $parent, Url $url)
+ {
+ $search = $url->getParam('q');
+
+ $form = Html::tag('form', [
+ 'action' => $url->without(array('q', 'page', 'modifyFilter'))->getAbsoluteUrl(),
+ 'class' => ['gipfl-quicksearch'],
+ 'method' => 'GET'
+ ]);
+
+ $form->add(
+ Html::tag('input', [
+ 'type' => 'text',
+ 'name' => 'q',
+ 'title' => $this->translate('Search is simple! Try to combine multiple words'),
+ 'value' => $search,
+ 'placeholder' => $this->translate('Search...'),
+ 'class' => 'search'
+ ])
+ );
+
+ $this->addQuickSearchToControls($parent, $form);
+
+ return $form;
+ }
+
+ protected function addQuickSearchToControls(BaseHtmlElement $parent, BaseHtmlElement $form)
+ {
+ if ($parent instanceof Controls) {
+ $title = $parent->getTitleElement();
+ if ($title === null) {
+ $parent->prepend($form);
+ } else {
+ $input = $form->getFirst('input');
+ $form->remove($input);
+ $title->add($input);
+ $form->add($title);
+ $parent->setTitleElement($form);
+ }
+ } else {
+ $parent->prepend($form);
+ }
+
+ return $this;
+ }
+}
diff --git a/vendor/gipfl/icingaweb2/src/Table/Extension/ZfSortablePriority.php b/vendor/gipfl/icingaweb2/src/Table/Extension/ZfSortablePriority.php
new file mode 100644
index 0000000..cb1eac6
--- /dev/null
+++ b/vendor/gipfl/icingaweb2/src/Table/Extension/ZfSortablePriority.php
@@ -0,0 +1,263 @@
+<?php
+
+namespace gipfl\IcingaWeb2\Table\Extension;
+
+use gipfl\IcingaWeb2\Table\ZfQueryBasedTable;
+use gipfl\IcingaWeb2\IconHelper;
+use gipfl\ZfDb\Exception\SelectException;
+use gipfl\ZfDb\Select;
+use Icinga\Web\Request;
+use Icinga\Web\Response;
+use ipl\Html\BaseHtmlElement;
+use ipl\Html\Html;
+use ipl\Html\HtmlString;
+use RuntimeException;
+use Zend_Db_Select_Exception as ZfDbSelectException;
+
+/**
+ * Trait ZfSortablePriority
+ *
+ * Assumes to run in a ZfQueryBasedTable
+ */
+trait ZfSortablePriority
+{
+ /** @var Request */
+ protected $request;
+
+ /** @var Response */
+ protected $response;
+
+ public function handleSortPriorityActions(Request $request, Response $response)
+ {
+ $this->request = $request;
+ $this->response = $response;
+ return $this;
+ }
+
+ protected function reallyHandleSortPriorityActions()
+ {
+ $request = $this->request;
+
+ if ($request->isPost() && $this->hasBeenSent($request)) {
+ // $this->fixPriorities();
+ foreach (array_keys($request->getPost()) as $key) {
+ if (substr($key, 0, 8) === 'MOVE_UP_') {
+ $id = (int) substr($key, 8);
+ $this->moveRow($id, 'up');
+ }
+ if (substr($key, 0, 10) === 'MOVE_DOWN_') {
+ $id = (int) substr($key, 10);
+ $this->moveRow($id, 'down');
+ }
+ }
+ $this->response->redirectAndExit($request->getUrl());
+ }
+ }
+
+ protected function hasBeenSent(Request $request)
+ {
+ return $request->getPost('__FORM_NAME') === $this->getUniqueFormName();
+ }
+
+ protected function addSortPriorityButtons(BaseHtmlElement $tr, $row)
+ {
+ $tr->add(
+ Html::tag(
+ 'td',
+ null,
+ $this->createUpDownButtons($row->{$this->getKeyColumn()})
+ )
+ );
+
+ return $tr;
+ }
+
+ protected function getKeyColumn()
+ {
+ if (isset($this->keyColumn)) {
+ return $this->keyColumn;
+ } else {
+ throw new RuntimeException(
+ 'ZfSortablePriority requires keyColumn'
+ );
+ }
+ }
+
+ protected function getPriorityColumn()
+ {
+ if (isset($this->priorityColumn)) {
+ return $this->priorityColumn;
+ } else {
+ throw new RuntimeException(
+ 'ZfSortablePriority requires priorityColumn'
+ );
+ }
+ }
+
+ protected function getPriorityColumns()
+ {
+ return [
+ 'id' => $this->getKeyColumn(),
+ 'prio' => $this->getPriorityColumn()
+ ];
+ }
+
+ protected function moveRow($id, $direction)
+ {
+ /** @var $this ZfQueryBasedTable */
+ $db = $this->db();
+ /** @var $this ZfQueryBasedTable */
+ $query = $this->getQuery();
+ $tableParts = $this->getQueryPart(Select::FROM);
+ $alias = key($tableParts);
+ $table = $tableParts[$alias]['tableName'];
+
+ $whereParts = $this->getQueryPart(Select::WHERE);
+ unset($query);
+ if (empty($whereParts)) {
+ $where = '';
+ } else {
+ $where = ' AND ' . implode(' ', $whereParts);
+ }
+
+ $prioCol = $this->getPriorityColumn();
+ $keyCol = $this->getKeyColumn();
+ $myPrio = (int) $db->fetchOne(
+ $db->select()
+ ->from($table, $prioCol)
+ ->where("$keyCol = ?", $id)
+ );
+
+ $op = $direction === 'up' ? '<' : '>';
+ $sortDir = $direction === 'up' ? 'DESC' : 'ASC';
+ $query = $db->select()
+ ->from([$alias => $table], $this->getPriorityColumns())
+ ->where("$prioCol $op ?", $myPrio)
+ ->order("$prioCol $sortDir")
+ ->limit(1);
+
+ if (! empty($whereParts)) {
+ $query->where(implode(' ', $whereParts));
+ }
+
+ $next = $db->fetchRow($query);
+
+ if ($next) {
+ $sql = 'UPDATE %s %s'
+ . ' SET %s = CASE WHEN %s = %s THEN %d ELSE %d END'
+ . ' WHERE %s IN (%s, %s)';
+
+ $query = sprintf(
+ $sql,
+ $table,
+ $alias,
+ $prioCol,
+ $keyCol,
+ $id,
+ (int) $next->prio,
+ $myPrio,
+ $keyCol,
+ $id,
+ (int) $next->id
+ ) . $where;
+
+ $db->query($query);
+ }
+ }
+
+ protected function getSortPriorityTitle()
+ {
+ /** @var ZfQueryBasedTable $table */
+ $table = $this;
+
+ return Html::tag(
+ 'span',
+ ['title' => $table->translate('Change priority')],
+ $table->translate('Prio')
+ );
+ }
+
+ protected function createUpDownButtons($key)
+ {
+ /** @var ZfQueryBasedTable $table */
+ $table = $this;
+ $up = $this->createIconButton(
+ "MOVE_UP_$key",
+ 'up-big',
+ $table->translate('Move up (raise priority)')
+ );
+ $down = $this->createIconButton(
+ "MOVE_DOWN_$key",
+ 'down-big',
+ $table->translate('Move down (lower priority)')
+ );
+
+ if ($table->isOnFirstRow()) {
+ $up->getAttributes()->add('disabled', 'disabled');
+ }
+
+ if ($table->isOnLastRow()) {
+ $down->getAttributes()->add('disabled', 'disabled');
+ }
+
+ return [$down, $up];
+ }
+
+ protected function createIconButton($key, $icon, $title)
+ {
+ return Html::tag('input', [
+ 'type' => 'submit',
+ 'class' => 'icon-button',
+ 'name' => $key,
+ 'title' => $title,
+ 'value' => IconHelper::instance()->iconCharacter($icon)
+ ]);
+ }
+
+ protected function getUniqueFormName()
+ {
+ $parts = explode('\\', get_class($this));
+ return end($parts);
+ }
+
+ protected function renderWithSortableForm()
+ {
+ if ($this->request === null) {
+ return parent::render();
+ }
+ $this->reallyHandleSortPriorityActions();
+
+ $url = $this->request->getUrl();
+ // TODO: No margin for form
+ $form = Html::tag('form', [
+ 'action' => $url->getAbsoluteUrl(),
+ 'method' => 'POST'
+ ], [
+ Html::tag('input', [
+ 'type' => 'hidden',
+ 'name' => '__FORM_NAME',
+ 'value' => $this->getUniqueFormName()
+ ]),
+ new HtmlString(parent::render())
+ ]);
+
+ return $form->render();
+ }
+
+ protected function getQueryPart($part)
+ {
+ /** @var ZfQueryBasedTable $table */
+ $table = $this;
+ /** @var Select|\Zend_Db_Select $query */
+ $query = $table->getQuery();
+ try {
+ return $query->getPart($part);
+ } catch (SelectException $e) {
+ // Will not happen if $part is correct.
+ throw new RuntimeException($e);
+ } catch (ZfDbSelectException $e) {
+ // Will not happen if $part is correct.
+ throw new RuntimeException($e);
+ }
+ }
+}
diff --git a/vendor/gipfl/icingaweb2/src/Table/QueryBasedTable.php b/vendor/gipfl/icingaweb2/src/Table/QueryBasedTable.php
new file mode 100644
index 0000000..e9281c7
--- /dev/null
+++ b/vendor/gipfl/icingaweb2/src/Table/QueryBasedTable.php
@@ -0,0 +1,281 @@
+<?php
+
+namespace gipfl\IcingaWeb2\Table;
+
+use Countable;
+use gipfl\Format\LocalDateFormat;
+use gipfl\IcingaWeb2\Data\Paginatable;
+use gipfl\IcingaWeb2\Zf1\Db\FilterRenderer;
+use gipfl\IcingaWeb2\Table\Extension\QuickSearch;
+use gipfl\IcingaWeb2\Url;
+use gipfl\IcingaWeb2\Widget\ControlsAndContent;
+use gipfl\IcingaWeb2\Widget\Paginator;
+use gipfl\Translation\TranslationHelper;
+use Icinga\Application\Benchmark;
+use Icinga\Data\Filter\Filter;
+use ipl\Html\Table;
+
+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;
+
+ private $firstRow;
+
+ private $lastRow = false;
+
+ private $rowNumber;
+
+ private $rowNumberOnPage;
+
+ protected $lastDay;
+
+ /** @var Paginator|null Will usually be defined at rendering time */
+ protected $paginator;
+
+ private $isUsEnglish;
+
+ private $dateFormatter;
+
+ 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;
+ }
+
+ public 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()
+ {
+ $titleColumns = $this->renderTitleColumns();
+ if ($titleColumns) {
+ $this->getHeader()->add($titleColumns);
+ }
+ $this->fetchRows();
+
+ return parent::renderContent();
+ }
+
+ protected function renderTitleColumns()
+ {
+ // TODO: drop this
+ if (method_exists($this, 'getColumnsToBeRendered')) {
+ $columns = $this->getColumnsToBeRendered();
+ if (isset($columns) && count($columns)) {
+ return static::row($columns, null, 'th');
+ }
+ }
+
+ return null;
+ }
+
+ protected function splitByDay($timestamp)
+ {
+ $this->renderDayIfNew((int) $timestamp);
+ }
+
+ public function isOnFirstPage()
+ {
+ if ($this->paginator === null) {
+ // No paginator? Then there should be only a single page
+ return true;
+ }
+
+ return $this->paginator->getCurrentPage() === 1;
+ }
+
+ public function isOnFirstRow()
+ {
+ return $this->firstRow === true;
+ }
+
+ public function isOnLastRow()
+ {
+ return $this->lastRow === true;
+ }
+
+ protected function fetchRows()
+ {
+ $firstPage = $this->isOnFirstPage();
+ $this->rowNumberOnPage = 0;
+ $this->rowNumber = $this->getPaginationAdapter()->getOffset();
+ $lastRow = count($this);
+ foreach ($this->fetch() as $row) {
+ $this->rowNumber++;
+ $this->rowNumberOnPage++;
+ if (null === $this->firstRow) {
+ if ($firstPage) {
+ $this->firstRow = true;
+ } else {
+ $this->firstRow = false;
+ }
+ } elseif (true === $this->firstRow) {
+ $this->firstRow = false;
+ }
+ if ($lastRow === $this->rowNumber) {
+ $this->lastRow = true;
+ }
+ // Hint: do not fetch the body first, the row might want to replace it
+ $tr = $this->renderRow($row);
+ $this->add($tr);
+ }
+ }
+
+ protected function renderRow($row)
+ {
+ return $this::row([$row]);
+ }
+
+ /**
+ * @deprecated
+ * @return bool
+ */
+ protected function isUsEnglish()
+ {
+ if ($this->isUsEnglish === null) {
+ $this->isUsEnglish = in_array(setlocale(LC_ALL, 0), ['en_US', 'en_US.UTF-8', 'C']);
+ }
+
+ return $this->isUsEnglish;
+ }
+
+ /**
+ * @param int $timestamp
+ */
+ protected function renderDayIfNew($timestamp)
+ {
+ $day = $this->getDateFormatter()->getFullDay($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();
+ $this->paginator = $this->getPaginator($url);
+ $this->initializeOptionalQuickSearch($controller);
+ $controller->actions()->add($this->paginator);
+ $c->add($this);
+
+ // TODO: move elsewhere
+ if (method_exists($this, 'dumpSqlQuery')) {
+ if ($url->getParam('format') === 'sql') {
+ $c->prepend($this->dumpSqlQuery($url));
+ }
+ }
+
+ return $this;
+ }
+
+ protected function getDateFormatter()
+ {
+ if ($this->dateFormatter === null) {
+ $this->dateFormatter = new LocalDateFormat();
+ }
+
+ return $this->dateFormatter;
+ }
+}
diff --git a/vendor/gipfl/icingaweb2/src/Table/SimpleQueryBasedTable.php b/vendor/gipfl/icingaweb2/src/Table/SimpleQueryBasedTable.php
new file mode 100644
index 0000000..8d6015a
--- /dev/null
+++ b/vendor/gipfl/icingaweb2/src/Table/SimpleQueryBasedTable.php
@@ -0,0 +1,34 @@
+<?php
+
+namespace gipfl\IcingaWeb2\Table;
+
+use Icinga\Data\SimpleQuery;
+use gipfl\IcingaWeb2\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;
+ }
+}
diff --git a/vendor/gipfl/icingaweb2/src/Table/ZfQueryBasedTable.php b/vendor/gipfl/icingaweb2/src/Table/ZfQueryBasedTable.php
new file mode 100644
index 0000000..8a421d5
--- /dev/null
+++ b/vendor/gipfl/icingaweb2/src/Table/ZfQueryBasedTable.php
@@ -0,0 +1,149 @@
+<?php
+
+namespace gipfl\IcingaWeb2\Table;
+
+use gipfl\IcingaWeb2\Link;
+use gipfl\IcingaWeb2\Url;
+use gipfl\IcingaWeb2\Widget\ControlsAndContent;
+use gipfl\IcingaWeb2\Zf1\Db\FilterRenderer;
+use gipfl\IcingaWeb2\Zf1\Db\SelectPaginationAdapter;
+use gipfl\ZfDb\Adapter\Adapter as Db;
+use gipfl\ZfDb\Select as DbSelect;
+use Icinga\Data\Db\DbConnection;
+use Icinga\Data\Filter\Filter;
+use ipl\Html\DeferredText;
+use ipl\Html\Html;
+use LogicException;
+use Zend_Db_Adapter_Abstract as DbAdapter;
+
+abstract class ZfQueryBasedTable extends QueryBasedTable
+{
+ /** @var ?DbConnection */
+ private $connection;
+
+ /** @var DbAdapter|Db */
+ private $db;
+
+ private $query;
+
+ private $paginationAdapter;
+
+ public function __construct($db)
+ {
+ if ($db instanceof Db || $db instanceof DbAdapter) {
+ $this->db = $db;
+ } elseif ($db instanceof DbConnection) {
+ $this->connection = $db;
+ $this->db = $db->getDbAdapter();
+ } else {
+ throw new LogicException(sprintf(
+ 'Unable to deal with %s db class',
+ get_class($db)
+ ));
+ }
+ }
+
+ public static function show(ControlsAndContent $controller, DbConnection $db)
+ {
+ $table = new static($db);
+ $table->renderTo($controller);
+ }
+
+ public function getCountQuery()
+ {
+ return $this->getPaginationAdapter()->getCountQuery();
+ }
+
+ protected function getPaginationAdapter()
+ {
+ if ($this->paginationAdapter === null) {
+ $this->paginationAdapter = new SelectPaginationAdapter($this->getQuery());
+ }
+
+ return $this->paginationAdapter;
+ }
+
+ public function applyFilter(Filter $filter)
+ {
+ FilterRenderer::applyToQuery($filter, $this->getQuery());
+ return $this;
+ }
+
+ public 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;
+ }
+
+ protected function fetchQueryRows()
+ {
+ return $this->db->fetchAll($this->getQuery());
+ }
+
+ /**
+ * @deprecated Might be null, we'll fade it out
+ * @return ?DbConnection
+ */
+ public function connection()
+ {
+ return $this->connection;
+ }
+
+ public function db()
+ {
+ return $this->db;
+ }
+
+ /**
+ * @return DbSelect|\Zend_Db_Select
+ */
+ public function getQuery()
+ {
+ if ($this->query === null) {
+ $this->query = $this->prepareQuery();
+ }
+
+ return $this->query;
+ }
+
+ public function dumpSqlQuery(Url $url)
+ {
+ $self = $this;
+ return Html::tag('div', ['class' => 'sql-dump'], [
+ Link::create('[ close ]', $url->without('format')),
+ Html::tag('h3', null, $this->translate('SQL Query')),
+ Html::tag('pre', null, new DeferredText(
+ function () use ($self) {
+ return wordwrap($self->getQuery());
+ }
+ )),
+ Html::tag('h3', null, $this->translate('Count Query')),
+ Html::tag('pre', null, new DeferredText(
+ function () use ($self) {
+ return wordwrap($self->getCountQuery());
+ }
+ )),
+ ]);
+ }
+}