mirror of
https://github.com/Icinga/icingaweb2.git
synced 2025-07-31 01:34:09 +02:00
Refactoring and Query and IDO code,
the Monitoring/View code was completly dropped in favor of the DataView implementations, as new Backends otherwise would require to implement two seperate query logics refs #3801
This commit is contained in:
parent
df81c85090
commit
44be5e85da
@ -1,400 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Icinga\Data;
|
||||
|
||||
use Icinga\Exception;
|
||||
|
||||
abstract class AbstractQuery implements QueryInterface
|
||||
{
|
||||
/**
|
||||
* Sort ascending
|
||||
*/
|
||||
const SORT_ASC = 1;
|
||||
|
||||
/**
|
||||
* Sort descending
|
||||
*/
|
||||
const SORT_DESC = -1;
|
||||
|
||||
/**
|
||||
* Query data source
|
||||
*
|
||||
* @var DatasourceInterface
|
||||
*/
|
||||
protected $ds;
|
||||
|
||||
/**
|
||||
* The table you are going to query
|
||||
*/
|
||||
protected $table;
|
||||
|
||||
/**
|
||||
* The columns you are interested in. All columns if empty
|
||||
*/
|
||||
protected $columns = array();
|
||||
|
||||
/**
|
||||
* A list of filters
|
||||
*/
|
||||
protected $filters = array();
|
||||
|
||||
/**
|
||||
* The columns you're using to sort the query result
|
||||
*/
|
||||
protected $order_columns = array();
|
||||
|
||||
/**
|
||||
* Return not more than that many rows
|
||||
*/
|
||||
protected $limit_count;
|
||||
|
||||
/**
|
||||
* Result starts with this row
|
||||
*/
|
||||
protected $limit_offset;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param DatasourceInterface $ds Your data source
|
||||
*/
|
||||
public function __construct(DatasourceInterface $ds, $columns = null)
|
||||
{
|
||||
$this->ds = $ds;
|
||||
|
||||
if ($columns === null) {
|
||||
$columns = $this->getDefaultColumns();
|
||||
}
|
||||
if ($columns !== null) {
|
||||
$this->columns($columns);
|
||||
}
|
||||
|
||||
$this->init();
|
||||
}
|
||||
|
||||
public function addColumn($name, $alias = null)
|
||||
{
|
||||
// TODO: Fail if adding column twice, but allow same col with new alias
|
||||
if ($alias === null) {
|
||||
$this->columns[] = $name;
|
||||
} else {
|
||||
$this->columns[$alias] = $name;
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getDatasource()
|
||||
{
|
||||
return $this->ds;
|
||||
}
|
||||
|
||||
protected function getDefaultColumns()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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($table, $columns = null)
|
||||
{
|
||||
$this->table = $table;
|
||||
if ($columns !== null) {
|
||||
$this->columns($columns);
|
||||
} else {
|
||||
// TODO: Really?
|
||||
$this->columns = $this->getDefaultColumns();
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function columns($columns)
|
||||
{
|
||||
if (is_array($columns)) {
|
||||
$this->columns = $columns;
|
||||
} else {
|
||||
$this->columns = array($columns);
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Use once or multiple times to filter result set
|
||||
*
|
||||
* Multiple where calls will be combined by a logical AND operation
|
||||
*
|
||||
* @param string $key Column or backend-specific search expression
|
||||
* @param string $val Search value, must be escaped automagically
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function where($key, $val = null)
|
||||
{
|
||||
$this->filters[] = array($key, $val);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sort query result by the given column name
|
||||
*
|
||||
* Sort direction can be ascending (self::SORT_ASC, being the default)
|
||||
* or descending (self::SORT_DESC).
|
||||
*
|
||||
* Preferred usage:
|
||||
* <code>
|
||||
* $query->sort('column_name ASC')
|
||||
* </code>
|
||||
*
|
||||
* @param string $col Column, may contain direction separated by space
|
||||
* @param int $dir Sort direction
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function order($col, $dir = null)
|
||||
{
|
||||
if ($dir === null) {
|
||||
if (($pos = strpos($col, ' ')) === false) {
|
||||
$dir = $this->getDefaultSortDir($col);
|
||||
} else {
|
||||
$dir = strtoupper(substr($col, $pos + 1));
|
||||
if ($dir === 'DESC') {
|
||||
$dir = self::SORT_DESC;
|
||||
} else {
|
||||
$dir = self::SORT_ASC;
|
||||
}
|
||||
$col = substr($col, 0, $pos);
|
||||
}
|
||||
} else {
|
||||
if ($dir === self::SORT_DESC || strtoupper($dir) === 'DESC') {
|
||||
$dir = self::SORT_DESC;
|
||||
} else {
|
||||
$dir = self::SORT_ASC;
|
||||
}
|
||||
}
|
||||
$this->order_columns[] = array($col, $dir);
|
||||
return $this;
|
||||
}
|
||||
|
||||
protected function getDefaultSortDir($col)
|
||||
{
|
||||
return self::SORT_ASC;
|
||||
}
|
||||
|
||||
/**
|
||||
* Limit the result set
|
||||
*
|
||||
* @param int $count Return not more than that many rows
|
||||
* @param int $offset Result starts with this row
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
// Nur wenn keine stats, sonst im RAM!!
|
||||
// Offset gibt es nicht, muss simuliert werden
|
||||
public function limit($count = null, $offset = null)
|
||||
{
|
||||
if (! preg_match('~^\d+~', $count . $offset)) {
|
||||
throw new Exception\ProgrammingError(
|
||||
sprintf(
|
||||
'Got invalid limit: %s, %s',
|
||||
$count,
|
||||
$offset
|
||||
)
|
||||
);
|
||||
}
|
||||
$this->limit_count = (int) $count;
|
||||
$this->limit_offset = (int) $offset;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Wheter at least one order column has been applied to this Query
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function hasOrder()
|
||||
{
|
||||
return ! empty($this->order_columns);
|
||||
}
|
||||
|
||||
/**
|
||||
* Wheter a limit has been applied to this Query
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function hasLimit()
|
||||
{
|
||||
return $this->limit_count !== null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Wheter a starting offset been applied to this Query
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function hasOffset()
|
||||
{
|
||||
return $this->limit_offset > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the query limit
|
||||
*
|
||||
* @return int|null
|
||||
*/
|
||||
public function getLimit()
|
||||
{
|
||||
return $this->limit_count;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the query starting offset
|
||||
*
|
||||
* @return int|null
|
||||
*/
|
||||
public function getOffset()
|
||||
{
|
||||
return $this->limit_offset;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the columns that have been asked for with this query
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function listColumns()
|
||||
{
|
||||
return $this->columns;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the filters that have been applied to this query
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function listFilters()
|
||||
{
|
||||
return $this->filters;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extend this function for things that should happen at construction time
|
||||
*/
|
||||
protected function init()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Extend this function for things that should happen before query execution
|
||||
*/
|
||||
protected function finish()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Total result size regardless of limit and offset
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function count()
|
||||
{
|
||||
return $this->ds->count($this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch result as an array of objects
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function fetchAll()
|
||||
{
|
||||
return $this->ds->fetchAll($this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch first result row
|
||||
*
|
||||
* @return object
|
||||
*/
|
||||
public function fetchRow()
|
||||
{
|
||||
return $this->ds->fetchRow($this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch first result column
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function fetchColumn()
|
||||
{
|
||||
return $this->ds->fetchColumn($this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch first column value from first result row
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function fetchOne()
|
||||
{
|
||||
return $this->ds->fetchOne($this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch result as a key/value pair array
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function fetchPairs()
|
||||
{
|
||||
return $this->ds->fetchPairs($this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a pagination adapter for this query
|
||||
*
|
||||
* @return \Zend_Paginator
|
||||
*/
|
||||
public function paginate($limit = null, $page = null)
|
||||
{
|
||||
$this->finish();
|
||||
if ($page === null && $limit === null) {
|
||||
$request = \Zend_Controller_Front::getInstance()->getRequest();
|
||||
|
||||
if ($page === null) {
|
||||
$page = $request->getParam('page', 0);
|
||||
}
|
||||
|
||||
if ($limit === null) {
|
||||
$limit = $request->getParam('limit', 20);
|
||||
}
|
||||
}
|
||||
$this->limit($limit, $page * $limit);
|
||||
|
||||
$paginator = new \Zend_Paginator(
|
||||
new \Icinga\Web\Paginator\Adapter\QueryAdapter($this)
|
||||
);
|
||||
|
||||
$paginator->setItemCountPerPage($limit);
|
||||
$paginator->setCurrentPageNumber($page);
|
||||
|
||||
return $paginator;
|
||||
}
|
||||
|
||||
public function getColumns()
|
||||
{
|
||||
return $this->columns;
|
||||
}
|
||||
|
||||
/**
|
||||
* Destructor. Remove $ds, just to be on the safe side
|
||||
*/
|
||||
public function __destruct()
|
||||
{
|
||||
unset($this->ds);
|
||||
}
|
||||
}
|
486
library/Icinga/Data/BaseQuery.php
Normal file
486
library/Icinga/Data/BaseQuery.php
Normal file
@ -0,0 +1,486 @@
|
||||
<?php
|
||||
|
||||
namespace Icinga\Data;
|
||||
|
||||
use Icinga\Application\Logger;
|
||||
use Icinga\Exception;
|
||||
use Icinga\Filter\Filterable;
|
||||
use Icinga\Filter\Query\Node;
|
||||
use Icinga\Filter\Query\Tree;
|
||||
use Zend_Paginator;
|
||||
use Icinga\Web\Paginator\Adapter\QueryAdapter;
|
||||
|
||||
abstract class BaseQuery implements Filterable
|
||||
{
|
||||
/**
|
||||
* Sort ascending
|
||||
*/
|
||||
const SORT_ASC = 1;
|
||||
|
||||
/**
|
||||
* Sort descending
|
||||
*/
|
||||
const SORT_DESC = -1;
|
||||
|
||||
/**
|
||||
* Query data source
|
||||
*
|
||||
* @var DatasourceInterface
|
||||
*/
|
||||
protected $ds;
|
||||
|
||||
/**
|
||||
* The target of this query
|
||||
* @var string
|
||||
*/
|
||||
protected $table;
|
||||
|
||||
/**
|
||||
* The columns of the target that should be returned
|
||||
* @var array
|
||||
*/
|
||||
private $columns;
|
||||
|
||||
/**
|
||||
* The columns you're using to sort the query result
|
||||
* @var array
|
||||
*/
|
||||
private $orderColumns = array();
|
||||
|
||||
/**
|
||||
* Return not more than that many rows
|
||||
* @var int
|
||||
*/
|
||||
private $limitCount;
|
||||
|
||||
/**
|
||||
* Result starts with this row
|
||||
* @var int
|
||||
*/
|
||||
private $limitOffset;
|
||||
|
||||
/**
|
||||
* The backend independent filter to use for this query
|
||||
*
|
||||
* @var Tree
|
||||
*/
|
||||
private $filter;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param DatasourceInterface $ds Your data source
|
||||
*/
|
||||
public function __construct(DatasourceInterface $ds, array $columns = null)
|
||||
{
|
||||
$this->ds = $ds;
|
||||
$this->columns = $columns;
|
||||
$this->clearFilter();
|
||||
$this->init();
|
||||
|
||||
}
|
||||
|
||||
public function getDatasource()
|
||||
{
|
||||
return $this->ds;
|
||||
}
|
||||
|
||||
|
||||
public function setColumns(array $columns)
|
||||
{
|
||||
$this->columns = $columns;
|
||||
}
|
||||
|
||||
/**
|
||||
* Define the target and attributes for this query
|
||||
*
|
||||
* The Query will return the default attribute the attributes parameter is omitted
|
||||
*
|
||||
* @param String $target The target of this query (tablename, objectname, depends on the concrete implementation)
|
||||
* @param array $columns An optional array of columns to select, if none are given the default
|
||||
* columnset is returned
|
||||
*
|
||||
* @return self Fluent interface
|
||||
*/
|
||||
public function from($target, array $attributes = null)
|
||||
{
|
||||
$this->table = $target;
|
||||
if ($attributes !== null) {
|
||||
$this->columns = $attributes;
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a filter expression to be applied on this query.
|
||||
*
|
||||
* This is an alias to andWhere()
|
||||
* The syntax of the expression and valid parameters are to be defined by the concrete
|
||||
* backend-specific query implementation.
|
||||
*
|
||||
* @param string $expression Implementation specific search expression
|
||||
* @param mixed $parameters Implementation specific search value to use for query placeholders
|
||||
*
|
||||
* @return self Fluent Interface
|
||||
* @see BaseQuery::andWhere() This is an alias to andWhere()
|
||||
*/
|
||||
public function where($expression, $parameters = null)
|
||||
{
|
||||
return $this->andWhere($expression, $parameters);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an mandatory filter expression to be applied on this query
|
||||
*
|
||||
* The syntax of the expression and valid parameters are to be defined by the concrete
|
||||
* backend-specific query implementation.
|
||||
*
|
||||
* @param string $expression Implementation specific search expression
|
||||
* @param mixed $parameters Implementation specific search value to use for query placeholders
|
||||
|
||||
* @return self Fluent interface
|
||||
*/
|
||||
public function andWhere($expression, $parameters = null)
|
||||
{
|
||||
$node = $this->parseFilterExpression($expression, $parameters);
|
||||
if ($node === null) {
|
||||
Logger::debug('Ignoring invalid filter expression: %s (params: %s)', $expression, $parameters);
|
||||
return $this;
|
||||
}
|
||||
$this->filter->insert(Node::createAndNode());
|
||||
$this->filter->insert($node);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an lower priority filter expression to be applied on this query
|
||||
*
|
||||
* The syntax of the expression and valid parameters are to be defined by the concrete
|
||||
* backend-specific query implementation.
|
||||
*
|
||||
* @param string $expression Implementation specific search expression
|
||||
* @param mixed $parameters Implementation specific search value to use for query placeholders
|
||||
|
||||
* @return self Fluent interface
|
||||
*/
|
||||
public function orWhere($expression, $parameters = null)
|
||||
{
|
||||
$node = $this->parseFilterExpression($expression, $parameters);
|
||||
if ($node === null) {
|
||||
Logger::debug('Ignoring invalid filter expression: %s (params: %s)', $expression, $parameters);
|
||||
return $this;
|
||||
}
|
||||
$this->filter->insert(Node::createOrNode());
|
||||
$this->filter->insert($node);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the given field is a valid filter target
|
||||
*
|
||||
* The base implementation always returns true, overwrite it in concrete backend-specific
|
||||
* implementations
|
||||
*
|
||||
* @param String $field The field to test for being filterable
|
||||
* @return bool True if the field can be filtered, otherwise false
|
||||
*/
|
||||
public function isValidFilterTarget($field)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the internally used field name for the given alias
|
||||
*
|
||||
* The base implementation just returns the given field, overwrite it in concrete backend-specific
|
||||
* implementations
|
||||
*
|
||||
* @param String $field The field to test for being filterable
|
||||
* @return bool True if the field can be filtered, otherwise false
|
||||
*/
|
||||
public function getMappedField($field)
|
||||
{
|
||||
return $field;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a filter to this query
|
||||
*
|
||||
* This is the implementation for the Filterable, use where instead
|
||||
*
|
||||
* @param $filter
|
||||
*/
|
||||
public function addFilter($filter)
|
||||
{
|
||||
if (is_string($filter)) {
|
||||
$this->addFilter(call_user_func_array(array($this, 'parseFilterExpression'), func_get_args()));
|
||||
} elseif ($filter instanceof Node) {
|
||||
$this->filter->insert($filter);
|
||||
}
|
||||
}
|
||||
|
||||
public function setFilter(Tree $filter)
|
||||
{
|
||||
$this->filter = $filter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse a backend specific filter expression and return a Query\Node object
|
||||
*
|
||||
* @param $expression The expression to parse
|
||||
* @param $parameters Optional parameters for the expression
|
||||
* @return Node A query node or null if it's an invalid expression
|
||||
*/
|
||||
abstract protected function parseFilterExpression($expression, $parameters = null);
|
||||
|
||||
/**
|
||||
* Return all default columns
|
||||
*
|
||||
* @return array An array of default columns to use when none are selected
|
||||
*/
|
||||
public function getDefaultColumns()
|
||||
{
|
||||
return array();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sort query result by the given column name
|
||||
*
|
||||
* Sort direction can be ascending (self::SORT_ASC, being the default)
|
||||
* or descending (self::SORT_DESC).
|
||||
*
|
||||
* Preferred usage:
|
||||
* <code>
|
||||
* $query->sort('column_name ASC')
|
||||
* </code>
|
||||
*
|
||||
* @param string $columnOrAlias Column, may contain direction separated by space
|
||||
* @param int $dir Sort direction
|
||||
*
|
||||
* @return BaseQuery
|
||||
*/
|
||||
public function order($columnOrAlias, $dir = null)
|
||||
{
|
||||
if ($dir === null) {
|
||||
$colDirPair = explode(' ', $columnOrAlias, 2);
|
||||
if (count($colDirPair) === 1) {
|
||||
$dir = $this->getDefaultSortDir($columnOrAlias);
|
||||
} else {
|
||||
$dir = $colDirPair[1];
|
||||
$columnOrAlias = $colDirPair[0];
|
||||
}
|
||||
}
|
||||
|
||||
$dir = (strtoupper(trim($dir)) === 'DESC') ? self::SORT_DESC : self::SORT_ASC;
|
||||
|
||||
$this->orderColumns[] = array($columnOrAlias, $dir);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine the default sort direction constant for the given column
|
||||
*
|
||||
* @param String $col The column to get the sort direction for
|
||||
* @return int Either SORT_ASC or SORT_DESC
|
||||
*/
|
||||
protected function getDefaultSortDir($col)
|
||||
{
|
||||
return self::SORT_ASC;
|
||||
}
|
||||
|
||||
/**
|
||||
* Limit the result set
|
||||
*
|
||||
* @param int $count The numeric maximum limit to apply on the query result
|
||||
* @param int $offset The offset to use for the result set
|
||||
*
|
||||
* @return BaseQuery
|
||||
*/
|
||||
public function limit($count = null, $offset = null)
|
||||
{
|
||||
$this->limitCount = $count !== null ? intval($count) : null;
|
||||
$this->limitOffset = intval($offset);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether this query will be ordered explicitly
|
||||
*
|
||||
* @return bool True when an order column has been set
|
||||
*/
|
||||
public function hasOrder()
|
||||
{
|
||||
return !empty($this->orderColumns);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether this query will be limited explicitly
|
||||
*
|
||||
* @return bool True when an limit count has been set, otherwise false
|
||||
*/
|
||||
public function hasLimit()
|
||||
{
|
||||
return $this->limitCount !== null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether an offset is set or not
|
||||
*
|
||||
* @return bool True when an offset > 0 is set
|
||||
*/
|
||||
public function hasOffset()
|
||||
{
|
||||
return $this->limitOffset > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the query limit
|
||||
*
|
||||
* @return int The query limit or null if none is set
|
||||
*/
|
||||
public function getLimit()
|
||||
{
|
||||
return $this->limitCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the query starting offset
|
||||
*
|
||||
* @return int The query offset or null if none is set
|
||||
*/
|
||||
public function getOffset()
|
||||
{
|
||||
return $this->limitOffset;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation specific initialization
|
||||
*
|
||||
* 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()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Return all columns set in this query or the default columns if none are set
|
||||
*
|
||||
* @return array An array of columns
|
||||
*/
|
||||
public function getColumns()
|
||||
{
|
||||
return ($this->columns !== null) ? $this->columns : $this->getDefaultColumns();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return all columns used for ordering
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getOrderColumns()
|
||||
{
|
||||
return $this->orderColumns;
|
||||
}
|
||||
|
||||
public function getFilter()
|
||||
{
|
||||
return $this->filter;
|
||||
}
|
||||
|
||||
public function clearFilter()
|
||||
{
|
||||
$this->filter = new Tree();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a pagination adapter for this query
|
||||
*
|
||||
* @return \Zend_Paginator
|
||||
*/
|
||||
public function paginate($limit = null, $page = null)
|
||||
{
|
||||
if ($page === null && $limit === null) {
|
||||
$request = \Zend_Controller_Front::getInstance()->getRequest();
|
||||
|
||||
if ($page === null) {
|
||||
$page = $request->getParam('page', 0);
|
||||
}
|
||||
|
||||
if ($limit === null) {
|
||||
$limit = $request->getParam('limit', 20);
|
||||
}
|
||||
}
|
||||
$this->limit($limit, $page * $limit);
|
||||
|
||||
$paginator = new Zend_Paginator(new QueryAdapter($this));
|
||||
|
||||
$paginator->setItemCountPerPage($limit);
|
||||
$paginator->setCurrentPageNumber($page);
|
||||
|
||||
return $paginator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Total result size regardless of limit and offset
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function count()
|
||||
{
|
||||
return $this->ds->count($this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch result as an array of objects
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function fetchAll()
|
||||
{
|
||||
return $this->ds->fetchAll($this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch first result row
|
||||
*
|
||||
* @return object
|
||||
*/
|
||||
public function fetchRow()
|
||||
{
|
||||
return $this->ds->fetchRow($this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch first result column
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function fetchColumn()
|
||||
{
|
||||
return $this->ds->fetchColumn($this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch first column value from first result row
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function fetchOne()
|
||||
{
|
||||
return $this->ds->fetchOne($this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch result as a key/value pair array
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function fetchPairs()
|
||||
{
|
||||
return $this->ds->fetchPairs($this);
|
||||
}
|
||||
}
|
@ -73,7 +73,7 @@ class Datasource implements DatasourceInterface
|
||||
}
|
||||
$result = array();
|
||||
$filters = $query->listFilters();
|
||||
$columns = $query->listColumns();
|
||||
$columns = $query->getColumns();
|
||||
foreach ($this->data as & $row) {
|
||||
|
||||
// Skip rows that do not match applied filters
|
||||
|
@ -2,9 +2,9 @@
|
||||
|
||||
namespace Icinga\Data\DataArray;
|
||||
|
||||
use Icinga\Data\AbstractQuery;
|
||||
use Icinga\Data\BaseQuery;
|
||||
|
||||
class Query extends AbstractQuery
|
||||
class Query extends BaseQuery
|
||||
{
|
||||
/**
|
||||
* Remember the last count
|
||||
@ -63,16 +63,18 @@ class Query extends AbstractQuery
|
||||
*/
|
||||
public function compare(& $a, & $b, $col_num = 0)
|
||||
{
|
||||
if (! array_key_exists($col_num, $this->order_columns)) {
|
||||
$orderColumns = $this->getOrderColumns();
|
||||
if (! array_key_exists($col_num, $orderColumns)) {
|
||||
return 0;
|
||||
}
|
||||
$col = $this->order_columns[$col_num][0];
|
||||
$dir = $this->order_columns[$col_num][1];
|
||||
|
||||
$col = $orderColumns[$col_num][0];
|
||||
$dir = $orderColumns[$col_num][1];
|
||||
|
||||
//$res = strnatcmp(strtolower($a->$col), strtolower($b->$col));
|
||||
$res = strcmp(strtolower($a->$col), strtolower($b->$col));
|
||||
if ($res === 0) {
|
||||
if (array_key_exists(++$col_num, $this->order_columns)) {
|
||||
if (array_key_exists(++$col_num, $orderColumns)) {
|
||||
return $this->compare($a, $b, $col_num);
|
||||
} else {
|
||||
return 0;
|
||||
@ -84,4 +86,16 @@ class Query extends AbstractQuery
|
||||
return $res * -1;
|
||||
}
|
||||
}
|
||||
|
||||
public function parseFilterExpression($expression, $parameters = null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public function applyFilter()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -8,7 +8,8 @@ interface DatasourceInterface
|
||||
/**
|
||||
* Instantiate a Query object
|
||||
*
|
||||
* @return AbstractQuery
|
||||
* @return BaseQuery
|
||||
*/
|
||||
public function select();
|
||||
|
||||
}
|
||||
|
@ -2,12 +2,22 @@
|
||||
|
||||
namespace Icinga\Data\Db;
|
||||
|
||||
use Icinga\Data\AbstractQuery;
|
||||
use Icinga\Data\Optional;
|
||||
use Icinga\Data\The;
|
||||
use Icinga\Filter\Query\Node;
|
||||
use Icinga\Filter\Query\Tree;
|
||||
use Zend_Db_Select;
|
||||
use Icinga\Data\BaseQuery;
|
||||
|
||||
class Query extends AbstractQuery
|
||||
/**
|
||||
* Db/Query class for implementing database queries
|
||||
*/
|
||||
class Query extends BaseQuery
|
||||
{
|
||||
/**
|
||||
* Zend_Db_Adapter_Abstract
|
||||
*
|
||||
*
|
||||
*/
|
||||
protected $db;
|
||||
|
||||
@ -20,19 +30,19 @@ class Query extends AbstractQuery
|
||||
/**
|
||||
* Select object
|
||||
*/
|
||||
protected $selectQuery;
|
||||
private $selectQuery;
|
||||
|
||||
/**
|
||||
* Select object used for count query
|
||||
*/
|
||||
protected $countQuery;
|
||||
private $countQuery;
|
||||
|
||||
/**
|
||||
* Allow to override COUNT(*)
|
||||
*/
|
||||
protected $countColumns;
|
||||
|
||||
protected $uglySlowConservativeCount = false;
|
||||
protected $useSubqueryCount = false;
|
||||
|
||||
protected $countCache;
|
||||
|
||||
@ -44,7 +54,36 @@ class Query extends AbstractQuery
|
||||
$this->baseQuery = $this->db->select();
|
||||
}
|
||||
|
||||
protected function getSelectQuery()
|
||||
/**
|
||||
* Return the raw base query
|
||||
*
|
||||
* Modifications on this requires a call to Query::refreshQueryObjects()
|
||||
*
|
||||
* @return Zend_Db_Select
|
||||
*
|
||||
*/
|
||||
public function getRawBaseQuery()
|
||||
{
|
||||
return $this->baseQuery;
|
||||
}
|
||||
|
||||
/**
|
||||
* Recreate the select and count queries
|
||||
*
|
||||
* Required when external modifications are made in the baseQuery
|
||||
*/
|
||||
public function refreshQueryObjects()
|
||||
{
|
||||
$this->createQueryObjects();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the select query and initialize it if not done yet
|
||||
*
|
||||
* @return Zend_Db_Select
|
||||
*/
|
||||
public function getSelectQuery()
|
||||
{
|
||||
if ($this->selectQuery === null) {
|
||||
$this->createQueryObjects();
|
||||
@ -56,7 +95,12 @@ class Query extends AbstractQuery
|
||||
return $this->selectQuery;
|
||||
}
|
||||
|
||||
protected function getCountQuery()
|
||||
/**
|
||||
* Return the current count query and initialize it if not done yet
|
||||
*
|
||||
* @return Zend_Db_Select
|
||||
*/
|
||||
public function getCountQuery()
|
||||
{
|
||||
if ($this->countQuery === null) {
|
||||
$this->createQueryObjects();
|
||||
@ -64,54 +108,99 @@ class Query extends AbstractQuery
|
||||
return $this->countQuery;
|
||||
}
|
||||
|
||||
protected function createQueryObjects()
|
||||
/**
|
||||
* Create the Zend_Db select query for this query
|
||||
*/
|
||||
private function createSelectQuery()
|
||||
{
|
||||
$this->beforeCreatingCountQuery();
|
||||
$this->beforeCreatingSelectQuery();
|
||||
|
||||
$this->selectQuery = clone($this->baseQuery);
|
||||
$this->selectQuery->columns($this->columns);
|
||||
$this->selectQuery->columns($this->getColumns());
|
||||
if ($this->hasOrder()) {
|
||||
foreach ($this->order_columns as $col) {
|
||||
foreach ($this->getOrderColumns() as $col) {
|
||||
$this->selectQuery->order(
|
||||
$col[0]
|
||||
. ' '
|
||||
. ( $col[1] === self::SORT_DESC ? 'DESC' : 'ASC')
|
||||
$col[0] . ' ' . (($col[1] === self::SORT_DESC) ? 'DESC' : 'ASC')
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->uglySlowConservativeCount) {
|
||||
$query = clone($this->selectQuery);
|
||||
if ($this->maxCount === null) {
|
||||
$this->countQuery = $this->db->select()->from(
|
||||
$query,
|
||||
'COUNT(*)'
|
||||
);
|
||||
} else {
|
||||
$this->countQuery = $this->db->select()->from(
|
||||
$query->reset('order')->limit($this->maxCount),
|
||||
'COUNT(*)'
|
||||
);
|
||||
}
|
||||
/**
|
||||
* Create a countquery by using the select query as a subselect and count it's result
|
||||
*
|
||||
* This is a rather naive approach and not suitable for complex queries or queries with many results
|
||||
*
|
||||
* @return Zend_Db_Select The query object representing the count
|
||||
*/
|
||||
private function createCountAsSubQuery()
|
||||
{
|
||||
$query = clone($this->selectQuery);
|
||||
if ($this->maxCount === null) {
|
||||
return $this->db->select()->from($query, 'COUNT(*)');
|
||||
} else {
|
||||
$this->countQuery = clone($this->baseQuery);
|
||||
if ($this->countColumns === null) {
|
||||
$this->countColumns = array('cnt' => 'COUNT(*)');
|
||||
}
|
||||
$this->countQuery->columns($this->countColumns);
|
||||
return $this->db->select()->from(
|
||||
$query->reset('order')->limit($this->maxCount),
|
||||
'COUNT(*)'
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
protected function beforeCreatingCountQuery()
|
||||
/**
|
||||
* Create a custom count query based on the columns set in countColumns
|
||||
*
|
||||
* @return Zend_Db_Select The query object representing the count
|
||||
*/
|
||||
private function createCustomCountQuery()
|
||||
{
|
||||
$query = clone($this->baseQuery);
|
||||
if ($this->countColumns === null) {
|
||||
$this->countColumns = array('cnt' => 'COUNT(*)');
|
||||
}
|
||||
$query->columns($this->countColumns);
|
||||
return $query;
|
||||
}
|
||||
|
||||
protected function beforeCreatingSelectQuery()
|
||||
/**
|
||||
* Create a query using the selected operation
|
||||
*
|
||||
* @see Query::createCountAsSubQuery() Used when useSubqueryCount is true
|
||||
* @see Query::createCustomCountQuery() Called when useSubqueryCount is false
|
||||
*/
|
||||
private function createCountQuery()
|
||||
{
|
||||
if ($this->useSubqueryCount) {
|
||||
$this->countQuery = $this->createCountAsSubquery();
|
||||
} else {
|
||||
$this->countQuery =$this->createCustomCountQuery();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected function beforeQueryCreation()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
protected function afterQueryCreation()
|
||||
{
|
||||
|
||||
}
|
||||
/**
|
||||
* Create the Zend_Db select and count query objects for this instance
|
||||
*/
|
||||
private function createQueryObjects()
|
||||
{
|
||||
$this->beforeQueryCreation();
|
||||
$this->applyFilter();
|
||||
$this->createSelectQuery();
|
||||
$this->createCountQuery();
|
||||
$this->afterQueryCreation();
|
||||
}
|
||||
|
||||
/**
|
||||
* Query the database and fetch the result count of this query
|
||||
*
|
||||
* @return int The result count of this query as returned by the database
|
||||
*/
|
||||
public function count()
|
||||
{
|
||||
if ($this->countCache === null) {
|
||||
@ -120,31 +209,62 @@ class Query extends AbstractQuery
|
||||
return $this->countCache;
|
||||
}
|
||||
|
||||
/**
|
||||
* Query the database and return all results
|
||||
*
|
||||
* @return array An array containing subarrays with all results contained in the database
|
||||
*/
|
||||
public function fetchAll()
|
||||
{
|
||||
return $this->db->fetchAll($this->getSelectQuery());
|
||||
}
|
||||
|
||||
/**
|
||||
* Query the database and return the next result row
|
||||
*
|
||||
* @return array An array containing the next row of the database result
|
||||
*/
|
||||
public function fetchRow()
|
||||
{
|
||||
return $this->db->fetchRow($this->getSelectQuery());
|
||||
}
|
||||
|
||||
/**
|
||||
* Query the database and return a single column of the result
|
||||
*
|
||||
* @return array An array containing the first column of the result
|
||||
*/
|
||||
public function fetchColumn()
|
||||
{
|
||||
return $this->db->fetchCol($this->getSelectQuery());
|
||||
}
|
||||
|
||||
/**
|
||||
* Query the database and return a single result
|
||||
*
|
||||
* @return array An associative array containing the first result
|
||||
*/
|
||||
public function fetchOne()
|
||||
{
|
||||
return $this->db->fetchOne($this->getSelectQuery());
|
||||
}
|
||||
|
||||
/**
|
||||
* Query the database and return key=>value pairs using hte first two columns
|
||||
*
|
||||
* @return array An array containing key=>value pairs
|
||||
*/
|
||||
public function fetchPairs()
|
||||
{
|
||||
return $this->db->fetchPairs($this->getSelectQuery());
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the select and count query as a textual representation
|
||||
*
|
||||
* @return string An String containing the select and count query, using unix style newlines
|
||||
* as linebreaks
|
||||
*/
|
||||
public function dump()
|
||||
{
|
||||
return "QUERY\n=====\n"
|
||||
@ -154,8 +274,50 @@ class Query extends AbstractQuery
|
||||
. "\n\n";
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the select query
|
||||
*
|
||||
* The paginator expects this, so we can't use debug output here
|
||||
*
|
||||
* @return Zend_Db_Select
|
||||
*/
|
||||
public function __toString()
|
||||
{
|
||||
return (string) $this->getSelectQuery();
|
||||
return strval($this->getSelectQuery());
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse a backend specific filter expression and return a Query\Node object
|
||||
*
|
||||
* @param $expression The expression to parse
|
||||
* @param $parameters Optional parameters for the expression
|
||||
*
|
||||
* @return Node A query node or null if it's an invalid expression
|
||||
*/
|
||||
protected function parseFilterExpression($expression, $parameter = null)
|
||||
{
|
||||
$splitted = explode(' ', $expression, 3);
|
||||
if (count($splitted) === 1 && $parameter) {
|
||||
return Node::createOperatorNode(Node::OPERATOR_EQUALS, $splitted[0], $parameter);
|
||||
} elseif (count($splitted) === 2 && $parameter) {
|
||||
Node::createOperatorNode($splitted[0], $splitted[1], is_string($parameter));
|
||||
return Node::createOperatorNode(Node::OPERATOR_EQUALS, $splitted[0], $parameter);
|
||||
} elseif (count($splitted) === 3) {
|
||||
if (trim($splitted[2]) === '?' && is_string($parameter)) {
|
||||
return Node::createOperatorNode($splitted[1], $splitted[0], $parameter);
|
||||
} else {
|
||||
return Node::createOperatorNode($splitted[1], $splitted[0], $splitted[2]);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public function applyFilter()
|
||||
{
|
||||
$parser = new TreeToSqlParser($this);
|
||||
$parser->treeToSql($this->getFilter(), $this->baseQuery);
|
||||
$this->clearFilter();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -26,20 +26,16 @@
|
||||
*/
|
||||
// {{{ICINGA_LICENSE_HEADER}}}
|
||||
|
||||
namespace Icinga\Module\Monitoring\Filter\Backend;
|
||||
namespace Icinga\Data\Db;
|
||||
|
||||
use Icinga\Data\DatasourceInterface;
|
||||
use Icinga\Data\Db\Query;
|
||||
use Icinga\Data\BaseQuery;
|
||||
use Icinga\Filter\Query\Tree;
|
||||
use Icinga\Filter\Query\Node;
|
||||
use Icinga\Filter\Filterable;
|
||||
use Icinga\Module\Monitoring\DataView\DataView;
|
||||
use Icinga\Module\Monitoring\Backend\Ido\Query\AbstractQuery;
|
||||
|
||||
/**
|
||||
* Converter class that takes a query tree and creates an SQL Query from it's state
|
||||
*/
|
||||
class IdoQueryConverter
|
||||
class TreeToSqlParser
|
||||
{
|
||||
/**
|
||||
* The query class to use as the base for converting
|
||||
@ -59,7 +55,7 @@ class IdoQueryConverter
|
||||
*
|
||||
* @param AbstractQuery $query The query to use for conversion
|
||||
*/
|
||||
public function __construct(AbstractQuery $query)
|
||||
public function __construct(BaseQuery $query)
|
||||
{
|
||||
$this->query = $query;
|
||||
}
|
||||
@ -128,7 +124,9 @@ class IdoQueryConverter
|
||||
if (!$this->query->isValidFilterTarget($node->left) && $this->query->getMappedField($node->left)) {
|
||||
return '';
|
||||
}
|
||||
$this->query->requireColumn($node->left);
|
||||
$queryString = $this->query->getMappedField($node->left);
|
||||
|
||||
if ($this->query->isAggregateColumn($node->left)) {
|
||||
$this->type = 'HAVING';
|
||||
}
|
||||
@ -174,6 +172,7 @@ class IdoQueryConverter
|
||||
if ($tree->root == null) {
|
||||
return;
|
||||
}
|
||||
$tree->root = $tree->normalizeTree($tree->root);
|
||||
$sql = $this->nodeToSqlQuery($tree->root);
|
||||
if ($this->filtersAggregate()) {
|
||||
$baseQuery->having($sql);
|
@ -1,54 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Data Filter
|
||||
*/
|
||||
namespace Icinga\Data;
|
||||
|
||||
use ArrayIterator;
|
||||
|
||||
/**
|
||||
* This class contains an array of filters
|
||||
*
|
||||
* @package Icinga\Data
|
||||
* @author Icinga-Web Team <info@icinga.org>
|
||||
* @copyright 2013 Icinga-Web Team <info@icinga.org>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU General Public License
|
||||
*/
|
||||
class Filter extends ArrayIterator
|
||||
{
|
||||
|
||||
public function without($keys)
|
||||
{
|
||||
$filter = new Filter();
|
||||
$params = $this->toParams();
|
||||
if (! is_array($keys)) {
|
||||
$keys = array($keys);
|
||||
}
|
||||
foreach ($keys as $key) {
|
||||
if (array_key_exists($key, $params)) {
|
||||
unset($params[$key]);
|
||||
}
|
||||
}
|
||||
foreach ($params as $k => $v) {
|
||||
$filter[] = array($k, $v);
|
||||
}
|
||||
return $filter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get filter as key-value array
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function toParams()
|
||||
{
|
||||
$params = array();
|
||||
|
||||
foreach ($this as $filter) {
|
||||
$params[$filter[0]] = $filter[1];
|
||||
}
|
||||
|
||||
return $params;
|
||||
}
|
||||
}
|
@ -1,162 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Icinga\Data;
|
||||
|
||||
use Countable;
|
||||
|
||||
interface QueryInterface extends Countable
|
||||
{
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param DatasourceInterface $ds Your data source
|
||||
*/
|
||||
public function __construct(DatasourceInterface $ds, $columns = null);
|
||||
|
||||
public function getDatasource();
|
||||
|
||||
/**
|
||||
* 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($table, $columns = null);
|
||||
|
||||
public function columns($columns);
|
||||
|
||||
/**
|
||||
* Use once or multiple times to filter result set
|
||||
*
|
||||
* Multiple where calls will be combined by a logical AND operation
|
||||
*
|
||||
* @param string $key Column or backend-specific search expression
|
||||
* @param string $val Search value, must be escaped automagically
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function where($key, $val = null);
|
||||
|
||||
/**
|
||||
* Sort query result by the given column name
|
||||
*
|
||||
* Sort direction can be ascending (self::SORT_ASC, being the default)
|
||||
* or descending (self::SORT_DESC).
|
||||
*
|
||||
* Preferred usage:
|
||||
* <code>
|
||||
* $query->sort('column_name ASC')
|
||||
* </code>
|
||||
*
|
||||
* @param string $col Column, may contain direction separated by space
|
||||
* @param int $dir Sort direction
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function order($col, $dir = null);
|
||||
|
||||
/**
|
||||
* Limit the result set
|
||||
*
|
||||
* @param int $count Return not more than that many rows
|
||||
* @param int $offset Result starts with this row
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function limit($count = null, $offset = null);
|
||||
|
||||
/**
|
||||
* Wheter at least one order column has been applied to this Query
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function hasOrder();
|
||||
|
||||
/**
|
||||
* Wheter a limit has been applied to this Query
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function hasLimit();
|
||||
|
||||
/**
|
||||
* Wheter a starting offset been applied to this Query
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function hasOffset();
|
||||
|
||||
/**
|
||||
* Get the query limit
|
||||
*
|
||||
* @return int|null
|
||||
*/
|
||||
public function getLimit();
|
||||
|
||||
/**
|
||||
* Get the query starting offset
|
||||
*
|
||||
* @return int|null
|
||||
*/
|
||||
public function getOffset();
|
||||
|
||||
/**
|
||||
* Get the columns that have been asked for with this query
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function listColumns();
|
||||
|
||||
public function getColumns();
|
||||
|
||||
/**
|
||||
* Get the filters that have been applied to this query
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function listFilters();
|
||||
|
||||
|
||||
/**
|
||||
* Fetch result as an array of objects
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function fetchAll();
|
||||
|
||||
/**
|
||||
* Fetch first result row
|
||||
*
|
||||
* @return object
|
||||
*/
|
||||
public function fetchRow();
|
||||
|
||||
/**
|
||||
* Fetch first result column
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function fetchColumn();
|
||||
|
||||
/**
|
||||
* Fetch first column value from first result row
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function fetchOne();
|
||||
|
||||
/**
|
||||
* Fetch result as a key/value pair array
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function fetchPairs();
|
||||
|
||||
/**
|
||||
* Return a pagination adapter for this query
|
||||
*
|
||||
* @return \Zend_Paginator
|
||||
*/
|
||||
public function paginate($limit = null, $page = null);
|
||||
}
|
@ -2,7 +2,7 @@
|
||||
|
||||
namespace Icinga\File;
|
||||
|
||||
use Icinga\Data\AbstractQuery;
|
||||
use Icinga\Data\BaseQuery;
|
||||
|
||||
class Csv
|
||||
{
|
||||
@ -12,7 +12,7 @@ class Csv
|
||||
{
|
||||
}
|
||||
|
||||
public static function fromQuery(AbstractQuery $query)
|
||||
public static function fromQuery(BaseQuery $query)
|
||||
{
|
||||
$csv = new Csv();
|
||||
$csv->query = $query;
|
||||
|
@ -29,12 +29,11 @@
|
||||
|
||||
namespace Icinga\Filter;
|
||||
|
||||
|
||||
use Icinga\Filter\Query\Tree;
|
||||
|
||||
interface Filterable
|
||||
{
|
||||
public function isValidFilterTarget($field);
|
||||
public function getMappedField($field);
|
||||
public function applyFilter(Tree $filter);
|
||||
public function applyFilter();
|
||||
public function clearFilter();
|
||||
public function addFilter($filter);
|
||||
}
|
||||
|
@ -73,7 +73,11 @@ class Tree
|
||||
$this->insertOrNode($node, $this->root);
|
||||
break;
|
||||
case Node::TYPE_OPERATOR:
|
||||
if ($this->lastNode->type == Node::TYPE_OPERATOR) {
|
||||
$this->insert(Node::createAndNode());
|
||||
}
|
||||
$node->parent = $this->lastNode;
|
||||
|
||||
if ($this->lastNode->left == null) {
|
||||
$this->lastNode->left = $node;
|
||||
} elseif ($this->lastNode->right == null) {
|
||||
|
@ -1,8 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Icinga\Objects;
|
||||
|
||||
class Host extends Object
|
||||
{
|
||||
// Nothing here
|
||||
}
|
@ -1,61 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Icinga\Objects;
|
||||
|
||||
class Object
|
||||
{
|
||||
protected $id;
|
||||
protected $name;
|
||||
protected $props;
|
||||
protected $defaults = array();
|
||||
protected $fromBackend = false;
|
||||
protected $hasBeenChanged = false;
|
||||
|
||||
protected function __construct($props = array())
|
||||
{
|
||||
$this->props = $this->defaults;
|
||||
if (! empty($props)) {
|
||||
$this->setProperties($props);
|
||||
}
|
||||
}
|
||||
|
||||
public function setProperties($props)
|
||||
{
|
||||
foreach ($props as $key => $val) {
|
||||
$this->props[$key] = $val;
|
||||
}
|
||||
}
|
||||
|
||||
protected function set($key, $val)
|
||||
{
|
||||
$this->props[$key] = $val;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function __set($key, $val)
|
||||
{
|
||||
$this->set($key, $val);
|
||||
}
|
||||
|
||||
public function __get($key)
|
||||
{
|
||||
if (array_key_exists($key, $this->props)) {
|
||||
return $this->props[$key];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
protected function setLoadedFromBackend($loaded = true)
|
||||
{
|
||||
$this->fromBackend = $loaded;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public static function fromBackend($row)
|
||||
{
|
||||
$class = get_called_class();
|
||||
$object = new $class($row);
|
||||
$object->setLoadedFromBackend();
|
||||
return $object;
|
||||
}
|
||||
}
|
@ -1,7 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Icinga\Objects;
|
||||
|
||||
class Service extends Object
|
||||
{
|
||||
}
|
@ -29,7 +29,7 @@
|
||||
namespace Icinga\Protocol;
|
||||
|
||||
/**
|
||||
* Class AbstractQuery
|
||||
* Class BaseQuery
|
||||
* @package Icinga\Protocol
|
||||
*/
|
||||
abstract class AbstractQuery
|
||||
|
@ -29,13 +29,13 @@
|
||||
namespace Icinga\Protocol\Statusdat;
|
||||
|
||||
use Icinga\Protocol;
|
||||
use Icinga\Data\AbstractQuery;
|
||||
use Icinga\Data\BaseQuery;
|
||||
|
||||
/**
|
||||
* Class Query
|
||||
* @package Icinga\Protocol\Statusdat
|
||||
*/
|
||||
class Query extends AbstractQuery
|
||||
class Query extends BaseQuery
|
||||
{
|
||||
/**
|
||||
* @var array
|
||||
@ -76,7 +76,7 @@ class Query extends AbstractQuery
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $order_columns = array();
|
||||
protected $orderColumns = array();
|
||||
|
||||
/**
|
||||
* @var array
|
||||
@ -108,7 +108,7 @@ class Query extends AbstractQuery
|
||||
*/
|
||||
public function hasOrder()
|
||||
{
|
||||
return !empty($this->order_columns);
|
||||
return !empty($this->orderColumns);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -200,7 +200,7 @@ class Query extends AbstractQuery
|
||||
$col = $col;
|
||||
}
|
||||
|
||||
$this->order_columns[] = array($col, $dir);
|
||||
$this->orderColumns[] = array($col, $dir);
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
@ -275,7 +275,7 @@ class Query extends AbstractQuery
|
||||
*/
|
||||
private function orderIndices(array &$indices)
|
||||
{
|
||||
if (!empty($this->order_columns)) {
|
||||
if (!empty($this->orderColumns)) {
|
||||
foreach ($indices as $type => &$subindices) {
|
||||
$this->currentType = $type; // we're singlethreaded, so let's do it a bit dirty
|
||||
usort($subindices, array($this, "orderResult"));
|
||||
@ -293,7 +293,7 @@ class Query extends AbstractQuery
|
||||
$o1 = $this->ds->getObjectByName($this->currentType, $a);
|
||||
$o2 = $this->ds->getObjectByName($this->currentType, $b);
|
||||
$result = 0;
|
||||
foreach ($this->order_columns as $col) {
|
||||
foreach ($this->orderColumns as $col) {
|
||||
$result += $col[1] * strnatcasecmp($o1->{$col[0]}, $o2->{$col[0]});
|
||||
}
|
||||
if ($result > 0) {
|
||||
|
@ -190,6 +190,7 @@ class Monitoring_ListController extends MonitoringController
|
||||
'downtime_trigger_time'
|
||||
)
|
||||
)->getQuery();
|
||||
|
||||
$this->view->downtimes = $query->paginate();
|
||||
$this->setupSortControl(array(
|
||||
'downtime_is_in_effect' => 'Is In Effect',
|
||||
@ -403,7 +404,7 @@ class Monitoring_ListController extends MonitoringController
|
||||
if ($this->getParam('format') === 'sql'
|
||||
&& IcingaConfig::app()->global->get('environment', 'production') === 'development') {
|
||||
echo '<pre>'
|
||||
. htmlspecialchars(wordwrap($query->dump()))
|
||||
. htmlspecialchars(wordwrap($query->__toString()))
|
||||
. '</pre>';
|
||||
exit;
|
||||
}
|
||||
|
@ -34,8 +34,8 @@ use \Icinga\Module\Monitoring\Object\Host;
|
||||
use \Icinga\Module\Monitoring\Object\Service;
|
||||
use \Icinga\Application\Benchmark;
|
||||
use \Icinga\Web\Widget\Tabextension\OutputFormat;
|
||||
use \Icinga\Web\Widget\Tabextension\DashboardAction;
|
||||
use \Icinga\Web\Widget\Tabextension\BasketAction;
|
||||
use Icinga\Web\Widget\Tabextension\DashboardAction;
|
||||
use Icinga\Module\Monitoring\Object\AbstractObject;
|
||||
use \Icinga\Web\Widget\Tabs;
|
||||
|
||||
/**
|
||||
@ -55,28 +55,7 @@ class Monitoring_ShowController extends MonitoringController
|
||||
*/
|
||||
public function init()
|
||||
{
|
||||
$host = $this->_getParam('host');
|
||||
$service = $this->_getParam('service');
|
||||
$this->backend = Backend::createBackend($this->_getParam('backend'));
|
||||
$object = null;
|
||||
// TODO: Do not allow wildcards in names!
|
||||
if ($host !== null) {
|
||||
// TODO: $this->assertPermission('host/read', $host);
|
||||
if ($this->getRequest()->getActionName() !== 'host' && $service !== null && $service !== '*') {
|
||||
// TODO: $this->assertPermission('service/read', $service);
|
||||
$object = Service::fetch($this->backend, $host, $service);
|
||||
} else {
|
||||
$object = Host::fetch($this->backend, $host);
|
||||
}
|
||||
}
|
||||
|
||||
$this->view->compact = $this->_getParam('view') === 'compact';
|
||||
if ($object === null) {
|
||||
// TODO: Notification, not found
|
||||
$this->redirectNow('monitoring/list/services');
|
||||
return;
|
||||
}
|
||||
$this->view->object = $object;
|
||||
$this->view->object = AbstractObject::fromRequest($this->getRequest());
|
||||
$this->createTabs();
|
||||
}
|
||||
|
||||
@ -85,8 +64,7 @@ class Monitoring_ShowController extends MonitoringController
|
||||
*/
|
||||
public function serviceAction()
|
||||
{
|
||||
$this->view->object->prefetch();
|
||||
$this->view->preserve = array();
|
||||
$this->view->object->populate();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -94,14 +72,15 @@ class Monitoring_ShowController extends MonitoringController
|
||||
*/
|
||||
public function hostAction()
|
||||
{
|
||||
$this->view->object->prefetch();
|
||||
$this->view->preserve = array();
|
||||
$this->view->object->populate();
|
||||
}
|
||||
|
||||
public function historyAction()
|
||||
{
|
||||
$this->view->object->populate();
|
||||
$this->view->object->fetchEventHistory();
|
||||
$this->view->history = $this->view->object->eventHistory->limit(10)->paginate();
|
||||
$this->view->history = $this->view->object->eventhistory->limit(10)->paginate();
|
||||
|
||||
}
|
||||
|
||||
public function servicesAction()
|
||||
|
@ -1,15 +1,23 @@
|
||||
<?= $this->tabs->render($this); ?>
|
||||
|
||||
<h1>History</h1>
|
||||
<?php if($history->count() === 0): ?>
|
||||
<div class="alert alert-info">
|
||||
No History Available For This Object
|
||||
|
||||
</div>
|
||||
<?php else: ?>
|
||||
|
||||
<?php if (!empty($history)): ?>
|
||||
<div data-icinga-component="app/mainDetailGrid">
|
||||
|
||||
<?= $this->paginationControl($history, null, null, array('preserve' => $this->preserve)); ?>
|
||||
<table class="table table-condensed">
|
||||
<tbody>
|
||||
|
||||
<?php foreach ($history as $event): ?>
|
||||
<tr>
|
||||
<td><?= date('d.m. H:i', $event->timestamp); ?></td>
|
||||
|
||||
<td><?= date('d.m. H:i', $event->raw_timestamp); ?></td>
|
||||
|
||||
<td>
|
||||
<?php if ($object instanceof Icinga\Module\Monitoring\Object\Service): ?>
|
||||
|
@ -1,251 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Icinga\Module\Monitoring\Backend;
|
||||
|
||||
use Icinga\Data\DatasourceInterface;
|
||||
use Icinga\Exception\ProgrammingError;
|
||||
use Icinga\Application\Benchmark;
|
||||
use Zend_Config;
|
||||
|
||||
class AbstractBackend implements DatasourceInterface
|
||||
{
|
||||
protected $config;
|
||||
|
||||
public function __construct(Zend_Config $config)
|
||||
{
|
||||
if ($config === null) {
|
||||
// $config = new Zend_Config(array()); ???
|
||||
}
|
||||
$this->config = $config;
|
||||
$this->init();
|
||||
}
|
||||
|
||||
protected function init()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Backend entry point
|
||||
*
|
||||
* return self
|
||||
*/
|
||||
public function select()
|
||||
{
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a Query object instance for given virtual table and desired fields
|
||||
*
|
||||
* Leave fields empty to get all available properties
|
||||
*
|
||||
* @param string $virtual_table Virtual table name
|
||||
* @param array $fields Fields
|
||||
* @throws \Icinga\Exception\ProgrammingError
|
||||
* @return self
|
||||
*/
|
||||
public function from($virtual_table, $fields = array())
|
||||
{
|
||||
$classname = $this->tableToClassName($virtual_table);
|
||||
if (!class_exists($classname)) {
|
||||
throw new ProgrammingError(
|
||||
sprintf(
|
||||
'Asking for invalid virtual table %s',
|
||||
$classname
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
$query = new $classname($this, $fields);
|
||||
return $query;
|
||||
}
|
||||
|
||||
public function hasView($virtual_table)
|
||||
{
|
||||
// TODO: This is no longer enough, have to check for Query right now
|
||||
return class_exists($this->tableToClassName($virtual_table));
|
||||
}
|
||||
|
||||
protected function tableToClassName($virtual_table)
|
||||
{
|
||||
return '\\Icinga\\Module\\Monitoring\\View\\'
|
||||
// . $this->getName()
|
||||
// . '\\'
|
||||
. ucfirst($virtual_table)
|
||||
. 'View';
|
||||
}
|
||||
|
||||
public function getName()
|
||||
{
|
||||
return preg_replace('~^.+\\\(.+?)$~', '$1', get_class($this));
|
||||
}
|
||||
|
||||
public function __toString()
|
||||
{
|
||||
return $this->getName();
|
||||
}
|
||||
|
||||
/**
|
||||
* UGLY temporary host fetch
|
||||
*
|
||||
* @param string $host
|
||||
* @param bool $fetchAll
|
||||
* @return mixed
|
||||
*/
|
||||
|
||||
public function fetchHost($host, $fetchAll = false)
|
||||
{
|
||||
$fields = array(
|
||||
'host_name',
|
||||
'host_address',
|
||||
'host_state',
|
||||
'host_handled',
|
||||
'host_icon_image',
|
||||
'host_in_downtime',
|
||||
'host_acknowledged',
|
||||
'host_check_command',
|
||||
'host_last_state_change',
|
||||
'host_alias',
|
||||
'host_output',
|
||||
'host_long_output',
|
||||
'host_perfdata',
|
||||
'host_notes_url',
|
||||
'host_action_url'
|
||||
);
|
||||
|
||||
if ($fetchAll === true) {
|
||||
$fields = array_merge(
|
||||
$fields,
|
||||
array(
|
||||
'host_current_check_attempt',
|
||||
'host_max_check_attempts',
|
||||
'host_attempt',
|
||||
'host_last_check',
|
||||
'host_next_check',
|
||||
'host_check_type',
|
||||
'host_last_state_change',
|
||||
'host_last_hard_state_change',
|
||||
'host_last_hard_state',
|
||||
'host_last_time_up',
|
||||
'host_last_time_down',
|
||||
'host_last_time_unreachable',
|
||||
'host_state_type',
|
||||
'host_last_notification',
|
||||
'host_next_notification',
|
||||
'host_no_more_notifications',
|
||||
'host_notifications_enabled',
|
||||
'host_problem_has_been_acknowledged',
|
||||
'host_acknowledgement_type',
|
||||
'host_current_notification_number',
|
||||
'host_passive_checks_enabled',
|
||||
'host_active_checks_enabled',
|
||||
'host_event_handler_enabled',
|
||||
'host_flap_detection_enabled',
|
||||
'host_is_flapping',
|
||||
'host_percent_state_change',
|
||||
'host_check_latency',
|
||||
'host_check_execution_time',
|
||||
'host_scheduled_downtime_depth',
|
||||
'host_failure_prediction_enabled',
|
||||
'host_process_performance_data',
|
||||
'host_obsessing',
|
||||
'host_modified_host_attributes',
|
||||
'host_event_handler',
|
||||
'host_check_command',
|
||||
'host_normal_check_interval',
|
||||
'host_retry_check_interval',
|
||||
'host_check_timeperiod_object_id',
|
||||
'host_status_update_time'
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
$select = $this->select()
|
||||
->from('status', $fields)
|
||||
->where('host_name', $host);
|
||||
|
||||
return $select->fetchRow();
|
||||
}
|
||||
|
||||
// UGLY temporary service fetch
|
||||
public function fetchService($host, $service, $fetchAll = false)
|
||||
{
|
||||
$fields = array(
|
||||
'service_description',
|
||||
'host_name',
|
||||
'host_address',
|
||||
'host_state',
|
||||
'host_handled',
|
||||
'host_icon_image',
|
||||
'service_state',
|
||||
'service_handled',
|
||||
'service_in_downtime',
|
||||
'service_acknowledged',
|
||||
'service_check_command',
|
||||
'service_last_state_change',
|
||||
'service_display_name',
|
||||
'service_output',
|
||||
'service_long_output',
|
||||
'service_perfdata',
|
||||
'service_action_url',
|
||||
'service_notes_url',
|
||||
'service_icon_image'
|
||||
);
|
||||
|
||||
if ($fetchAll === true) {
|
||||
$fields = array_merge(
|
||||
$fields,
|
||||
array(
|
||||
'service_current_check_attempt',
|
||||
'service_max_check_attempts',
|
||||
'service_attempt',
|
||||
'service_last_check',
|
||||
'service_next_check',
|
||||
'service_check_type',
|
||||
'service_last_state_change',
|
||||
'service_last_hard_state_change',
|
||||
'service_last_hard_state',
|
||||
'service_last_time_ok',
|
||||
'service_last_time_warning',
|
||||
'service_last_time_unknown',
|
||||
'service_last_time_critical',
|
||||
'service_state_type',
|
||||
'service_last_notification',
|
||||
'service_next_notification',
|
||||
'service_no_more_notifications',
|
||||
'service_notifications_enabled',
|
||||
'service_problem_has_been_acknowledged',
|
||||
'service_acknowledgement_type',
|
||||
'service_current_notification_number',
|
||||
'service_passive_checks_enabled',
|
||||
'service_active_checks_enabled',
|
||||
'service_event_handler_enabled',
|
||||
'service_flap_detection_enabled',
|
||||
'service_is_flapping',
|
||||
'service_percent_state_change',
|
||||
'service_check_latency',
|
||||
'service_check_execution_time',
|
||||
'service_scheduled_downtime_depth',
|
||||
'service_failure_prediction_enabled',
|
||||
'service_process_performance_data',
|
||||
'service_obsessing',
|
||||
'service_modified_service_attributes',
|
||||
'service_event_handler',
|
||||
'service_check_command',
|
||||
'service_normal_check_interval',
|
||||
'service_retry_check_interval',
|
||||
'service_check_timeperiod_object_id',
|
||||
'service_status_update_time'
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
$select = $this->select()
|
||||
->from('status', $fields)
|
||||
->where('service_description', $service)
|
||||
->where('host_name', $host);
|
||||
return $select->fetchRow();
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -1,341 +0,0 @@
|
||||
<?php
|
||||
// {{{ICINGA_LICENSE_HEADER}}}
|
||||
/**
|
||||
* This file is part of Icinga 2 Web.
|
||||
*
|
||||
* Icinga 2 Web - Head for multiple monitoring backends.
|
||||
* Copyright (C) 2013 Icinga Development Team
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* @copyright 2013 Icinga Development Team <info@icinga.org>
|
||||
* @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2
|
||||
* @author Icinga Development Team <info@icinga.org>
|
||||
*/
|
||||
// {{{ICINGA_LICENSE_HEADER}}}
|
||||
|
||||
namespace Icinga\Module\Monitoring\Backend\Ido\Query;
|
||||
|
||||
use Icinga\Data\Db\Query;
|
||||
use Icinga\Application\Benchmark;
|
||||
use Icinga\Exception\ProgrammingError;
|
||||
use Icinga\Filter\Query\Tree;
|
||||
use Icinga\Filter\Filterable;
|
||||
use Icinga\Module\Monitoring\Filter\Backend\IdoQueryConverter;
|
||||
use Icinga\Module\Monitoring\Filter\UrlViewFilter;
|
||||
|
||||
abstract class AbstractQuery extends Query implements Filterable
|
||||
{
|
||||
protected $prefix;
|
||||
protected $idxAliasColumn;
|
||||
protected $idxAliasTable;
|
||||
protected $columnMap = array();
|
||||
protected $query;
|
||||
protected $customVars = array();
|
||||
protected $joinedVirtualTables = array();
|
||||
protected $object_id = 'object_id';
|
||||
protected $host_id = 'host_id';
|
||||
protected $hostgroup_id = 'hostgroup_id';
|
||||
protected $service_id = 'service_id';
|
||||
protected $servicegroup_id = 'servicegroup_id';
|
||||
protected $contact_id = 'contact_id';
|
||||
protected $contactgroup_id = 'contactgroup_id';
|
||||
protected $aggregateColumnIdx = array();
|
||||
protected $allowCustomVars = false;
|
||||
|
||||
public function isAggregateColumn($column)
|
||||
{
|
||||
return array_key_exists($column, $this->aggregateColumnIdx);
|
||||
}
|
||||
|
||||
public function order($col, $dir = null)
|
||||
{
|
||||
$this->requireColumn($col);
|
||||
if ($this->isCustomvar($col)) {
|
||||
// TODO: Doesn't work right now. Does it?
|
||||
$col = $this->getCustomvarColumnName($col);
|
||||
} elseif ($this->hasAliasName($col)) {
|
||||
$col = $this->aliasToColumnName($col);
|
||||
} else {
|
||||
throw new \InvalidArgumentException('Can\'t order by column '.$col);
|
||||
}
|
||||
$this->order_columns[] = array($col, $dir);
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function applyFilter(Tree $filter)
|
||||
{
|
||||
foreach ($filter->getAttributes() as $target) {
|
||||
$this->requireColumn($target);
|
||||
}
|
||||
$converter = new IdoQueryConverter($this);
|
||||
$converter->treeToSql($filter, $this->baseQuery);
|
||||
}
|
||||
|
||||
public function isValidFilterTarget($field)
|
||||
{
|
||||
return $this->getMappedField($field) !== null;
|
||||
}
|
||||
|
||||
public function getMappedField($field)
|
||||
{
|
||||
foreach ($this->columnMap as $columnSource => $columnSet) {
|
||||
if (isset($columnSet[$field])) {
|
||||
return $columnSet[$field];
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public function isTimestamp($field)
|
||||
{
|
||||
$mapped = $this->getMappedField($field);
|
||||
if ($mapped === null) {
|
||||
return false;
|
||||
}
|
||||
return stripos($mapped, 'UNIX_TIMESTAMP') !== false;
|
||||
}
|
||||
|
||||
protected function init()
|
||||
{
|
||||
parent::init();
|
||||
// TODO: $this->applyDbSpecificWorkarounds
|
||||
$this->prefix = $this->ds->getTablePrefix();
|
||||
|
||||
if ($this->ds->getDbType() === 'oracle') {
|
||||
$this->object_id = $this->host_id = $this->service_id
|
||||
= $this->hostgroup_id = $this->servicegroup_id
|
||||
= $this->contact_id = $this->contactgroup_id = 'id'; // REALLY?
|
||||
foreach ($this->columnMap as $table => & $columns) {
|
||||
foreach ($columns as $key => & $value) {
|
||||
$value = preg_replace('/UNIX_TIMESTAMP/', 'localts2unixts', $value);
|
||||
$value = preg_replace('/ COLLATE .+$/', '', $value);
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($this->ds->getDbType() === 'pgsql') {
|
||||
foreach ($this->columnMap as $table => & $columns) {
|
||||
foreach ($columns as $key => & $value) {
|
||||
$value = preg_replace('/ COLLATE .+$/', '', $value);
|
||||
$value = preg_replace('/inet_aton\(([[:word:].]+)\)/i', '$1::inet - \'0.0.0.0\'', $value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$this->joinBaseTables();
|
||||
$this->prepareAliasIndexes();
|
||||
}
|
||||
|
||||
protected function joinBaseTables()
|
||||
{
|
||||
reset($this->columnMap);
|
||||
$table = key($this->columnMap);
|
||||
|
||||
$this->baseQuery = $this->db->select()->from(
|
||||
array($table => $this->prefix . $table),
|
||||
array()
|
||||
);
|
||||
|
||||
$this->joinedVirtualTables = array($table => true);
|
||||
}
|
||||
|
||||
protected function prepareAliasIndexes()
|
||||
{
|
||||
foreach ($this->columnMap as $tbl => & $cols) {
|
||||
foreach ($cols as $alias => $col) {
|
||||
$this->idxAliasTable[$alias] = $tbl;
|
||||
$this->idxAliasColumn[$alias] = preg_replace('~\n\s*~', ' ', $col);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected function beforeCreatingCountQuery()
|
||||
{
|
||||
}
|
||||
|
||||
protected function beforeCreatingSelectQuery()
|
||||
{
|
||||
$this->setRealColumns();
|
||||
$classParts = explode('\\', get_class($this));
|
||||
Benchmark::measure(sprintf('%s ready to run', array_pop($classParts)));
|
||||
}
|
||||
|
||||
public function setRealColumns()
|
||||
{
|
||||
$columns = $this->columns;
|
||||
$this->columns = array();
|
||||
if (empty($columns)) {
|
||||
$columns = $this->getDefaultColumns();
|
||||
}
|
||||
|
||||
foreach ($columns as $alias => $col) {
|
||||
$this->requireColumn($col);
|
||||
if ($this->isCustomvar($col)) {
|
||||
$name = $this->getCustomvarColumnName($col);
|
||||
} else {
|
||||
$name = $this->aliasToColumnName($col);
|
||||
}
|
||||
if (is_int($alias)) {
|
||||
$alias = $col;
|
||||
}
|
||||
|
||||
$this->columns[$alias] = preg_replace('|\n|', ' ', $name);
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
protected function getDefaultColumns()
|
||||
{
|
||||
reset($this->columnMap);
|
||||
$table = key($this->columnMap);
|
||||
return array_keys($this->columnMap[$table]);
|
||||
}
|
||||
|
||||
protected function requireColumn($alias)
|
||||
{
|
||||
if ($this->hasAliasName($alias)) {
|
||||
$this->requireVirtualTable($this->aliasToTableName($alias));
|
||||
} elseif ($this->isCustomVar($alias)) {
|
||||
$this->requireCustomvar($alias);
|
||||
} else {
|
||||
throw new ProgrammingError(sprintf('Got invalid column: %s', $alias));
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
protected function hasAliasName($alias)
|
||||
{
|
||||
return array_key_exists($alias, $this->idxAliasColumn);
|
||||
}
|
||||
|
||||
protected function requireVirtualTable($name)
|
||||
{
|
||||
if ($this->hasJoinedVirtualTable($name)) {
|
||||
return $this;
|
||||
}
|
||||
return $this->joinVirtualTable($name);
|
||||
}
|
||||
|
||||
protected function joinVirtualTable($table)
|
||||
{
|
||||
$func = 'join' . ucfirst($table);
|
||||
if (method_exists($this, $func)) {
|
||||
$this->$func();
|
||||
} else {
|
||||
throw new ProgrammingError(
|
||||
sprintf(
|
||||
'Cannot join "%s", no such table found',
|
||||
$table
|
||||
)
|
||||
);
|
||||
}
|
||||
$this->joinedVirtualTables[$table] = true;
|
||||
return $this;
|
||||
}
|
||||
|
||||
protected function aliasToTableName($alias)
|
||||
{
|
||||
return $this->idxAliasTable[$alias];
|
||||
}
|
||||
|
||||
protected function isCustomVar($alias)
|
||||
{
|
||||
return $this->allowCustomVars && $alias[0] === '_';
|
||||
}
|
||||
|
||||
protected function requireCustomvar($customvar)
|
||||
{
|
||||
if (! $this->hasCustomvar($customvar)) {
|
||||
$this->joinCustomvar($customvar);
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
protected function hasCustomvar($customvar)
|
||||
{
|
||||
return array_key_exists($customvar, $this->customVars);
|
||||
}
|
||||
|
||||
protected function joinCustomvar($customvar)
|
||||
{
|
||||
// TODO: This is not generic enough yet
|
||||
list($type, $name) = $this->customvarNameToTypeName($customvar);
|
||||
$alias = ($type === 'host' ? 'hcv_' : 'scv_') . strtolower($name);
|
||||
|
||||
$this->customVars[$customvar] = $alias;
|
||||
|
||||
// TODO: extend if we allow queries with only hosts / only services
|
||||
// ($leftcol s.host_object_id vs h.host_object_id
|
||||
if ($this->hasJoinedVirtualTable('services')) {
|
||||
$leftcol = 's.' . $type . '_object_id';
|
||||
} else {
|
||||
$leftcol = 'h.' . $type . '_object_id';
|
||||
}
|
||||
$joinOn = $leftcol
|
||||
. ' = '
|
||||
. $alias
|
||||
. '.object_id'
|
||||
. ' AND '
|
||||
. $alias
|
||||
. '.varname = '
|
||||
. $this->db->quote(strtoupper($name));
|
||||
|
||||
$this->baseQuery->joinLeft(
|
||||
array($alias => $this->prefix . 'customvariablestatus'),
|
||||
$joinOn,
|
||||
array()
|
||||
);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
protected function customvarNameToTypeName($customvar)
|
||||
{
|
||||
// TODO: Improve this:
|
||||
if (! preg_match('~^_(host|service)_([a-zA-Z0-9_]+)$~', $customvar, $m)) {
|
||||
throw new ProgrammingError(
|
||||
sprintf(
|
||||
'Got invalid custom var: "%s"',
|
||||
$customvar
|
||||
)
|
||||
);
|
||||
}
|
||||
return array($m[1], $m[2]);
|
||||
}
|
||||
|
||||
protected function hasJoinedVirtualTable($name)
|
||||
{
|
||||
return array_key_exists($name, $this->joinedVirtualTables);
|
||||
}
|
||||
|
||||
protected function getCustomvarColumnName($customvar)
|
||||
{
|
||||
return $this->customVars[$customvar] . '.varvalue';
|
||||
}
|
||||
|
||||
public function aliasToColumnName($alias)
|
||||
{
|
||||
return $this->idxAliasColumn[$alias];
|
||||
}
|
||||
|
||||
protected function createSubQuery($queryName, $columns = array())
|
||||
{
|
||||
$class = '\\'
|
||||
. substr(__CLASS__, 0, strrpos(__CLASS__, '\\') + 1)
|
||||
. ucfirst($queryName) . 'Query';
|
||||
$query = new $class($this->ds, $columns);
|
||||
return $query;
|
||||
}
|
||||
}
|
@ -4,7 +4,7 @@ namespace Icinga\Module\Monitoring\Backend\Ido\Query;
|
||||
|
||||
use Zend_Db_Select;
|
||||
|
||||
class AllcontactsQuery extends AbstractQuery
|
||||
class AllcontactsQuery extends IdoQuery
|
||||
{
|
||||
protected $columnMap = array(
|
||||
'contacts' => array(
|
||||
@ -39,7 +39,7 @@ class AllcontactsQuery extends AbstractQuery
|
||||
|
||||
protected $contacts;
|
||||
protected $contactgroups;
|
||||
protected $uglySlowConservativeCount = true;
|
||||
protected $useSubqueryCount = true;
|
||||
|
||||
protected function requireColumn($alias)
|
||||
{
|
||||
|
@ -32,7 +32,7 @@ namespace Icinga\Module\Monitoring\Backend\Ido\Query;
|
||||
/**
|
||||
* Query map for comments
|
||||
*/
|
||||
class CommentQuery extends AbstractQuery
|
||||
class CommentQuery extends IdoQuery
|
||||
{
|
||||
protected $columnMap = array(
|
||||
'comments' => array(
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
namespace Icinga\Module\Monitoring\Backend\Ido\Query;
|
||||
|
||||
class CommenthistoryQuery extends AbstractQuery
|
||||
class CommenthistoryQuery extends IdoQuery
|
||||
{
|
||||
protected $columnMap = array(
|
||||
'commenthistory' => array(
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
namespace Icinga\Module\Monitoring\Backend\Ido\Query;
|
||||
|
||||
class ContactQuery extends AbstractQuery
|
||||
class ContactQuery extends IdoQuery
|
||||
{
|
||||
protected $columnMap = array(
|
||||
'contacts' => array(
|
||||
@ -33,10 +33,12 @@ class ContactQuery extends AbstractQuery
|
||||
'hosts' => array(
|
||||
'host_object_id' => 'ho.object_id',
|
||||
'host_name' => 'ho.name1 COLLATE latin1_general_ci',
|
||||
'host' => 'ho.name1 COLLATE latin1_general_ci',
|
||||
),
|
||||
'services' => array(
|
||||
'service_object_id' => 'so.object_id',
|
||||
'service_host_name' => 'so.name1 COLLATE latin1_general_ci',
|
||||
'service' => 'so.name1 COLLATE latin1_general_ci',
|
||||
'service_description' => 'so.name2 COLLATE latin1_general_ci',
|
||||
)
|
||||
);
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
namespace Icinga\Module\Monitoring\Backend\Ido\Query;
|
||||
|
||||
class ContactgroupQuery extends AbstractQuery
|
||||
class ContactgroupQuery extends IdoQuery
|
||||
{
|
||||
protected $columnMap = array(
|
||||
'contactgroups' => array(
|
||||
@ -32,14 +32,16 @@ class ContactgroupQuery extends AbstractQuery
|
||||
'hosts' => array(
|
||||
'host_object_id' => 'ho.object_id',
|
||||
'host_name' => 'ho.name1',
|
||||
'host' => 'ho.name1'
|
||||
),
|
||||
'services' => array(
|
||||
'service_object_id' => 'so.object_id',
|
||||
'service_host_name' => 'so.name1 COLLATE latin1_general_ci',
|
||||
'service' => 'so.name1 COLLATE latin1_general_ci',
|
||||
'service_description' => 'so.name2 COLLATE latin1_general_ci',
|
||||
)
|
||||
);
|
||||
protected $uglySlowConservativeCount = true;
|
||||
protected $useSubqueryCount = true;
|
||||
|
||||
protected function joinBaseTables()
|
||||
{
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
namespace Icinga\Module\Monitoring\Backend\Ido\Query;
|
||||
|
||||
class CustomvarQuery extends AbstractQuery
|
||||
class CustomvarQuery extends IdoQuery
|
||||
{
|
||||
protected $object_id = 'object_id';
|
||||
|
||||
|
@ -28,7 +28,7 @@ namespace Icinga\Module\Monitoring\Backend\Ido\Query;
|
||||
/**
|
||||
* Handling downtime queries
|
||||
*/
|
||||
class DowntimeQuery extends AbstractQuery
|
||||
class DowntimeQuery extends IdoQuery
|
||||
{
|
||||
/**
|
||||
* Column map
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
namespace Icinga\Module\Monitoring\Backend\Ido\Query;
|
||||
|
||||
class DowntimeendhistoryQuery extends AbstractQuery
|
||||
class DowntimeendhistoryQuery extends IdoQuery
|
||||
{
|
||||
protected $columnMap = array(
|
||||
'downtimehistory' => array(
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
namespace Icinga\Module\Monitoring\Backend\Ido\Query;
|
||||
|
||||
class DowntimestarthistoryQuery extends AbstractQuery
|
||||
class DowntimestarthistoryQuery extends IdoQuery
|
||||
{
|
||||
protected $columnMap = array(
|
||||
'downtimehistory' => array(
|
||||
|
@ -5,7 +5,7 @@ namespace Icinga\Module\Monitoring\Backend\Ido\Query;
|
||||
use \Zend_Db_Select;
|
||||
use Icinga\Exception\ProgrammingError;
|
||||
|
||||
class EventHistoryQuery extends AbstractQuery
|
||||
class EventHistoryQuery extends IdoQuery
|
||||
{
|
||||
protected $subQueries = array();
|
||||
|
||||
@ -21,27 +21,27 @@ class EventHistoryQuery extends AbstractQuery
|
||||
'host_name' => 'eho.name1 COLLATE latin1_general_ci',
|
||||
'service_description' => 'eho.name2 COLLATE latin1_general_ci',
|
||||
'object_type' => "CASE WHEN eho.objecttype_id = 1 THEN 'host' ELSE 'service' END",
|
||||
'timestamp' => 'eh.timestamp',
|
||||
'raw_timestamp' => 'eh.raw_timestamp',
|
||||
'state' => 'eh.state',
|
||||
// 'last_state' => 'eh.last_state',
|
||||
// 'last_hard_state' => 'eh.last_hard_state',
|
||||
'attempt' => 'eh.attempt',
|
||||
'max_attempts' => 'eh.max_attempts',
|
||||
'output' => 'eh.output', // we do not want long_output
|
||||
//'problems' => 'CASE WHEN eh.state = 0 OR eh.state IS NULL THEN 0 ELSE 1 END',
|
||||
'type' => 'eh.type'
|
||||
'timestamp' => 'eh.timestamp',
|
||||
'raw_timestamp' => 'UNIX_TIMESTAMP(eh.raw_timestamp)',
|
||||
'state' => 'eh.state',
|
||||
'attempt' => 'eh.attempt',
|
||||
'max_attempts' => 'eh.max_attempts',
|
||||
'output' => 'eh.output', // we do not want long_output
|
||||
'type' => 'eh.type',
|
||||
'service_host_name' => 'eho.name1 COLLATE latin1_general_ci',
|
||||
'service_description' => 'eho.name2 COLLATE latin1_general_ci'
|
||||
),
|
||||
'hostgroups' => array(
|
||||
'hostgroup' => 'hgo.name1 COLLATE latin1_general_ci',
|
||||
),
|
||||
);
|
||||
|
||||
protected $uglySlowConservativeCount = true;
|
||||
protected $useSubqueryCount = true;
|
||||
protected $maxCount = 1000;
|
||||
|
||||
protected function joinBaseTables()
|
||||
{
|
||||
|
||||
// $start = date('Y-m-d H:i:s', time() - 3600 * 24 * 1);
|
||||
$start = date('Y-m-d H:i:s', time() - 3600 * 24 * 2);
|
||||
$end = date('Y-m-d H:i:s');
|
||||
@ -67,14 +67,15 @@ class EventHistoryQuery extends AbstractQuery
|
||||
$this->createSubQuery('Commenthistory', $columns),
|
||||
$this->createSubQuery('Notificationhistory', $columns)
|
||||
);
|
||||
|
||||
if ($start) {
|
||||
foreach ($this->subQueries as $query) {
|
||||
$query->where('raw_timestamp', '>' . $start);
|
||||
$query->where('timestamp > ?', $start);
|
||||
}
|
||||
}
|
||||
if ($end) {
|
||||
foreach ($this->subQueries as $query) {
|
||||
$query->where('raw_timestamp', '<' . $end);
|
||||
$query->where('timestamp < ? ', $end);
|
||||
}
|
||||
}
|
||||
$sub = $this->db->select()->union($this->subQueries, Zend_Db_Select::SQL_UNION_ALL);
|
||||
@ -88,7 +89,6 @@ class EventHistoryQuery extends AbstractQuery
|
||||
. ' AND eho.is_active = 1',
|
||||
array()
|
||||
);
|
||||
|
||||
$this->joinedVirtualTables = array('eventhistory' => true);
|
||||
}
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
namespace Icinga\Module\Monitoring\Backend\Ido\Query;
|
||||
|
||||
class HostgroupQuery extends AbstractQuery
|
||||
class HostgroupQuery extends IdoQuery
|
||||
{
|
||||
protected $columnMap = array(
|
||||
'hostgroups' => array(
|
||||
@ -12,6 +12,7 @@ class HostgroupQuery extends AbstractQuery
|
||||
'id' => 'hg.hostgroup_id',
|
||||
),
|
||||
'hosts' => array(
|
||||
'host' => 'ho.name1 COLLATE latin1_general_ci',
|
||||
'host_name' => 'ho.name1 COLLATE latin1_general_ci'
|
||||
)
|
||||
);
|
||||
|
@ -28,7 +28,7 @@
|
||||
|
||||
namespace Icinga\Module\Monitoring\Backend\Ido\Query;
|
||||
|
||||
class HoststatusQuery extends AbstractQuery
|
||||
class HoststatusQuery extends IdoQuery
|
||||
{
|
||||
protected $allowCustomVars = true;
|
||||
protected $columnMap = array(
|
||||
@ -135,10 +135,9 @@ class HoststatusQuery extends AbstractQuery
|
||||
);
|
||||
protected $hcgSub;
|
||||
|
||||
protected function getDefaultColumns()
|
||||
public function getDefaultColumns()
|
||||
{
|
||||
return $this->columnMap['hosts']
|
||||
+ $this->columnMap['hoststatus'];
|
||||
return $this->columnMap['hosts'] + $this->columnMap['hoststatus'];
|
||||
}
|
||||
|
||||
protected function joinBaseTables()
|
||||
@ -187,14 +186,14 @@ class HoststatusQuery extends AbstractQuery
|
||||
"so.$this->object_id = ss.service_object_id",
|
||||
array()
|
||||
);
|
||||
foreach ($this->columns as $col) {
|
||||
foreach ($this->getColumns() as $col) {
|
||||
$real = $this->aliasToColumnName($col);
|
||||
if (substr($real, 0, 4) === 'SUM(') {
|
||||
continue;
|
||||
}
|
||||
$this->baseQuery->group($real);
|
||||
}
|
||||
$this->uglySlowConservativeCount = true;
|
||||
$this->useSubqueryCount = true;
|
||||
}
|
||||
|
||||
protected function joinHostgroups()
|
||||
|
@ -0,0 +1,572 @@
|
||||
<?php
|
||||
// {{{ICINGA_LICENSE_HEADER}}}
|
||||
/**
|
||||
* This file is part of Icinga 2 Web.
|
||||
*
|
||||
* Icinga 2 Web - Head for multiple monitoring backends.
|
||||
* Copyright (C) 2013 Icinga Development Team
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* @copyright 2013 Icinga Development Team <info@icinga.org>
|
||||
* @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2
|
||||
* @author Icinga Development Team <info@icinga.org>
|
||||
*/
|
||||
// {{{ICINGA_LICENSE_HEADER}}}
|
||||
|
||||
namespace Icinga\Module\Monitoring\Backend\Ido\Query;
|
||||
|
||||
use Icinga\Application\Logger;
|
||||
use Icinga\Data\Db\Query;
|
||||
use Icinga\Application\Benchmark;
|
||||
use Icinga\Exception\ProgrammingError;
|
||||
use Icinga\Filter\Query\Tree;
|
||||
use Icinga\Module\Monitoring\Filter\UrlViewFilter;
|
||||
|
||||
/**
|
||||
* Base class for Ido Queries
|
||||
*
|
||||
* This is the base class for all Ido queries and should be extended for new queries
|
||||
* The starting point for implementations is the columnMap attribute. This is an asscociative array in the
|
||||
* following form:
|
||||
*
|
||||
* <pre>
|
||||
* <code>
|
||||
* array(
|
||||
* 'virtualTable' => array(
|
||||
* 'fieldalias1' => 'queryColumn1',
|
||||
* 'fieldalias2' => 'queryColumn2',
|
||||
* ....
|
||||
* ),
|
||||
* 'virtualTable2' => array(
|
||||
* 'host' => 'host_name1'
|
||||
* )
|
||||
* )
|
||||
* </code>
|
||||
* </pre>
|
||||
*
|
||||
* This allows you to select e.g. fieldalias1, which automatically calls the query code for joining 'virtualTable'. If
|
||||
* you afterwards select 'host', 'virtualTable2' will be joined. The joining logic is up to you, in order to make the
|
||||
* above example work you need to implement the joinVirtualTable() and joinVirtualTable2() method which contain your
|
||||
* custom (Zend_Db) logic for joining, filtering and querying the data you want.
|
||||
*
|
||||
*/
|
||||
abstract class IdoQuery extends Query
|
||||
{
|
||||
/**
|
||||
* The prefix to use
|
||||
*
|
||||
* @var String
|
||||
*/
|
||||
protected $prefix;
|
||||
|
||||
/**
|
||||
* The alias name for the index column
|
||||
*
|
||||
* @var String
|
||||
*/
|
||||
protected $idxAliasColumn;
|
||||
|
||||
/**
|
||||
* The table containing the index column alias
|
||||
*
|
||||
* @var String
|
||||
*/
|
||||
protected $idxAliasTable;
|
||||
|
||||
/**
|
||||
* The column map containing all filterable columns
|
||||
*
|
||||
* This must be overwritten by child classes, in the format
|
||||
* array(
|
||||
* 'virtualTable' => array(
|
||||
* 'fieldalias1' => 'queryColumn1',
|
||||
* 'fieldalias2' => 'queryColumn2',
|
||||
* ....
|
||||
* )
|
||||
* )
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $columnMap = array();
|
||||
|
||||
/**
|
||||
* Custom vars available for this query
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $customVars = array();
|
||||
|
||||
/**
|
||||
* An array with all 'virtual' tables that are already joined
|
||||
*
|
||||
* Virtual tables are the keys of the columnMap array and require a
|
||||
* join%VirtualTableName%() method to be defined in the concrete
|
||||
* query
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $joinedVirtualTables = array();
|
||||
|
||||
/**
|
||||
* The primary field name for the object table
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $object_id = 'object_id';
|
||||
|
||||
/**
|
||||
* The primary field name for the IDO host table
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $host_id = 'host_id';
|
||||
|
||||
/**
|
||||
* The primary field name for the IDO hostgroup table
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $hostgroup_id = 'hostgroup_id';
|
||||
|
||||
/**
|
||||
* The primary field name for the IDO service table
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $service_id = 'service_id';
|
||||
|
||||
/**
|
||||
* The primary field name for the IDO serviegroup table
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $servicegroup_id = 'servicegroup_id';
|
||||
|
||||
/**
|
||||
* The primary field name for the IDO contact table
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $contact_id = 'contact_id';
|
||||
|
||||
/**
|
||||
* The primary field name for the IDO contactgroup table
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $contactgroup_id = 'contactgroup_id';
|
||||
|
||||
/**
|
||||
* An array containing Column names that cause an aggregation of the query
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $aggregateColumnIdx = array();
|
||||
|
||||
/**
|
||||
* True to allow customvar filters and queries
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $allowCustomVars = false;
|
||||
|
||||
/**
|
||||
* Return true when the column is an aggregate column
|
||||
*
|
||||
* @param String $column The column to test
|
||||
* @return bool True when the column is an aggregate column
|
||||
*/
|
||||
public function isAggregateColumn($column)
|
||||
{
|
||||
return array_key_exists($column, $this->aggregateColumnIdx);
|
||||
}
|
||||
|
||||
/**
|
||||
* Order the result by the given column
|
||||
*
|
||||
* @param string $columnOrAlias The column or column alias to order by
|
||||
* @param int $dir The sort direction or null to use default direction
|
||||
*
|
||||
* @return self Fluent interface
|
||||
*/
|
||||
public function order($columnOrAlias, $dir = null)
|
||||
{
|
||||
$this->requireColumn($columnOrAlias);
|
||||
if ($this->isCustomvar($columnOrAlias)) {
|
||||
$columnOrAlias = $this->getCustomvarColumnName($columnOrAlias);
|
||||
} elseif ($this->hasAliasName($columnOrAlias)) {
|
||||
$columnOrAlias = $this->aliasToColumnName($columnOrAlias);
|
||||
} else {
|
||||
Logger::info('Can\'t order by column '.$columnOrAlias);
|
||||
return $this;
|
||||
}
|
||||
return parent::order($columnOrAlias, $dir);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true when the given field can be used for filtering
|
||||
*
|
||||
* @param String $field The field to test
|
||||
* @return bool True when the field can be used for querying, otherwise false
|
||||
*/
|
||||
public function isValidFilterTarget($field)
|
||||
{
|
||||
return $this->getMappedField($field) !== null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the resolved field for an alias
|
||||
*
|
||||
* @param String $field The alias to resolve
|
||||
* @return String The resolved alias or null if unknown
|
||||
*/
|
||||
public function getMappedField($field)
|
||||
{
|
||||
foreach ($this->columnMap as $columnSource => $columnSet) {
|
||||
if (isset($columnSet[$field])) {
|
||||
return $columnSet[$field];
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if an field contains an explicit timestamp
|
||||
*
|
||||
* @param String $field The field to test for containing an timestamp
|
||||
* @return bool True when the field represents an timestamp
|
||||
*/
|
||||
public function isTimestamp($field)
|
||||
{
|
||||
$mapped = $this->getMappedField($field);
|
||||
if ($mapped === null) {
|
||||
return false;
|
||||
}
|
||||
return stripos($mapped, 'UNIX_TIMESTAMP') !== false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply oracle specific query initialization
|
||||
*/
|
||||
private function initializeForOracle()
|
||||
{
|
||||
// Oracle uses the reserved field 'id' for primary keys, so
|
||||
// these must be used instead of the normally defined ids
|
||||
$this->object_id = $this->host_id = $this->service_id
|
||||
= $this->hostgroup_id = $this->servicegroup_id
|
||||
= $this->contact_id = $this->contactgroup_id = 'id';
|
||||
foreach ($this->columnMap as &$columns) {
|
||||
foreach ($columns as &$value) {
|
||||
$value = preg_replace('/UNIX_TIMESTAMP/', 'localts2unixts', $value);
|
||||
$value = preg_replace('/ COLLATE .+$/', '', $value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply postgresql specific query initialization
|
||||
*/
|
||||
private function initializeForPostgres()
|
||||
{
|
||||
foreach ($this->columnMap as $table => & $columns) {
|
||||
foreach ($columns as $key => & $value) {
|
||||
$value = preg_replace('/ COLLATE .+$/', '', $value);
|
||||
$value = preg_replace('/inet_aton\(([[:word:].]+)\)/i', '$1::inet - \'0.0.0.0\'', $value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set up this query and join the initial tables
|
||||
*
|
||||
* @see IdoQuery::initializeForPostgres For postgresql specific setup
|
||||
*/
|
||||
protected function init()
|
||||
{
|
||||
parent::init();
|
||||
$this->prefix = $this->ds->getTablePrefix();
|
||||
|
||||
if ($this->ds->getDbType() === 'oracle') {
|
||||
$this->initializeForOracle();
|
||||
} elseif ($this->ds->getDbType() === 'pgsql') {
|
||||
$this->initializeForPostgres();
|
||||
}
|
||||
$this->joinBaseTables();
|
||||
$this->prepareAliasIndexes();
|
||||
}
|
||||
|
||||
/**
|
||||
* Join the base tables for this query
|
||||
*/
|
||||
protected function joinBaseTables()
|
||||
{
|
||||
reset($this->columnMap);
|
||||
$table = key($this->columnMap);
|
||||
|
||||
$this->baseQuery = $this->db->select()->from(
|
||||
array($table => $this->prefix . $table),
|
||||
array()
|
||||
);
|
||||
|
||||
$this->joinedVirtualTables = array($table => true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Populates the idxAliasTAble and idxAliasColumn properties
|
||||
*/
|
||||
protected function prepareAliasIndexes()
|
||||
{
|
||||
foreach ($this->columnMap as $tbl => & $cols) {
|
||||
foreach ($cols as $alias => $col) {
|
||||
$this->idxAliasTable[$alias] = $tbl;
|
||||
$this->idxAliasColumn[$alias] = preg_replace('~\n\s*~', ' ', $col);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare query execution
|
||||
*
|
||||
* @see IdoQuery::resolveColumns() For column alias resolving
|
||||
*/
|
||||
protected function beforeQueryCreation()
|
||||
{
|
||||
$this->resolveColumns();
|
||||
$classParts = explode('\\', get_class($this));
|
||||
Benchmark::measure(sprintf('%s ready to run', array_pop($classParts)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve columns aliases to their database field using the columnMap
|
||||
*
|
||||
* @return self Fluent interface
|
||||
*/
|
||||
public function resolveColumns()
|
||||
{
|
||||
$columns = $this->getColumns();
|
||||
$resolvedColumns = array();
|
||||
|
||||
foreach ($columns as $alias => $col) {
|
||||
$this->requireColumn($col);
|
||||
if ($this->isCustomvar($col)) {
|
||||
$name = $this->getCustomvarColumnName($col);
|
||||
} else {
|
||||
$name = $this->aliasToColumnName($col);
|
||||
}
|
||||
if (is_int($alias)) {
|
||||
$alias = $col;
|
||||
}
|
||||
|
||||
$resolvedColumns[$alias] = preg_replace('|\n|', ' ', $name);
|
||||
}
|
||||
$this->setColumns($resolvedColumns);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return all columns that will be selected when no columns are given in the constructor or from
|
||||
*
|
||||
* @return array An array of column aliases
|
||||
*/
|
||||
public function getDefaultColumns()
|
||||
{
|
||||
reset($this->columnMap);
|
||||
$table = key($this->columnMap);
|
||||
return array_keys($this->columnMap[$table]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Modify the query to the given alias can be used in the result set or queries
|
||||
*
|
||||
* This calls requireVirtualTable if needed
|
||||
*
|
||||
* @param $alias The alias of the column to require
|
||||
*
|
||||
* @return self Fluent interface
|
||||
* @see IdoQuery::requireVirtualTable The method initializing required joins
|
||||
* @throws \Icinga\Exception\ProgrammingError When an unknown column is requested
|
||||
*/
|
||||
public function requireColumn($alias)
|
||||
{
|
||||
if ($this->hasAliasName($alias)) {
|
||||
$this->requireVirtualTable($this->aliasToTableName($alias));
|
||||
} elseif ($this->isCustomVar($alias)) {
|
||||
$this->requireCustomvar($alias);
|
||||
} else {
|
||||
throw new ProgrammingError(sprintf('%s : Got invalid column: %s', get_called_class(), $alias));
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the given alias exists
|
||||
*
|
||||
* @param String $alias The alias to test for
|
||||
* @return bool True when the alias exists, otherwise false
|
||||
*/
|
||||
protected function hasAliasName($alias)
|
||||
{
|
||||
return array_key_exists($alias, $this->idxAliasColumn);
|
||||
}
|
||||
|
||||
/**
|
||||
* Require a virtual table for the given table name if not already required
|
||||
*
|
||||
* @param String $name The table name to require
|
||||
* @return self Fluent interface
|
||||
*/
|
||||
protected function requireVirtualTable($name)
|
||||
{
|
||||
if ($this->hasJoinedVirtualTable($name)) {
|
||||
return $this;
|
||||
}
|
||||
return $this->joinVirtualTable($name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Call the method for joining a virtual table
|
||||
*
|
||||
* This requires a join$Table() method to exist
|
||||
*
|
||||
* @param String $table The table to join by calling join$Table() in the concrete implementation
|
||||
* @return self Fluent interface
|
||||
*
|
||||
* @throws \Icinga\Exception\ProgrammingError If the join method for this table does not exist
|
||||
*/
|
||||
protected function joinVirtualTable($table)
|
||||
{
|
||||
$func = 'join' . ucfirst($table);
|
||||
if (method_exists($this, $func)) {
|
||||
$this->$func();
|
||||
} else {
|
||||
throw new ProgrammingError(
|
||||
sprintf(
|
||||
'Cannot join "%s", no such table found',
|
||||
$table
|
||||
)
|
||||
);
|
||||
}
|
||||
$this->joinedVirtualTables[$table] = true;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the table for a specific alias
|
||||
*
|
||||
* @param String $alias The alias to request the table for
|
||||
* @return String The table for the alias or null if it doesn't exist
|
||||
*/
|
||||
protected function aliasToTableName($alias)
|
||||
{
|
||||
return isset($this->idxAliasTable[$alias]) ? $this->idxAliasTable[$alias] : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the given alias denotes a custom variable
|
||||
*
|
||||
* @param String $alias The alias to test for being a customvariable
|
||||
* @return bool True if the alias is a customvariable, otherwise false
|
||||
*/
|
||||
protected function isCustomVar($alias)
|
||||
{
|
||||
return $this->allowCustomVars && $alias[0] === '_';
|
||||
}
|
||||
|
||||
protected function requireCustomvar($customvar)
|
||||
{
|
||||
if (! $this->hasCustomvar($customvar)) {
|
||||
$this->joinCustomvar($customvar);
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
protected function hasCustomvar($customvar)
|
||||
{
|
||||
return array_key_exists($customvar, $this->customVars);
|
||||
}
|
||||
|
||||
protected function joinCustomvar($customvar)
|
||||
{
|
||||
// TODO: This is not generic enough yet
|
||||
list($type, $name) = $this->customvarNameToTypeName($customvar);
|
||||
$alias = ($type === 'host' ? 'hcv_' : 'scv_') . strtolower($name);
|
||||
|
||||
$this->customVars[$customvar] = $alias;
|
||||
|
||||
// TODO: extend if we allow queries with only hosts / only services
|
||||
// ($leftcol s.host_object_id vs h.host_object_id
|
||||
if ($this->hasJoinedVirtualTable('services')) {
|
||||
$leftcol = 's.' . $type . '_object_id';
|
||||
} else {
|
||||
$leftcol = 'h.' . $type . '_object_id';
|
||||
}
|
||||
$joinOn = $leftcol
|
||||
. ' = '
|
||||
. $alias
|
||||
. '.object_id'
|
||||
. ' AND '
|
||||
. $alias
|
||||
. '.varname = '
|
||||
. $this->db->quote(strtoupper($name));
|
||||
|
||||
$this->baseQuery->joinLeft(
|
||||
array($alias => $this->prefix . 'customvariablestatus'),
|
||||
$joinOn,
|
||||
array()
|
||||
);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
protected function customvarNameToTypeName($customvar)
|
||||
{
|
||||
// TODO: Improve this:
|
||||
if (! preg_match('~^_(host|service)_([a-zA-Z0-9_]+)$~', $customvar, $m)) {
|
||||
throw new ProgrammingError(
|
||||
sprintf(
|
||||
'Got invalid custom var: "%s"',
|
||||
$customvar
|
||||
)
|
||||
);
|
||||
}
|
||||
return array($m[1], $m[2]);
|
||||
}
|
||||
|
||||
protected function hasJoinedVirtualTable($name)
|
||||
{
|
||||
return array_key_exists($name, $this->joinedVirtualTables);
|
||||
}
|
||||
|
||||
protected function getCustomvarColumnName($customvar)
|
||||
{
|
||||
return $this->customVars[$customvar] . '.varvalue';
|
||||
}
|
||||
|
||||
public function aliasToColumnName($alias)
|
||||
{
|
||||
return $this->idxAliasColumn[$alias];
|
||||
}
|
||||
|
||||
protected function createSubQuery($queryName, $columns = array())
|
||||
{
|
||||
$class = '\\'
|
||||
. substr(__CLASS__, 0, strrpos(__CLASS__, '\\') + 1)
|
||||
. ucfirst($queryName) . 'Query';
|
||||
$query = new $class($this->ds, $columns);
|
||||
return $query;
|
||||
}
|
||||
}
|
@ -28,7 +28,7 @@ namespace Icinga\Module\Monitoring\Backend\Ido\Query;
|
||||
/**
|
||||
* Notification query
|
||||
*/
|
||||
class NotificationQuery extends AbstractQuery
|
||||
class NotificationQuery extends IdoQuery
|
||||
{
|
||||
/**
|
||||
* Column map
|
||||
@ -44,7 +44,9 @@ class NotificationQuery extends AbstractQuery
|
||||
),
|
||||
'objects' => array(
|
||||
'host_name' => 'o.name1',
|
||||
'service_description' => 'o.name2'
|
||||
'service_description' => 'o.name2',
|
||||
'service' => 'o.name2',
|
||||
'host_name' => 'o.name1'
|
||||
),
|
||||
'contact' => array(
|
||||
'notification_contact' => 'c_o.name1'
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
namespace Icinga\Module\Monitoring\Backend\Ido\Query;
|
||||
|
||||
class NotificationhistoryQuery extends AbstractQuery
|
||||
class NotificationhistoryQuery extends IdoQuery
|
||||
{
|
||||
protected $columnMap = array(
|
||||
'history' => array(
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
namespace Icinga\Module\Monitoring\Backend\Ido\Query;
|
||||
|
||||
class ServicegroupQuery extends AbstractQuery
|
||||
class ServicegroupQuery extends IdoQuery
|
||||
{
|
||||
protected $columnMap = array(
|
||||
'servicegroups' => array(
|
||||
@ -10,7 +10,9 @@ class ServicegroupQuery extends AbstractQuery
|
||||
'servicegroup_alias' => 'sg.alias',
|
||||
),
|
||||
'services' => array(
|
||||
'host' => 'so.name1 COLLATE latin1_general_ci',
|
||||
'host_name' => 'so.name1 COLLATE latin1_general_ci',
|
||||
'service' => 'so.name2 COLLATE latin1_general_ci',
|
||||
'service_host_name' => 'so.name1 COLLATE latin1_general_ci',
|
||||
'service_description' => 'so.name2 COLLATE latin1_general_ci'
|
||||
)
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
namespace Icinga\Module\Monitoring\Backend\Ido\Query;
|
||||
|
||||
class ServicestatusQuery extends AbstractQuery
|
||||
class ServicestatusQuery extends IdoQuery
|
||||
{
|
||||
protected $allowCustomVars = true;
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
namespace Icinga\Module\Monitoring\Backend\Ido\Query;
|
||||
|
||||
class StatehistoryQuery extends AbstractQuery
|
||||
class StatehistoryQuery extends IdoQuery
|
||||
{
|
||||
protected $columnMap = array(
|
||||
'statehistory' => array(
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
namespace Icinga\Module\Monitoring\Backend\Ido\Query;
|
||||
|
||||
class StatusQuery extends AbstractQuery
|
||||
class StatusQuery extends IdoQuery
|
||||
{
|
||||
protected $allowCustomVars = true;
|
||||
|
||||
@ -29,8 +29,6 @@ class StatusQuery extends AbstractQuery
|
||||
'host_acknowledged' => 'hs.problem_has_been_acknowledged',
|
||||
'host_in_downtime' => 'CASE WHEN (hs.scheduled_downtime_depth = 0) THEN 0 ELSE 1 END',
|
||||
'host_handled' => 'CASE WHEN (hs.problem_has_been_acknowledged + hs.scheduled_downtime_depth) > 0 THEN 1 ELSE 0 END',
|
||||
'host_does_active_checks' => 'hs.active_checks_enabled',
|
||||
'host_accepts_passive_checks' => 'hs.passive_checks_enabled',
|
||||
'host_last_state_change' => 'UNIX_TIMESTAMP(hs.last_state_change)',
|
||||
'host_last_hard_state' => 'hs.last_hard_state',
|
||||
'host_last_hard_state_change' => 'UNIX_TIMESTAMP(hs.last_hard_state_change)',
|
||||
@ -130,8 +128,6 @@ class StatusQuery extends AbstractQuery
|
||||
'service_acknowledged' => 'ss.problem_has_been_acknowledged',
|
||||
'service_in_downtime' => 'CASE WHEN (ss.scheduled_downtime_depth = 0) THEN 0 ELSE 1 END',
|
||||
'service_handled' => 'CASE WHEN (ss.problem_has_been_acknowledged + ss.scheduled_downtime_depth + COALESCE(hs.current_state, 0)) > 0 THEN 1 ELSE 0 END',
|
||||
'service_does_active_checks' => 'ss.active_checks_enabled',
|
||||
'service_accepts_passive_checks' => 'ss.passive_checks_enabled',
|
||||
'service_last_state_change' => 'UNIX_TIMESTAMP(ss.last_state_change)',
|
||||
'service_check_command' => 'ss.check_command',
|
||||
'service_last_time_ok' => 'ss.last_time_ok',
|
||||
|
@ -2,9 +2,9 @@
|
||||
|
||||
namespace \Icinga\Module\Monitoring\Backend\Livestatus\Query;
|
||||
|
||||
use Icinga\Data\AbstractQuery;
|
||||
use Icinga\Data\BaseQuery;
|
||||
|
||||
class StatusQuery extends AbstractQuery implements Filterable
|
||||
class StatusQuery extends BaseQuery implements Filterable
|
||||
{
|
||||
protected $available_columns = array(
|
||||
'host_name',
|
||||
|
@ -64,7 +64,7 @@ abstract class GroupsummaryQuery extends Query
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $order_columns = array(
|
||||
protected $orderColumns = array(
|
||||
'state' => array(
|
||||
'ASC' => array(
|
||||
'ok ASC',
|
||||
|
@ -31,7 +31,7 @@ namespace Icinga\Module\Monitoring\Backend\Statusdat\Query;
|
||||
use Icinga\Filter\Query\Tree;
|
||||
use Icinga\Protocol\Statusdat;
|
||||
use Icinga\Exception;
|
||||
use Icinga\Data\AbstractQuery;
|
||||
use Icinga\Data\BaseQuery;
|
||||
use Icinga\Protocol\Statusdat\View\MonitoringObjectList as MList;
|
||||
use Icinga\Protocol\Statusdat\Query as StatusdatQuery;
|
||||
use Icinga\Filter\Filterable;
|
||||
@ -40,7 +40,7 @@ use Icinga\Filter\Filterable;
|
||||
* Class Query
|
||||
* @package Icinga\Backend\Statusdat
|
||||
*/
|
||||
abstract class Query extends AbstractQuery implements Filterable
|
||||
abstract class Query extends BaseQuery implements Filterable
|
||||
{
|
||||
/**
|
||||
* @var null
|
||||
|
@ -51,7 +51,9 @@ class Comment extends DataView
|
||||
'comment_is_persistent',
|
||||
'comment_expiration_timestamp',
|
||||
'host_name',
|
||||
'service_name'
|
||||
'service_name',
|
||||
'host',
|
||||
'service'
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -40,7 +40,9 @@ class Contact extends DataView
|
||||
'host_name',
|
||||
'service_object_id',
|
||||
'service_host_name',
|
||||
'service_description'
|
||||
'service_description',
|
||||
'service',
|
||||
'host',
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -18,7 +18,9 @@ class Contactgroup extends DataView
|
||||
return array(
|
||||
'contact_name',
|
||||
'contactgroup_name',
|
||||
'contactgroup_alias'
|
||||
'contactgroup_alias',
|
||||
'host',
|
||||
'service'
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
namespace Icinga\Module\Monitoring\DataView;
|
||||
|
||||
use Icinga\Data\AbstractQuery;
|
||||
use Icinga\Data\BaseQuery;
|
||||
use Icinga\Filter\Filterable;
|
||||
use Icinga\Filter\Query\Tree;
|
||||
use Icinga\Module\Monitoring\Backend;
|
||||
@ -19,15 +19,15 @@ abstract class DataView implements Filterable
|
||||
/**
|
||||
* Sort in ascending order, default
|
||||
*/
|
||||
const SORT_ASC = AbstractQuery::SORT_ASC;
|
||||
const SORT_ASC = BaseQuery::SORT_ASC;
|
||||
/**
|
||||
* Sort in reverse order
|
||||
*/
|
||||
const SORT_DESC = AbstractQuery::SORT_DESC;
|
||||
const SORT_DESC = BaseQuery::SORT_DESC;
|
||||
/**
|
||||
* The query used to populate the view
|
||||
*
|
||||
* @var AbstractQuery
|
||||
* @var BaseQuery
|
||||
*/
|
||||
private $query;
|
||||
|
||||
@ -39,9 +39,7 @@ abstract class DataView implements Filterable
|
||||
*/
|
||||
public function __construct(Backend $ds, array $columns = null)
|
||||
{
|
||||
$filter = new UrlViewFilter($this);
|
||||
$this->query = $ds->select()->from(static::getTableName(), $columns === null ? $this->getColumns() : $columns);
|
||||
$this->applyFilter($filter->parseUrl());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -63,11 +61,6 @@ abstract class DataView implements Filterable
|
||||
*/
|
||||
abstract public function getColumns();
|
||||
|
||||
public function applyFilter(Tree $filter)
|
||||
{
|
||||
return $this->query->applyFilter($filter);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create view from request
|
||||
*
|
||||
@ -78,8 +71,11 @@ abstract class DataView implements Filterable
|
||||
*/
|
||||
public static function fromRequest($request, array $columns = null)
|
||||
{
|
||||
|
||||
$view = new static(Backend::createBackend($request->getParam('backend')), $columns);
|
||||
$view->filter($request->getParams());
|
||||
$parser = new UrlViewFilter($view);
|
||||
$view->getQuery()->setFilter($parser->parseUrl());
|
||||
|
||||
$order = $request->getParam('dir');
|
||||
if ($order !== null) {
|
||||
if (strtolower($order) === 'desc') {
|
||||
@ -106,7 +102,9 @@ abstract class DataView implements Filterable
|
||||
public static function fromParams(array $params, array $columns = null)
|
||||
{
|
||||
$view = new static(Backend::createBackend($params['backend']), $columns);
|
||||
$view->filter($params);
|
||||
foreach ($params as $key => $value) {
|
||||
$view->getQuery()->where($key, $value);
|
||||
}
|
||||
$order = isset($params['order']) ? $params['order'] : null;
|
||||
if ($order !== null) {
|
||||
if (strtolower($order) === 'desc') {
|
||||
@ -115,6 +113,7 @@ abstract class DataView implements Filterable
|
||||
$order = self::SORT_ASC;
|
||||
}
|
||||
}
|
||||
|
||||
$view->sort(
|
||||
isset($params['sort']) ? $params['sort'] : null,
|
||||
$order
|
||||
@ -122,22 +121,6 @@ abstract class DataView implements Filterable
|
||||
return $view;
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter rows that match all of the given filters. If a filter is not valid, it's silently ignored
|
||||
*
|
||||
* @param array $filters
|
||||
*
|
||||
* @see Filterable::isValidFilterTarget()
|
||||
*/
|
||||
public function filter(array $filters)
|
||||
{
|
||||
foreach ($filters as $column => $filter) {
|
||||
if ($this->isValidFilterTarget($column)) {
|
||||
$this->query->where($column, $filter);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether the given column is a valid filter column, i.e. the view actually provides the column or it's
|
||||
* a non-queryable filter column
|
||||
@ -186,10 +169,14 @@ abstract class DataView implements Filterable
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
$order = $order === null ? (isset($sortColumns['order']) ? $sortColumns['order'] : self::SORT_ASC) : $order;
|
||||
$order = ($order === self::SORT_ASC) ? 'ASC' : 'DESC';
|
||||
|
||||
foreach ($sortColumns['columns'] as $column) {
|
||||
$this->query->order($column, $order);
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -214,8 +201,21 @@ abstract class DataView implements Filterable
|
||||
return $this->query;
|
||||
}
|
||||
|
||||
public function getFilterDomain()
|
||||
public function applyFilter()
|
||||
{
|
||||
return null;
|
||||
$this->query->applyFilter();
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function clearFilter()
|
||||
{
|
||||
$this->query->clearFilter();
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function addFilter($filter)
|
||||
{
|
||||
$this->query->addFilter($filter);
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,29 @@
|
||||
<?php
|
||||
// {{{ICINGA_LICENSE_HEADER}}}
|
||||
/**
|
||||
* This file is part of Icinga 2 Web.
|
||||
*
|
||||
* Icinga 2 Web - Head for multiple monitoring backends.
|
||||
* Copyright (C) 2013 Icinga Development Team
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* @copyright 2013 Icinga Development Team <info@icinga.org>
|
||||
* @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2
|
||||
* @author Icinga Development Team <info@icinga.org>
|
||||
*/
|
||||
// {{{ICINGA_LICENSE_HEADER}}}
|
||||
|
||||
namespace Icinga\Module\Monitoring\DataView;
|
||||
@ -14,11 +38,16 @@ class EventHistory extends DataView
|
||||
public function getColumns()
|
||||
{
|
||||
return array(
|
||||
'raw_timestamp',
|
||||
'timestamp',
|
||||
'host',
|
||||
'service',
|
||||
'cnt_notification',
|
||||
'cnt_hard_state',
|
||||
'cnt_soft_state',
|
||||
'cnt_downtime_start',
|
||||
'cnt_downtime_end',
|
||||
'host_name',
|
||||
'service_description',
|
||||
'object_type',
|
||||
'timestamp',
|
||||
'raw_timestamp',
|
||||
'state',
|
||||
'attempt',
|
||||
'max_attempts',
|
||||
@ -46,3 +75,34 @@ class EventHistory extends DataView
|
||||
);
|
||||
}
|
||||
}
|
||||
=======
|
||||
'type',
|
||||
'host',
|
||||
'service'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the table name
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function getTableName()
|
||||
{
|
||||
return 'eventhistory';
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve default sorting rules for particular columns. These involve sort order and potential additional to sort
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getSortRules()
|
||||
{
|
||||
return array(
|
||||
'raw_timestamp' => array(
|
||||
'order' => self::SORT_DESC
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -16,48 +16,60 @@ class HostStatus extends DataView
|
||||
public function getColumns()
|
||||
{
|
||||
return array(
|
||||
'host',
|
||||
'host_name',
|
||||
'host_alias',
|
||||
'host_address',
|
||||
'host_state',
|
||||
'host_state_type',
|
||||
'host_last_state_change',
|
||||
'host_address',
|
||||
'host_handled',
|
||||
'host_icon_image',
|
||||
'host_acknowledged',
|
||||
'host_output',
|
||||
'host_long_output',
|
||||
'host_in_downtime',
|
||||
'host_is_flapping',
|
||||
'host_acknowledged',
|
||||
'host_last_state_change',
|
||||
'host_last_state_change',
|
||||
'host_last_notification',
|
||||
'host_last_check',
|
||||
'host_next_check',
|
||||
'host_check_execution_time',
|
||||
'host_check_latency',
|
||||
'host_output',
|
||||
'host_long_output',
|
||||
'host_check_command',
|
||||
'host_perfdata',
|
||||
'host_passive_checks_enabled',
|
||||
'host_obsessing',
|
||||
'host_notifications_enabled',
|
||||
'host_unhandled_service_count',
|
||||
'host_event_handler_enabled',
|
||||
'host_flap_detection_enabled',
|
||||
'host_active_checks_enabled',
|
||||
'host_current_check_attempt',
|
||||
'host_max_check_attempts',
|
||||
'host_last_notification',
|
||||
'host_current_notification_number',
|
||||
'host_percent_state_change',
|
||||
'host_is_flapping',
|
||||
'host_last_comment',
|
||||
'host_action_url',
|
||||
'host_notes_url',
|
||||
'host_last_comment',
|
||||
'host',
|
||||
'host_display_name',
|
||||
'host_alias',
|
||||
'host_ipv4',
|
||||
'host_severity',
|
||||
'host_perfdata',
|
||||
'host_does_active_checks',
|
||||
'host_accepts_passive_checks',
|
||||
'host_last_hard_state',
|
||||
'host_last_hard_state_change',
|
||||
'host_last_time_up',
|
||||
'host_last_time_down',
|
||||
'host_last_time_unreachable'
|
||||
'host_percent_state_change'
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Return the table name
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function getTableName()
|
||||
{
|
||||
return 'status';
|
||||
}
|
||||
|
||||
/**
|
||||
* The sort rules for this query
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getSortRules()
|
||||
{
|
||||
return array(
|
||||
|
75
modules/monitoring/library/Monitoring/DataView/Hostgroup.php
Normal file
75
modules/monitoring/library/Monitoring/DataView/Hostgroup.php
Normal file
@ -0,0 +1,75 @@
|
||||
<?php
|
||||
// {{{ICINGA_LICENSE_HEADER}}}
|
||||
/**
|
||||
* This file is part of Icinga 2 Web.
|
||||
*
|
||||
* Icinga 2 Web - Head for multiple monitoring backends.
|
||||
* Copyright (C) 2013 Icinga Development Team
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* @copyright 2013 Icinga Development Team <info@icinga.org>
|
||||
* @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2
|
||||
* @author Icinga Development Team <info@icinga.org>
|
||||
*/
|
||||
// {{{ICINGA_LICENSE_HEADER}}}
|
||||
|
||||
|
||||
namespace Icinga\Module\Monitoring\DataView;
|
||||
|
||||
/**
|
||||
* View for hostgroups
|
||||
*/
|
||||
class Hostgroup extends DataView
|
||||
{
|
||||
/**
|
||||
* Retrieve columns provided by this view
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getColumns()
|
||||
{
|
||||
return array(
|
||||
'host',
|
||||
'hostgroup_name',
|
||||
'hostgroup_alias'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the table name for this view
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function getTableName()
|
||||
{
|
||||
return 'hostgroup';
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve default sorting rules for particular columns. These involve sort order and potential additional to sort
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getSortRules()
|
||||
{
|
||||
return array(
|
||||
'hostgroup_name' => array(
|
||||
'order' => self::SORT_ASC
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
}
|
@ -21,7 +21,9 @@ class Notification extends DataView
|
||||
'notification_start_time',
|
||||
'notification_contact',
|
||||
'notification_information',
|
||||
'notification_command'
|
||||
'notification_command',
|
||||
'host',
|
||||
'service'
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -38,6 +38,10 @@ class ServiceStatus extends DataView
|
||||
'service_action_url',
|
||||
'service_notes_url',
|
||||
'service_last_comment',
|
||||
'service_last_check',
|
||||
'service_next_check',
|
||||
'service_last_notification',
|
||||
'service_check_command',
|
||||
'host_icon_image',
|
||||
'host_acknowledged',
|
||||
'host_output',
|
||||
@ -56,8 +60,8 @@ class ServiceStatus extends DataView
|
||||
'host_ipv4',
|
||||
'host_severity',
|
||||
'host_perfdata',
|
||||
'host_does_active_checks',
|
||||
'host_accepts_passive_checks',
|
||||
'host_active_checks_enabled',
|
||||
'host_passive_checks_enabled',
|
||||
'host_last_hard_state',
|
||||
'host_last_hard_state_change',
|
||||
'host_last_time_up',
|
||||
@ -66,8 +70,8 @@ class ServiceStatus extends DataView
|
||||
'service',
|
||||
'service_hard_state',
|
||||
'service_perfdata',
|
||||
'service_does_active_checks',
|
||||
'service_accepts_passive_checks',
|
||||
'service_active_checks_enabled',
|
||||
'service_passive_checks_enabled',
|
||||
'service_last_hard_state',
|
||||
'service_last_hard_state_change',
|
||||
'service_last_time_ok',
|
||||
|
@ -0,0 +1,70 @@
|
||||
<?php
|
||||
// {{{ICINGA_LICENSE_HEADER}}}
|
||||
/**
|
||||
* This file is part of Icinga 2 Web.
|
||||
*
|
||||
* Icinga 2 Web - Head for multiple monitoring backends.
|
||||
* Copyright (C) 2013 Icinga Development Team
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* @copyright 2013 Icinga Development Team <info@icinga.org>
|
||||
* @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2
|
||||
* @author Icinga Development Team <info@icinga.org>
|
||||
*/
|
||||
// {{{ICINGA_LICENSE_HEADER}}}
|
||||
|
||||
|
||||
namespace Icinga\Module\Monitoring\DataView;
|
||||
|
||||
|
||||
class Servicegroup extends DataView
|
||||
{
|
||||
/**
|
||||
* Retrieve columns provided by this view
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getColumns()
|
||||
{
|
||||
return array(
|
||||
'service',
|
||||
'host',
|
||||
'servicegroup_name',
|
||||
'servicegroup_alias'
|
||||
);
|
||||
}
|
||||
|
||||
public static function getTableName()
|
||||
{
|
||||
return 'servicegroup';
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve default sorting rules for particular columns. These involve sort order and potential additional to sort
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getSortRules()
|
||||
{
|
||||
return array(
|
||||
'servicegroup_name' => array(
|
||||
'order' => self::SORT_ASC
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -1,244 +1,187 @@
|
||||
<?php
|
||||
// {{{ICINGA_LICENSE_HEADER}}}
|
||||
/**
|
||||
* This file is part of Icinga 2 Web.
|
||||
*
|
||||
* Icinga 2 Web - Head for multiple monitoring backends.
|
||||
* Copyright (C) 2013 Icinga Development Team
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
*
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* @copyright 2013 Icinga Development Team <info@icinga.org>
|
||||
* @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2
|
||||
* @author Icinga Development Team <info@icinga.org>
|
||||
*/
|
||||
// {{{ICINGA_LICENSE_HEADER}}}
|
||||
|
||||
namespace Icinga\Module\Monitoring\Object;
|
||||
|
||||
use Icinga\Data\AbstractQuery as Query;
|
||||
use Icinga\Data\BaseQuery as Query;
|
||||
use \Icinga\Module\Monitoring\Backend;
|
||||
use Icinga\Module\Monitoring\DataView\Contact;
|
||||
use Icinga\Module\Monitoring\DataView\Contactgroup;
|
||||
use Icinga\Module\Monitoring\DataView\Downtime;
|
||||
use Icinga\Module\Monitoring\DataView\EventHistory;
|
||||
use Icinga\Module\Monitoring\DataView\Hostgroup;
|
||||
use Icinga\Module\Monitoring\DataView\HostStatus;
|
||||
use Icinga\Module\Monitoring\DataView\Comment;
|
||||
use Icinga\Module\Monitoring\DataView\Servicegroup;
|
||||
use Icinga\Module\Monitoring\DataView\ServiceStatus;
|
||||
use Icinga\Web\Request;
|
||||
|
||||
/**
|
||||
* Generic icinga object with belongings
|
||||
*/
|
||||
abstract class AbstractObject
|
||||
{
|
||||
protected $backend;
|
||||
const TYPE_HOST = 1;
|
||||
const TYPE_SERVICE = 2;
|
||||
|
||||
protected $type;
|
||||
public $type = self::TYPE_HOST;
|
||||
public $prefix = 'host_';
|
||||
|
||||
protected $name1;
|
||||
public $comments = array();
|
||||
public $downtimes = array();
|
||||
public $hostgroups = array();
|
||||
public $servicegroups = array();
|
||||
public $contacts = array();
|
||||
public $contactgroups = array();
|
||||
public $customvars = array();
|
||||
public $events = array();
|
||||
|
||||
protected $name2;
|
||||
private $request = null;
|
||||
|
||||
protected $properties;
|
||||
|
||||
protected $foreign = array();
|
||||
|
||||
public function __construct(Backend $backend, $name1, $name2 = null)
|
||||
public function __construct(Request $request)
|
||||
{
|
||||
$this->backend = $backend;
|
||||
$this->name1 = $name1;
|
||||
$this->name2 = $name2;
|
||||
|
||||
if ($name1 && $name2) {
|
||||
$this->type = 2;
|
||||
} elseif ($name1 && !$name2) {
|
||||
$this->type = 1;
|
||||
}
|
||||
|
||||
$this->properties = (array) $this->fetchObject();
|
||||
}
|
||||
|
||||
public static function fetch(Backend $backend, $name1, $name2 = null)
|
||||
{
|
||||
return new static($backend, $name1, $name2);
|
||||
}
|
||||
|
||||
abstract protected function fetchObject();
|
||||
|
||||
public function __isset($key)
|
||||
{
|
||||
return $this->$key !== null;
|
||||
}
|
||||
|
||||
public function __get($key)
|
||||
{
|
||||
if (isset($this->properties[$key])) {
|
||||
return $this->properties[$key];
|
||||
}
|
||||
if (array_key_exists($key, $this->foreign)) {
|
||||
if ($this->foreign[$key] === null) {
|
||||
$func = 'fetch' . ucfirst($key);
|
||||
if (! method_exists($this, $func)) {
|
||||
return null;
|
||||
}
|
||||
$this->$func($key);
|
||||
$this->request = $request;
|
||||
$properties = $this->getProperties();
|
||||
if ($properties) {
|
||||
foreach ($properties as $key => $value) {
|
||||
$this->$key = $value;
|
||||
}
|
||||
return $this->foreign[$key];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public function prefetch()
|
||||
{
|
||||
return $this;
|
||||
}
|
||||
abstract protected function getProperties();
|
||||
|
||||
abstract protected function applyObjectFilter(Query $query);
|
||||
|
||||
protected function fetchHostgroups()
|
||||
public function fetchComments()
|
||||
{
|
||||
$this->foreign['hostgroups'] = $this->applyObjectFilter(
|
||||
$this->backend->select()->from(
|
||||
'hostgroup',
|
||||
array(
|
||||
'hostgroup_name',
|
||||
'hostgroup_alias'
|
||||
)
|
||||
$this->comments = Comment::fromRequest(
|
||||
$this->request,
|
||||
array(
|
||||
'comment_timestamp',
|
||||
'comment_author',
|
||||
'comment_data',
|
||||
'comment_type',
|
||||
)
|
||||
)->fetchPairs();
|
||||
)->getQuery()
|
||||
->where('comment_objecttype_id', 1)
|
||||
->fetchAll();
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
protected function fetchServicegroups()
|
||||
public function fetchDowntimes()
|
||||
{
|
||||
$this->foreign['servicegroups'] = $this->applyObjectFilter(
|
||||
$this->backend->select()->from(
|
||||
'servicegroup',
|
||||
array(
|
||||
'servicegroup_name',
|
||||
'servicegroup_alias'
|
||||
)
|
||||
$this->downtimes = Downtime::fromRequest(
|
||||
$this->request,
|
||||
array(
|
||||
'downtime_type',
|
||||
'downtime_author_name',
|
||||
'downtime_comment_data',
|
||||
'downtime_is_fixed',
|
||||
'downtime_duration',
|
||||
'downtime_entry_time',
|
||||
'downtime_scheduled_start_time',
|
||||
'downtime_scheduled_end_time',
|
||||
'downtime_was_started',
|
||||
'downtime_actual_start_time',
|
||||
'downtime_is_in_effect',
|
||||
'downtime_triggered_by_id',
|
||||
)
|
||||
)->fetchPairs();
|
||||
)->getQuery()->fetchAll();
|
||||
return $this;
|
||||
}
|
||||
|
||||
protected function fetchContacts()
|
||||
public function fetchHostgroups()
|
||||
{
|
||||
$this->foreign['contacts'] = $this->applyObjectFilter(
|
||||
$this->backend->select()->from(
|
||||
'contact',
|
||||
array(
|
||||
'contact_name',
|
||||
'contact_alias',
|
||||
'contact_email',
|
||||
'contact_pager',
|
||||
)
|
||||
$this->hostgroups = Hostgroup::fromRequest(
|
||||
$this->request,
|
||||
array(
|
||||
'hostgroup_name',
|
||||
'hostgroup_alias'
|
||||
)
|
||||
)->fetchAll();
|
||||
)->getQuery()->fetchPairs();
|
||||
return $this;
|
||||
}
|
||||
|
||||
protected function fetchContactgroups()
|
||||
public function fetchContacts()
|
||||
{
|
||||
$this->foreign['contactgroups'] = $this->applyObjectFilter(
|
||||
$this->backend->select()->from(
|
||||
'contactgroup',
|
||||
array(
|
||||
'contactgroup_name',
|
||||
'contactgroup_alias',
|
||||
)
|
||||
$this->contacts = Contact::fromRequest(
|
||||
$this->request,
|
||||
array(
|
||||
'contact_name',
|
||||
'contact_alias',
|
||||
'contact_email',
|
||||
'contact_pager',
|
||||
)
|
||||
)->fetchAll();
|
||||
)->getQuery()
|
||||
->where('host_name', $this->host_name)
|
||||
->fetchAll();
|
||||
return $this;
|
||||
}
|
||||
|
||||
protected function fetchComments()
|
||||
public function fetchServicegroups()
|
||||
{
|
||||
$this->foreign['comments'] = $this->applyObjectFilter(
|
||||
$this->backend->select()->from(
|
||||
'comment',
|
||||
array(
|
||||
'comment_timestamp',
|
||||
'comment_author',
|
||||
'comment_data',
|
||||
'comment_type',
|
||||
'comment_internal_id'
|
||||
)
|
||||
)->where('comment_objecttype_id', $this->type)
|
||||
)->fetchAll();
|
||||
$this->servicegroups = Servicegroup::fromRequest(
|
||||
$this->request,
|
||||
array(
|
||||
'servicegroup_name',
|
||||
'servicegroup_alias',
|
||||
)
|
||||
)->getQuery()->fetchPairs();
|
||||
return $this;
|
||||
}
|
||||
|
||||
protected function fetchCustomvars()
|
||||
public function fetchContactgroups()
|
||||
{
|
||||
$this->foreign['customvars'] = $this->applyObjectFilter(
|
||||
$this->backend->select()->from(
|
||||
'customvar',
|
||||
array(
|
||||
'varname',
|
||||
'varvalue'
|
||||
)
|
||||
)->where('varname', '-*PW*,-*PASS*,-*COMMUNITY*')
|
||||
)->fetchPairs();
|
||||
$this->contactgroups = Contactgroup::fromRequest(
|
||||
$this->request,
|
||||
array(
|
||||
'contactgroup_name',
|
||||
'contactgroup_alias'
|
||||
)
|
||||
)->getQuery()->fetchAll();
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function fetchEventHistory()
|
||||
{
|
||||
$this->foreign['eventHistory'] = $this->applyObjectFilter(
|
||||
$this->backend->select()->from(
|
||||
'eventHistory',
|
||||
array(
|
||||
'object_type',
|
||||
'host_name',
|
||||
'service_description',
|
||||
'timestamp',
|
||||
'state',
|
||||
'attempt',
|
||||
'max_attempts',
|
||||
'output',
|
||||
'type'
|
||||
)
|
||||
$this->eventhistory = EventHistory::fromRequest(
|
||||
$this->request,
|
||||
array(
|
||||
'object_type',
|
||||
'host_name',
|
||||
'service_description',
|
||||
'timestamp',
|
||||
'raw_timestamp',
|
||||
'state',
|
||||
'attempt',
|
||||
'max_attempts',
|
||||
'output',
|
||||
'type'
|
||||
)
|
||||
);
|
||||
)->sort('timestamp', 'DESC')->getQuery();
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function fetchDowtimes()
|
||||
public function __get($param)
|
||||
{
|
||||
$this->foreign['downtimes'] = $this->applyObjectFilter(
|
||||
$this->backend->select()->from(
|
||||
'downtime',
|
||||
array(
|
||||
'host_name',
|
||||
'object_type',
|
||||
'service_host_name',
|
||||
'service_description',
|
||||
'downtime_type',
|
||||
'downtime_author_name',
|
||||
'downtime_comment_data',
|
||||
'downtime_is_fixed',
|
||||
'downtime_duration',
|
||||
'downtime_entry_time',
|
||||
'downtime_scheduled_start_time',
|
||||
'downtime_scheduled_end_time',
|
||||
'downtime_was_started',
|
||||
'downtime_actual_start_time',
|
||||
'downtime_actual_start_time_usec',
|
||||
'downtime_is_in_effect',
|
||||
'downtime_trigger_time',
|
||||
'downtime_triggered_by_id',
|
||||
'downtime_internal_downtime_id'
|
||||
)
|
||||
)
|
||||
)->fetchAll(9);
|
||||
return $this;
|
||||
if (substr($param, 0, strlen($this->prefix)) === $this->prefix) {
|
||||
return false;
|
||||
}
|
||||
$expandedName = $this->prefix . strtolower($param);
|
||||
return $this->$expandedName;
|
||||
}
|
||||
|
||||
public function getRequest()
|
||||
{
|
||||
return $this->request;
|
||||
}
|
||||
|
||||
abstract public function populate();
|
||||
|
||||
|
||||
public static function fromRequest(Request $request)
|
||||
{
|
||||
if ($request->has('service') && $request->has('host')) {
|
||||
return new Service($request);
|
||||
} else if ($request->has('host')) {
|
||||
return new Host($request);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,133 +1,31 @@
|
||||
<?php
|
||||
// {{{ICINGA_LICENSE_HEADER}}}
|
||||
/**
|
||||
* This file is part of Icinga 2 Web.
|
||||
*
|
||||
* Icinga 2 Web - Head for multiple monitoring backends.
|
||||
* Copyright (C) 2013 Icinga Development Team
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
*
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* @copyright 2013 Icinga Development Team <info@icinga.org>
|
||||
* @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2
|
||||
* @author Icinga Development Team <info@icinga.org>
|
||||
*/
|
||||
// {{{ICINGA_LICENSE_HEADER}}}
|
||||
|
||||
namespace Icinga\Module\Monitoring\Object;
|
||||
|
||||
use Icinga\Data\AbstractQuery as Query;
|
||||
use Icinga\Data\BaseQuery as Query;
|
||||
use Icinga\Module\Monitoring\DataView\HostStatus;
|
||||
|
||||
/**
|
||||
* Represent a host object
|
||||
*/
|
||||
class Host extends AbstractObject
|
||||
{
|
||||
protected $foreign = array(
|
||||
'hostgroups' => null,
|
||||
'contacts' => null,
|
||||
'contactgroups' => null,
|
||||
'customvars' => null,
|
||||
'comments' => null,
|
||||
'downtimes' => null,
|
||||
'customvars' => null
|
||||
);
|
||||
|
||||
/**
|
||||
* Statename
|
||||
*/
|
||||
public function stateName()
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
public $type = self::TYPE_HOST;
|
||||
public $prefix = 'host_';
|
||||
private $view = null;
|
||||
|
||||
/**
|
||||
* Filter object belongings
|
||||
*
|
||||
* @param Query $query
|
||||
*
|
||||
* @return Query
|
||||
*/
|
||||
protected function applyObjectFilter(Query $query)
|
||||
{
|
||||
return $query->where('host_name', $this->name1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Load foreign object data
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function prefetch()
|
||||
public function populate()
|
||||
{
|
||||
return $this->fetchHostgroups()
|
||||
$this->fetchComments()
|
||||
->fetchDowntimes()
|
||||
->fetchHostgroups()
|
||||
->fetchContacts()
|
||||
->fetchContactgroups()
|
||||
->fetchCustomvars()
|
||||
->fetchComments()
|
||||
->fetchDowtimes()
|
||||
->fetchCustomvars();
|
||||
->fetchContactGroups();
|
||||
}
|
||||
|
||||
/**
|
||||
* Load object data
|
||||
* @return object
|
||||
*/
|
||||
protected function fetchObject()
|
||||
protected function getProperties()
|
||||
{
|
||||
return $this->backend->select()->from(
|
||||
'status',
|
||||
array(
|
||||
'host_name',
|
||||
'host_alias',
|
||||
'host_address',
|
||||
'host_state',
|
||||
'host_handled',
|
||||
'host_in_downtime',
|
||||
'in_downtime' => 'host_in_downtime',
|
||||
'host_acknowledged',
|
||||
'host_last_state_change',
|
||||
'last_state_change' => 'host_last_state_change',
|
||||
'last_notification' => 'host_last_notification',
|
||||
'last_check' => 'host_last_check',
|
||||
'next_check' => 'host_next_check',
|
||||
'check_execution_time' => 'host_check_execution_time',
|
||||
'check_latency' => 'host_check_latency',
|
||||
'output' => 'host_output',
|
||||
'long_output' => 'host_long_output',
|
||||
'check_command' => 'host_check_command',
|
||||
'perfdata' => 'host_perfdata',
|
||||
'host_icon_image',
|
||||
'passive_checks_enabled' => 'host_passive_checks_enabled',
|
||||
'obsessing' => 'host_obsessing',
|
||||
'notifications_enabled' => 'host_notifications_enabled',
|
||||
'event_handler_enabled' => 'host_event_handler_enabled',
|
||||
'flap_detection_enabled' => 'host_flap_detection_enabled',
|
||||
'active_checks_enabled' => 'host_active_checks_enabled',
|
||||
'current_check_attempt' => 'host_current_check_attempt',
|
||||
'max_check_attempts' => 'host_max_check_attempts',
|
||||
'last_notification' => 'host_last_notification',
|
||||
'current_notification_number' => 'host_current_notification_number',
|
||||
'percent_state_change' => 'host_percent_state_change',
|
||||
'is_flapping' => 'host_is_flapping',
|
||||
'last_comment' => 'host_last_comment',
|
||||
'action_url' => 'host_action_url',
|
||||
'notes_url' => 'host_notes_url',
|
||||
'percent_state_change' => 'host_percent_state_change'
|
||||
)
|
||||
)->where('host_name', $this->name1)->fetchRow();
|
||||
$this->view = HostStatus::fromRequest($this->getRequest());
|
||||
return $this->view->getQuery()->fetchRow();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,148 +1,30 @@
|
||||
<?php
|
||||
// {{{ICINGA_LICENSE_HEADER}}}
|
||||
/**
|
||||
* This file is part of Icinga 2 Web.
|
||||
*
|
||||
* Icinga 2 Web - Head for multiple monitoring backends.
|
||||
* Copyright (C) 2013 Icinga Development Team
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
*
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* @copyright 2013 Icinga Development Team <info@icinga.org>
|
||||
* @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2
|
||||
* @author Icinga Development Team <info@icinga.org>
|
||||
*/
|
||||
// {{{ICINGA_LICENSE_HEADER}}}
|
||||
|
||||
namespace Icinga\Module\Monitoring\Object;
|
||||
|
||||
use Icinga\Data\AbstractQuery as Query;
|
||||
use Icinga\Data\BaseQuery as Query;
|
||||
use Icinga\Module\Monitoring\DataView\ServiceStatus;
|
||||
|
||||
/**
|
||||
* Represent a single service
|
||||
*/
|
||||
class Service extends AbstractObject
|
||||
{
|
||||
/**
|
||||
* Foreign references to objects
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $foreign = array(
|
||||
'servicegroups' => null,
|
||||
'contacts' => null,
|
||||
'contactgroups' => null,
|
||||
'customvars' => null,
|
||||
'comments' => null,
|
||||
'downtimes' => null,
|
||||
'customvars' => null
|
||||
);
|
||||
|
||||
/**
|
||||
* Statename
|
||||
*/
|
||||
public function stateName()
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
public $type = self::TYPE_SERVICE;
|
||||
public $prefix = 'service_';
|
||||
private $view = null;
|
||||
|
||||
/**
|
||||
* Filter foreign object belongings
|
||||
*
|
||||
* @param Query $query
|
||||
*
|
||||
* @return Query
|
||||
*/
|
||||
protected function applyObjectFilter(Query $query)
|
||||
public function populate()
|
||||
{
|
||||
return $query->where('service_host_name', $this->name1)
|
||||
->where('service_description', $this->name2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Collect foreign data
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function prefetch()
|
||||
{
|
||||
return $this->fetchServicegroups()
|
||||
$this->fetchComments()
|
||||
->fetchDowntimes()
|
||||
->fetchHostgroups()
|
||||
->fetchServicegroups()
|
||||
->fetchContacts()
|
||||
->fetchContactgroups()
|
||||
->fetchCustomvars()
|
||||
->fetchComments()
|
||||
->fetchDowtimes()
|
||||
->fetchCustomvars();
|
||||
->fetchContactGroups();
|
||||
}
|
||||
|
||||
/**
|
||||
* Load object data
|
||||
*
|
||||
* @return object
|
||||
*/
|
||||
protected function fetchObject()
|
||||
protected function getProperties()
|
||||
{
|
||||
return $this->backend->select()->from(
|
||||
'status',
|
||||
array(
|
||||
'host_name',
|
||||
'host_alias',
|
||||
'host_address',
|
||||
'host_state',
|
||||
'host_handled',
|
||||
'host_in_downtime',
|
||||
'host_acknowledged',
|
||||
'host_last_state_change',
|
||||
'service_description',
|
||||
'service_state',
|
||||
'service_handled',
|
||||
'service_acknowledged',
|
||||
'service_in_downtime',
|
||||
'service_last_state_change',
|
||||
'last_check' => 'service_last_check',
|
||||
'next_check' => 'service_next_check',
|
||||
'check_execution_time' => 'service_check_execution_time',
|
||||
'check_latency' => 'service_check_latency',
|
||||
'output' => 'service_output',
|
||||
'long_output' => 'service_long_output',
|
||||
'check_command' => 'service_check_command',
|
||||
'perfdata' => 'service_perfdata',
|
||||
'current_check_attempt' => 'service_current_check_attempt',
|
||||
'max_check_attempts' => 'service_max_check_attempts',
|
||||
'state_type' => 'service_state_type',
|
||||
'passive_checks_enabled' => 'service_passive_checks_enabled',
|
||||
'last_state_change' => 'service_last_state_change',
|
||||
'last_notification' => 'service_last_notification',
|
||||
'current_notification_number' => 'service_current_notification_number',
|
||||
'is_flapping' => 'service_is_flapping',
|
||||
'percent_state_change' => 'service_percent_state_change',
|
||||
'in_downtime' => 'service_in_downtime',
|
||||
'passive_checks_enabled' => 'service_passive_checks_enabled',
|
||||
'obsessing' => 'service_obsessing',
|
||||
'notifications_enabled' => 'service_notifications_enabled',
|
||||
'event_handler_enabled' => 'service_event_handler_enabled',
|
||||
'flap_detection_enabled' => 'service_flap_detection_enabled',
|
||||
'active_checks_enabled' => 'service_active_checks_enabled',
|
||||
'last_comment' => 'service_last_comment',
|
||||
'action_url' => 'service_action_url',
|
||||
'notes_url' => 'service_notes_url'
|
||||
)
|
||||
)
|
||||
->where('host_name', $this->name1)
|
||||
->where('service_description', $this->name2)
|
||||
->fetchRow();
|
||||
$this->view = ServiceStatus::fromRequest($this->getRequest());
|
||||
return $this->view->getQuery()->fetchRow();
|
||||
}
|
||||
}
|
||||
|
@ -1,339 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Icinga\Module\Monitoring\View;
|
||||
|
||||
use Icinga\Data\AbstractQuery;
|
||||
use Icinga\Data\Filter;
|
||||
|
||||
/**
|
||||
* AbstractView provides consistent views to our Icinga Backends
|
||||
*
|
||||
* TODO: * This could be renamed to AbstractView
|
||||
* * We might need more complex filters (let's do the simple ones first)
|
||||
*
|
||||
* You should not directly instantiate such a view but always go through the
|
||||
* Monitoring Backend. Using the Backend's select() method selecting from
|
||||
* 'virtualtable' returns a Icinga\Module\Monitoring\View\VirtualtableView instance.
|
||||
*
|
||||
* Usage example:
|
||||
* <code>
|
||||
* use \Icinga\Module\Monitoring\Backend;
|
||||
* $backend = Backend::getInstance();
|
||||
* $query = $backend->select()->from('viewname', array(
|
||||
* 'one_column',
|
||||
* 'another_column',
|
||||
* 'alias' => 'whatever_column',
|
||||
* ))->where('any_column', $search);
|
||||
*
|
||||
* print_r($query->fetchAll());
|
||||
* </code>
|
||||
*
|
||||
* What we see in the example is that:
|
||||
* * you can (and should) use a defined set of columns when issueing a query
|
||||
* * you can use proper alias names to have an influence on column names
|
||||
* in the result set
|
||||
* * the AbstractView behaves like any Query object and provides useful
|
||||
* methods such as fetchAll, count, fetchPairs and so on
|
||||
*
|
||||
* If you want to fill a dropdown form element with all your hostgroups
|
||||
* starting with "net", using the hostgroup name as the form elements value but
|
||||
* showing the hostgroup aliases in the dropdown you would probably do this as
|
||||
* follows:
|
||||
*
|
||||
* <code>
|
||||
* $pairs = $backend->select->from(
|
||||
* 'hostgroups',
|
||||
* array('hostgroup_name', 'hostgroup_alias')
|
||||
* )->where('hostgroup_name', 'net*')->fetchPairs();
|
||||
* $formElement->setMultiOptions($pairs);
|
||||
* </code>
|
||||
*
|
||||
* AbstractView is a proxy to your Backend Query. While both are Query objects
|
||||
* providing partially the same interface, they are not directly related to
|
||||
* each other.
|
||||
*/
|
||||
class AbstractView extends AbstractQuery
|
||||
{
|
||||
/**
|
||||
* Stores the backend-specific Query Object
|
||||
* @var AbstractQuery
|
||||
*/
|
||||
protected $query;
|
||||
|
||||
/**
|
||||
* All the columns provided by this View MUST be specified here
|
||||
* @var Array
|
||||
*/
|
||||
protected $availableColumns = array();
|
||||
|
||||
/**
|
||||
* Columns available for search only but not in result sets
|
||||
* @var Array
|
||||
*/
|
||||
protected $specialFilters = array();
|
||||
|
||||
/**
|
||||
* All views COULD have a generic column called 'search', if available the
|
||||
* real column name is defined here.
|
||||
* TODO: This may be subject to change as a "search" could involve multiple
|
||||
* columns
|
||||
* @var string
|
||||
*/
|
||||
protected $searchColumn;
|
||||
|
||||
/**
|
||||
* Defines default sorting rules for specific column names. This helps in
|
||||
* providing "intelligent" sort defaults for different columns (involving
|
||||
* also other columns where needed)
|
||||
* @var Array
|
||||
*/
|
||||
protected $sortDefaults = array();
|
||||
|
||||
/**
|
||||
* Filters that will be enforced (e.g. AND for SQL), will be used for auth
|
||||
* restrictions
|
||||
*
|
||||
* TODO: rename to enforcedFilters?
|
||||
*
|
||||
* @var Array
|
||||
*/
|
||||
protected $forcedFilters = array();
|
||||
|
||||
/**
|
||||
* Whether this view provides a specific column name
|
||||
*
|
||||
* @param string $column Column name
|
||||
* @return bool
|
||||
*/
|
||||
public function hasColumn($column)
|
||||
{
|
||||
return in_array($column, $this->availableColumns);
|
||||
}
|
||||
|
||||
// TODO: Not sure about this yet
|
||||
public function getDefaultColumns()
|
||||
{
|
||||
return $this->availableColumns;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of all available column names
|
||||
*
|
||||
* This might be useful for dynamic frontend tables or similar
|
||||
*
|
||||
* @return Array
|
||||
*/
|
||||
public function getAvailableColumns()
|
||||
{
|
||||
return $this->availableColumns;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract and apply filters and sort rules from a given request object
|
||||
*
|
||||
* TODO: Enforce Icinga\Web\Request (or similar) as soon as we replaced
|
||||
* Zend_Controller_Request
|
||||
*
|
||||
* @param mixed $request The request object
|
||||
* @return self
|
||||
*/
|
||||
public function applyRequest($request)
|
||||
{
|
||||
return $this->applyRequestFilters($request)
|
||||
->applyRequestSorting($request);
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract and apply sort column and directon from given request object
|
||||
*
|
||||
* @param mixed $request The request object
|
||||
* @return self
|
||||
*/
|
||||
protected function applyRequestSorting($request)
|
||||
{
|
||||
|
||||
return $this->order(
|
||||
// TODO: Use first sortDefaults entry if available, fall back to
|
||||
// column if not
|
||||
$request->getParam('sort', $this->getDefaultSortColumn()),
|
||||
$request->getParam('dir')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract and apply filters from a given request object
|
||||
*
|
||||
* Columns not fitting any defined available column or special filter column
|
||||
* will be silently ignored.
|
||||
*
|
||||
* @param mixed $request The request object
|
||||
* @return self
|
||||
*/
|
||||
protected function applyRequestFilters($request)
|
||||
{
|
||||
foreach ($request->getParams() as $key => $value) {
|
||||
if ($key === 'search' && $value !== '') {
|
||||
if (strpos($value, '=') === false) {
|
||||
if ($this->searchColumn !== null) {
|
||||
$this->where($this->searchColumn, $value);
|
||||
}
|
||||
} else {
|
||||
list($k, $v) = preg_split('~\s*=\s*~', $value, 2);
|
||||
if ($this->isValidFilterColumn($k)) {
|
||||
$this->where($k, $v);
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if ($this->isValidFilterColumn($key)) {
|
||||
$this->where($key, $value);
|
||||
}
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
// TODO: applyAuthFilters(Auth $auth = null)
|
||||
// AbstractView will enforce restrictions as provided by the Auth
|
||||
// backend. Those filters work like normal ones and have to be stored
|
||||
// by applyAuthFilters to $this->forcedFilters
|
||||
|
||||
/**
|
||||
* Apply an array of filters. This might become obsolete or even improved
|
||||
* and accept Filter objects - this is still to be defined.
|
||||
*
|
||||
* @param Array $filters Filter array
|
||||
* @return self
|
||||
*/
|
||||
public function applyFilters($filters)
|
||||
{
|
||||
foreach ($filters as $col => $filter) {
|
||||
$this->where($col, $filter);
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gives you a filter object with all applied filters excluding auth filters
|
||||
* Might be used to build URLs fitting query objects.
|
||||
*
|
||||
* Please take care, as Url has been improved the Filter object might
|
||||
* become subject to change
|
||||
*
|
||||
* @return Filter
|
||||
*/
|
||||
public function getAppliedFilter()
|
||||
{
|
||||
return new Filter($this->filters);
|
||||
}
|
||||
|
||||
public function hasSingleSortColumn()
|
||||
{
|
||||
return count($this->order_columns) === 1;
|
||||
}
|
||||
|
||||
public function getFirstSortColumn()
|
||||
{
|
||||
return $this->order_columns[0];
|
||||
}
|
||||
|
||||
protected function getDefaultSortColumn()
|
||||
{
|
||||
if (empty($this->sortDefaults)) {
|
||||
return $this->availableColumns[0];
|
||||
} else {
|
||||
reset($this->sortDefaults);
|
||||
return key($this->sortDefaults);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Default sort direction for given column, ASCending if not defined
|
||||
*
|
||||
* @param String $col Column name
|
||||
* @return int
|
||||
*/
|
||||
protected function getDefaultSortDir($col)
|
||||
{
|
||||
if (isset($this->sortDefaults[$col]['default_dir'])) {
|
||||
return $this->sortDefaults[$col]['default_dir'];
|
||||
}
|
||||
return self::SORT_ASC;
|
||||
}
|
||||
|
||||
/**
|
||||
* getQuery gives you an instance of the Query object implementing this
|
||||
* view for the chosen backend.
|
||||
*
|
||||
* @return AbstractQuery
|
||||
*/
|
||||
public function getQuery()
|
||||
{
|
||||
|
||||
if ($this->query === null) {
|
||||
$classParts = preg_split('|\\\|', get_class($this));
|
||||
$class = substr(
|
||||
array_pop($classParts),
|
||||
0,
|
||||
-4
|
||||
) . 'Query';
|
||||
$class = '\\' . get_class($this->ds) . '\\Query\\' . $class;
|
||||
$query = new $class($this->ds, $this->columns);
|
||||
foreach ($this->filters as $f) {
|
||||
$query->where($f[0], $f[1]);
|
||||
}
|
||||
foreach ($this->forcedFilters as $col => $filter) {
|
||||
$query->where($col, $filter);
|
||||
}
|
||||
foreach ($this->order_columns as $col) {
|
||||
|
||||
if (isset($this->sortDefaults[$col[0]]['columns'])) {
|
||||
foreach ($this->sortDefaults[$col[0]]['columns'] as $c) {
|
||||
$query->order($c, $col[1]);
|
||||
}
|
||||
} else {
|
||||
$query->order($col[0], $col[1]);
|
||||
}
|
||||
}
|
||||
|
||||
$this->query = $query;
|
||||
}
|
||||
if ($this->hasLimit()) {
|
||||
$this->query->limit($this->getLimit(), $this->getOffset());
|
||||
}
|
||||
|
||||
return $this->query;
|
||||
}
|
||||
|
||||
public function count()
|
||||
{
|
||||
return $this->getQuery()->count();
|
||||
}
|
||||
|
||||
public function fetchAll()
|
||||
{
|
||||
return $this->getQuery()->fetchAll();
|
||||
}
|
||||
|
||||
public function fetchRow()
|
||||
{
|
||||
return $this->getQuery()->fetchRow();
|
||||
}
|
||||
|
||||
public function fetchColumn()
|
||||
{
|
||||
return $this->getQuery()->fetchColumn();
|
||||
}
|
||||
|
||||
public function fetchPairs()
|
||||
{
|
||||
return $this->getQuery()->fetchPairs();
|
||||
}
|
||||
|
||||
public function isValidFilterColumn($column)
|
||||
{
|
||||
if (in_array($column, $this->specialFilters)) {
|
||||
return true;
|
||||
}
|
||||
return in_array($column, $this->availableColumns);
|
||||
}
|
||||
}
|
@ -1,50 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Icinga\Module\Monitoring\View;
|
||||
|
||||
class AllcontactsView extends AbstractView
|
||||
{
|
||||
protected $query;
|
||||
|
||||
protected $availableColumns = array(
|
||||
'host_name',
|
||||
'contact_name',
|
||||
'contact_alias',
|
||||
'contact_email',
|
||||
'contact_pager',
|
||||
'contact_notify_hosts',
|
||||
'contact_notify_services',
|
||||
'contact_has_host_notfications',
|
||||
'contact_has_service_notfications',
|
||||
'contact_can_submit_commands',
|
||||
'contact_notify_service_recovery',
|
||||
'contact_notify_service_warning',
|
||||
'contact_notify_service_critical',
|
||||
'contact_notify_service_unknown',
|
||||
'contact_notify_service_flapping',
|
||||
'contact_notify_service_downtime',
|
||||
'contact_notify_host_recovery',
|
||||
'contact_notify_host_down',
|
||||
'contact_notify_host_unreachable',
|
||||
'contact_notify_host_flapping',
|
||||
'contact_notify_host_downtime',
|
||||
'host_object_id',
|
||||
'host_name',
|
||||
'service_object_id',
|
||||
'service_host_name',
|
||||
'service_description',
|
||||
/* 'contact_alias',
|
||||
'contact_email',
|
||||
'contact_pager',
|
||||
'contact_notify_hosts',
|
||||
'contact_notify_services',
|
||||
*/
|
||||
);
|
||||
|
||||
/*
|
||||
protected $sortDefaults = array(
|
||||
'contact_alias' => array(
|
||||
'default_dir' => self::SORT_ASC
|
||||
)
|
||||
);*/
|
||||
}
|
@ -1,44 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Icinga\Module\Monitoring\View;
|
||||
|
||||
class ContactView extends AbstractView
|
||||
{
|
||||
protected $query;
|
||||
|
||||
protected $availableColumns = array(
|
||||
'contact_name',
|
||||
'contact_alias',
|
||||
'contact_email',
|
||||
'contact_pager',
|
||||
'contact_notify_hosts',
|
||||
'contact_notify_services',
|
||||
'contact_has_host_notfications',
|
||||
'contact_has_service_notfications',
|
||||
'contact_can_submit_commands',
|
||||
'contact_notify_service_recovery',
|
||||
'contact_notify_service_warning',
|
||||
'contact_notify_service_critical',
|
||||
'contact_notify_service_unknown',
|
||||
'contact_notify_service_flapping',
|
||||
'contact_notify_service_downtime',
|
||||
'contact_notify_host_recovery',
|
||||
'contact_notify_host_down',
|
||||
'contact_notify_host_unreachable',
|
||||
'contact_notify_host_flapping',
|
||||
'contact_notify_host_downtime',
|
||||
'host_object_id',
|
||||
'host_name',
|
||||
'service_object_id',
|
||||
'service_host_name',
|
||||
'service_description',
|
||||
);
|
||||
|
||||
protected $specialFilters = array();
|
||||
|
||||
protected $sortDefaults = array(
|
||||
'contact_alias' => array(
|
||||
'default_dir' => self::SORT_ASC
|
||||
)
|
||||
);
|
||||
}
|
@ -1,47 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Icinga\Module\Monitoring\View;
|
||||
|
||||
class ContactgroupView extends AbstractView
|
||||
{
|
||||
protected $query;
|
||||
|
||||
protected $availableColumns = array(
|
||||
'contactgroup_name',
|
||||
'contactgroup_alias',
|
||||
|
||||
'contact_name',
|
||||
'contact_alias',
|
||||
'contact_email',
|
||||
'contact_pager',
|
||||
'contact_notify_hosts',
|
||||
'contact_notify_services',
|
||||
'contact_has_host_notfications',
|
||||
'contact_has_service_notfications',
|
||||
'contact_can_submit_commands',
|
||||
'contact_notify_service_recovery',
|
||||
'contact_notify_service_warning',
|
||||
'contact_notify_service_critical',
|
||||
'contact_notify_service_unknown',
|
||||
'contact_notify_service_flapping',
|
||||
'contact_notify_service_downtime',
|
||||
'contact_notify_host_recovery',
|
||||
'contact_notify_host_down',
|
||||
'contact_notify_host_unreachable',
|
||||
'contact_notify_host_flapping',
|
||||
'contact_notify_host_downtime',
|
||||
|
||||
|
||||
'host_object_id',
|
||||
'host_name',
|
||||
'service_description'
|
||||
);
|
||||
|
||||
protected $specialFilters = array();
|
||||
|
||||
protected $sortDefaults = array(
|
||||
'contactgroup_alias' => array(
|
||||
'default_dir' => self::SORT_ASC
|
||||
)
|
||||
);
|
||||
}
|
@ -1,23 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Icinga\Module\Monitoring\View;
|
||||
|
||||
class CustomvarView extends AbstractView
|
||||
{
|
||||
protected $query;
|
||||
|
||||
protected $availableColumns = array(
|
||||
'varname',
|
||||
'varvalue',
|
||||
'object_type',
|
||||
);
|
||||
|
||||
protected $specialFilters = array();
|
||||
|
||||
protected $sortDefaults = array(
|
||||
'varname' => array(
|
||||
'varname' => self::SORT_ASC,
|
||||
'varvalue' => self::SORT_ASC,
|
||||
)
|
||||
);
|
||||
}
|
@ -1,82 +0,0 @@
|
||||
<?php
|
||||
// {{{ICINGA_LICENSE_HEADER}}}
|
||||
/**
|
||||
* Icinga 2 Web - Head for multiple monitoring frontends
|
||||
* Copyright (C) 2013 Icinga Development Team
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* @copyright 2013 Icinga Development Team <info@icinga.org>
|
||||
* @author Icinga Development Team <info@icinga.org>
|
||||
*/
|
||||
// {{{ICINGA_LICENSE_HEADER}}}
|
||||
namespace Icinga\Module\Monitoring\View;
|
||||
|
||||
/**
|
||||
* Class DowntimeView
|
||||
*/
|
||||
class DowntimeView extends AbstractView
|
||||
{
|
||||
/**
|
||||
* Query object
|
||||
* @var mixed
|
||||
*/
|
||||
protected $query;
|
||||
|
||||
/**
|
||||
* Available columns
|
||||
* @var string[]
|
||||
*/
|
||||
protected $availableColumns = array(
|
||||
'host_name',
|
||||
'object_type',
|
||||
'service_host_name',
|
||||
'service_description',
|
||||
'downtime_type',
|
||||
'downtime_author_name',
|
||||
'downtime_comment_data',
|
||||
'downtime_is_fixed',
|
||||
'downtime_duration',
|
||||
'downtime_entry_time',
|
||||
'downtime_scheduled_start_time',
|
||||
'downtime_scheduled_end_time',
|
||||
'downtime_was_started',
|
||||
'downtime_actual_start_time',
|
||||
'downtime_actual_start_time_usec',
|
||||
'downtime_is_in_effect',
|
||||
'downtime_trigger_time',
|
||||
'downtime_triggered_by_id',
|
||||
'downtime_internal_downtime_id'
|
||||
);
|
||||
|
||||
/**
|
||||
* Filters
|
||||
* @var array
|
||||
*/
|
||||
protected $specialFilters = array();
|
||||
|
||||
/**
|
||||
* Default sorting of data set
|
||||
* @var array
|
||||
*/
|
||||
protected $sortDefaults = array(
|
||||
'downtime_is_in_effect' => array(
|
||||
'default_dir' => self::SORT_DESC
|
||||
),
|
||||
'downtime_actual_start_time' => array(
|
||||
'default_dir' => self::SORT_DESC
|
||||
)
|
||||
);
|
||||
}
|
@ -1,36 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Icinga\Module\Monitoring\View;
|
||||
|
||||
class EventHistoryView extends AbstractView
|
||||
{
|
||||
protected $query;
|
||||
|
||||
protected $availableColumns = array(
|
||||
'raw_timestamp',
|
||||
'timestamp',
|
||||
'host',
|
||||
'service',
|
||||
'host_name',
|
||||
'state',
|
||||
'last_state',
|
||||
'last_hard_state',
|
||||
'attempt',
|
||||
'max_attempts',
|
||||
'output',
|
||||
'type'
|
||||
);
|
||||
|
||||
protected $specialFilters = array(
|
||||
'hostgroup',
|
||||
);
|
||||
|
||||
protected $sortDefaults = array(
|
||||
'raw_timestamp' => array(
|
||||
'default_dir' => self::SORT_DESC
|
||||
),
|
||||
'timestamp' => array(
|
||||
'default_dir' => self::SORT_DESC
|
||||
),
|
||||
);
|
||||
}
|
@ -1,22 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Icinga\Module\Monitoring\View;
|
||||
|
||||
class HostgroupView extends AbstractView
|
||||
{
|
||||
protected $query;
|
||||
|
||||
protected $availableColumns = array(
|
||||
'hostgroups',
|
||||
'hostgroup_name',
|
||||
'hostgroup_alias',
|
||||
);
|
||||
|
||||
protected $specialFilters = array();
|
||||
|
||||
protected $sortDefaults = array(
|
||||
'hostgroup_alias' => array(
|
||||
'default_dir' => self::SORT_ASC
|
||||
)
|
||||
);
|
||||
}
|
@ -1,90 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Icinga\Module\Monitoring\View;
|
||||
|
||||
class HoststatusView extends AbstractView
|
||||
{
|
||||
protected $query;
|
||||
protected $searchColumn = 'host';
|
||||
|
||||
protected $availableColumns = array(
|
||||
// Hosts
|
||||
'host',
|
||||
'host_name',
|
||||
'host_display_name',
|
||||
'host_alias',
|
||||
'host_address',
|
||||
'host_ipv4',
|
||||
'host_icon_image',
|
||||
// Hoststatus
|
||||
'host_state',
|
||||
'host_problem',
|
||||
'host_severity',
|
||||
'host_state_type',
|
||||
'host_output',
|
||||
'host_long_output',
|
||||
'host_perfdata',
|
||||
'host_acknowledged',
|
||||
'host_in_downtime',
|
||||
'host_handled',
|
||||
'host_does_active_checks',
|
||||
'host_accepts_passive_checks',
|
||||
'host_last_state_change',
|
||||
'host_last_hard_state',
|
||||
'host_last_hard_state_change',
|
||||
'host_notifications_enabled',
|
||||
'host_last_time_up',
|
||||
'host_last_time_down',
|
||||
'host_last_time_unreachable',
|
||||
'host_current_check_attempt',
|
||||
'host_max_check_attempts',
|
||||
// Services
|
||||
'services_cnt',
|
||||
'services_problem',
|
||||
'services_problem_handled',
|
||||
'services_problem_unhandled',
|
||||
);
|
||||
|
||||
protected $specialFilters = array(
|
||||
'hostgroup',
|
||||
'servicegroup',
|
||||
'contact',
|
||||
'contactgroup',
|
||||
);
|
||||
|
||||
protected $sortDefaults = array(
|
||||
'host_name' => array(
|
||||
'columns' => array(
|
||||
'host_name',
|
||||
),
|
||||
'default_dir' => self::SORT_ASC
|
||||
),
|
||||
'host_address' => array(
|
||||
'columns' => array(
|
||||
'host_ipv4',
|
||||
'service_description'
|
||||
),
|
||||
'default_dir' => self::SORT_ASC
|
||||
),
|
||||
'host_last_state_change' => array(
|
||||
'default_dir' => self::SORT_DESC
|
||||
),
|
||||
'host_severity' => array(
|
||||
'columns' => array(
|
||||
'host_severity',
|
||||
'host_last_state_change',
|
||||
),
|
||||
'default_dir' => self::SORT_DESC
|
||||
)
|
||||
);
|
||||
|
||||
public function isValidFilterColumn($column)
|
||||
{
|
||||
if ($column[0] === '_'
|
||||
&& preg_match('~^_host~', $column)
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
return parent::isValidFilterColumn($column);
|
||||
}
|
||||
}
|
@ -1,59 +0,0 @@
|
||||
<?php
|
||||
// {{{ICINGA_LICENSE_HEADER}}}
|
||||
/**
|
||||
* Icinga 2 Web - Head for multiple monitoring frontends
|
||||
* Copyright (C) 2013 Icinga Development Team
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* @copyright 2013 Icinga Development Team <info@icinga.org>
|
||||
* @author Icinga Development Team <info@icinga.org>
|
||||
*/
|
||||
// {{{ICINGA_LICENSE_HEADER}}}
|
||||
|
||||
namespace Icinga\Module\Monitoring\View;
|
||||
|
||||
/**
|
||||
* NotificationView
|
||||
*/
|
||||
class NotificationView extends AbstractView
|
||||
{
|
||||
/**
|
||||
* Available columns provided by this view
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $availableColumns = array(
|
||||
'host_name',
|
||||
'service_description',
|
||||
'notification_type',
|
||||
'notification_reason',
|
||||
'notification_start_time',
|
||||
'notification_contact',
|
||||
'notification_information',
|
||||
'notification_command'
|
||||
);
|
||||
|
||||
/**
|
||||
* Default sorting rules
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $sortDefaults = array(
|
||||
'notification_start_time' => array(
|
||||
'default_dir' => self::SORT_DESC
|
||||
)
|
||||
);
|
||||
}
|
@ -1,21 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Icinga\Module\Monitoring\View;
|
||||
|
||||
class ServicegroupView extends AbstractView
|
||||
{
|
||||
protected $query;
|
||||
|
||||
protected $availableColumns = array(
|
||||
'servicegroup_name',
|
||||
'servicegroup_alias',
|
||||
);
|
||||
|
||||
protected $specialFilters = array();
|
||||
|
||||
protected $sortDefaults = array(
|
||||
'servicegroup_alias' => array(
|
||||
'default_dir' => self::SORT_ASC
|
||||
)
|
||||
);
|
||||
}
|
@ -1,25 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Icinga\Monitoring\View;
|
||||
|
||||
use Icinga\Module\Monitoring\View\AbstractView;
|
||||
|
||||
class StatehistoryView extends AbstractView
|
||||
{
|
||||
protected $availableColumns = array(
|
||||
'raw_timestamp',
|
||||
'timestamp',
|
||||
'state',
|
||||
'attempt',
|
||||
'max_attempts',
|
||||
'output',
|
||||
'type'
|
||||
);
|
||||
|
||||
protected $sortDefaults = array(
|
||||
'timestamp' => array(
|
||||
'columns' => array('raw_timestamp'),
|
||||
'default_dir' => self::SORT_DESC
|
||||
),
|
||||
);
|
||||
}
|
@ -1,135 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Icinga\Module\Monitoring\View;
|
||||
|
||||
class StatusView extends AbstractView
|
||||
{
|
||||
protected $query;
|
||||
// protected $searchColumn = 'host'; -> besser in der Query, 'search' mitgeben
|
||||
|
||||
protected $availableColumns = array(
|
||||
// Hosts
|
||||
'host',
|
||||
'host_name',
|
||||
'host_display_name',
|
||||
'host_alias',
|
||||
'host_address',
|
||||
'host_ipv4',
|
||||
'host_icon_image',
|
||||
|
||||
// Hoststatus
|
||||
'host_state',
|
||||
'host_problems',
|
||||
'host_severity',
|
||||
'host_state_type',
|
||||
'host_output',
|
||||
'host_long_output',
|
||||
'host_perfdata',
|
||||
'host_acknowledged',
|
||||
'host_in_downtime',
|
||||
'host_handled',
|
||||
'host_does_active_checks',
|
||||
'host_accepts_passive_checks',
|
||||
'host_last_state_change',
|
||||
'host_last_hard_state',
|
||||
'host_last_hard_state_change',
|
||||
'host_notifications_enabled',
|
||||
'host_last_time_up',
|
||||
'host_last_time_down',
|
||||
'host_last_time_unreachable',
|
||||
'host_unhandled_service_count',
|
||||
|
||||
// Services
|
||||
'service',
|
||||
'service_description',
|
||||
'service_display_name',
|
||||
|
||||
// Servicetatus
|
||||
'current_state',
|
||||
'service_state',
|
||||
'service_state_type',
|
||||
'service_hard_state',
|
||||
'service_output',
|
||||
'service_long_output',
|
||||
'service_perfdata',
|
||||
'service_acknowledged',
|
||||
'service_in_downtime',
|
||||
'service_handled',
|
||||
'service_does_active_checks',
|
||||
'service_accepts_passive_checks',
|
||||
'service_last_state_change',
|
||||
'service_last_hard_state',
|
||||
'service_last_hard_state_change',
|
||||
'service_notifications_enabled',
|
||||
'service_last_time_ok',
|
||||
'service_last_time_warning',
|
||||
'service_last_time_critical',
|
||||
'service_last_time_unknown',
|
||||
|
||||
'object_type',
|
||||
|
||||
// Status
|
||||
'problems',
|
||||
'handled',
|
||||
'severity'
|
||||
);
|
||||
|
||||
protected $specialFilters = array(
|
||||
'hostgroups',
|
||||
'servicegroups'
|
||||
);
|
||||
|
||||
protected $sortDefaults = array(
|
||||
'host_name' => array(
|
||||
'columns' => array(
|
||||
'host_name',
|
||||
),
|
||||
'default_dir' => self::SORT_ASC
|
||||
),
|
||||
'service_host_name' => array(
|
||||
'columns' => array(
|
||||
'service_host_name',
|
||||
'service_description'
|
||||
),
|
||||
'default_dir' => self::SORT_ASC
|
||||
),
|
||||
'host_address' => array(
|
||||
'columns' => array(
|
||||
'host_ipv4',
|
||||
'service_description'
|
||||
),
|
||||
'default_dir' => self::SORT_ASC
|
||||
),
|
||||
'host_last_state_change' => array(
|
||||
'default_dir' => self::SORT_DESC
|
||||
),
|
||||
'service_last_state_change' => array(
|
||||
'default_dir' => self::SORT_DESC
|
||||
),
|
||||
'severity' => array(
|
||||
'columns' => array(
|
||||
'severity',
|
||||
'host_name',
|
||||
'service_last_state_change',
|
||||
),
|
||||
'default_dir' => self::SORT_DESC
|
||||
),
|
||||
'host_severity' => array(
|
||||
'columns' => array(
|
||||
'host_severity',
|
||||
'host_last_state_change',
|
||||
),
|
||||
'default_dir' => self::SORT_DESC
|
||||
)
|
||||
);
|
||||
|
||||
public function isValidFilterColumn($column)
|
||||
{
|
||||
if ($column[0] === '_'
|
||||
&& preg_match('~^_(?:host|service)_~', $column)
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
return parent::isValidFilterColumn($column);
|
||||
}
|
||||
}
|
@ -8,7 +8,7 @@ require_once realpath(__DIR__ . '/../../../../../../library/Icinga/Test/BaseTest
|
||||
use Icinga\Test\BaseTestCase;
|
||||
|
||||
require_once(realpath(BaseTestCase::$moduleDir . '/monitoring/test/php/testlib/MonitoringControllerTest.php'));
|
||||
require_once(realpath(BaseTestCase::$moduleDir . '/monitoring/library/Monitoring/Filter/Backend/IdoQueryConverter.php'));
|
||||
require_once(realpath(BaseTestCase::$moduleDir . '/monitoring/library/Monitoring/Filter/Backend/TreeToSqlParser.php);
|
||||
require_once(realpath(BaseTestCase::$moduleDir . '/monitoring/library/Monitoring/DataView/DataView.php'));
|
||||
require_once(realpath(BaseTestCase::$moduleDir . '/monitoring/library/Monitoring/DataView/HostStatus.php'));
|
||||
require_once(realpath(BaseTestCase::$moduleDir . '/monitoring/library/Monitoring/DataView/Notification.php'));
|
||||
|
@ -7,7 +7,7 @@ use Icinga\Test\BaseTestCase;
|
||||
require_once realpath(__DIR__ . '/../../../../../../library/Icinga/Test/BaseTestCase.php');
|
||||
|
||||
require_once(realpath(BaseTestCase::$moduleDir . '/monitoring/test/php/testlib/MonitoringControllerTest.php'));
|
||||
require_once(realpath(BaseTestCase::$moduleDir . '/monitoring/library/Monitoring/Filter/Backend/IdoQueryConverter.php'));
|
||||
require_once(realpath(BaseTestCase::$moduleDir . '/monitoring/library/Monitoring/Filter/Backend/TreeToSqlParser.php);
|
||||
require_once(realpath(BaseTestCase::$moduleDir . '/monitoring/library/Monitoring/DataView/DataView.php'));
|
||||
require_once(realpath(BaseTestCase::$moduleDir . '/monitoring/library/Monitoring/DataView/ServiceStatus.php'));
|
||||
require_once(realpath(BaseTestCase::$moduleDir . '/monitoring/library/Monitoring/DataView/Notification.php'));
|
||||
|
@ -156,7 +156,7 @@ abstract class MonitoringControllerTest extends Zend_Test_PHPUnit_ControllerTest
|
||||
private function requireBase()
|
||||
{
|
||||
require_once('Application/Benchmark.php');
|
||||
require_once('Data/AbstractQuery.php');
|
||||
require_once('Data/BaseQuery.php');
|
||||
require_once('Data/DatasourceInterface.php');
|
||||
require_once('Data/Db/Connection.php');
|
||||
require_once('Data/Db/Query.php');
|
||||
|
@ -6,7 +6,7 @@ use Icinga\Protocol\Livestatus\Connection;
|
||||
use Icinga\Protocol\Livestatus\Query;
|
||||
use PHPUnit_Framework_TestCase as TestCase;
|
||||
|
||||
require_once('../../library/Icinga/Protocol/AbstractQuery.php');
|
||||
require_once('../../library/Icinga/Protocol/BaseQuery.php');
|
||||
require_once('../../library/Icinga/Protocol/Livestatus/Connection.php');
|
||||
require_once('../../library/Icinga/Protocol/Livestatus/Query.php');
|
||||
|
||||
|
@ -1,9 +1,9 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Icinga\Protocol\Statusdat;
|
||||
require_once("../../library/Icinga/Data/QueryInterface.php");
|
||||
require_once("../../library/Icinga/Data/AbstractQuery.php");
|
||||
require_once("../../library/Icinga/Protocol/Statusdat/Query.php");
|
||||
require_once('../../library/Icinga/Data/QueryInterface.php');
|
||||
require_once('../../library/Icinga/Data/BaseQuery.php');
|
||||
require_once('../../library/Icinga/Protocol/Statusdat/Query.php');
|
||||
require_once(dirname(__FILE__)."/ReaderMock.php");
|
||||
|
||||
use Icinga\Protocol\Statusdat as Statusdat;
|
||||
|
@ -12,8 +12,7 @@ class StatusdatTestLoader extends LibraryLoader
|
||||
require_once 'Zend/Config.php';
|
||||
require_once 'Zend/Cache.php';
|
||||
require_once 'Zend/Log.php';
|
||||
require_once($libPath."/Data/AbstractQuery.php");
|
||||
require_once($libPath."/Application/Logger.php");
|
||||
require_once($libPath."/Data/BaseQuery.php require_once($libPath."/Application/Logger.php");
|
||||
require_once($libPath."/Filter/Filterable.php");
|
||||
require_once($libPath."/Data/DatasourceInterface.php");
|
||||
$statusdat = realpath($libPath."/Protocol/Statusdat/");
|
||||
|
@ -25,8 +25,7 @@ require_once '../../modules/monitoring/library/Monitoring/View/AbstractView.php'
|
||||
require_once '../../modules/monitoring/library/Monitoring/View/StatusView.php';
|
||||
require_once '../../modules/monitoring/library/Monitoring/Backend.php';
|
||||
|
||||
require_once '../../library/Icinga/Protocol/AbstractQuery.php';
|
||||
require_once '../../library/Icinga/Data/ResourceFactory.php';
|
||||
require_once '../../library/Icinga/Protocol/BaseQuery.phpequire_once '../../library/Icinga/Data/ResourceFactory.php';
|
||||
|
||||
class QueryAdapterTest extends PHPUnit_Framework_TestCase
|
||||
{
|
||||
|
Loading…
x
Reference in New Issue
Block a user