From b8fb193bdde53dc4006499a525e97a163612041e Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Thu, 11 Jul 2019 14:39:58 +0200 Subject: [PATCH 1/8] Add FilterChain::setFilters() --- library/Icinga/Data/Filter/FilterChain.php | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/library/Icinga/Data/Filter/FilterChain.php b/library/Icinga/Data/Filter/FilterChain.php index 7e377d91f..1c5cdf956 100644 --- a/library/Icinga/Data/Filter/FilterChain.php +++ b/library/Icinga/Data/Filter/FilterChain.php @@ -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) { From 9a75e101eeaf545984a62c99c01df07805bf3ed4 Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Thu, 11 Jul 2019 14:46:30 +0200 Subject: [PATCH 2/8] Support subquery filters in filter chains Before, combined membership filters were only possible in filter expressions, e.g. hostgroup_name=(a&b). Now, also (hostgroup_name=a&hostgroup_name=b) is supported which makes it easier to build such filters with the filter editor. --- .../Monitoring/Backend/Ido/Query/IdoQuery.php | 42 +++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/IdoQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/IdoQuery.php index df1de61d1..89f70efec 100644 --- a/modules/monitoring/library/Monitoring/Backend/Ido/Query/IdoQuery.php +++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/IdoQuery.php @@ -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; @@ -691,6 +692,47 @@ 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) { + 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[] = $child->getExpression(); + } + $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) { From cc94c12e55239baba48989a12df4db2b9c4c1d23 Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Thu, 11 Jul 2019 14:50:09 +0200 Subject: [PATCH 3/8] Fix show all hosts/services links in the hostgroup overview Before, the forced hostgroup_name paramemter may interfere with an existing hostgroup_name filter. --- .../views/scripts/list/hostgroups.phtml | 30 ++++++++++++------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/modules/monitoring/application/views/scripts/list/hostgroups.phtml b/modules/monitoring/application/views/scripts/list/hostgroups.phtml index a2b8a1efb..aab39f800 100644 --- a/modules/monitoring/application/views/scripts/list/hostgroups.phtml +++ b/modules/monitoring/application/views/scripts/list/hostgroups.phtml @@ -1,4 +1,5 @@ compact): ?> @@ -42,12 +43,15 @@ if (! $this->compact): ?> 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 - )) + )] ) ?> @@ -140,12 +144,18 @@ if (! $this->compact): ?> 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' + ] ) ?> From 58e3ae46a72d11dc6b7f415b85c0039adb3ab310 Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Tue, 16 Jul 2019 10:12:00 +0200 Subject: [PATCH 4/8] Fix servicegroup subquery filter in the servicegroup view --- .../library/Monitoring/Backend/Ido/Query/ServicegroupQuery.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/ServicegroupQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/ServicegroupQuery.php index bdf08fb38..d43c7d7a3 100644 --- a/modules/monitoring/library/Monitoring/Backend/Ido/Query/ServicegroupQuery.php +++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/ServicegroupQuery.php @@ -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']; From bee5099a085550a1bed44091ef8bab54fdfbef72 Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Tue, 16 Jul 2019 10:12:33 +0200 Subject: [PATCH 5/8] Fix show all services links in the servicegroup overview Before, the forced servicegroup_name paramemter may interfere with an existing servicegroup_name filter. --- .../application/views/scripts/list/servicegroups.phtml | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/modules/monitoring/application/views/scripts/list/servicegroups.phtml b/modules/monitoring/application/views/scripts/list/servicegroups.phtml index 1e4103f6a..431fc8e56 100644 --- a/modules/monitoring/application/views/scripts/list/servicegroups.phtml +++ b/modules/monitoring/application/views/scripts/list/servicegroups.phtml @@ -38,9 +38,12 @@ if (! $this->compact): ?> 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)] ) ?> From 0de923fc5ff1b5b4e7821d08090558dc6579afc8 Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Tue, 16 Jul 2019 14:24:33 +0200 Subject: [PATCH 6/8] Support "old" combined group membership filter in subquery filter chains --- .../Monitoring/Backend/Ido/Query/IdoQuery.php | 29 ++++++++++++++----- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/IdoQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/IdoQuery.php index 89f70efec..723227a4a 100644 --- a/modules/monitoring/library/Monitoring/Backend/Ido/Query/IdoQuery.php +++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/IdoQuery.php @@ -703,6 +703,17 @@ abstract class IdoQuery extends DbQuery $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 { @@ -719,15 +730,17 @@ abstract class IdoQuery extends DbQuery $lastSign = $sign; } } - $expressions[] = $child->getExpression(); + $expressions[] = $expression; + } + if (! empty($expressions)) { + $filters[] = new FilterExpression( + $column, + $lastSign, + $filter->getOperatorSymbol() === '&' + ? [implode('&', $expressions)] + : $expressions + ); } - $filters[] = new FilterExpression( - $column, - $lastSign, - $filter->getOperatorSymbol() === '&' - ? [implode('&', $expressions)] - : $expressions - ); $filter->setFilters($filters); } } From e61cb71c17e16342af556bacb7c8d98935f71752 Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Tue, 16 Jul 2019 14:25:03 +0200 Subject: [PATCH 7/8] Use unique values for combined AND group membership filters --- .../library/Monitoring/Backend/Ido/Query/IdoQuery.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/IdoQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/IdoQuery.php index 723227a4a..7a39f48d1 100644 --- a/modules/monitoring/library/Monitoring/Backend/Ido/Query/IdoQuery.php +++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/IdoQuery.php @@ -560,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 { From ac08fb2c3be5f8ada034b6a6bd2c92aeedd9bba3 Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Fri, 26 Jul 2019 14:35:50 +0200 Subject: [PATCH 8/8] Fix filtered links in the tactical overview Filter chains require parantheses to work properly. --- .../application/controllers/TacticalController.php | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/modules/monitoring/application/controllers/TacticalController.php b/modules/monitoring/application/controllers/TacticalController.php index c60a373bb..6f9ae7fef 100644 --- a/modules/monitoring/application/controllers/TacticalController.php +++ b/modules/monitoring/application/controllers/TacticalController.php @@ -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);