From dcd36877ea926be237ea38980524716f41315801 Mon Sep 17 00:00:00 2001 From: raviks789 <33730024+raviks789@users.noreply.github.com> Date: Thu, 3 Aug 2023 16:56:52 +0200 Subject: [PATCH] Make `TemplateUsageTable`s and other tables compatible with `director branches` `TemplateUsageTable`, `ApplyRulesTable`, `ObjectsTableSetmembers` and `TemplatesTable` are made compatible with `director branches`. --- .../Web/Controller/ObjectsController.php | 2 +- .../Web/Controller/TemplateController.php | 4 +- .../Director/Web/Table/ApplyRulesTable.php | 105 ++++++++++++++++- .../Table/DependencyTemplateUsageTable.php | 12 +- .../Web/Table/HostTemplateUsageTable.php | 8 -- .../Table/IcingaServiceSetServiceTable.php | 4 + .../Table/NotificationTemplateUsageTable.php | 12 +- library/Director/Web/Table/ObjectSetTable.php | 7 +- library/Director/Web/Table/ObjectsTable.php | 56 +++++---- .../Web/Table/ObjectsTableService.php | 6 + .../Web/Table/ObjectsTableSetMembers.php | 111 +++++++++++++++++- .../Web/Table/ServiceTemplateUsageTable.php | 25 +++- .../Director/Web/Table/TemplateUsageTable.php | 75 +++++------- 13 files changed, 318 insertions(+), 109 deletions(-) diff --git a/library/Director/Web/Controller/ObjectsController.php b/library/Director/Web/Controller/ObjectsController.php index 8fffefb9b..cc003a716 100644 --- a/library/Director/Web/Controller/ObjectsController.php +++ b/library/Director/Web/Controller/ObjectsController.php @@ -157,7 +157,7 @@ protected function getTable() */ protected function getApplyRulesTable() { - $table = new ApplyRulesTable($this->db()); + $table = (new ApplyRulesTable($this->db()))->setBranch($this->getBranch()); $table->setType($this->getType()) ->setBaseObjectUrl($this->getBaseObjectUrl()); $this->eventuallyFilterCommand($table); diff --git a/library/Director/Web/Controller/TemplateController.php b/library/Director/Web/Controller/TemplateController.php index 47511beca..3572c3ccd 100644 --- a/library/Director/Web/Controller/TemplateController.php +++ b/library/Director/Web/Controller/TemplateController.php @@ -66,6 +66,7 @@ public function setmembersAction() ObjectsTableSetMembers::create($this->getType(), $this->db(), $this->Auth()) ->setBaseObjectUrl($this->getBaseObjectUrl()) + ->setBranch($this->getBranch()) ->filterTemplate($template, $this->getInheritance()) ->renderTo($this); } @@ -84,6 +85,7 @@ public function applyrulesAction() ApplyRulesTable::create($type, $this->db()) ->setBaseObjectUrl($this->getBaseObjectUrl()) + ->setBranch($this->getBranch()) ->filterTemplate($template, $this->params->get('inheritance', 'direct')) ->renderTo($this); } @@ -212,7 +214,7 @@ public function usageAction() try { $this->content()->add( - TemplateUsageTable::forTemplate($template) + TemplateUsageTable::forTemplate($template, $this->getBranch()) ); } catch (NestingError $e) { $this->content()->add(Hint::error($e->getMessage())); diff --git a/library/Director/Web/Table/ApplyRulesTable.php b/library/Director/Web/Table/ApplyRulesTable.php index 985b5f3b9..a5379b5da 100644 --- a/library/Director/Web/Table/ApplyRulesTable.php +++ b/library/Director/Web/Table/ApplyRulesTable.php @@ -6,6 +6,7 @@ use Icinga\Data\Filter\Filter; use Icinga\Exception\IcingaException; use Icinga\Module\Director\Db; +use Icinga\Module\Director\Db\DbSelectParenthesis; use Icinga\Module\Director\Db\DbUtil; use Icinga\Module\Director\Db\IcingaObjectFilterHelper; use Icinga\Module\Director\IcingaConfig\AssignRenderer; @@ -20,6 +21,8 @@ class ApplyRulesTable extends ZfQueryBasedTable { + use TableWithBranchSupport; + protected $searchColumns = [ 'o.object_name', 'o.assign_filter', @@ -94,10 +97,14 @@ public function renderRow($row) // NOT (YET) static::td($this->createActionLinks($row))->setSeparator(' ') ]); + $classes = $this->getRowClasses($row); + if ($row->disabled === 'y') { - $tr->getAttributes()->add('class', 'disabled'); + $classes[] = 'disabled'; } + $tr->getAttributes()->add('class', $classes); + return $tr; } @@ -117,7 +124,8 @@ public function filterTemplate( $this->getQuery(), $template, 'o', - $inheritance + $inheritance, + $this->branchUuid ); return $this; @@ -196,6 +204,15 @@ protected function applyRestrictions(ZfSelect $query) return FilterRenderer::applyToQuery($filter, $query); } + protected function getRowClasses($row) + { + // TODO: remove isset, to figure out where it is missing + if (isset($row->branch_uuid) && $row->branch_uuid !== null) { + return ['branch_modified']; + } + return []; + } + /** * @return IcingaObject @@ -216,6 +233,7 @@ public function prepareQuery() 'id' => 'o.id', 'uuid' => 'o.uuid', 'object_name' => 'o.object_name', + 'object_type' => 'o.object_type', 'disabled' => 'o.disabled', 'assign_filter' => 'o.assign_filter', 'apply_for' => '(NULL)', @@ -224,17 +242,92 @@ public function prepareQuery() if ($table === 'icinga_service') { $columns['apply_for'] = 'o.apply_for'; } + + $conn = $this->connection(); $query = $this->db()->select()->from( ['o' => $table], $columns - )->where( - "object_type = 'apply'" )->order('o.object_name'); - if ($this->type === 'service') { - $query->where('service_set_id IS NULL'); + if ($this->branchUuid) { + $columns = $this->branchifyColumns($columns); + $columns['branch_uuid'] = 'bo.branch_uuid'; + if ($conn->isPgsql()) { + $columns['imports'] = 'CONCAT(\'[\', ARRAY_TO_STRING(ARRAY_AGG' + . '(CONCAT(\'"\', sub_o.object_name, \'"\')), \',\'), \']\')'; + } else { + $columns['imports'] = 'CONCAT(\'[\', ' + . 'GROUP_CONCAT(CONCAT(\'"\', sub_o.object_name, \'"\')), \']\')'; + } + + $this->stripSearchColumnAliases(); + + $query->reset('columns'); + $right = clone($query); + + $query->columns($columns) + ->joinLeft( + ['oi' => $table . '_inheritance'], + 'o.id = oi.' . $this->getType() . '_id', + [] + )->joinLeft( + ['sub_o' => $table], + 'sub_o.id = oi.parent_' . $this->getType() . '_id', + [] + )->group(['o.id', 'bo.uuid', 'bo.branch_uuid']); + + $query->joinLeft( + ['bo' => "branched_$table"], + // TODO: PgHexFunc + $this->db()->quoteInto( + 'bo.uuid = o.uuid AND bo.branch_uuid = ?', + DbUtil::quoteBinaryLegacy($this->branchUuid->getBytes(), $this->db()) + ), + [] + )->where("(bo.branch_deleted IS NULL OR bo.branch_deleted = 'n')"); + + if ($this->type === 'service') { + $query->where('o.service_set_id IS NULL AND bo.service_set IS NULL'); + } + + $columns['imports'] = 'bo.imports'; + + $right->columns($columns) + ->joinRight( + ['bo' => "branched_$table"], + 'bo.uuid = o.uuid', + [] + ) + ->where('o.uuid IS NULL') + ->where('bo.branch_uuid = ?', $conn->quoteBinary($this->branchUuid->getBytes())); + + $query = $this->db()->select()->union([ + 'l' => new DbSelectParenthesis($query), + 'r' => new DbSelectParenthesis($right), + ]); + + $query = $this->db()->select()->from(['u' => $query]); + $query->order('object_name')->limit(100); + } else { + if ($this->type === 'service') { + $query->where('service_set_id IS NULL'); + } } + $query->where( + "object_type = 'apply'" + ); + + $this->applyRestrictions($query); + return $this->applyRestrictions($query); } + + /** + * @return Db + */ + public function connection() + { + return parent::connection(); + } } diff --git a/library/Director/Web/Table/DependencyTemplateUsageTable.php b/library/Director/Web/Table/DependencyTemplateUsageTable.php index d7537c58a..2c1de501f 100644 --- a/library/Director/Web/Table/DependencyTemplateUsageTable.php +++ b/library/Director/Web/Table/DependencyTemplateUsageTable.php @@ -2,6 +2,8 @@ namespace Icinga\Module\Director\Web\Table; +use Icinga\Module\Director\Db; + class DependencyTemplateUsageTable extends TemplateUsageTable { public function getTypes() @@ -12,11 +14,15 @@ public function getTypes() ]; } - protected function getTypeSummaryDefinitions() + protected function getSummaryTables(string $templateType, Db $connection) { return [ - 'templates' => $this->getSummaryLine('template'), - 'applyrules' => $this->getSummaryLine('apply'), + 'templates' => TemplatesTable::create( + $templateType, + $connection + ), + 'applyrules' => ApplyRulesTable::create($templateType, $connection) + ->setBranchUuid($this->branchUuid) ]; } } diff --git a/library/Director/Web/Table/HostTemplateUsageTable.php b/library/Director/Web/Table/HostTemplateUsageTable.php index 2d1ee2f1a..672691fb6 100644 --- a/library/Director/Web/Table/HostTemplateUsageTable.php +++ b/library/Director/Web/Table/HostTemplateUsageTable.php @@ -11,12 +11,4 @@ public function getTypes() 'objects' => $this->translate('Objects'), ]; } - - protected function getTypeSummaryDefinitions() - { - return [ - 'templates' => $this->getSummaryLine('template'), - 'objects' => $this->getSummaryLine('object'), - ]; - } } diff --git a/library/Director/Web/Table/IcingaServiceSetServiceTable.php b/library/Director/Web/Table/IcingaServiceSetServiceTable.php index ee8a3efe3..981cd5380 100644 --- a/library/Director/Web/Table/IcingaServiceSetServiceTable.php +++ b/library/Director/Web/Table/IcingaServiceSetServiceTable.php @@ -123,6 +123,10 @@ protected function getServiceLink($row) ]; $url = 'director/host/servicesetservice'; } else { + if (is_resource($row->uuid)) { + $row->uuid =stream_get_contents($row->uuid); + } + $params = [ 'uuid' => Uuid::fromBytes($row->uuid)->toString(), ]; diff --git a/library/Director/Web/Table/NotificationTemplateUsageTable.php b/library/Director/Web/Table/NotificationTemplateUsageTable.php index da411a3a0..d8cd3d86d 100644 --- a/library/Director/Web/Table/NotificationTemplateUsageTable.php +++ b/library/Director/Web/Table/NotificationTemplateUsageTable.php @@ -2,6 +2,8 @@ namespace Icinga\Module\Director\Web\Table; +use Icinga\Module\Director\Db; + class NotificationTemplateUsageTable extends TemplateUsageTable { public function getTypes() @@ -12,11 +14,15 @@ public function getTypes() ]; } - protected function getTypeSummaryDefinitions() + protected function getSummaryTables(string $templateType, Db $connection) { return [ - 'templates' => $this->getSummaryLine('template'), - 'applyrules' => $this->getSummaryLine('apply', 'o.host_id IS NULL'), + 'templates' => TemplatesTable::create( + $templateType, + $connection + ), + 'applyrules' => ApplyRulesTable::create($templateType, $connection) + ->setBranchUuid($this->branchUuid) ]; } } diff --git a/library/Director/Web/Table/ObjectSetTable.php b/library/Director/Web/Table/ObjectSetTable.php index e9960af26..ad022ae41 100644 --- a/library/Director/Web/Table/ObjectSetTable.php +++ b/library/Director/Web/Table/ObjectSetTable.php @@ -154,12 +154,12 @@ protected function prepareQuery() ['bo' => "branched_icinga_{$type}"], "bo.{$type}_set = bos.object_name", [] - ); + )->group(['bo.object_name', 'o.object_name']); $query->joinLeft( ['bo' => "branched_icinga_{$type}"], "bo.{$type}_set = bos.object_name", [] - ); + )->group(['bo.object_name', 'o.object_name']); $this->queries = [ $query, $right @@ -185,8 +185,9 @@ protected function prepareQuery() ->group('object_type') ->group('assign_filter') ->group('description') + ->group('service_object_name') ->group('count_services'); - }; + } } else { // Disabled for now, check for correctness: // $query->joinLeft( diff --git a/library/Director/Web/Table/ObjectsTable.php b/library/Director/Web/Table/ObjectsTable.php index 6f0e786a4..7ed0bbb67 100644 --- a/library/Director/Web/Table/ObjectsTable.php +++ b/library/Director/Web/Table/ObjectsTable.php @@ -289,37 +289,35 @@ protected function prepareQuery() ); // keep the imported templates as columns - if ($this->getType() === 'host' || $this->getType() === 'service') { - $leftColumns = $columns; - $rightColumns = $columns; - - if ($this->db() instanceof Zend_Db_Adapter_Pdo_Pgsql) { - $leftColumns['imports'] = 'CONCAT(\'[\', ARRAY_TO_STRING(ARRAY_AGG' - . '(CONCAT(\'"\', sub_o.object_name, \'"\')), \',\'), \']\')'; - } else { - $leftColumns['imports'] = 'CONCAT(\'[\', ' - . 'GROUP_CONCAT(CONCAT(\'"\', sub_o.object_name, \'"\')), \']\')'; - } - - $query->reset('columns'); - - $query->columns($leftColumns) - ->joinLeft( - ['oi' => $table . '_inheritance'], - 'o.id = oi.' . $this->getType() . '_id', - [] - )->joinLeft( - ['sub_o' => $table], - 'sub_o.id = oi.parent_' . $this->getType() . '_id', - [] - )->group(['o.id', 'bo.uuid', 'bo.branch_uuid']); - - $rightColumns['imports'] = 'bo.imports'; - - $right->reset('columns'); - $right->columns($rightColumns); + $leftColumns = $columns; + $rightColumns = $columns; + + if ($this->db() instanceof Zend_Db_Adapter_Pdo_Pgsql) { + $leftColumns['imports'] = 'CONCAT(\'[\', ARRAY_TO_STRING(ARRAY_AGG' + . '(CONCAT(\'"\', sub_o.object_name, \'"\')), \',\'), \']\')'; + } else { + $leftColumns['imports'] = 'CONCAT(\'[\', ' + . 'GROUP_CONCAT(CONCAT(\'"\', sub_o.object_name, \'"\')), \']\')'; } + $query->reset('columns'); + + $query->columns($leftColumns) + ->joinLeft( + ['oi' => $table . '_inheritance'], + 'o.id = oi.' . $this->getType() . '_id', + [] + )->joinLeft( + ['sub_o' => $table], + 'sub_o.id = oi.parent_' . $this->getType() . '_id', + [] + )->group(['o.id', 'bo.uuid', 'bo.branch_uuid']); + + $rightColumns['imports'] = 'bo.imports'; + + $right->reset('columns'); + $right->columns($rightColumns); + $query->where("(bo.branch_deleted IS NULL OR bo.branch_deleted = 'n')"); $this->applyObjectTypeFilter($query, $right); $right->joinRight( diff --git a/library/Director/Web/Table/ObjectsTableService.php b/library/Director/Web/Table/ObjectsTableService.php index 2d4ad41b1..c9bce72ba 100644 --- a/library/Director/Web/Table/ObjectsTableService.php +++ b/library/Director/Web/Table/ObjectsTableService.php @@ -203,8 +203,14 @@ public function prepareQuery() 'hsb.service_id = o.id AND hsb.host_id = o.host_id', [] )->where('o.service_set_id IS NULL') + ->group(['o.id', 'h.id','hsb.service_id', 'hsb.host_id']) ->order('o.object_name')->order('h.object_name'); + if ($this->branchUuid) { + $subQuery->where('bo.service_set IS NULL') + ->group(['bo.uuid', 'bo.branch_uuid']); + } + if ($this->host) { if ($this->branchUuid) { $subQuery->where('COALESCE(h.object_name, bo.host) = ?', $this->host->getObjectName()); diff --git a/library/Director/Web/Table/ObjectsTableSetMembers.php b/library/Director/Web/Table/ObjectsTableSetMembers.php index 7e70f1789..b3d455b0b 100644 --- a/library/Director/Web/Table/ObjectsTableSetMembers.php +++ b/library/Director/Web/Table/ObjectsTableSetMembers.php @@ -7,6 +7,7 @@ use gipfl\IcingaWeb2\Link; use gipfl\IcingaWeb2\Table\ZfQueryBasedTable; use gipfl\IcingaWeb2\Url; +use Icinga\Module\Director\Db\DbSelectParenthesis; use Icinga\Module\Director\Db\IcingaObjectFilterHelper; use Icinga\Module\Director\Objects\IcingaObject; use Icinga\Module\Director\Restriction\FilterByNameRestriction; @@ -58,6 +59,15 @@ public function setBaseObjectUrl($url) return $this; } + protected function getRowClasses($row) + { + // TODO: remove isset, to figure out where it is missing + if (isset($row->branch_uuid) && $row->branch_uuid !== null) { + return ['branch_modified']; + } + return []; + } + /** * Should be triggered from renderRow, still unused. * @@ -74,7 +84,8 @@ public function filterTemplate( $this->getQuery(), $template, 'o', - $inheritance + $inheritance, + $this->branchUuid ); return $this; @@ -85,7 +96,7 @@ public function renderRow($row) { $url = Url::fromPath('director/service/edit', [ 'name' => $row->object_name, - 'id' => $row->id, + 'uuid' => $row->uuid, ]); return static::tr([ @@ -93,7 +104,7 @@ public function renderRow($row) Link::create($row->service_set, $url), ]), static::td($row->object_name), - ]); + ])->addAttributes(['class' => $this->getRowClasses($row)]); } /** @@ -115,6 +126,7 @@ protected function prepareQuery() $columns = [ 'id' => 'o.id', + 'uuid' => 'o.uuid', 'service_set' => 'os.object_name', 'object_name' => 'o.object_name', 'object_type' => 'os.object_type', @@ -138,9 +150,96 @@ protected function prepareQuery() ); $nameFilter->applyToQuery($query, 'os'); - $query - ->where('o.object_type = ?', 'object') - ->order('os.object_name'); + if ($this->branchUuid) { + $columns['branch_uuid'] = 'bos.branch_uuid'; + $conn = $this->connection(); + if ($conn->isPgsql()) { + $columns['imports'] = 'CONCAT(\'[\', ARRAY_TO_STRING(ARRAY_AGG' + . '(CONCAT(\'"\', sub_o.object_name, \'"\')), \',\'), \']\')'; + } else { + $columns['imports'] = 'CONCAT(\'[\', ' + . 'GROUP_CONCAT(CONCAT(\'"\', sub_o.object_name, \'"\')), \']\')'; + } + + $columns = $this->branchifyColumns($columns); + $this->stripSearchColumnAliases(); + + $query->reset('columns'); + $right = clone($query); + $conn = $this->connection(); + + $query->columns($columns)->joinLeft( + ['bos' => "branched_icinga_{$type}_set"], + // TODO: PgHexFunc + $this->db()->quoteInto( + 'bos.uuid = os.uuid AND bos.branch_uuid = ?', + $conn->quoteBinary($this->branchUuid->getBytes()) + ), + [] + )->joinLeft( + ['oi' => $table . '_inheritance'], + 'o.id = oi.' . $this->getType() . '_id', + [] + )->joinLeft( + ['sub_o' => $table], + 'sub_o.id = oi.parent_' . $this->getType() . '_id', + [] + )->where("(bos.branch_deleted IS NULL OR bos.branch_deleted = 'n')"); + + $columns['imports'] = 'bo.imports'; + $right->columns($columns)->joinRight( + ['bos' => "branched_icinga_{$type}_set"], + 'bos.uuid = os.uuid', + [] + ) + ->where('os.uuid IS NULL') + ->where('bos.branch_uuid = ?', $conn->quoteBinary($this->branchUuid->getBytes())); + $query->group('COALESCE(os.uuid, bos.uuid)'); + $right->group('COALESCE(os.uuid, bos.uuid)'); + if ($conn->isPgsql()) { + // This is ugly, might want to modify the query - even a subselect looks better + $query->group('bos.uuid')->group('os.uuid')->group('os.id')->group('bos.branch_uuid')->group('o.id'); + $right->group('bos.uuid')->group('os.uuid')->group('os.id')->group('bos.branch_uuid')->group('o.id'); + } + $right->joinLeft( + ['bo' => "branched_icinga_{$type}"], + "bo.{$type}_set = bos.object_name", + [] + )->group(['bo.object_name', 'o.object_name', 'bo.uuid', 'bo.imports']); + $query->joinLeft( + ['bo' => "branched_icinga_{$type}"], + "bo.{$type}_set = bos.object_name", + [] + )->group(['bo.object_name', 'o.object_name', 'bo.uuid']); + + $query = $this->db()->select()->union([ + 'l' => new DbSelectParenthesis($query), + 'r' => new DbSelectParenthesis($right), + ]); + $query = $this->db()->select()->from(['u' => $query]); + $query->order('object_name')->limit(100); + + $query + ->group('uuid') + ->where('object_type = ?', 'template') + ->order('object_name'); + if ($conn->isPgsql()) { + $query + ->group('uuid') + ->group('id') + ->group('imports') + ->group('branch_uuid') + ->group('object_name') + ->group('object_type') + ->group('assign_filter') + ->group('description') + ->group('service_set'); + } + } else { + $query + ->where('o.object_type = ?', 'object') + ->order('os.object_name'); + } return $query; } diff --git a/library/Director/Web/Table/ServiceTemplateUsageTable.php b/library/Director/Web/Table/ServiceTemplateUsageTable.php index 27fccdb50..5829d3051 100644 --- a/library/Director/Web/Table/ServiceTemplateUsageTable.php +++ b/library/Director/Web/Table/ServiceTemplateUsageTable.php @@ -2,6 +2,9 @@ namespace Icinga\Module\Director\Web\Table; +use Icinga\Authentication\Auth; +use Icinga\Module\Director\Db; + class ServiceTemplateUsageTable extends TemplateUsageTable { public function getTypes() @@ -14,14 +17,24 @@ public function getTypes() ]; } - protected function getTypeSummaryDefinitions() + protected function getSummaryTables(string $templateType, Db $connection) { + $auth = Auth::getInstance(); return [ - 'templates' => $this->getSummaryLine('template'), - 'objects' => $this->getSummaryLine('object', 'o.service_set_id IS NULL AND o.host_id IS NOT NULL'), - 'applyrules' => $this->getSummaryLine('apply', 'o.service_set_id IS NULL'), - // TODO: re-enable - 'setmembers' => $this->getSummaryLine('object', 'o.service_set_id IS NOT NULL'), + 'templates' => TemplatesTable::create( + $templateType, + $connection + ), + 'objects' => ObjectsTable::create($templateType, $connection) + ->setAuth($auth) + ->setBranchUuid($this->branchUuid), + 'applyrules' => ApplyRulesTable::create($templateType, $connection) + ->setBranchUuid($this->branchUuid), + 'setmembers' => ObjectsTableSetMembers::create( + $templateType, + $connection, + $auth + ) ]; } } diff --git a/library/Director/Web/Table/TemplateUsageTable.php b/library/Director/Web/Table/TemplateUsageTable.php index 8c6d88c81..4a1f2e4b4 100644 --- a/library/Director/Web/Table/TemplateUsageTable.php +++ b/library/Director/Web/Table/TemplateUsageTable.php @@ -2,12 +2,12 @@ namespace Icinga\Module\Director\Web\Table; +use Icinga\Authentication\Auth; use Icinga\Exception\ProgrammingError; +use Icinga\Module\Director\Db; use Icinga\Module\Director\Db\Branch\Branch; use Icinga\Module\Director\Objects\IcingaObject; -use Icinga\Module\Director\Resolver\TemplateTree; use gipfl\IcingaWeb2\Link; -use Icinga\Module\Director\Web\Controller\BranchHelper; use ipl\Html\Table; use gipfl\Translation\TranslationHelper; @@ -31,17 +31,13 @@ public function getTypes() ]; } - protected function getTypeSummaryDefinitions() - { - return [ - 'templates' => $this->getSummaryLine('template'), - 'objects' => $this->getSummaryLine('object'), - ]; - } - /** * @param IcingaObject $template + * @param Branch|null $branch + * * @return TemplateUsageTable + * + * @throws ProgrammingError */ public static function forTemplate(IcingaObject $template, Branch $branch = null) { @@ -114,52 +110,45 @@ protected function __construct(IcingaObject $template, Branch $branch = null) protected function getUsageSummary(IcingaObject $template) { - $id = $template->getAutoincId(); $connection = $template->getConnection(); $db = $connection->getDbAdapter(); - $oType = $this->objectType; - $tree = new TemplateTree($oType, $connection); - $ids = $tree->listDescendantIdsFor($template); - if (empty($ids)) { - $ids = [0]; + + $types = array_keys($this->getTypes()); + $direct = []; + $indirect = []; + $templateType = $template->getShortTableName(); + + foreach ($this->getSummaryTables($templateType, $connection) as $type => $summaryTable) { + $direct[$type] = $db + ->query($summaryTable->filterTemplate($template, 'direct')->getQuery()) + ->rowCount(); + $indirect[$type] = $db + ->query($summaryTable->filterTemplate($template, 'indirect')->getQuery()) + ->rowCount(); } - $baseQuery = $db->select()->from( - ['o' => 'icinga_' . $oType], - $this->getTypeSummaryDefinitions() - )->joinLeft( - ['oi' => "icinga_{$oType}_inheritance"], - "oi.{$oType}_id = o.id", - [] - ); - - $query = clone($baseQuery); - $direct = $db->fetchRow( - $query->where("oi.parent_{$oType}_id = ?", $id) - ); - $query = clone($baseQuery); - $indirect = $db->fetchRow( - $query->where("oi.parent_{$oType}_id IN (?)", $ids) - ); - //$indirect->templates = count($ids) - 1; $total = []; - $types = array_keys($this->getTypes()); foreach ($types as $type) { - $total[$type] = $direct->$type + $indirect->$type; + $total[$type] = $direct[$type] + $indirect[$type]; } return (object) [ - 'direct' => $direct, - 'indirect' => $indirect, + 'direct' => (object) $direct, + 'indirect' => (object) $indirect, 'total' => (object) $total ]; } - protected function getSummaryLine($type, $extra = null) + protected function getSummaryTables(string $templateType, Db $connection) { - if ($extra !== null) { - $extra = " AND $extra"; - } - return "COALESCE(SUM(CASE WHEN o.object_type = '{$type}'{$extra} THEN 1 ELSE 0 END), 0)"; + return [ + 'templates' => TemplatesTable::create( + $templateType, + $connection + ), + 'objects' => ObjectsTable::create($templateType, $connection) + ->setAuth(Auth::getInstance()) + ->setBranchUuid($this->branchUuid) + ]; } }