icingaweb2/library/Icinga/Data/SimpleQuery.php

417 lines
9.4 KiB
PHP
Raw Normal View History

<?php
/* Icinga Web 2 | (c) 2013-2015 Icinga Development Team | http://www.gnu.org/licenses/gpl-2.0.txt */
namespace Icinga\Data;
use Icinga\Application\Icinga;
use Icinga\Data\Filter\Filter;
use Icinga\Web\Paginator\Adapter\QueryAdapter;
use Zend_Paginator;
use Exception;
use Icinga\Exception\IcingaException;
class SimpleQuery implements QueryInterface, Queryable
{
/**
* Query data source
*
* @var mixed
*/
protected $ds;
/**
* The table you are going to query
*/
protected $table;
/**
* The columns you asked for
*
* All columns if null, no column if empty??? Alias handling goes here!
*
* @var array
*/
protected $desiredColumns = array();
/**
* The columns you are interested in
*
* All columns if null, no column if empty??? Alias handling goes here!
*
* @var array
*/
protected $columns = array();
/**
* The columns you're using to sort the query result
*
* @var array
*/
protected $order = array();
/**
* Number of rows to return
*
* @var int
*/
protected $limitCount;
/**
* Result starts with this row
*
* @var int
*/
protected $limitOffset;
protected $filter;
/**
* Constructor
*
* @param mixed $ds
*/
public function __construct($ds, $columns = null)
{
$this->ds = $ds;
$this->filter = Filter::matchAll();
if ($columns !== null) {
$this->desiredColumns = $columns;
}
$this->init();
if ($this->desiredColumns !== null) {
$this->columns($this->desiredColumns);
}
}
/**
* Initialize query
*
* Overwrite this instead of __construct (it's called at the end of the construct) to
* implement custom initialization logic on construction time
*/
protected function init() {}
/**
* Get the data source
*
* @return mixed
*/
public function getDatasource()
2013-10-17 21:40:02 +02:00
{
return $this->ds;
2013-10-17 21:40:02 +02:00
}
/**
* Choose a table and the colums you are interested in
*
* Query will return all available columns if none are given here
*
* @return self
*/
public function from($target, array $fields = null)
{
$this->target = $target;
if ($fields !== null) {
$this->columns($fields);
}
return $this;
}
/**
* Add a where condition to the query by and
*
* The syntax of the condition and valid values are defined by the concrete backend-specific query implementation.
*
* @param string $condition
* @param mixed $value
*
* @return self
*/
public function where($condition, $value = null)
{
// TODO: more intelligence please
$this->filter->addFilter(Filter::expression($condition, '=', $value));
return $this;
}
public function getFilter()
{
return $this->filter;
}
public function applyFilter(Filter $filter)
{
return $this->addFilter($filter);
}
public function addFilter(Filter $filter)
{
$this->filter->addFilter($filter);
return $this;
}
public function setFilter(Filter $filter)
{
$this->filter = $filter;
return $this;
}
public function setOrderColumns(array $orderColumns)
{
throw new IcingaException('This function does nothing and will be removed');
}
/**
* Sort result set by the given field (and direction)
*
* Preferred usage:
* <code>
* $query->order('field, 'ASC')
* </code>
*
* @param string $field
* @param string $direction
*
* @return self
*/
public function order($field, $direction = null)
{
if ($direction === null) {
$fieldAndDirection = explode(' ', $field, 2);
if (count($fieldAndDirection) === 1) {
$direction = self::SORT_ASC;
} else {
$field = $fieldAndDirection[0];
$direction = (strtoupper(trim($fieldAndDirection[1])) === 'DESC') ?
Sortable::SORT_DESC : Sortable::SORT_ASC;
}
} else {
switch (($direction = strtoupper($direction))) {
case Sortable::SORT_ASC:
case Sortable::SORT_DESC:
break;
default:
$direction = Sortable::SORT_ASC;
break;
}
}
$this->order[] = array($field, $direction);
return $this;
}
public function compare($a, $b, $col_num = 0)
{
// Last column to sort reached, rows are considered being equal
if (! array_key_exists($col_num, $this->order)) {
return 0;
}
$col = $this->order[$col_num][0];
$dir = $this->order[$col_num][1];
// TODO: throw Exception if column is missing
//$res = strnatcmp(strtolower($a->$col), strtolower($b->$col));
$res = @strcmp(strtolower($a->$col), strtolower($b->$col));
if ($res === 0) {
// return $this->compare($a, $b, $col_num++);
if (array_key_exists(++$col_num, $this->order)) {
return $this->compare($a, $b, $col_num);
} else {
return 0;
}
}
if ($dir === self::SORT_ASC) {
return $res;
} else {
return $res * -1;
}
}
2014-03-20 13:21:18 +01:00
/**
* Whether an order is set
2014-03-20 13:21:18 +01:00
*
* @return bool
2014-03-20 13:21:18 +01:00
*/
public function hasOrder()
2014-03-20 13:21:18 +01:00
{
return !empty($this->order);
2014-03-20 13:21:18 +01:00
}
/**
* Get the order if any
*
* @return array|null
*/
public function getOrder()
{
return $this->order;
}
/**
* Set a limit count and offset to the query
*
* @param int $count Number of rows to return
* @param int $offset Start returning after this many rows
*
* @return self
*/
public function limit($count = null, $offset = null)
{
$this->limitCount = $count !== null ? (int) $count : null;
$this->limitOffset = (int) $offset;
return $this;
}
/**
* Whether a limit is set
*
* @return bool
*/
public function hasLimit()
{
return $this->limitCount !== null;
}
/**
* Get the limit if any
*
* @return int|null
*/
public function getLimit()
{
return $this->limitCount;
}
/**
* Whether an offset is set
*
* @return bool
*/
public function hasOffset()
{
return $this->limitOffset > 0;
}
/**
* Get the offset if any
*
* @return int|null
*/
public function getOffset()
{
return $this->limitOffset;
}
/**
* Paginate data
*
* Auto-detects pagination parameters from request when unset
*
* @param int $itemsPerPage Number of items per page
* @param int $pageNumber Current page number
*
* @return Zend_Paginator
*/
public function paginate($itemsPerPage = null, $pageNumber = null)
{
if ($itemsPerPage === null || $pageNumber === null) {
// Detect parameters from request
$request = Icinga::app()->getFrontController()->getRequest();
if ($itemsPerPage === null) {
$itemsPerPage = $request->getParam('limit', 25);
}
if ($pageNumber === null) {
$pageNumber = $request->getParam('page', 0);
}
}
$this->limit($itemsPerPage, $pageNumber * $itemsPerPage);
$paginator = new Zend_Paginator(new QueryAdapter($this));
$paginator->setItemCountPerPage($itemsPerPage);
$paginator->setCurrentPageNumber($pageNumber);
return $paginator;
}
2013-10-19 20:09:17 +02:00
/**
* Retrieve an array containing all rows of the result set
2013-10-19 20:09:17 +02:00
*
* @return array
2013-10-19 20:09:17 +02:00
*/
public function fetchAll()
2013-10-19 20:09:17 +02:00
{
return $this->ds->fetchAll($this);
2013-10-19 20:09:17 +02:00
}
/**
* Fetch the first row of the result set
*
* @return mixed
*/
public function fetchRow()
{
return $this->ds->fetchRow($this);
}
/**
* Fetch a column of all rows of the result set as an array
*
* @param int $columnIndex Index of the column to fetch
*
* @return array
*/
public function fetchColumn($columnIndex = 0)
{
return $this->ds->fetchColumn($this, $columnIndex);
}
/**
* Fetch the first column of the first row of the result set
*
* @return string
*/
public function fetchOne()
{
return $this->ds->fetchOne($this);
}
/**
* Fetch all rows of the result set as an array of key-value pairs
*
* The first column is the key, the second column is the value.
*
* @return array
*/
public function fetchPairs()
{
return $this->ds->fetchPairs($this);
}
/**
* Count all rows of the result set
*
* @return int
*/
public function count()
{
return $this->ds->count($this);
}
/**
* Set columns
*
* @param array $columns
*
* @return self
*/
public function columns(array $columns)
{
$this->columns = $columns;
return $this;
}
public function getColumns()
{
return $this->columns;
}
}