From 421f47d08d84874ffdd38bc6916e28d1d00c69d7 Mon Sep 17 00:00:00 2001 From: Thomas Gelf Date: Fri, 10 Jan 2020 17:41:13 +0100 Subject: [PATCH 1/5] IcingaObjectResolver: new for ServicesetController --- .../controllers/ServicesetController.php | 13 +- .../Resolver/IcingaHostObjectResolver.php | 44 ++ .../Resolver/IcingaObjectResolver.php | 510 ++++++++++++++++++ .../Table/IcingaHostsMatchingFilterTable.php | 75 +++ 4 files changed, 641 insertions(+), 1 deletion(-) create mode 100644 library/Director/Resolver/IcingaHostObjectResolver.php create mode 100644 library/Director/Resolver/IcingaObjectResolver.php create mode 100644 library/Director/Web/Table/IcingaHostsMatchingFilterTable.php diff --git a/application/controllers/ServicesetController.php b/application/controllers/ServicesetController.php index dec7de43..93792745 100644 --- a/application/controllers/ServicesetController.php +++ b/application/controllers/ServicesetController.php @@ -2,11 +2,13 @@ namespace Icinga\Module\Director\Controllers; +use Icinga\Data\Filter\Filter; use Icinga\Module\Director\Forms\IcingaServiceSetForm; use Icinga\Module\Director\Objects\IcingaHost; use Icinga\Module\Director\Objects\IcingaServiceSet; use Icinga\Module\Director\Web\Controller\ObjectController; use Icinga\Module\Director\Web\Form\DirectorObjectForm; +use Icinga\Module\Director\Web\Table\IcingaHostsMatchingFilterTable; use Icinga\Module\Director\Web\Table\IcingaServiceSetHostTable; use Icinga\Module\Director\Web\Table\IcingaServiceSetServiceTable; use gipfl\IcingaWeb2\Link; @@ -82,7 +84,16 @@ class ServicesetController extends ObjectController $set->getObjectName() ); - IcingaServiceSetHostTable::load($set)->renderTo($this); + $table = IcingaServiceSetHostTable::load($set); + if ($table->count()) { + $table->renderTo($this); + } + $filter = $set->get('assign_filter'); + if (\strlen($filter) > 0) { + $this->content()->add( + IcingaHostsMatchingFilterTable::load(Filter::fromQueryString($filter), $this->db()) + ); + } } protected function addServiceSetTabs() diff --git a/library/Director/Resolver/IcingaHostObjectResolver.php b/library/Director/Resolver/IcingaHostObjectResolver.php new file mode 100644 index 00000000..210645f6 --- /dev/null +++ b/library/Director/Resolver/IcingaHostObjectResolver.php @@ -0,0 +1,44 @@ + 'icinga_command', + 'event_command_id' => 'icinga_command', + 'check_period_id' => 'icinga_timeperiod', + 'command_endpoint_id' => 'icinga_endpoint', + 'zone_id' => 'icinga_zone', + ]; + + protected $booleans = [ + 'enable_notifications', + 'enable_active_checks', + 'enable_passive_checks', + 'enable_event_handler', + 'enable_flapping', + 'enable_perfdata', + 'volatile', + ]; +} diff --git a/library/Director/Resolver/IcingaObjectResolver.php b/library/Director/Resolver/IcingaObjectResolver.php new file mode 100644 index 00000000..8a4e9b96 --- /dev/null +++ b/library/Director/Resolver/IcingaObjectResolver.php @@ -0,0 +1,510 @@ +baseTable . ' warming up'); + $this->db = $db; + // Fetch: ignore disabled? + $this->prepareNameMaps(); + $this->templates = []; + foreach ($this->fetchPlainObjects($this->baseTable, 'template') as $template) { + $id = $template->id; + $this->stripIgnoredProperties($template); + // Let's to this only on final objects: + // $this->replaceRelatedNames($object); + // $this->convertBooleans($object); + $this->stripNullProperties($template); + $this->templates[$id] = (array) $template; + } + $this->templateVars = $this->fetchTemplateVars(); + // Using already resolved data, so this is unused right now: + // $this->groupMemberShips = $this->fetchAllGroups(); + $this->resolvedGroupMemberShips = $this->fetchAllResolvedGroups(); + $this->inheritancePaths = $this->fetchInheritancePaths($this->baseTable, 'host_id'); + foreach ($this->inheritancePaths as $path) { + if (! isset($this->resolvedTemplateProperties[$path])) { + $properties = (object) $this->getResolvedProperties($path); + $this->replaceRelatedNames($properties); + $this->convertBooleans($properties); + $this->resolvedTemplateProperties[$path] = $properties; + $this->resolvedTemplateVars[$path] = $this->getResolvedVars($path); + } + } + + Benchmark::measure('Object Resolver for ' . $this->baseTable . ' is ready'); + + // Notes: + // default != null: + // most icinga objects: disabled => n + // Icinga(ScheduledDowntime|TimePeriod)Range: range_type => include, merge_behaviour => set + // IcingaTemplateChoice: min_required => 0, max_allowed => 1 + // IcingaZone: is_global => n + // ImportSource: import_state => unknown + // SyncRule: sync_state => unknown + } + + protected static function addUniqueMembers(&$list, $newMembers) + { + foreach ($newMembers as $member) { + $pos = \array_search($member, $list); + if ($pos !== false) { + unset($list[$pos]); + } + + \array_unshift($list, $member); + } + } + + public function fetchResolvedObjects() + { + $objects = []; + $allVars = $this->fetchNonTemplateVars(); + foreach ($this->fetchPlainObjects($this->baseTable, 'object') as $object) { + $id = $object->id; // id will be stripped + $objects[$id] = $this->enrichObject($object, $allVars); + } + + return $objects; + } + + public function fetchObjectsMatchingFilter(Filter $filter) + { + DynamicApplyMatches::setType($this->getType()); + DynamicApplyMatches::fixFilterColumns($filter); + $objects = []; + $allVars = $this->fetchNonTemplateVars(); + foreach ($this->fetchPlainObjects($this->baseTable, 'object') as $object) { + $id = $object->id; // id will be stripped + if ($filter->matches($object)) { + $objects[$id] = $this->enrichObject($object, $allVars); + } + } + + return $objects; + } + + protected function enrichObject($object, $allVars) + { + $id = $object->id; + $this->stripIgnoredProperties($object); + if (isset($allVars[$id])) { + $vars = $allVars[$id]; + } else { + $vars = []; + } + $vars += $this->getInheritedVarsById($id); + + // There is no merge, +/-, not yet. Unused, as we use resolved groups: + // if (isset($this->groupMemberShips[$id])) { + // $groups = $this->groupMemberShips[$id]; + // } else { + // $groups = $this->getInheritedGroupsById($id); + // } + if (isset($this->resolvedGroupMemberShips[$id])) { + $groups = $this->resolvedGroupMemberShips[$id]; + } else { + $groups = []; + } + + foreach ($this->getInheritedPropertiesById($id) as $property => $value) { + if (! isset($object->$property)) { + $object->$property = $value; + } + } + $this->replaceRelatedNames($object); + $this->convertBooleans($object); + $this->stripNullProperties($object); + if (! empty($vars)) { + $object->vars = (object) $vars; + static::flattenVars($object); + } + if (! empty($groups)) { + $object->groups = $groups; + } + + return $object; + } + + /** + * @param string $baseTable e.g. icinga_host + * @param string $relColumn e.g. host_id + * @return array + */ + protected function fetchInheritancePaths($baseTable, $relColumn) + { + // select host_id, GROUP_CONCAT(parent_host_id ORDER BY weight) FROM icinga_host_inheritance group by host_id; + $query = $this->db->select() + ->from([ + 'oi' => "${baseTable}_inheritance" + ], [ + $relColumn, + "GROUP_CONCAT(parent_$relColumn ORDER BY weight SEPARATOR ',')" + ]) + ->group($relColumn) + ->order("LENGTH(GROUP_CONCAT(parent_$relColumn ORDER BY weight SEPARATOR ','))"); + + // pgsql: ARRAY_TO_STRING(ARRAY_AGG(---), ',') -> order? + + return $this->db->fetchPairs($query); + } + + protected function getInheritedPropertiesById($objectId) + { + if (isset($this->inheritancePaths[$objectId])) { + return $this->getResolvedProperties($this->inheritancePaths[$objectId]); + } else { + return []; + } + } + + protected function getInheritedVarsById($objectId) + { + if (isset($this->inheritancePaths[$objectId])) { + return $this->getResolvedVars($this->inheritancePaths[$objectId]); + } else { + return []; + } + } + + protected function getInheritedGroupsById($objectId) + { + if (isset($this->inheritancePaths[$objectId])) { + return $this->getResolvedGroups($this->inheritancePaths[$objectId]); + } else { + return []; + } + } + + /** + * @param $path + * @return array[] + */ + protected function getResolvedProperties($path) + { + $pos = \strpos($path, ','); + if ($pos === false) { + return $this->templates[$path]; + } else { + $first = \substr($path, 0, $pos); + $parentPath = \substr($path, $pos + 1); + $result = $this->templates[$first] + + $this->getResolvedProperties($parentPath); + unset($result['object_name']); + + return $result; + } + } + + protected function getResolvedVars($path) + { + $pos = \strpos($path, ','); + if ($pos === false) { + if (isset($this->templateVars[$path])) { + return $this->templateVars[$path]; + } else { + return []; + } + } else { + $first = \substr($path, 0, $pos); + $parentPath = \substr($path, $pos + 1); + return $this->getResolvedVars($first) + + $this->getResolvedVars($parentPath); + } + } + + protected function getResolvedGroups($path) + { + $pos = \strpos($path, ','); + if ($pos === false) { + if (isset($this->groupMemberShips[$path])) { + return $this->groupMemberShips[$path]; + } else { + return []; + } + } else { + $first = \substr($path, 0, $pos); + $parentPath = \substr($path, $pos + 1); + $currentGroups = $this->getResolvedVars($first); + + // There is no merging +/-, not yet + if (empty($currentGroups)) { + return $this->getResolvedVars($parentPath); + } else { + return $currentGroups; + } + } + } + + protected function cleanupObjects(&$objects) + { + foreach ($objects as $object) { + $this->stripIgnoredProperties($object); + $this->replaceRelatedNames($object); + $this->convertBooleans($object); + } + } + + protected function fetchPlainObjects($table, $objectType = null) + { + $query = $this->db->select() + ->from(['o' => $table]) + ->order('o.object_name'); + + if ($objectType !== null) { + $query->where('o.object_type = ?', $objectType); + } + + return $this->db->fetchAll($query); + } + + + /** + * @param \stdClass $object + */ + protected function replaceRelatedNames($object) + { + foreach ($this->nameMaps as $property => $map) { + if (\property_exists($object, $property)) { + // Hint: substr strips _id + if ($object->$property === null) { + $object->{\substr($property, 0, -3)} = null; + } else { + $object->{\substr($property, 0, -3)} = $map[$object->$property]; + } + unset($object->$property); + } + } + } + + protected function translateTemplateIdsToNames($ids) + { + $names = []; + foreach ($ids as $id) { + if (isset($this->templates[$id])) { + $names[] = $this->templates[$id]->object_name; + } else { + throw new \RuntimeException("There is no template with ID $id"); + } + } + + return $names; + } + + protected function stripIgnoredProperties($object) + { + foreach ($this->ignoredProperties as $key) { + unset($object->$key); + } + } + + public function prepareNameMaps() + { + // TODO: fetch from dummy Object? How to ignore irrelevant ones like choices? + $relatedNames = []; + foreach ($this->relatedTables as $key => $relatedTable) { + $relatedNames[$key] = $this->fetchRelationMap($this->baseTable, $relatedTable, $key); + } + + $this->nameMaps = $relatedNames; + } + + protected function convertBooleans($object) + { + foreach ($this->booleans as $property) { + if (\property_exists($object, $property) && $object->$property !== null) { + // Hint: substr strips _id + $object->$property = $object->$property === 'y'; + } + } + } + + protected function stripNullProperties($object) + { + foreach (\array_keys((array) $object) as $property) { + if ($object->$property === null) { + unset($object->$property); + } + } + } + + protected function fetchRelationMap($sourceTable, $destinationTable, $property) + { + $query = $this->db->select() + ->from(['d' => $destinationTable], ['d.id', 'd.object_name']) + ->join(['o' => $sourceTable], "d.id = o.$property", []) + ->order('d.object_name'); + + return $this->db->fetchPairs($query); + } + + protected function fetchTemplateVars() + { + $query = $this->prepareVarsQuery()->where('o.object_type = ?', 'template'); + return $this->fetchAndCombineVars($query); + } + + protected function fetchNonTemplateVars() + { + $query = $this->prepareVarsQuery()->where('o.object_type != ?', 'template'); + return $this->fetchAndCombineVars($query); + } + + protected function fetchAndCombineVars($query) + { + $vars = []; + foreach ($this->db->fetchAll($query) as $var) { + $id = $var->object_id; + if (! isset($vars[$id])) { + $vars[$id] = []; + } + if ($var->format === 'json') { + $vars[$id][$var->varname] = \json_decode($var->varvalue); + } else { + $vars[$id][$var->varname] = $var->varvalue; + } + } + + return $vars; + } + + protected function fetchAllGroups() + { + $query = $this->prepareGroupsQuery(); + return $this->fetchAndCombineGroups($query); + } + + protected function fetchAllResolvedGroups() + { + $query = $this->prepareGroupsQuery(true); + return $this->fetchAndCombineGroups($query); + } + + protected function fetchAndCombineGroups($query) + { + $groups = []; + foreach ($this->db->fetchAll($query) as $group) { + $id = $group->object_id; + if (isset($groups[$id])) { + $groups[$id][$group->group_id] = $group->group_name; + } else { + $groups[$id] = [ + $group->group_id => $group->group_name + ]; + } + } + + return $groups; + } + + protected function prepareGroupsQuery($resolved = false) + { + $type = $this->getType(); + $groupsTable = $this->baseTable . 'group'; + $groupMembershipTable = "${groupsTable}_$type"; + if ($resolved) { + $groupMembershipTable .= '_resolved'; + } + $oRef = "${type}_id"; + $gRef = "${type}group_id"; + + return $this->db->select() + ->from(['gm' => $groupMembershipTable], [ + 'object_id' => $oRef, + 'group_id' => $gRef, + 'group_name' => 'g.object_name' + ]) + ->join(['g' => $groupsTable], "g.id = gm.$gRef", []) + ->order("gm.$oRef") + ->order('g.object_name'); + } + + protected function prepareVarsQuery() + { + $table = $this->baseTable . '_var'; + $ref = $this->getType() . '_id'; + return $this->db->select() + ->from(['v' => $table], [ + 'object_id' => $ref, + 'v.varname', + 'v.varvalue', + 'v.format', + // 'v.checksum', + ]) + ->join(['o' => $this->baseTable], "o.id = v.$ref", []) + ->order('o.id') + ->order('v.varname'); + } + + protected function getType() + { + return \preg_replace('/^icinga_/', '', $this->baseTable); + } + + /** + * Helper, flattens all vars of a given object + * + * The object itself will be modified, and the 'vars' property will be + * replaced with corresponding 'vars.whatever' properties + * + * @param $object + * @param string $key + */ + protected static function flattenVars(\stdClass $object, $key = 'vars') + { + if (property_exists($object, $key)) { + foreach ($object->vars as $k => $v) { + if (is_object($v)) { + static::flattenVars($v, $k); + } + $object->{$key . '.' . $k} = $v; + } + unset($object->$key); + } + } +} diff --git a/library/Director/Web/Table/IcingaHostsMatchingFilterTable.php b/library/Director/Web/Table/IcingaHostsMatchingFilterTable.php new file mode 100644 index 00000000..5c1a9b93 --- /dev/null +++ b/library/Director/Web/Table/IcingaHostsMatchingFilterTable.php @@ -0,0 +1,75 @@ +filter = $filter; + + $table->dataSource = new ArrayDatasource( + (new IcingaHostObjectResolver($db->getDbAdapter())) + ->fetchObjectsMatchingFilter($filter) + ); + + return $table; + } + + public function renderRow($row) + { + return $this::row([ + Link::create( + $row->object_name, + 'director/host', + ['name' => $row->object_name] + ) + ]); + } + + public function getColumnsToBeRendered() + { + return [ + $this->translate('Hostname'), + ]; + } + + protected function getPaginationAdapter() + { + return new SimpleQueryPaginationAdapter($this->getQuery()); + } + + public function getQuery() + { + return $this->prepareQuery(); + } + + protected function fetchQueryRows() + { + return $this->dataSource->fetchAll($this->getQuery()); + } + + protected function prepareQuery() + { + return new SimpleQuery($this->dataSource, ['object_name']); + } +} From babae3e068aa6048c0bc15dbfbb1620179ee4b31 Mon Sep 17 00:00:00 2001 From: Thomas Gelf Date: Wed, 12 Feb 2020 10:59:38 +0100 Subject: [PATCH 2/5] IcingaObjectResolver: support PostgreSQL --- library/Director/Resolver/IcingaObjectResolver.php | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/library/Director/Resolver/IcingaObjectResolver.php b/library/Director/Resolver/IcingaObjectResolver.php index 8a4e9b96..78297259 100644 --- a/library/Director/Resolver/IcingaObjectResolver.php +++ b/library/Director/Resolver/IcingaObjectResolver.php @@ -178,18 +178,20 @@ class IcingaObjectResolver */ protected function fetchInheritancePaths($baseTable, $relColumn) { - // select host_id, GROUP_CONCAT(parent_host_id ORDER BY weight) FROM icinga_host_inheritance group by host_id; + if ($this->db instanceof \Zend_Db_Adapter_Pdo_Pgsql) { + $groupColumn = "ARRAY_TO_STRING(ARRAY_AGG(parent_$relColumn ORDER BY weight), ',')"; + } else { + $groupColumn = "GROUP_CONCAT(parent_$relColumn ORDER BY weight SEPARATOR ',')"; + } $query = $this->db->select() ->from([ 'oi' => "${baseTable}_inheritance" ], [ $relColumn, - "GROUP_CONCAT(parent_$relColumn ORDER BY weight SEPARATOR ',')" + $groupColumn ]) ->group($relColumn) - ->order("LENGTH(GROUP_CONCAT(parent_$relColumn ORDER BY weight SEPARATOR ','))"); - - // pgsql: ARRAY_TO_STRING(ARRAY_AGG(---), ',') -> order? + ->order("LENGTH($groupColumn)"); return $this->db->fetchPairs($query); } From f7403f43d0da1c52dfdd97d43b9a6914d9d10148 Mon Sep 17 00:00:00 2001 From: Thomas Gelf Date: Wed, 12 Feb 2020 13:56:41 +0100 Subject: [PATCH 3/5] IcingaObjectResolver: use import lists Fixes an issue with nested inheritance --- .../Resolver/IcingaObjectResolver.php | 112 ++++++++++++------ 1 file changed, 77 insertions(+), 35 deletions(-) diff --git a/library/Director/Resolver/IcingaObjectResolver.php b/library/Director/Resolver/IcingaObjectResolver.php index 78297259..07066658 100644 --- a/library/Director/Resolver/IcingaObjectResolver.php +++ b/library/Director/Resolver/IcingaObjectResolver.php @@ -37,6 +37,8 @@ class IcingaObjectResolver */ protected $inheritancePaths; + protected $flatImports = []; + protected $templateVars; protected $resolvedTemplateVars = []; @@ -56,17 +58,19 @@ class IcingaObjectResolver foreach ($this->fetchPlainObjects($this->baseTable, 'template') as $template) { $id = $template->id; $this->stripIgnoredProperties($template); - // Let's to this only on final objects: - // $this->replaceRelatedNames($object); - // $this->convertBooleans($object); $this->stripNullProperties($template); $this->templates[$id] = (array) $template; } $this->templateVars = $this->fetchTemplateVars(); + $this->inheritancePaths = $this->fetchInheritancePaths($this->baseTable, 'host_id'); + foreach ($this->inheritancePaths as $path) { + $this->getResolvedImports($path); + } + // Using already resolved data, so this is unused right now: // $this->groupMemberShips = $this->fetchAllGroups(); $this->resolvedGroupMemberShips = $this->fetchAllResolvedGroups(); - $this->inheritancePaths = $this->fetchInheritancePaths($this->baseTable, 'host_id'); + foreach ($this->inheritancePaths as $path) { if (! isset($this->resolvedTemplateProperties[$path])) { $properties = (object) $this->getResolvedProperties($path); @@ -91,7 +95,7 @@ class IcingaObjectResolver protected static function addUniqueMembers(&$list, $newMembers) { - foreach ($newMembers as $member) { + foreach (\array_reverse($newMembers) as $member) { $pos = \array_search($member, $list); if ($pos !== false) { unset($list[$pos]); @@ -168,6 +172,11 @@ class IcingaObjectResolver $object->groups = $groups; } + $templates = $this->getTemplateNamesById($id); + if (! empty($templates)) { + $object->templates = \array_reverse($templates); + } + return $object; } @@ -191,6 +200,7 @@ class IcingaObjectResolver $groupColumn ]) ->group($relColumn) + // Ordering by length increases the possibility to have less cycles afterwards ->order("LENGTH($groupColumn)"); return $this->db->fetchPairs($query); @@ -223,40 +233,49 @@ class IcingaObjectResolver } } + protected function getTemplateNamesByID($objectId) + { + if (isset($this->inheritancePaths[$objectId])) { + return $this->translateTemplateIdsToNames( + $this->getResolvedImports($this->inheritancePaths[$objectId]) + ); + } else { + return []; + } + } + /** * @param $path * @return array[] */ protected function getResolvedProperties($path) { - $pos = \strpos($path, ','); - if ($pos === false) { - return $this->templates[$path]; - } else { - $first = \substr($path, 0, $pos); - $parentPath = \substr($path, $pos + 1); - $result = $this->templates[$first] - + $this->getResolvedProperties($parentPath); - unset($result['object_name']); - - return $result; + $result = []; + // + adds only non existing members, so let's reverse our templates + foreach ($this->getResolvedImports($path) as $templateId) { + $result += $this->templates[$templateId]; } + unset($result['object_name']); + + return $result; } protected function getResolvedVars($path) { - $pos = \strpos($path, ','); - if ($pos === false) { - if (isset($this->templateVars[$path])) { - return $this->templateVars[$path]; - } else { - return []; - } + $result = []; + foreach ($this->getResolvedImports($path) as $templateId) { + $result += $this->getTemplateVars($templateId); + } + + return $result; + } + + protected function getTemplateVars($templateId) + { + if (isset($this->templateVars[$templateId])) { + return $this->templateVars[$templateId]; } else { - $first = \substr($path, 0, $pos); - $parentPath = \substr($path, $pos + 1); - return $this->getResolvedVars($first) - + $this->getResolvedVars($parentPath); + return []; } } @@ -283,13 +302,36 @@ class IcingaObjectResolver } } - protected function cleanupObjects(&$objects) + /** + * Hint: this ships most important (last) imports first + * + * @param $path + * @return array + */ + protected function getResolvedImports($path) { - foreach ($objects as $object) { - $this->stripIgnoredProperties($object); - $this->replaceRelatedNames($object); - $this->convertBooleans($object); + if (! isset($this->flatImports[$path])) { + $this->flatImports[$path] = $this->calculateFlatImports($path); } + + return $this->flatImports[$path]; + } + + protected function calculateFlatImports($path) + { + $imports = \preg_split('/,/', $path); + $ancestors = []; + foreach ($imports as $template) { + if (isset($this->inheritancePaths[$template])) { + $this->addUniqueMembers( + $ancestors, + $this->calculateFlatImports($this->inheritancePaths[$template]) + ); + } + $this->addUniqueMembers($ancestors, [$template]); + } + + return $ancestors; } protected function fetchPlainObjects($table, $objectType = null) @@ -329,7 +371,7 @@ class IcingaObjectResolver $names = []; foreach ($ids as $id) { if (isset($this->templates[$id])) { - $names[] = $this->templates[$id]->object_name; + $names[] = $this->templates[$id]['object_name']; } else { throw new \RuntimeException("There is no template with ID $id"); } @@ -499,9 +541,9 @@ class IcingaObjectResolver */ protected static function flattenVars(\stdClass $object, $key = 'vars') { - if (property_exists($object, $key)) { + if (\property_exists($object, $key)) { foreach ($object->vars as $k => $v) { - if (is_object($v)) { + if (\is_object($v)) { static::flattenVars($v, $k); } $object->{$key . '.' . $k} = $v; From 15b52a323c82b05b60138c4f165959b06f7f54c8 Mon Sep 17 00:00:00 2001 From: Thomas Gelf Date: Wed, 12 Feb 2020 14:52:03 +0100 Subject: [PATCH 4/5] AssignFilterHelper: fix error message --- library/Director/Data/AssignFilterHelper.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/library/Director/Data/AssignFilterHelper.php b/library/Director/Data/AssignFilterHelper.php index 82a35e77..b0253cf0 100644 --- a/library/Director/Data/AssignFilterHelper.php +++ b/library/Director/Data/AssignFilterHelper.php @@ -100,12 +100,12 @@ class AssignFilterHelper return true; } else { - $class = get_class($filter); - $parts = preg_split('~\\~', $class); + $class = \get_class($filter); + $parts = \preg_split('/\\\/', $class); throw new NotImplementedError( 'Matching for Filter of type "%s" is not implemented', - end($parts) + \end($parts) ); } } From 04557aad1cd799334aab7f12bde586353e7b12f0 Mon Sep 17 00:00:00 2001 From: Thomas Gelf Date: Wed, 12 Feb 2020 15:08:51 +0100 Subject: [PATCH 5/5] IcingaObjectResolver: clone filter, use helper --- library/Director/Resolver/IcingaObjectResolver.php | 8 ++++++-- .../Director/Web/Table/IcingaHostsMatchingFilterTable.php | 4 ---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/library/Director/Resolver/IcingaObjectResolver.php b/library/Director/Resolver/IcingaObjectResolver.php index 07066658..540e2c24 100644 --- a/library/Director/Resolver/IcingaObjectResolver.php +++ b/library/Director/Resolver/IcingaObjectResolver.php @@ -4,6 +4,7 @@ namespace Icinga\Module\Director\Resolver; use Icinga\Application\Benchmark; use Icinga\Data\Filter\Filter; +use Icinga\Module\Director\Data\AssignFilterHelper; use Icinga\Module\Director\Objects\DynamicApplyMatches; use Zend_Db_Adapter_Abstract as ZfDB; @@ -119,14 +120,17 @@ class IcingaObjectResolver public function fetchObjectsMatchingFilter(Filter $filter) { + $filter = clone($filter); DynamicApplyMatches::setType($this->getType()); DynamicApplyMatches::fixFilterColumns($filter); + $helper = new AssignFilterHelper($filter); $objects = []; $allVars = $this->fetchNonTemplateVars(); foreach ($this->fetchPlainObjects($this->baseTable, 'object') as $object) { $id = $object->id; // id will be stripped - if ($filter->matches($object)) { - $objects[$id] = $this->enrichObject($object, $allVars); + $object = $this->enrichObject($object, $allVars); + if ($helper->matches($object)) { + $objects[$id] = $object; } } diff --git a/library/Director/Web/Table/IcingaHostsMatchingFilterTable.php b/library/Director/Web/Table/IcingaHostsMatchingFilterTable.php index 5c1a9b93..8d225bf9 100644 --- a/library/Director/Web/Table/IcingaHostsMatchingFilterTable.php +++ b/library/Director/Web/Table/IcingaHostsMatchingFilterTable.php @@ -13,8 +13,6 @@ use Icinga\Module\Director\Resolver\IcingaHostObjectResolver; class IcingaHostsMatchingFilterTable extends QueryBasedTable { - protected $filter; - protected $searchColumns = [ 'object_name', ]; @@ -25,8 +23,6 @@ class IcingaHostsMatchingFilterTable extends QueryBasedTable public static function load(Filter $filter, Db $db) { $table = new static(); - $table->filter = $filter; - $table->dataSource = new ArrayDatasource( (new IcingaHostObjectResolver($db->getDbAdapter())) ->fetchObjectsMatchingFilter($filter)