diff options
Diffstat (limited to 'library/Director/Web/Table/GroupMemberTable.php')
-rw-r--r-- | library/Director/Web/Table/GroupMemberTable.php | 201 |
1 files changed, 201 insertions, 0 deletions
diff --git a/library/Director/Web/Table/GroupMemberTable.php b/library/Director/Web/Table/GroupMemberTable.php new file mode 100644 index 0000000..b0814ad --- /dev/null +++ b/library/Director/Web/Table/GroupMemberTable.php @@ -0,0 +1,201 @@ +<?php + +namespace Icinga\Module\Director\Web\Table; + +use gipfl\IcingaWeb2\Table\Extension\MultiSelect; +use Icinga\Data\Filter\Filter; +use Icinga\Module\Director\Db; +use Icinga\Module\Director\IcingaConfig\AssignRenderer; +use Icinga\Module\Director\Objects\IcingaObjectGroup; +use Exception; +use gipfl\IcingaWeb2\Link; +use gipfl\IcingaWeb2\Table\ZfQueryBasedTable; +use gipfl\IcingaWeb2\Url; + +class GroupMemberTable extends ZfQueryBasedTable +{ + use MultiSelect; + + protected $searchColumns = [ + 'o.object_name', + // membership_type + ]; + + protected $type; + + /** @var IcingaObjectGroup */ + protected $group; + + /** + * @param $type + * @param Db $db + * @return static + */ + public static function create($type, Db $db) + { + $class = __NAMESPACE__ . '\\GroupMemberTable' . ucfirst($type); + if (! class_exists($class)) { + $class = __CLASS__; + } + + /** @var static $table */ + $table = new $class($db); + $table->type = $type; + return $table; + } + public function assemble() + { + if ($this->type === 'host') { + $this->enableMultiSelect( + 'director/hosts/edit', + 'director/hosts', + ['name'] + ); + } + } + + public function setGroup(IcingaObjectGroup $group) + { + $this->group = $group; + return $this; + } + + public function getType() + { + return $this->type; + } + + public function getColumnsToBeRendered() + { + if ($this->group === null) { + return [ + $this->translate('Group'), + $this->translate('Member'), + $this->translate('via') + ]; + } else { + return [ + $this->translate('Member'), + $this->translate('via') + ]; + } + } + + public function renderRow($row) + { + $type = $this->getType(); + if ($row->object_type === 'apply') { + $params = [ + 'id' => $row->id + ]; + } elseif (isset($row->host_id)) { + // I would prefer to see host=<name> and set=<name>, but joining + // them here is pointless. We should use DeferredHtml for these, + // remember hosts/sets we need and fetch them in a single query at + // rendering time. For now, this works fine - just... the URLs are + // not so nice + $params = [ + 'name' => $row->object_name, + 'host_id' => $row->host_id + ]; + } elseif (isset($row->service_set_id)) { + $params = [ + 'name' => $row->object_name, + 'set_id' => $row->service_set_id + ]; + } else { + $params = [ + 'name' => $row->object_name + ]; + } + + $url = Url::fromPath("director/${type}", $params); + + $tr = $this::tr(); + + if ($this->group === null) { + $tr->add($this::td($row->group_name)); + } + $link = Link::create($row->object_name, $url); + if ($row->object_type === 'apply') { + $link = [ + $link, + ' (where ', + $this->renderApplyFilter($row->assign_filter), + ')' + ]; + } + + $tr->add([ + $this::td($link), + $this::td($row->membership_type) + ]); + + return $tr; + } + + protected function renderApplyFilter($assignFilter) + { + try { + $string = AssignRenderer::forFilter( + Filter::fromQueryString($assignFilter) + )->renderAssign(); + // Do not prefix it + $string = preg_replace('/^assign where /', '', $string); + } catch (Exception $e) { + // ignore errors in filter rendering + $string = 'Error in Filter rendering: ' . $e->getMessage(); + } + + return $string; + } + + protected function prepareQuery() + { + // select h.object_name, hg.object_name, + // CASE WHEN hgh.host_id IS NULL THEN 'apply' ELSE 'direct' END AS assi + // from icinga_hostgroup_host_resolved hgr join icinga_host h on h.id = hgr.host_id + // join icinga_hostgroup hg on hgr.hostgroup_id = hg.id + // left join icinga_hostgroup_host hgh on hgh.host_id = h.id and hgh.hostgroup_id = hg.id; + + $type = $this->getType(); + $columns = [ + 'o.id', + 'o.object_type', + 'o.object_name', + 'membership_type' => "CASE WHEN go.${type}_id IS NULL THEN 'apply' ELSE 'direct' END" + ]; + + if ($this->group === null) { + $columns = ['group_name' => 'g.object_name'] + $columns; + } + if ($type === 'service') { + $columns[] = 'o.assign_filter'; + $columns[] = 'o.host_id'; + $columns[] = 'o.service_set_id'; + } + + $query = $this->db()->select()->from( + ['gro' => "icinga_${type}group_${type}_resolved"], + $columns + )->join( + ['o' => "icinga_${type}"], + "o.id = gro.${type}_id", + [] + )->join( + ['g' => "icinga_${type}group"], + "gro.${type}group_id = g.id", + [] + )->joinLeft( + ['go' => "icinga_${type}group_${type}"], + "go.${type}_id = o.id AND go.${type}group_id = g.id", + [] + )->order('o.object_name'); + + if ($this->group !== null) { + $query->where('g.id = ?', $this->group->get('id')); + } + + return $query; + } +} |