diff options
Diffstat (limited to 'library/Director/Web/Table/ObjectSetTable.php')
-rw-r--r-- | library/Director/Web/Table/ObjectSetTable.php | 211 |
1 files changed, 211 insertions, 0 deletions
diff --git a/library/Director/Web/Table/ObjectSetTable.php b/library/Director/Web/Table/ObjectSetTable.php new file mode 100644 index 0000000..2773841 --- /dev/null +++ b/library/Director/Web/Table/ObjectSetTable.php @@ -0,0 +1,211 @@ +<?php + +namespace Icinga\Module\Director\Web\Table; + +use Icinga\Authentication\Auth; +use Icinga\Module\Director\Db; +use gipfl\IcingaWeb2\Link; +use gipfl\IcingaWeb2\Table\ZfQueryBasedTable; +use gipfl\IcingaWeb2\Url; +use Icinga\Module\Director\Db\DbSelectParenthesis; +use Icinga\Module\Director\Restriction\FilterByNameRestriction; +use ipl\Html\Html; +use Ramsey\Uuid\Uuid; + +class ObjectSetTable extends ZfQueryBasedTable +{ + use TableWithBranchSupport; + + protected $searchColumns = [ + 'os.object_name', + 'os.description', + 'os.assign_filter', + 'o.object_name', + ]; + + private $type; + + /** @var Auth */ + private $auth; + + public static function create($type, Db $db, Auth $auth) + { + $table = new static($db); + $table->type = $type; + $table->auth = $auth; + return $table; + } + + public function getType() + { + return $this->type; + } + + public function getColumnsToBeRendered() + { + return [$this->translate('Name')]; + } + + public function renderRow($row) + { + $type = $this->getType(); + $params = [ + 'uuid' => Uuid::fromBytes(Db\DbUtil::binaryResult($row->uuid))->toString(), + ]; + + $url = Url::fromPath("director/${type}set", $params); + + $classes = $this->getRowClasses($row); + $tr = static::tr([ + static::td([ + Link::create(sprintf( + $this->translate('%s (%d members)'), + $row->object_name, + $row->count_services + ), $url), + $row->description ? [Html::tag('br'), Html::tag('i', $row->description)] : null + ]) + ]); + if (! empty($classes)) { + $tr->getAttributes()->add('class', $classes); + } + + return $tr; + } + + protected function getRowClasses($row) + { + if ($row->branch_uuid !== null) { + return ['branch_modified']; + } + return []; + } + + protected function prepareQuery() + { + $type = $this->getType(); + + $table = "icinga_${type}_set"; + $columns = [ + 'id' => 'os.id', + 'uuid' => 'os.uuid', + 'branch_uuid' => '(NULL)', + 'object_name' => 'os.object_name', + 'object_type' => 'os.object_type', + 'assign_filter' => 'os.assign_filter', + 'description' => 'os.description', + 'count_services' => 'COUNT(DISTINCT o.uuid)', + ]; + if ($this->branchUuid) { + $columns['branch_uuid'] = 'bos.branch_uuid'; + $columns = $this->branchifyColumns($columns); + $this->stripSearchColumnAliases(); + } + + $query = $this->db()->select()->from( + ['os' => $table], + $columns + )->joinLeft( + ['o' => "icinga_${type}"], + "o.${type}_set_id = os.id", + [] + ); + + $nameFilter = new FilterByNameRestriction( + $this->connection(), + $this->auth, + "${type}_set" + ); + $nameFilter->applyToQuery($query, 'os'); + /** @var Db $conn */ + $conn = $this->connection(); + if ($this->branchUuid) { + $right = clone($query); + + $query->joinLeft( + ['bos' => "branched_$table"], + // TODO: PgHexFunc + $this->db()->quoteInto( + 'bos.uuid = os.uuid AND bos.branch_uuid = ?', + $conn->quoteBinary($this->branchUuid->getBytes()) + ), + [] + )->where("(bos.branch_deleted IS NULL OR bos.branch_deleted = 'n')"); + $right->joinRight( + ['bos' => "branched_$table"], + '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'); + $right->group('bos.uuid')->group('os.uuid')->group('os.id')->group('bos.branch_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()) { + // BS. Drop count? Sub-select? Better query? + $query + ->group('uuid') + ->group('id') + ->group('branch_uuid') + ->group('object_name') + ->group('object_type') + ->group('assign_filter') + ->group('description') + ->group('count_services'); + }; + } else { + // Disabled for now, check for correctness: + // $query->joinLeft( + // ['osi' => "icinga_${type}_set_inheritance"], + // "osi.parent_${type}_set_id = os.id", + // [] + // )->joinLeft( + // ['oso' => "icinga_${type}_set"], + // "oso.id = oso.${type}_set_id", + // [] + // ); + // 'count_hosts' => 'COUNT(DISTINCT oso.id)', + + $query + ->group('os.uuid') + ->where('os.object_type = ?', 'template') + ->order('os.object_name'); + if ($conn->isPgsql()) { + // BS. Drop count? Sub-select? Better query? + $query + ->group('os.uuid') + ->group('os.id') + ->group('os.object_name') + ->group('os.object_type') + ->group('os.assign_filter') + ->group('os.description'); + }; + } + + return $query; + } + + /** + * @return Db + */ + public function connection() + { + return parent::connection(); + } +} |