Merge pull request #3868 from Icinga/feature/subquery-filter-in-chain
Support subquery filters in filter chains
This commit is contained in:
commit
00e499024f
|
@ -21,6 +21,22 @@ abstract class FilterChain extends Filter
|
|||
|
||||
protected $allowedColumns;
|
||||
|
||||
/**
|
||||
* Set the filters
|
||||
*
|
||||
* @param array $filters
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setFilters(array $filters)
|
||||
{
|
||||
$this->filters = $filters;
|
||||
|
||||
$this->refreshChildIds();
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function hasId($id)
|
||||
{
|
||||
foreach ($this->filters() as $filter) {
|
||||
|
|
|
@ -55,11 +55,8 @@ class TacticalController extends Controller
|
|||
$this->setupFilterControl($stats, null, ['host', 'service'], ['format']);
|
||||
$this->view->setHelperFunction('filteredUrl', function ($path, array $params) {
|
||||
$filter = clone $this->view->filterEditor->getFilter();
|
||||
foreach ($params as $column => $value) {
|
||||
$filter = $filter->andFilter($filter->where($column, $value));
|
||||
}
|
||||
|
||||
return $this->view->url($path)->setQueryString($filter->toQueryString());
|
||||
return $this->view->url($path)->setParams($params)->addFilter($filter);
|
||||
});
|
||||
|
||||
$this->handleFormatRequest($stats);
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
<?php
|
||||
|
||||
use Icinga\Module\Monitoring\Web\Widget\StateBadges;
|
||||
|
||||
if (! $this->compact): ?>
|
||||
|
@ -42,12 +43,15 @@ if (! $this->compact): ?>
|
|||
<th>
|
||||
<?= $this->qlink(
|
||||
$hostGroup->hostgroup_alias,
|
||||
$this->url('monitoring/list/hosts')->addFilter($this->filterEditor->getFilter()),
|
||||
array('hostgroup_name' => $hostGroup->hostgroup_name, 'sort' => 'host_severity'),
|
||||
array('title' => sprintf(
|
||||
$this
|
||||
->url('monitoring/list/hosts')
|
||||
->setParams(['hostgroup_name' => $hostGroup->hostgroup_name])
|
||||
->addFilter($this->filterEditor->getFilter()),
|
||||
['sort' => 'host_severity'],
|
||||
['title' => sprintf(
|
||||
$this->translate('List all hosts in the group "%s"'),
|
||||
$hostGroup->hostgroup_alias
|
||||
))
|
||||
)]
|
||||
) ?>
|
||||
</th>
|
||||
<td>
|
||||
|
@ -140,12 +144,18 @@ if (! $this->compact): ?>
|
|||
<td class="count-col">
|
||||
<?= $this->qlink(
|
||||
$hostGroup->services_total,
|
||||
$this->url('monitoring/list/services')->addFilter($this->filterEditor->getFilter()),
|
||||
array('hostgroup_name' => $hostGroup->hostgroup_name, 'sort' => 'service_severity'),
|
||||
array('title' => sprintf(
|
||||
$this->translate('List all services of all hosts in host group "%s"'),
|
||||
$hostGroup->hostgroup_alias
|
||||
), 'class' => 'badge')
|
||||
$this
|
||||
->url('monitoring/list/services')
|
||||
->setParams(['hostgroup_name' => $hostGroup->hostgroup_name])
|
||||
->addFilter($this->filterEditor->getFilter()),
|
||||
['sort' => 'service_severity'],
|
||||
[
|
||||
'title' => sprintf(
|
||||
$this->translate('List all services of all hosts in host group "%s"'),
|
||||
$hostGroup->hostgroup_alias
|
||||
),
|
||||
'class' => 'badge'
|
||||
]
|
||||
) ?>
|
||||
</td>
|
||||
<td>
|
||||
|
|
|
@ -38,9 +38,12 @@ if (! $this->compact): ?>
|
|||
<th>
|
||||
<?= $this->qlink(
|
||||
$serviceGroup->servicegroup_alias,
|
||||
$this->url('monitoring/list/services')->addFilter($this->filterEditor->getFilter()),
|
||||
array('servicegroup_name' => $serviceGroup->servicegroup_name, 'sort' => 'service_severity'),
|
||||
array('title' => sprintf($this->translate('List all services in the group "%s"'), $serviceGroup->servicegroup_alias))
|
||||
$this
|
||||
->url('monitoring/list/services')
|
||||
->setParams(['servicegroup_name' => $serviceGroup->servicegroup_name])
|
||||
->addFilter($this->filterEditor->getFilter()),
|
||||
['sort' => 'service_severity'],
|
||||
['title' => sprintf($this->translate('List all services in the group "%s"'), $serviceGroup->servicegroup_alias)]
|
||||
) ?>
|
||||
</th>
|
||||
<td>
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
namespace Icinga\Module\Monitoring\Backend\Ido\Query;
|
||||
|
||||
use Icinga\Data\Filter\FilterNot;
|
||||
use Zend_Db_Expr;
|
||||
use Icinga\Application\Icinga;
|
||||
use Icinga\Application\Hook;
|
||||
|
@ -559,7 +560,7 @@ abstract class IdoQuery extends DbQuery
|
|||
if (count($expr) === 1 && strpos($expr[0], '&') !== false) {
|
||||
// Our current filter implementation does not specify & as a control character so the count of the
|
||||
// expression array is always one in this case
|
||||
$expr = explode('&', $expr[0]);
|
||||
$expr = array_unique(explode('&', $expr[0]));
|
||||
$subQueryFilter->setExpression($expr);
|
||||
$and = true;
|
||||
} else {
|
||||
|
@ -691,6 +692,60 @@ abstract class IdoQuery extends DbQuery
|
|||
|
||||
$filter->setColumn($column);
|
||||
} else {
|
||||
if (! $filter instanceof FilterNot) {
|
||||
// Allow subquery filters in a filter chain
|
||||
$columns = $filter->listFilteredColumns();
|
||||
if (count($columns) === 1) {
|
||||
$column = $columns[0];
|
||||
$virtualTable = $this->aliasToTableName($column);
|
||||
if (isset($this->subQueryTargets[$virtualTable])) {
|
||||
$lastSign = null;
|
||||
$filters = [];
|
||||
$expressions = [];
|
||||
foreach ($filter->filters() as $child) {
|
||||
switch (true) {
|
||||
case $child instanceof FilterExpression:
|
||||
$expression = $child->getExpression();
|
||||
if (! is_array($expression)) {
|
||||
break;
|
||||
}
|
||||
// Move to default
|
||||
default:
|
||||
$filters[] = $child;
|
||||
continue 2;
|
||||
}
|
||||
if ($lastSign === null) {
|
||||
$lastSign = $child->getSign();
|
||||
} else {
|
||||
$sign = $child->getSign();
|
||||
if ($sign !== $lastSign) {
|
||||
$filters[] = new FilterExpression(
|
||||
$column,
|
||||
$lastSign,
|
||||
$filter->getOperatorSymbol() === '&'
|
||||
? [implode('&', $expressions)]
|
||||
: $expressions
|
||||
);
|
||||
$expressions = [];
|
||||
$lastSign = $sign;
|
||||
}
|
||||
}
|
||||
$expressions[] = $expression;
|
||||
}
|
||||
if (! empty($expressions)) {
|
||||
$filters[] = new FilterExpression(
|
||||
$column,
|
||||
$lastSign,
|
||||
$filter->getOperatorSymbol() === '&'
|
||||
? [implode('&', $expressions)]
|
||||
: $expressions
|
||||
);
|
||||
}
|
||||
$filter->setFilters($filters);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($filter->filters() as $child) {
|
||||
$replacement = $this->requireFilterColumns($child);
|
||||
if ($replacement !== null) {
|
||||
|
|
|
@ -298,6 +298,8 @@ class ServicegroupQuery extends IdoQuery
|
|||
$additionalFilter = clone $filter;
|
||||
}
|
||||
|
||||
$this->requireVirtualTable('members');
|
||||
|
||||
$query->joinVirtualTable('members');
|
||||
|
||||
return ['sgm.service_object_id', 'so.object_id'];
|
||||
|
|
Loading…
Reference in New Issue