2013-06-03 16:14:46 +02:00
|
|
|
<?php
|
2013-06-07 13:29:11 +02:00
|
|
|
// {{{ICINGA_LICENSE_HEADER}}}
|
2013-06-28 16:47:30 +02:00
|
|
|
/**
|
2013-10-23 15:10:33 +02:00
|
|
|
* This file is part of Icinga Web 2.
|
2013-09-04 18:27:16 +02:00
|
|
|
*
|
2013-10-23 15:10:33 +02:00
|
|
|
* Icinga Web 2 - Head for multiple monitoring backends.
|
2013-06-28 16:47:30 +02:00
|
|
|
* Copyright (C) 2013 Icinga Development Team
|
2013-09-04 18:27:16 +02:00
|
|
|
*
|
2013-06-28 16:47:30 +02:00
|
|
|
* 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.
|
2013-09-04 18:27:16 +02:00
|
|
|
*
|
2013-06-28 16:47:30 +02:00
|
|
|
* 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.
|
2013-09-04 18:27:16 +02:00
|
|
|
*
|
2013-06-28 16:47:30 +02:00
|
|
|
* 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.
|
2013-09-04 18:27:16 +02:00
|
|
|
*
|
2013-10-23 15:10:33 +02:00
|
|
|
* @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>
|
|
|
|
*
|
2013-06-28 16:47:30 +02:00
|
|
|
*/
|
2013-06-07 13:29:11 +02:00
|
|
|
// {{{ICINGA_LICENSE_HEADER}}}
|
2013-06-03 16:14:46 +02:00
|
|
|
|
|
|
|
namespace Icinga\Protocol\Statusdat;
|
2013-06-07 13:29:11 +02:00
|
|
|
|
2013-10-19 20:09:17 +02:00
|
|
|
use Exception;
|
2013-10-21 16:02:46 +02:00
|
|
|
use Icinga\Exception\ProgrammingError;
|
2013-10-15 20:21:40 +02:00
|
|
|
use Icinga\Filter\Query\Node;
|
2013-06-03 16:14:46 +02:00
|
|
|
use Icinga\Protocol;
|
2013-10-15 19:56:33 +02:00
|
|
|
use Icinga\Data\BaseQuery;
|
2013-10-19 20:09:17 +02:00
|
|
|
use Icinga\Protocol\Statusdat\View\MonitoringObjectList;
|
|
|
|
use Icinga\Protocol\Statusdat\Query\IQueryPart;
|
2013-09-02 17:33:12 +02:00
|
|
|
|
2013-06-07 13:29:11 +02:00
|
|
|
/**
|
2013-10-20 15:15:30 +02:00
|
|
|
* Base implementation for Statusdat queries.
|
2013-06-07 13:29:11 +02:00
|
|
|
*/
|
2013-10-15 19:56:33 +02:00
|
|
|
class Query extends BaseQuery
|
2013-06-03 16:14:46 +02:00
|
|
|
{
|
2013-06-07 13:29:11 +02:00
|
|
|
/**
|
2013-10-20 15:15:30 +02:00
|
|
|
* An array denoting valid targets by mapping the query target to
|
|
|
|
* the 'define' directives found in the status.dat/objects.cache files
|
2013-10-21 16:02:46 +02:00
|
|
|
*
|
2013-06-07 13:29:11 +02:00
|
|
|
* @var array
|
|
|
|
*/
|
2013-06-03 16:14:46 +02:00
|
|
|
public static $VALID_TARGETS = array(
|
2013-10-20 15:15:30 +02:00
|
|
|
'hosts' => array('host'),
|
|
|
|
'services' => array('service'),
|
|
|
|
'downtimes' => array('downtime'),
|
|
|
|
'groups' => array('hostgroup', 'servicegroup'),
|
|
|
|
'hostgroups' => array('hostgroup'),
|
|
|
|
'servicegroups' => array('servicegroup'),
|
|
|
|
'comments' => array('comment'),
|
|
|
|
'contacts' => array('contact'),
|
|
|
|
'contactgroups' => array('contactgroup')
|
2013-06-03 16:14:46 +02:00
|
|
|
);
|
|
|
|
|
2013-06-07 13:29:11 +02:00
|
|
|
/**
|
2013-10-20 15:15:30 +02:00
|
|
|
* The current StatusDat query that will be applied upon calling fetchAll
|
|
|
|
*
|
|
|
|
* @var IQueryPart
|
2013-06-07 13:29:11 +02:00
|
|
|
*/
|
2013-10-20 15:15:30 +02:00
|
|
|
private $queryFilter = null;
|
2013-06-07 13:29:11 +02:00
|
|
|
|
|
|
|
/**
|
2013-10-20 15:15:30 +02:00
|
|
|
* The current query source being used
|
|
|
|
*
|
|
|
|
* @var string
|
2013-06-07 13:29:11 +02:00
|
|
|
*/
|
2013-10-20 15:15:30 +02:00
|
|
|
private $source = '';
|
2013-06-07 13:29:11 +02:00
|
|
|
|
|
|
|
/**
|
2013-10-20 15:15:30 +02:00
|
|
|
* An array containing all columns used for sorting
|
|
|
|
*
|
2013-06-07 13:29:11 +02:00
|
|
|
* @var array
|
|
|
|
*/
|
2013-10-15 19:56:33 +02:00
|
|
|
protected $orderColumns = array();
|
2013-06-07 13:29:11 +02:00
|
|
|
|
|
|
|
/**
|
2013-10-20 15:15:30 +02:00
|
|
|
* An array containig all columns used for (simple) grouping
|
|
|
|
*
|
2013-06-07 13:29:11 +02:00
|
|
|
* @var array
|
|
|
|
*/
|
2013-06-03 16:14:46 +02:00
|
|
|
private $groupColumns = array();
|
2013-06-07 13:29:11 +02:00
|
|
|
|
|
|
|
/**
|
2013-10-20 15:15:30 +02:00
|
|
|
* An optional function callback to use for more specific grouping
|
|
|
|
*
|
2013-10-19 20:09:17 +02:00
|
|
|
* @var array
|
|
|
|
*/
|
2013-10-20 15:15:30 +02:00
|
|
|
private $groupByFn = null;
|
2013-06-03 16:14:46 +02:00
|
|
|
|
2013-06-07 13:29:11 +02:00
|
|
|
/**
|
2013-10-20 15:15:30 +02:00
|
|
|
* The scope index for the callback function
|
2013-06-07 13:29:11 +02:00
|
|
|
*/
|
2013-06-03 16:14:46 +02:00
|
|
|
const FN_SCOPE = 0;
|
2013-06-07 13:29:11 +02:00
|
|
|
|
|
|
|
/**
|
2013-10-20 15:15:30 +02:00
|
|
|
* The name index for the callback function
|
2013-06-07 13:29:11 +02:00
|
|
|
*/
|
2013-06-03 16:14:46 +02:00
|
|
|
const FN_NAME = 1;
|
|
|
|
|
2013-06-07 13:29:11 +02:00
|
|
|
/**
|
2013-10-20 15:15:30 +02:00
|
|
|
* Return true if columns are set for this query
|
|
|
|
*
|
2013-06-07 13:29:11 +02:00
|
|
|
* @return bool
|
|
|
|
*/
|
2013-06-03 16:14:46 +02:00
|
|
|
public function hasColumns()
|
|
|
|
{
|
2013-10-15 20:21:40 +02:00
|
|
|
$columns = $this->getColumns();
|
|
|
|
return !empty($columns);
|
2013-06-03 16:14:46 +02:00
|
|
|
}
|
|
|
|
|
2013-06-07 13:29:11 +02:00
|
|
|
/**
|
2013-10-20 15:15:30 +02:00
|
|
|
* Set the status.dat specific IQueryPart filter to use
|
|
|
|
*
|
|
|
|
* @param IQueryPart $filter
|
2013-06-07 13:29:11 +02:00
|
|
|
*/
|
2013-10-20 15:15:30 +02:00
|
|
|
public function setQueryFilter($filter)
|
2013-06-03 16:14:46 +02:00
|
|
|
{
|
2013-10-20 15:15:30 +02:00
|
|
|
$this->queryFilter = $filter;
|
2013-06-03 16:14:46 +02:00
|
|
|
}
|
|
|
|
|
2013-06-07 13:29:11 +02:00
|
|
|
/**
|
2013-10-20 15:15:30 +02:00
|
|
|
* Order the query result by the given columns
|
|
|
|
*
|
|
|
|
* @param String|array $columns An array of columns to order by
|
|
|
|
* @param String $dir The direction (asc or desc) in string form
|
|
|
|
*
|
|
|
|
* @return $this Fluent interface
|
2013-06-07 13:29:11 +02:00
|
|
|
*/
|
2013-10-19 20:09:17 +02:00
|
|
|
public function order($columns, $dir = null, $isFunction = false)
|
2013-06-03 16:14:46 +02:00
|
|
|
{
|
2013-10-20 15:15:30 +02:00
|
|
|
if ($dir && strtolower($dir) == 'desc') {
|
2013-06-03 16:14:46 +02:00
|
|
|
$dir = self::SORT_DESC;
|
2013-06-07 13:29:11 +02:00
|
|
|
} else {
|
2013-06-03 16:14:46 +02:00
|
|
|
$dir = self::SORT_ASC;
|
2013-06-07 13:29:11 +02:00
|
|
|
}
|
|
|
|
if (!is_array($columns)) {
|
2013-06-03 16:14:46 +02:00
|
|
|
$columns = array($columns);
|
2013-06-07 13:29:11 +02:00
|
|
|
}
|
2013-06-03 16:14:46 +02:00
|
|
|
|
2013-10-19 20:09:17 +02:00
|
|
|
foreach ($columns as $col) {
|
2013-06-03 16:14:46 +02:00
|
|
|
if (($pos = strpos($col, ' ')) !== false) {
|
|
|
|
$dir = strtoupper(substr($col, $pos + 1));
|
|
|
|
if ($dir === 'DESC') {
|
|
|
|
$dir = self::SORT_DESC;
|
|
|
|
} else {
|
|
|
|
$dir = self::SORT_ASC;
|
|
|
|
}
|
|
|
|
$col = substr($col, 0, $pos);
|
|
|
|
} else {
|
|
|
|
$col = $col;
|
|
|
|
}
|
|
|
|
|
2013-10-15 19:56:33 +02:00
|
|
|
$this->orderColumns[] = array($col, $dir);
|
2013-06-03 16:14:46 +02:00
|
|
|
}
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
2013-06-07 13:29:11 +02:00
|
|
|
/**
|
2013-10-20 15:15:30 +02:00
|
|
|
* Order the query result using the callback to retrieve values for items
|
|
|
|
*
|
|
|
|
* @param array $columns A scope, function array to use for retrieving the values when ordering
|
|
|
|
* @param String $dir The direction (asc or desc) in string form
|
|
|
|
*
|
|
|
|
* @return $this Fluent interface
|
2013-06-07 13:29:11 +02:00
|
|
|
*/
|
2013-10-20 15:15:30 +02:00
|
|
|
public function orderByFn(array $callBack, $dir = null)
|
2013-06-03 16:14:46 +02:00
|
|
|
{
|
2013-10-20 15:15:30 +02:00
|
|
|
if ($dir && strtolower($dir) == 'desc') {
|
|
|
|
$dir = self::SORT_DESC;
|
2013-06-03 16:14:46 +02:00
|
|
|
} else {
|
2013-10-20 15:15:30 +02:00
|
|
|
$dir = self::SORT_ASC;
|
2013-06-03 16:14:46 +02:00
|
|
|
}
|
2013-10-20 15:15:30 +02:00
|
|
|
$this->orderColumns[] = array($callBack, $dir);
|
2013-06-03 16:14:46 +02:00
|
|
|
}
|
|
|
|
|
2013-10-15 20:21:40 +02:00
|
|
|
|
2013-10-20 15:15:30 +02:00
|
|
|
|
2013-06-07 13:29:11 +02:00
|
|
|
/**
|
2013-10-20 15:15:30 +02:00
|
|
|
* Set the query target
|
|
|
|
*
|
|
|
|
* @param String $table The table/target to select the query from
|
|
|
|
* @param array $columns An array of attributes to use (required for fetchPairs())
|
|
|
|
*
|
|
|
|
* @return $this Fluent interface
|
|
|
|
* @throws \Exception If the target is unknonw
|
2013-06-07 13:29:11 +02:00
|
|
|
*/
|
2013-10-15 20:21:40 +02:00
|
|
|
public function from($table, array $attributes = null)
|
2013-06-03 16:14:46 +02:00
|
|
|
{
|
2013-10-19 20:09:17 +02:00
|
|
|
if (!$this->getColumns() && $attributes) {
|
|
|
|
$this->setColumns($attributes);
|
|
|
|
}
|
2013-06-07 13:29:11 +02:00
|
|
|
if (isset(self::$VALID_TARGETS[$table])) {
|
2013-06-03 16:14:46 +02:00
|
|
|
$this->source = $table;
|
2013-06-07 13:29:11 +02:00
|
|
|
} else {
|
2013-10-20 15:15:30 +02:00
|
|
|
throw new \Exception('Unknown from target for status.dat :' . $table);
|
2013-06-07 13:29:11 +02:00
|
|
|
}
|
2013-06-03 16:14:46 +02:00
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2013-10-20 15:15:30 +02:00
|
|
|
* Return an index of all objects matching the filter of this query
|
2013-06-03 16:14:46 +02:00
|
|
|
*
|
2013-10-20 15:15:30 +02:00
|
|
|
* This index will be used for ordering, grouping and limiting
|
2013-06-03 16:14:46 +02:00
|
|
|
*/
|
2013-10-20 15:15:30 +02:00
|
|
|
private function getFilteredIndices($classType = '\Icinga\Protocol\Statusdat\Query\Group')
|
2013-06-03 16:14:46 +02:00
|
|
|
{
|
2013-10-19 20:09:17 +02:00
|
|
|
$baseGroup = $this->queryFilter;
|
2013-10-20 15:15:30 +02:00
|
|
|
$state = $this->ds->getState();
|
2013-06-03 16:14:46 +02:00
|
|
|
$result = array();
|
2013-07-19 17:45:51 +02:00
|
|
|
$source = self::$VALID_TARGETS[$this->source];
|
2013-10-19 20:09:17 +02:00
|
|
|
|
2013-07-19 17:45:51 +02:00
|
|
|
foreach ($source as $target) {
|
2013-10-20 15:15:30 +02:00
|
|
|
|
2013-10-19 20:09:17 +02:00
|
|
|
if (! isset($state[$target])) {
|
|
|
|
continue;
|
|
|
|
}
|
2013-10-20 15:15:30 +02:00
|
|
|
|
2013-07-23 12:18:27 +02:00
|
|
|
$indexes = array_keys($state[$target]);
|
2013-06-03 16:14:46 +02:00
|
|
|
if ($baseGroup) {
|
2013-10-19 20:09:17 +02:00
|
|
|
$baseGroup->setQuery($this);
|
2013-10-21 17:04:05 +02:00
|
|
|
$idx = array_keys($state[$target]);
|
|
|
|
$indexes = $baseGroup->filter($state[$target], $idx );
|
2013-06-03 16:14:46 +02:00
|
|
|
}
|
|
|
|
if (!isset($result[$target])) {
|
|
|
|
$result[$target] = $indexes;
|
|
|
|
} else {
|
|
|
|
array_merge($result[$target], $indexes);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return $result;
|
|
|
|
}
|
|
|
|
|
2013-06-07 13:29:11 +02:00
|
|
|
/**
|
2013-10-20 15:15:30 +02:00
|
|
|
* Order the given result set
|
|
|
|
*
|
|
|
|
* @param array $indices The result set of the query that should be ordered
|
2013-06-07 13:29:11 +02:00
|
|
|
*/
|
|
|
|
private function orderIndices(array &$indices)
|
|
|
|
{
|
2013-10-15 19:56:33 +02:00
|
|
|
if (!empty($this->orderColumns)) {
|
2013-06-07 13:29:11 +02:00
|
|
|
foreach ($indices as $type => &$subindices) {
|
2013-10-19 20:09:17 +02:00
|
|
|
$this->currentType = $type;
|
2013-10-20 15:15:30 +02:00
|
|
|
usort($subindices, array($this, 'orderResult'));
|
2013-06-03 16:14:46 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-10-20 15:15:30 +02:00
|
|
|
/**
|
|
|
|
* Start a query
|
|
|
|
*
|
|
|
|
* This is just a dummy function to allow a more convenient syntax
|
|
|
|
*
|
|
|
|
* @return self Fluent interface
|
|
|
|
*/
|
2013-10-19 20:09:17 +02:00
|
|
|
public function select()
|
|
|
|
{
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
2013-06-07 13:29:11 +02:00
|
|
|
/**
|
2013-10-20 15:15:30 +02:00
|
|
|
* Order implementation called by usort
|
|
|
|
*
|
|
|
|
* @param String $a The left object index
|
|
|
|
* @param Strinv $b The right object index
|
|
|
|
* @return int 0, 1 or -1, see usort for detail
|
2013-06-07 13:29:11 +02:00
|
|
|
*/
|
|
|
|
private function orderResult($a, $b)
|
|
|
|
{
|
2013-07-23 12:18:27 +02:00
|
|
|
$o1 = $this->ds->getObjectByName($this->currentType, $a);
|
|
|
|
$o2 = $this->ds->getObjectByName($this->currentType, $b);
|
2013-06-03 16:14:46 +02:00
|
|
|
$result = 0;
|
2013-10-19 20:09:17 +02:00
|
|
|
|
|
|
|
foreach ($this->orderColumns as &$col) {
|
|
|
|
if (is_array($col[0])) {
|
2013-10-20 15:15:30 +02:00
|
|
|
// sort by function
|
|
|
|
$result += $col[1] * strnatcasecmp(
|
|
|
|
$col[0][0]->$col[0][1]($o1),
|
|
|
|
$col[0][0]->$col[0][1]($o2)
|
|
|
|
);
|
2013-10-19 20:09:17 +02:00
|
|
|
} else {
|
2013-10-20 15:15:30 +02:00
|
|
|
$result += $col[1] * strnatcasecmp($o1->{$col[0]}, $o2->{$col[0]});
|
2013-10-19 20:09:17 +02:00
|
|
|
}
|
2013-06-07 13:29:11 +02:00
|
|
|
}
|
2013-10-19 20:09:17 +02:00
|
|
|
return $result;
|
2013-06-03 16:14:46 +02:00
|
|
|
}
|
|
|
|
|
2013-06-07 13:29:11 +02:00
|
|
|
/**
|
2013-10-20 15:15:30 +02:00
|
|
|
* Limit the given resultset
|
|
|
|
*
|
|
|
|
* @param array $indices The filtered, ordered indices
|
2013-06-07 13:29:11 +02:00
|
|
|
*/
|
2013-06-03 16:14:46 +02:00
|
|
|
private function limitIndices(array &$indices)
|
|
|
|
{
|
2013-06-07 13:29:11 +02:00
|
|
|
foreach ($indices as $type => $subindices) {
|
2013-10-20 15:15:30 +02:00
|
|
|
$indices[$type] = array_slice($subindices, $this->getOffset(), $this->getLimit());
|
2013-06-03 16:14:46 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-06-07 13:29:11 +02:00
|
|
|
/**
|
2013-10-20 15:15:30 +02:00
|
|
|
* Register the given function for grouping the result
|
|
|
|
*
|
|
|
|
* @param String $fn The function to use for grouping
|
|
|
|
* @param Object $scope An optional scope to use instead of $this
|
|
|
|
*
|
|
|
|
* @return self Fluent interface
|
2013-06-07 13:29:11 +02:00
|
|
|
*/
|
|
|
|
public function groupByFunction($fn, $scope = null)
|
2013-06-03 16:14:46 +02:00
|
|
|
{
|
2013-06-07 13:29:11 +02:00
|
|
|
$this->groupByFn = array($scope ? $scope : $this, $fn);
|
2013-06-03 16:14:46 +02:00
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
2013-06-07 13:29:11 +02:00
|
|
|
/**
|
2013-10-20 15:15:30 +02:00
|
|
|
* Group by the given column
|
|
|
|
*
|
|
|
|
* @param array|string $columns The columns to use for grouping
|
|
|
|
* @return self Fluent interface
|
|
|
|
* @see Query::columnGroupFn() The implementation used for grouping
|
2013-06-07 13:29:11 +02:00
|
|
|
*/
|
2013-06-03 16:14:46 +02:00
|
|
|
public function groupByColumns($columns)
|
|
|
|
{
|
2013-06-07 13:29:11 +02:00
|
|
|
if (!is_array($columns)) {
|
2013-06-03 16:14:46 +02:00
|
|
|
$columns = array($columns);
|
2013-06-07 13:29:11 +02:00
|
|
|
}
|
2013-06-03 16:14:46 +02:00
|
|
|
$this->groupColumns = $columns;
|
2013-10-20 15:15:30 +02:00
|
|
|
$this->groupByFn = array($this, 'columnGroupFn');
|
2013-06-03 16:14:46 +02:00
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
2013-06-07 13:29:11 +02:00
|
|
|
/**
|
2013-10-20 15:15:30 +02:00
|
|
|
* The internal handler function used by the group function
|
|
|
|
*
|
|
|
|
* @param array $indices The indices to group
|
|
|
|
* @return array The grouped result set
|
2013-06-07 13:29:11 +02:00
|
|
|
*/
|
2013-06-03 16:14:46 +02:00
|
|
|
private function columnGroupFn(array &$indices)
|
|
|
|
{
|
|
|
|
$cols = $this->groupColumns;
|
|
|
|
$result = array();
|
2013-06-07 13:29:11 +02:00
|
|
|
foreach ($indices as $type => $subindices) {
|
|
|
|
foreach ($subindices as $objectIndex) {
|
2013-07-23 12:18:27 +02:00
|
|
|
$r = $this->ds->getObjectByName($type, $objectIndex);
|
2013-10-20 15:15:30 +02:00
|
|
|
$hash = '';
|
2013-06-03 16:14:46 +02:00
|
|
|
$cols = array();
|
2013-06-07 13:29:11 +02:00
|
|
|
foreach ($this->groupColumns as $col) {
|
|
|
|
$hash = md5($hash . $r->$col);
|
2013-06-03 16:14:46 +02:00
|
|
|
$cols[$col] = $r->$col;
|
|
|
|
}
|
2013-06-07 13:29:11 +02:00
|
|
|
if (!isset($result[$hash])) {
|
|
|
|
$result[$hash] = (object)array(
|
2013-10-20 15:15:30 +02:00
|
|
|
'columns' => (object)$cols,
|
|
|
|
'count' => 0
|
2013-06-03 16:14:46 +02:00
|
|
|
);
|
2013-06-07 13:29:11 +02:00
|
|
|
}
|
2013-06-03 16:14:46 +02:00
|
|
|
$result[$hash]->count++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return array_values($result);
|
|
|
|
}
|
|
|
|
|
2013-06-07 13:29:11 +02:00
|
|
|
/**
|
2013-10-20 15:15:30 +02:00
|
|
|
* Query Filter, Order, Group, Limit and return the result set
|
|
|
|
*
|
|
|
|
* @return array The resultset matching this query
|
2013-06-07 13:29:11 +02:00
|
|
|
*/
|
2013-06-03 16:14:46 +02:00
|
|
|
public function getResult()
|
|
|
|
{
|
2013-07-23 12:18:27 +02:00
|
|
|
$indices = $this->getFilteredIndices();
|
2013-06-03 16:14:46 +02:00
|
|
|
$this->orderIndices($indices);
|
2013-06-07 13:29:11 +02:00
|
|
|
if ($this->groupByFn) {
|
2013-06-03 16:14:46 +02:00
|
|
|
$scope = $this->groupByFn[self::FN_SCOPE];
|
2013-06-07 13:29:11 +02:00
|
|
|
$fn = $this->groupByFn[self::FN_NAME];
|
2013-06-03 16:14:46 +02:00
|
|
|
|
|
|
|
return $scope->$fn($indices);
|
2013-06-07 13:29:11 +02:00
|
|
|
}
|
2013-06-03 16:14:46 +02:00
|
|
|
|
|
|
|
$this->limitIndices($indices);
|
|
|
|
|
|
|
|
$result = array();
|
2013-10-20 15:15:30 +02:00
|
|
|
$state = $this->ds->getState();
|
|
|
|
|
2013-06-07 13:29:11 +02:00
|
|
|
foreach ($indices as $type => $subindices) {
|
|
|
|
foreach ($subindices as $index) {
|
|
|
|
$result[] = & $state[$type][$index];
|
2013-06-03 16:14:46 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return $result;
|
|
|
|
}
|
2013-10-15 20:21:40 +02:00
|
|
|
|
2013-10-21 16:02:46 +02:00
|
|
|
|
2013-10-15 20:21:40 +02:00
|
|
|
/**
|
2013-10-19 20:09:17 +02:00
|
|
|
* Apply all filters of this filterable on the datasource
|
2013-10-15 20:21:40 +02:00
|
|
|
*/
|
2013-10-19 20:09:17 +02:00
|
|
|
public function applyFilter()
|
2013-10-15 20:21:40 +02:00
|
|
|
{
|
2013-10-19 20:09:17 +02:00
|
|
|
$parser = new TreeToStatusdatQueryParser();
|
|
|
|
if ($this->getFilter()) {
|
2013-10-20 15:15:30 +02:00
|
|
|
$query = $parser->treeToQuery($this->getFilter(), $this);
|
2013-10-19 20:09:17 +02:00
|
|
|
$this->setQueryFilter($query);
|
|
|
|
}
|
|
|
|
|
2013-10-15 20:21:40 +02:00
|
|
|
}
|
|
|
|
|
2013-10-19 20:09:17 +02:00
|
|
|
/**
|
2013-10-21 16:02:46 +02:00
|
|
|
* Return only the first row fetched from the result set
|
2013-10-20 15:15:30 +02:00
|
|
|
*
|
|
|
|
* @return MonitoringObjectList The monitoring object matching this query
|
2013-10-19 20:09:17 +02:00
|
|
|
*/
|
|
|
|
public function fetchRow()
|
|
|
|
{
|
2013-10-21 16:02:46 +02:00
|
|
|
$rs = $this->fetchAll();
|
|
|
|
$rs->rewind();
|
|
|
|
return $rs->current();
|
2013-10-19 20:09:17 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2013-10-20 15:15:30 +02:00
|
|
|
* Fetch the result as an associative array using the first column as the key and the second as the value
|
|
|
|
*
|
|
|
|
* @return array An associative array with the result
|
|
|
|
* @throws \Exception If no attributes are defined
|
2013-10-19 20:09:17 +02:00
|
|
|
*/
|
|
|
|
public function fetchPairs()
|
|
|
|
{
|
|
|
|
$result = array();
|
|
|
|
if (count($this->getColumns()) < 2) {
|
|
|
|
throw new Exception(
|
|
|
|
'Status.dat "fetchPairs()" query expects at least' .
|
|
|
|
' columns to be set in the query expression'
|
|
|
|
);
|
|
|
|
}
|
|
|
|
$attributes = $this->getColumns();
|
|
|
|
|
|
|
|
$param1 = $attributes[0];
|
|
|
|
$param2 = $attributes[1];
|
|
|
|
foreach ($this->fetchAll() as $resultList) {
|
|
|
|
$result[$resultList->$param1] = $resultList->$param2;
|
|
|
|
}
|
|
|
|
|
|
|
|
return $result;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2013-10-20 15:15:30 +02:00
|
|
|
* Fetch all results
|
|
|
|
*
|
|
|
|
* @return MonitoringObjectList An MonitoringObjectList wrapping the given resultset
|
2013-10-19 20:09:17 +02:00
|
|
|
*/
|
|
|
|
public function fetchAll()
|
|
|
|
{
|
|
|
|
$this->applyFilter();
|
|
|
|
if (!isset($this->cursor)) {
|
|
|
|
$result = $this->getResult();
|
|
|
|
$this->cursor = new MonitoringObjectList($result, $this);
|
|
|
|
}
|
|
|
|
return $this->cursor;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2013-10-21 16:02:46 +02:00
|
|
|
* Return the value of the first column for the first row fetched from the result set
|
2013-10-20 15:15:30 +02:00
|
|
|
*/
|
|
|
|
public function fetchOne()
|
|
|
|
{
|
2013-10-21 16:02:46 +02:00
|
|
|
throw new ProgrammingError('Statusdat/Query::fetchOne not yet implemented');
|
2013-10-20 15:15:30 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Count the number of results
|
|
|
|
*
|
|
|
|
* @return int
|
2013-10-19 20:09:17 +02:00
|
|
|
*/
|
|
|
|
public function count()
|
2013-10-15 20:21:40 +02:00
|
|
|
{
|
2013-10-19 20:09:17 +02:00
|
|
|
$q = clone $this;
|
|
|
|
$q->limit(null, null);
|
|
|
|
return count($q->fetchAll());
|
2013-10-15 20:21:40 +02:00
|
|
|
}
|
2013-06-03 16:14:46 +02:00
|
|
|
}
|