summaryrefslogtreecommitdiffstats
path: root/library/Director/Web/Table
diff options
context:
space:
mode:
Diffstat (limited to 'library/Director/Web/Table')
-rw-r--r--library/Director/Web/Table/ActivityLogTable.php19
-rw-r--r--library/Director/Web/Table/ApplyRulesTable.php107
-rw-r--r--library/Director/Web/Table/BasketSnapshotTable.php5
-rw-r--r--library/Director/Web/Table/BranchActivityTable.php13
-rw-r--r--library/Director/Web/Table/ChoicesTable.php4
-rw-r--r--library/Director/Web/Table/CustomvarTable.php6
-rw-r--r--library/Director/Web/Table/CustomvarVariantsTable.php6
-rw-r--r--library/Director/Web/Table/DatafieldTable.php17
-rw-r--r--library/Director/Web/Table/DependencyTemplateUsageTable.php12
-rw-r--r--library/Director/Web/Table/DeploymentLogTable.php3
-rw-r--r--library/Director/Web/Table/GroupMemberTable.php18
-rw-r--r--library/Director/Web/Table/HostTemplateUsageTable.php8
-rw-r--r--library/Director/Web/Table/IcingaServiceSetServiceTable.php31
-rw-r--r--library/Director/Web/Table/IntlZfQueryBasedTable.php51
-rw-r--r--library/Director/Web/Table/NotificationTemplateUsageTable.php12
-rw-r--r--library/Director/Web/Table/ObjectSetTable.php68
-rw-r--r--library/Director/Web/Table/ObjectsTable.php77
-rw-r--r--library/Director/Web/Table/ObjectsTableService.php6
-rw-r--r--library/Director/Web/Table/ObjectsTableSetMembers.php255
-rw-r--r--library/Director/Web/Table/ReadOnlyFormAvpTable.php113
-rw-r--r--library/Director/Web/Table/ServiceTemplateUsageTable.php26
-rw-r--r--library/Director/Web/Table/SyncRunTable.php9
-rw-r--r--library/Director/Web/Table/TableWithBranchSupport.php3
-rw-r--r--library/Director/Web/Table/TemplateUsageTable.php104
-rw-r--r--library/Director/Web/Table/TemplatesTable.php22
25 files changed, 703 insertions, 292 deletions
diff --git a/library/Director/Web/Table/ActivityLogTable.php b/library/Director/Web/Table/ActivityLogTable.php
index 5460bc2..a57b86e 100644
--- a/library/Director/Web/Table/ActivityLogTable.php
+++ b/library/Director/Web/Table/ActivityLogTable.php
@@ -2,14 +2,15 @@
namespace Icinga\Module\Director\Web\Table;
-use gipfl\Format\LocalTimeFormat;
+use DateTime;
use gipfl\IcingaWeb2\Link;
-use gipfl\IcingaWeb2\Table\ZfQueryBasedTable;
+use Icinga\Module\Director\Auth\Permission;
use Icinga\Module\Director\Util;
+use IntlDateFormatter;
use ipl\Html\Html;
use ipl\Html\HtmlElement;
-class ActivityLogTable extends ZfQueryBasedTable
+class ActivityLogTable extends IntlZfQueryBasedTable
{
protected $filters = [];
@@ -27,9 +28,6 @@ class ActivityLogTable extends ZfQueryBasedTable
'object_type',
];
- /** @var LocalTimeFormat */
- protected $timeFormat;
-
protected $ranges = [];
/** @var ?object */
@@ -44,7 +42,6 @@ class ActivityLogTable extends ZfQueryBasedTable
public function __construct($db)
{
parent::__construct($db);
- $this->timeFormat = new LocalTimeFormat();
}
public function assemble()
@@ -96,7 +93,9 @@ class ActivityLogTable extends ZfQueryBasedTable
if (! $this->hasObjectFilter) {
$columns[] = $this->makeRangeInfo($row->id);
}
- $columns[] = $this::td($this->timeFormat->getTime($row->ts_change_time));
+
+
+ $columns[] = $this::td($this->getTime($row->ts_change_time));
return $this::tr($columns)->addAttributes(['class' => $action]);
}
@@ -107,7 +106,7 @@ class ActivityLogTable extends ZfQueryBasedTable
*/
protected function renderDayIfNew($timestamp)
{
- $day = $this->getDateFormatter()->getFullDay($timestamp);
+ $day = $this->getDateFormatter()->format((new DateTime())->setTimestamp($timestamp));
if ($this->lastDay !== $day) {
$this->nextHeader()->add(
@@ -206,7 +205,7 @@ class ActivityLogTable extends ZfQueryBasedTable
$type = substr($type, 7);
}
- if (Util::hasPermission('director/showconfig')) {
+ if (Util::hasPermission(Permission::SHOW_CONFIG)) {
// Later on replacing, service_set -> serviceset
// multi column key :(
diff --git a/library/Director/Web/Table/ApplyRulesTable.php b/library/Director/Web/Table/ApplyRulesTable.php
index a861bac..a5379b5 100644
--- a/library/Director/Web/Table/ApplyRulesTable.php
+++ b/library/Director/Web/Table/ApplyRulesTable.php
@@ -6,6 +6,7 @@ use Icinga\Authentication\Auth;
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 @@ use Zend_Db_Select as ZfSelect;
class ApplyRulesTable extends ZfQueryBasedTable
{
+ use TableWithBranchSupport;
+
protected $searchColumns = [
'o.object_name',
'o.assign_filter',
@@ -94,10 +97,14 @@ class ApplyRulesTable extends ZfQueryBasedTable
// 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 @@ class ApplyRulesTable extends ZfQueryBasedTable
$this->getQuery(),
$template,
'o',
- $inheritance
+ $inheritance,
+ $this->branchUuid
);
return $this;
@@ -146,7 +154,7 @@ class ApplyRulesTable extends ZfQueryBasedTable
$links = [];
$links[] = Link::create(
Icon::create('sitemap'),
- "${baseUrl}template/applytargets",
+ "{$baseUrl}template/applytargets",
['id' => $row->id],
['title' => $this->translate('Show affected Objects')]
);
@@ -196,6 +204,15 @@ class ApplyRulesTable extends ZfQueryBasedTable
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 @@ class ApplyRulesTable extends ZfQueryBasedTable
'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 @@ class ApplyRulesTable extends ZfQueryBasedTable
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/BasketSnapshotTable.php b/library/Director/Web/Table/BasketSnapshotTable.php
index 08f808a..6fe0e16 100644
--- a/library/Director/Web/Table/BasketSnapshotTable.php
+++ b/library/Director/Web/Table/BasketSnapshotTable.php
@@ -4,13 +4,12 @@ namespace Icinga\Module\Director\Web\Table;
use ipl\Html\Html;
use gipfl\IcingaWeb2\Link;
-use gipfl\IcingaWeb2\Table\ZfQueryBasedTable;
use Icinga\Date\DateFormatter;
use Icinga\Module\Director\Core\Json;
use Icinga\Module\Director\DirectorObject\Automation\Basket;
use RuntimeException;
-class BasketSnapshotTable extends ZfQueryBasedTable
+class BasketSnapshotTable extends IntlZfQueryBasedTable
{
use DbHelper;
@@ -67,7 +66,7 @@ class BasketSnapshotTable extends ZfQueryBasedTable
if (! is_object($summary) && ! is_array($summary)) {
throw new RuntimeException(sprintf(
'Got invalid basket summary: %s ',
- var_export($summary, 1)
+ var_export($summary, true)
));
}
diff --git a/library/Director/Web/Table/BranchActivityTable.php b/library/Director/Web/Table/BranchActivityTable.php
index e7131ef..cbf940d 100644
--- a/library/Director/Web/Table/BranchActivityTable.php
+++ b/library/Director/Web/Table/BranchActivityTable.php
@@ -2,15 +2,14 @@
namespace Icinga\Module\Director\Web\Table;
-use gipfl\Format\LocalTimeFormat;
+use Icinga\Module\Director\Auth\Permission;
use Icinga\Module\Director\Db;
use Icinga\Module\Director\Db\Branch\BranchActivity;
use Icinga\Module\Director\Util;
use gipfl\IcingaWeb2\Link;
-use gipfl\IcingaWeb2\Table\ZfQueryBasedTable;
use Ramsey\Uuid\UuidInterface;
-class BranchActivityTable extends ZfQueryBasedTable
+class BranchActivityTable extends IntlZfQueryBasedTable
{
protected $extraParams = [];
@@ -20,16 +19,12 @@ class BranchActivityTable extends ZfQueryBasedTable
/** @var ?UuidInterface */
protected $objectUuid;
- /** @var LocalTimeFormat */
- protected $timeFormat;
-
protected $linkToObject = true;
public function __construct(UuidInterface $branchUuid, $db, UuidInterface $objectUuid = null)
{
$this->branchUuid = $branchUuid;
$this->objectUuid = $objectUuid;
- $this->timeFormat = new LocalTimeFormat();
parent::__construct($db);
}
@@ -45,7 +40,7 @@ class BranchActivityTable extends ZfQueryBasedTable
$activity = BranchActivity::fromDbRow($row);
return $this::tr([
$this::td($this->makeBranchLink($activity))->setSeparator(' '),
- $this::td($this->timeFormat->getTime($ts))
+ $this::td($this->getTime($ts))
])->addAttributes(['class' => ['action-' . $activity->getAction(), 'branched']]);
}
@@ -75,7 +70,7 @@ class BranchActivityTable extends ZfQueryBasedTable
{
$type = preg_replace('/^icinga_/', '', $activity->getObjectTable());
- if (Util::hasPermission('director/showconfig')) {
+ if (Util::hasPermission(Permission::SHOW_CONFIG)) {
// Later on replacing, service_set -> serviceset
return [
'[' . $activity->getAuthor() . ']',
diff --git a/library/Director/Web/Table/ChoicesTable.php b/library/Director/Web/Table/ChoicesTable.php
index 4ba2460..9574520 100644
--- a/library/Director/Web/Table/ChoicesTable.php
+++ b/library/Director/Web/Table/ChoicesTable.php
@@ -44,7 +44,7 @@ class ChoicesTable extends ZfQueryBasedTable
public function renderRow($row)
{
$type = $this->getType();
- $url = Url::fromPath("director/templatechoice/${type}", [
+ $url = Url::fromPath("director/templatechoice/{$type}", [
'name' => $row->object_name
]);
@@ -56,7 +56,7 @@ class ChoicesTable extends ZfQueryBasedTable
protected function prepareQuery()
{
$type = $this->getType();
- $table = "icinga_${type}_template_choice";
+ $table = "icinga_{$type}_template_choice";
return $this->db()
->select()
->from(['o' => $table], 'object_name')
diff --git a/library/Director/Web/Table/CustomvarTable.php b/library/Director/Web/Table/CustomvarTable.php
index f9a3844..1aead19 100644
--- a/library/Director/Web/Table/CustomvarTable.php
+++ b/library/Director/Web/Table/CustomvarTable.php
@@ -91,11 +91,11 @@ class CustomvarTable extends ZfQueryBasedTable
$columns["cnt_$type"] = 'COUNT(*)';
$columns["distinct_$type"] = 'COUNT(DISTINCT varvalue)';
return $db->select()->from(
- ['v' => "icinga_${type}_var"],
+ ['v' => "icinga_{$type}_var"],
$columns
)->join(
- ['o' => "icinga_${type}"],
- "o.id = v.${type}_id",
+ ['o' => "icinga_{$type}"],
+ "o.id = v.{$type}_id",
[]
)->where('o.object_type != ?', 'external_object')->group('varname');
}
diff --git a/library/Director/Web/Table/CustomvarVariantsTable.php b/library/Director/Web/Table/CustomvarVariantsTable.php
index 80fca70..8447e36 100644
--- a/library/Director/Web/Table/CustomvarVariantsTable.php
+++ b/library/Director/Web/Table/CustomvarVariantsTable.php
@@ -108,11 +108,11 @@ class CustomvarVariantsTable extends ZfQueryBasedTable
$columns["cnt_$type"] = 'COUNT(*)';
$columns['format'] = 'v.format';
return $db->select()->from(
- ['v' => "icinga_${type}_var"],
+ ['v' => "icinga_{$type}_var"],
$columns
)->join(
- ['o' => "icinga_${type}"],
- "o.id = v.${type}_id",
+ ['o' => "icinga_{$type}"],
+ "o.id = v.{$type}_id",
[]
)->where(
'v.varname = ?',
diff --git a/library/Director/Web/Table/DatafieldTable.php b/library/Director/Web/Table/DatafieldTable.php
index 4b321d7..0062626 100644
--- a/library/Director/Web/Table/DatafieldTable.php
+++ b/library/Director/Web/Table/DatafieldTable.php
@@ -5,12 +5,13 @@ namespace Icinga\Module\Director\Web\Table;
use gipfl\IcingaWeb2\Link;
use gipfl\IcingaWeb2\Table\ZfQueryBasedTable;
use Zend_Db_Adapter_Abstract as ZfDbAdapter;
+use Zend_Db_Expr as DbExpr;
use Zend_Db_Select as ZfDbSelect;
class DatafieldTable extends ZfQueryBasedTable
{
protected $searchColumns = [
- 'df.varname',
+ 'lc_varname',
'df.caption',
];
@@ -19,6 +20,7 @@ class DatafieldTable extends ZfQueryBasedTable
return [
'id' => 'df.id',
'varname' => 'df.varname',
+ 'lc_varname' => new DbExpr('LOWER(df.varname)'),
'caption' => 'df.caption',
'description' => 'df.description',
'datatype' => 'df.datatype',
@@ -88,6 +90,15 @@ class DatafieldTable extends ZfQueryBasedTable
)->group('df.id')->group('df.varname')->group('dfc.category_name')->order('caption ASC');
}
+ public function search($search)
+ {
+ if ($search !== null) {
+ $search = strtolower($search);
+ }
+
+ return parent::search($search);
+ }
+
/**
* @param $type
* @param ZfDbAdapter $db
@@ -96,7 +107,7 @@ class DatafieldTable extends ZfQueryBasedTable
*/
protected function makeDatafieldSub($type, ZfDbAdapter $db)
{
- return $db->select()->from("icinga_${type}_field", [
+ return $db->select()->from("icinga_{$type}_field", [
'cnt' => 'COUNT(*)',
'datafield_id'
])->group('datafield_id');
@@ -110,7 +121,7 @@ class DatafieldTable extends ZfQueryBasedTable
*/
protected function makeVarSub($type, ZfDbAdapter $db)
{
- return $db->select()->from("icinga_${type}_var", [
+ return $db->select()->from("icinga_{$type}_var", [
'cnt' => 'COUNT(*)',
'varname'
])->group('varname');
diff --git a/library/Director/Web/Table/DependencyTemplateUsageTable.php b/library/Director/Web/Table/DependencyTemplateUsageTable.php
index d7537c5..2c1de50 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 @@ class DependencyTemplateUsageTable extends TemplateUsageTable
];
}
- 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/DeploymentLogTable.php b/library/Director/Web/Table/DeploymentLogTable.php
index 2d5cb94..4849218 100644
--- a/library/Director/Web/Table/DeploymentLogTable.php
+++ b/library/Director/Web/Table/DeploymentLogTable.php
@@ -3,10 +3,9 @@
namespace Icinga\Module\Director\Web\Table;
use gipfl\IcingaWeb2\Link;
-use gipfl\IcingaWeb2\Table\ZfQueryBasedTable;
use Icinga\Date\DateFormatter;
-class DeploymentLogTable extends ZfQueryBasedTable
+class DeploymentLogTable extends IntlZfQueryBasedTable
{
use DbHelper;
diff --git a/library/Director/Web/Table/GroupMemberTable.php b/library/Director/Web/Table/GroupMemberTable.php
index b0814ad..c24c6af 100644
--- a/library/Director/Web/Table/GroupMemberTable.php
+++ b/library/Director/Web/Table/GroupMemberTable.php
@@ -109,7 +109,7 @@ class GroupMemberTable extends ZfQueryBasedTable
];
}
- $url = Url::fromPath("director/${type}", $params);
+ $url = Url::fromPath("director/{$type}", $params);
$tr = $this::tr();
@@ -163,7 +163,7 @@ class GroupMemberTable extends ZfQueryBasedTable
'o.id',
'o.object_type',
'o.object_name',
- 'membership_type' => "CASE WHEN go.${type}_id IS NULL THEN 'apply' ELSE 'direct' END"
+ 'membership_type' => "CASE WHEN go.{$type}_id IS NULL THEN 'apply' ELSE 'direct' END"
];
if ($this->group === null) {
@@ -176,19 +176,19 @@ class GroupMemberTable extends ZfQueryBasedTable
}
$query = $this->db()->select()->from(
- ['gro' => "icinga_${type}group_${type}_resolved"],
+ ['gro' => "icinga_{$type}group_{$type}_resolved"],
$columns
)->join(
- ['o' => "icinga_${type}"],
- "o.id = gro.${type}_id",
+ ['o' => "icinga_{$type}"],
+ "o.id = gro.{$type}_id",
[]
)->join(
- ['g' => "icinga_${type}group"],
- "gro.${type}group_id = g.id",
+ ['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",
+ ['go' => "icinga_{$type}group_{$type}"],
+ "go.{$type}_id = o.id AND go.{$type}group_id = g.id",
[]
)->order('o.object_name');
diff --git a/library/Director/Web/Table/HostTemplateUsageTable.php b/library/Director/Web/Table/HostTemplateUsageTable.php
index 2d1ee2f..672691f 100644
--- a/library/Director/Web/Table/HostTemplateUsageTable.php
+++ b/library/Director/Web/Table/HostTemplateUsageTable.php
@@ -11,12 +11,4 @@ class HostTemplateUsageTable extends TemplateUsageTable
'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 c205e66..2c3dbc4 100644
--- a/library/Director/Web/Table/IcingaServiceSetServiceTable.php
+++ b/library/Director/Web/Table/IcingaServiceSetServiceTable.php
@@ -12,6 +12,7 @@ use Icinga\Module\Director\Objects\IcingaServiceSet;
use gipfl\IcingaWeb2\Link;
use gipfl\IcingaWeb2\Table\ZfQueryBasedTable;
use gipfl\IcingaWeb2\Url;
+use Ramsey\Uuid\Uuid;
class IcingaServiceSetServiceTable extends ZfQueryBasedTable
{
@@ -122,9 +123,12 @@ class IcingaServiceSetServiceTable extends ZfQueryBasedTable
];
$url = 'director/host/servicesetservice';
} else {
+ if (is_resource($row->uuid)) {
+ $row->uuid =stream_get_contents($row->uuid);
+ }
+
$params = [
- 'name' => $row->service,
- 'set' => $row->service_set
+ 'uuid' => Uuid::fromBytes($row->uuid)->toString(),
];
$url = 'director/service';
}
@@ -194,14 +198,28 @@ class IcingaServiceSetServiceTable extends ZfQueryBasedTable
$connection = $this->connection();
assert($connection instanceof Db);
$builder = new ServiceSetQueryBuilder($connection, $this->branchUuid);
- return $builder->selectServicesForSet($this->set)->limit(100);
+ $query = $builder->selectServicesForSet($this->set);
+ $alias = $this->branchUuid ? 'u' : 'o';
+
+ if ($this->affectedHost) {
+ if ($hostId = $this->affectedHost->get('id')) {
+ $query->joinLeft(
+ ['hsb' => 'icinga_host_service_blacklist'],
+ $this->db()->quoteInto("$alias.id = hsb.service_id AND hsb.host_id = ?", $hostId),
+ []
+ )->columns([
+ 'blacklisted' => "CASE WHEN hsb.service_id IS NULL THEN 'n' ELSE 'y' END"
+ ]);
+ }
+ }
+
+ return $query->limit(100);
}
protected function createFakeRemoveLinkForReadonlyView()
{
return Html::tag('span', [
- 'class' => 'icon-paste',
- 'style' => 'float: right; font-weight: normal',
+ 'class' => ['icon-paste', 'seviceset-obj-link'],
], $this->host->getObjectName());
}
@@ -209,8 +227,7 @@ class IcingaServiceSetServiceTable extends ZfQueryBasedTable
{
$hostname = $host->getObjectName();
return Link::create($hostname, 'director/host/services', ['name' => $hostname], [
- 'class' => 'icon-paste',
- 'style' => 'float: right; font-weight: normal',
+ 'class' => ['icon-paste', 'seviceset-obj-link'],
'data-base-target' => '_next',
'title' => sprintf(
$this->translate('This set has been inherited from %s'),
diff --git a/library/Director/Web/Table/IntlZfQueryBasedTable.php b/library/Director/Web/Table/IntlZfQueryBasedTable.php
new file mode 100644
index 0000000..81ef14c
--- /dev/null
+++ b/library/Director/Web/Table/IntlZfQueryBasedTable.php
@@ -0,0 +1,51 @@
+<?php
+
+namespace Icinga\Module\Director\Web\Table;
+
+use DateTime;
+use gipfl\IcingaWeb2\Table\ZfQueryBasedTable;
+use IntlDateFormatter;
+use Locale;
+
+abstract class IntlZfQueryBasedTable extends ZfQueryBasedTable
+{
+ protected function getDateFormatter()
+ {
+ return (new IntlDateFormatter(
+ Locale::getDefault(),
+ IntlDateFormatter::FULL,
+ IntlDateFormatter::NONE
+ ));
+ }
+
+ /**
+ * @param int $timestamp
+ */
+ protected function renderDayIfNew($timestamp)
+ {
+ $day = $this->getDateFormatter()->format((new DateTime())->setTimestamp($timestamp));
+
+ if ($this->lastDay !== $day) {
+ $this->nextHeader()->add(
+ $this::th($day, [
+ 'colspan' => 2,
+ 'class' => 'table-header-day'
+ ])
+ );
+
+ $this->lastDay = $day;
+ $this->nextBody();
+ }
+ }
+
+ protected function getTime(int $timeStamp)
+ {
+ $timeFormatter = $this->getDateFormatter();
+
+ $timeFormatter->setPattern(
+ in_array(Locale::getDefault(), ['en_US', 'en_US.UTF-8']) ? 'h:mm:ss a': 'H:mm:ss'
+ );
+
+ return $timeFormatter->format((new DateTime())->setTimestamp($timeStamp));
+ }
+}
diff --git a/library/Director/Web/Table/NotificationTemplateUsageTable.php b/library/Director/Web/Table/NotificationTemplateUsageTable.php
index da411a3..d8cd3d8 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 @@ class NotificationTemplateUsageTable extends TemplateUsageTable
];
}
- 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 2773841..4df9bdd 100644
--- a/library/Director/Web/Table/ObjectSetTable.php
+++ b/library/Director/Web/Table/ObjectSetTable.php
@@ -2,7 +2,9 @@
namespace Icinga\Module\Director\Web\Table;
+use gipfl\IcingaWeb2\Zf1\Db\FilterRenderer;
use Icinga\Authentication\Auth;
+use Icinga\Data\Filter\Filter;
use Icinga\Module\Director\Db;
use gipfl\IcingaWeb2\Link;
use gipfl\IcingaWeb2\Table\ZfQueryBasedTable;
@@ -28,6 +30,8 @@ class ObjectSetTable extends ZfQueryBasedTable
/** @var Auth */
private $auth;
+ protected $queries = [];
+
public static function create($type, Db $db, Auth $auth)
{
$table = new static($db);
@@ -53,7 +57,7 @@ class ObjectSetTable extends ZfQueryBasedTable
'uuid' => Uuid::fromBytes(Db\DbUtil::binaryResult($row->uuid))->toString(),
];
- $url = Url::fromPath("director/${type}set", $params);
+ $url = Url::fromPath("director/{$type}set", $params);
$classes = $this->getRowClasses($row);
$tr = static::tr([
@@ -85,7 +89,7 @@ class ObjectSetTable extends ZfQueryBasedTable
{
$type = $this->getType();
- $table = "icinga_${type}_set";
+ $table = "icinga_{$type}_set";
$columns = [
'id' => 'os.id',
'uuid' => 'os.uuid',
@@ -106,15 +110,15 @@ class ObjectSetTable extends ZfQueryBasedTable
['os' => $table],
$columns
)->joinLeft(
- ['o' => "icinga_${type}"],
- "o.${type}_set_id = os.id",
+ ['o' => "icinga_{$type}"],
+ "o.{$type}_set_id = os.id",
[]
);
$nameFilter = new FilterByNameRestriction(
$this->connection(),
$this->auth,
- "${type}_set"
+ "{$type}_set"
);
$nameFilter->applyToQuery($query, 'os');
/** @var Db $conn */
@@ -145,7 +149,20 @@ class ObjectSetTable extends ZfQueryBasedTable
$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');
}
-
+ $right->joinLeft(
+ ['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
+ ];
$query = $this->db()->select()->union([
'l' => new DbSelectParenthesis($query),
'r' => new DbSelectParenthesis($right),
@@ -168,16 +185,16 @@ class ObjectSetTable extends ZfQueryBasedTable
->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",
+ // ['osi' => "icinga_{$type}_set_inheritance"],
+ // "osi.parent_{$type}_set_id = os.id",
// []
// )->joinLeft(
- // ['oso' => "icinga_${type}_set"],
- // "oso.id = oso.${type}_set_id",
+ // ['oso' => "icinga_{$type}_set"],
+ // "oso.id = oso.{$type}_set_id",
// []
// );
// 'count_hosts' => 'COUNT(DISTINCT oso.id)',
@@ -196,11 +213,40 @@ class ObjectSetTable extends ZfQueryBasedTable
->group('os.assign_filter')
->group('os.description');
};
+ $this->queries = [$query];
}
return $query;
}
+ public function search($search)
+ {
+ if (! empty($search)) {
+ $columns = $this->getSearchColumns();
+ if (strpos($search, ' ') === false) {
+ $filter = Filter::matchAny();
+ foreach ($columns as $column) {
+ $filter->addFilter(Filter::expression($column, '=', "*$search*"));
+ }
+ } else {
+ $filter = Filter::matchAll();
+ foreach (explode(' ', $search) as $s) {
+ $sub = Filter::matchAny();
+ foreach ($columns as $column) {
+ $sub->addFilter(Filter::expression($column, '=', "*$s*"));
+ }
+ $filter->addFilter($sub);
+ }
+ }
+
+ foreach ($this->queries as $query) {
+ FilterRenderer::applyToQuery($filter, $query);
+ }
+ }
+
+ return $this;
+ }
+
/**
* @return Db
*/
diff --git a/library/Director/Web/Table/ObjectsTable.php b/library/Director/Web/Table/ObjectsTable.php
index 792cb6d..4ad1166 100644
--- a/library/Director/Web/Table/ObjectsTable.php
+++ b/library/Director/Web/Table/ObjectsTable.php
@@ -14,6 +14,7 @@ use gipfl\IcingaWeb2\Link;
use gipfl\IcingaWeb2\Table\ZfQueryBasedTable;
use gipfl\IcingaWeb2\Url;
use Ramsey\Uuid\Uuid;
+use Zend_Db_Adapter_Pdo_Pgsql;
use Zend_Db_Select as ZfSelect;
class ObjectsTable extends ZfQueryBasedTable
@@ -50,12 +51,18 @@ class ObjectsTable extends ZfQueryBasedTable
/** @var Auth */
private $auth;
+ public function __construct($db, Auth $auth)
+ {
+ $this->auth = $auth;
+ parent::__construct($db);
+ }
+
/**
* @param $type
* @param Db $db
* @return static
*/
- public static function create($type, Db $db)
+ public static function create($type, Db $db, Auth $auth)
{
$class = __NAMESPACE__ . '\\ObjectsTable' . ucfirst($type);
if (! class_exists($class)) {
@@ -63,7 +70,7 @@ class ObjectsTable extends ZfQueryBasedTable
}
/** @var static $table */
- $table = new $class($db);
+ $table = new $class($db, $auth);
$table->type = $type;
return $table;
}
@@ -84,20 +91,6 @@ class ObjectsTable extends ZfQueryBasedTable
return $this;
}
- /**
- * @return Auth
- */
- public function getAuth()
- {
- return $this->auth;
- }
-
- public function setAuth(Auth $auth)
- {
- $this->auth = $auth;
- return $this;
- }
-
public function filterObjectType($type)
{
$this->filterObjectType = $type;
@@ -124,11 +117,17 @@ class ObjectsTable extends ZfQueryBasedTable
IcingaObject $template,
$inheritance = Db\IcingaObjectFilterHelper::INHERIT_DIRECT
) {
+ if ($this->branchUuid) {
+ $tableAlias = 'u';
+ } else {
+ $tableAlias = 'o';
+ }
IcingaObjectFilterHelper::filterByTemplate(
$this->getQuery(),
$template,
- 'o',
- $inheritance
+ $tableAlias,
+ $inheritance,
+ $this->branchUuid
);
return $this;
@@ -142,7 +141,7 @@ class ObjectsTable extends ZfQueryBasedTable
protected function renderObjectNameColumn($row)
{
$type = $this->baseObjectUrl;
- $url = Url::fromPath("director/${type}", [
+ $url = Url::fromPath("director/{$type}", [
'uuid' => Uuid::fromBytes($row->uuid)->toString()
]);
@@ -227,11 +226,10 @@ class ObjectsTable extends ZfQueryBasedTable
{
/** @var Db $db */
$db = $this->connection();
- $auth = $this->getAuth();
return [
- new HostgroupRestriction($db, $auth),
- new FilterByNameRestriction($db, $auth, $this->getDummyObject()->getShortTableName())
+ new HostgroupRestriction($db, $this->auth),
+ new FilterByNameRestriction($db, $this->auth, $this->getDummyObject()->getShortTableName())
];
}
@@ -279,7 +277,39 @@ class ObjectsTable extends ZfQueryBasedTable
$conn->quoteBinary($this->branchUuid->getBytes())
),
[]
- )->where("(bo.branch_deleted IS NULL OR bo.branch_deleted = 'n')");
+ );
+
+ // keep the imported templates as columns
+ $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(
['bo' => "branched_$table"],
@@ -298,6 +328,7 @@ class ObjectsTable extends ZfQueryBasedTable
$query->order('object_name')->limit(100);
} else {
$this->applyObjectTypeFilter($query);
+ $query = $this->applyRestrictions($query);
$query->order('o.object_name')->limit(100);
}
diff --git a/library/Director/Web/Table/ObjectsTableService.php b/library/Director/Web/Table/ObjectsTableService.php
index 2d4ad41..c9bce72 100644
--- a/library/Director/Web/Table/ObjectsTableService.php
+++ b/library/Director/Web/Table/ObjectsTableService.php
@@ -203,8 +203,14 @@ class ObjectsTableService extends ObjectsTable
'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
new file mode 100644
index 0000000..6b18ac9
--- /dev/null
+++ b/library/Director/Web/Table/ObjectsTableSetMembers.php
@@ -0,0 +1,255 @@
+<?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\Db\IcingaObjectFilterHelper;
+use Icinga\Module\Director\Objects\IcingaObject;
+use Icinga\Module\Director\Restriction\FilterByNameRestriction;
+use Ramsey\Uuid\Uuid;
+
+class ObjectsTableSetMembers extends ZfQueryBasedTable
+{
+ use TableWithBranchSupport;
+
+ protected $searchColumns = [
+ 'os.object_name',
+ 'o.object_name',
+ ];
+
+ private $type;
+
+ /** @var IcingaObject */
+ protected $dummyObject;
+
+ protected $baseObjectUrl;
+
+ /** @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 [
+ 'os.object_name' => 'Service Set',
+ 'o.object_name' => 'Service Name'
+ ];
+ }
+
+ public function setBaseObjectUrl($url)
+ {
+ $this->baseObjectUrl = $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.
+ *
+ * @param IcingaObject $template
+ * @param string $inheritance
+ * @return $this
+ * @throws \Icinga\Exception\ProgrammingError
+ */
+ public function filterTemplate(
+ IcingaObject $template,
+ $inheritance = IcingaObjectFilterHelper::INHERIT_DIRECT
+ ) {
+ IcingaObjectFilterHelper::filterByTemplate(
+ $this->getQuery(),
+ $template,
+ 'o',
+ $inheritance,
+ $this->branchUuid
+ );
+
+ return $this;
+ }
+
+
+ public function renderRow($row)
+ {
+ $url = Url::fromPath('director/service/edit', [
+ 'name' => $row->object_name,
+ 'uuid' => Uuid::fromBytes($row->uuid)->toString(),
+ ]);
+
+ return static::tr([
+ static::td([
+ Link::create($row->service_set, $url),
+ ]),
+ static::td($row->object_name),
+ ])->addAttributes(['class' => $this->getRowClasses($row)]);
+ }
+
+ /**
+ * @return IcingaObject
+ */
+ protected function getDummyObject()
+ {
+ if ($this->dummyObject === null) {
+ $type = $this->type;
+ $this->dummyObject = IcingaObject::createByType($type);
+ }
+ return $this->dummyObject;
+ }
+
+ protected function prepareQuery()
+ {
+ $table = $this->getDummyObject()->getTableName();
+ $type = $this->getType();
+
+ $columns = [
+ 'id' => 'o.id',
+ 'uuid' => 'o.uuid',
+ 'service_set' => 'os.object_name',
+ 'object_name' => 'o.object_name',
+ 'object_type' => 'os.object_type',
+ 'assign_filter' => 'os.assign_filter',
+ 'description' => 'os.description',
+ ];
+
+ $query = $this->db()->select()->from(
+ ['o' => $table],
+ $columns
+ )->joinLeft(
+ ['os' => "icinga_{$type}_set"],
+ "o.{$type}_set_id = os.id",
+ []
+ )->where('o.host_id IS NULL');
+
+ $nameFilter = new FilterByNameRestriction(
+ $this->connection(),
+ $this->auth,
+ "{$type}_set"
+ );
+ $nameFilter->applyToQuery($query, 'os');
+
+ 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;
+ }
+
+ /**
+ * @return Db
+ */
+ public function connection()
+ {
+ return parent::connection();
+ }
+}
diff --git a/library/Director/Web/Table/ReadOnlyFormAvpTable.php b/library/Director/Web/Table/ReadOnlyFormAvpTable.php
deleted file mode 100644
index c3b44f3..0000000
--- a/library/Director/Web/Table/ReadOnlyFormAvpTable.php
+++ /dev/null
@@ -1,113 +0,0 @@
-<?php
-
-namespace Icinga\Module\Director\Web\Table;
-
-use Icinga\Module\Director\PlainObjectRenderer;
-use Icinga\Module\Director\Web\Form\QuickForm;
-use Zend_Form_Element as ZfElement;
-use Zend_Form_DisplayGroup as ZfDisplayGroup;
-
-class ReadOnlyFormAvpTable
-{
- protected $form;
-
- public function __construct(QuickForm $form)
- {
- $this->form = $form;
- }
-
- protected function renderDisplayGroups(QuickForm $form)
- {
- $html = '';
-
- foreach ($form->getDisplayGroups() as $group) {
- $elements = $this->filterGroupElements($group);
-
- if (empty($elements)) {
- continue;
- }
-
- $html .= '<tr><th colspan="2" style="text-align: right">' . $group->getLegend() . '</th></tr>';
- $html .= $this->renderElements($elements);
- }
-
- return $html;
- }
-
- /**
- * @param ZfDisplayGroup $group
- * @return ZfElement[]
- */
- protected function filterGroupElements(ZfDisplayGroup $group)
- {
- $blacklist = array('disabled', 'assign_filter');
- $elements = array();
- /** @var ZfElement $element */
- foreach ($group->getElements() as $element) {
- if ($element->getValue() === null) {
- continue;
- }
-
- if ($element->getType() === 'Zend_Form_Element_Hidden') {
- continue;
- }
-
- if (in_array($element->getName(), $blacklist)) {
- continue;
- }
-
-
- $elements[] = $element;
- }
-
- return $elements;
- }
-
- protected function renderElements($elements)
- {
- $html = '';
- foreach ($elements as $element) {
- $html .= $this->renderElement($element);
- }
-
- return $html;
- }
-
- /**
- * @param ZfElement $element
- *
- * @return string
- */
- protected function renderElement(ZfElement $element)
- {
- $value = $element->getValue();
- return '<tr><th>'
- . $this->escape($element->getLabel())
- . '</th><td>'
- . $this->renderValue($value)
- . '</td></tr>';
- }
-
- protected function renderValue($value)
- {
- if (is_string($value)) {
- return $this->escape($value);
- } elseif (is_array($value)) {
- return $this->escape(implode(', ', $value));
- }
- return $this->escape(PlainObjectRenderer::render($value));
- }
-
- protected function escape($string)
- {
- return htmlspecialchars($string);
- }
-
- public function render()
- {
- $this->form->initializeForObject();
- return '<table class="name-value-table">' . "\n"
- . $this->renderDisplayGroups($this->form)
- . '</table>';
- }
-}
diff --git a/library/Director/Web/Table/ServiceTemplateUsageTable.php b/library/Director/Web/Table/ServiceTemplateUsageTable.php
index 82f9643..c2806f6 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()
@@ -10,18 +13,27 @@ class ServiceTemplateUsageTable extends TemplateUsageTable
'templates' => $this->translate('Templates'),
'objects' => $this->translate('Objects'),
'applyrules' => $this->translate('Apply Rules'),
- // 'setmembers' => $this->translate('Set Members'),
+ 'setmembers' => $this->translate('Set Members'),
];
}
- protected function getTypeSummaryDefinitions()
+ protected function getSummaryTables(string $templateType, Db $connection)
{
+ $auth = Auth::getInstance();
return [
- 'templates' => $this->getSummaryLine('template'),
- 'objects' => $this->getSummaryLine('object'),
- 'applyrules' => $this->getSummaryLine('apply', 'o.service_set_id IS NULL'),
- // TODO: re-enable
- // 'setmembers' => $this->getSummaryLine('apply', 'o.service_set_id IS NOT NULL'),
+ 'templates' => TemplatesTable::create(
+ $templateType,
+ $connection
+ ),
+ 'objects' => ObjectsTable::create($templateType, $connection, $this->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/SyncRunTable.php b/library/Director/Web/Table/SyncRunTable.php
index e08aad7..19f2678 100644
--- a/library/Director/Web/Table/SyncRunTable.php
+++ b/library/Director/Web/Table/SyncRunTable.php
@@ -2,22 +2,17 @@
namespace Icinga\Module\Director\Web\Table;
-use gipfl\Format\LocalTimeFormat;
use Icinga\Module\Director\Objects\SyncRule;
use gipfl\IcingaWeb2\Link;
-use gipfl\IcingaWeb2\Table\ZfQueryBasedTable;
-class SyncRunTable extends ZfQueryBasedTable
+class SyncRunTable extends IntlZfQueryBasedTable
{
/** @var SyncRule */
protected $rule;
- protected $timeFormat;
-
public function __construct(SyncRule $rule)
{
parent::__construct($rule->getConnection());
- $this->timeFormat = new LocalTimeFormat();
$this->getAttributes()
->set('data-base-target', '_self')
->add('class', 'history');
@@ -31,7 +26,7 @@ class SyncRunTable extends ZfQueryBasedTable
return $this::tr([
$this::td($this->makeSummary($row)),
$this::td(new Link(
- $this->timeFormat->getTime($time),
+ $this->getTime($time),
'director/syncrule/history',
[
'id' => $row->rule_id,
diff --git a/library/Director/Web/Table/TableWithBranchSupport.php b/library/Director/Web/Table/TableWithBranchSupport.php
index 7c5b15c..9e412c3 100644
--- a/library/Director/Web/Table/TableWithBranchSupport.php
+++ b/library/Director/Web/Table/TableWithBranchSupport.php
@@ -56,6 +56,9 @@ trait TableWithBranchSupport
$result[$alias] = $column;
}
+ if (isset($result['count_services'])) {
+ $result['count_services'] = 'COUNT(DISTINCT COALESCE(o.uuid, bo.uuid))';
+ }
return $result;
}
diff --git a/library/Director/Web/Table/TemplateUsageTable.php b/library/Director/Web/Table/TemplateUsageTable.php
index 66e56ea..376a499 100644
--- a/library/Director/Web/Table/TemplateUsageTable.php
+++ b/library/Director/Web/Table/TemplateUsageTable.php
@@ -2,9 +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\Db\IcingaObjectFilterHelper;
use Icinga\Module\Director\Objects\IcingaObject;
-use Icinga\Module\Director\Resolver\TemplateTree;
use gipfl\IcingaWeb2\Link;
use ipl\Html\Table;
use gipfl\Translation\TranslationHelper;
@@ -13,10 +16,17 @@ class TemplateUsageTable extends Table
{
use TranslationHelper;
+ use TableWithBranchSupport;
+
+ /** @var Auth */
+ protected $auth;
+
protected $defaultAttributes = ['class' => 'pivot'];
protected $objectType;
+ protected $searchColumns = [];
+
public function getTypes()
{
return [
@@ -25,26 +35,22 @@ class TemplateUsageTable extends Table
];
}
- 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)
+ public static function forTemplate(IcingaObject $template, Auth $auth, Branch $branch = null)
{
$type = ucfirst($template->getShortTableName());
- $class = __NAMESPACE__ . "\\${type}TemplateUsageTable";
+ $class = __NAMESPACE__ . "\\{$type}TemplateUsageTable";
if (class_exists($class)) {
- return new $class($template);
+ return new $class($template, $auth, $branch);
} else {
- return new static($template);
+ return new static($template, $auth, $branch);
}
}
@@ -58,8 +64,9 @@ class TemplateUsageTable extends Table
];
}
- protected function __construct(IcingaObject $template)
+ protected function __construct(IcingaObject $template, Auth $auth, Branch $branch = null)
{
+ $this->auth = $auth;
if ($template->get('object_type') !== 'template') {
throw new ProgrammingError(
@@ -68,6 +75,7 @@ class TemplateUsageTable extends Table
);
}
+ $this->setBranch($branch);
$this->objectType = $objectType = $template->getShortTableName();
$types = $this->getTypes();
$usage = $this->getUsageSummary($template);
@@ -85,7 +93,7 @@ class TemplateUsageTable extends Table
Table::td(
Link::create(
$count,
- "director/${objectType}template/$type",
+ "director/{$objectType}template/$type",
[
'name' => $template->getObjectName(),
'inheritance' => $inheritance
@@ -98,6 +106,7 @@ class TemplateUsageTable extends Table
}
if ($used) {
+ $this->getHeader()->add(Table::row($this->getColumnsToBeRendered(), null, 'th'));
$this->add($rows);
} else {
$this->add($this->translate('This template is not in use'));
@@ -106,52 +115,51 @@ class TemplateUsageTable extends Table
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) {
+ $directTable = clone $summaryTable;
+ $inDirectTable = clone $summaryTable;
+
+ $direct[$type] = $db->query(
+ $directTable
+ ->filterTemplate($template, IcingaObjectFilterHelper::INHERIT_DIRECT)
+ ->getQuery()
+ )->rowCount();
+ $indirect[$type] = $db->query(
+ $inDirectTable
+ ->filterTemplate($template, IcingaObjectFilterHelper::INHERIT_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, $this->auth)
+ ->setBranchUuid($this->branchUuid)
+ ];
}
}
diff --git a/library/Director/Web/Table/TemplatesTable.php b/library/Director/Web/Table/TemplatesTable.php
index be195b2..d6582fd 100644
--- a/library/Director/Web/Table/TemplatesTable.php
+++ b/library/Director/Web/Table/TemplatesTable.php
@@ -36,8 +36,8 @@ class TemplatesTable extends ZfQueryBasedTable implements FilterableByUsage
{
$type = $this->type;
$this->enableMultiSelect(
- "director/${type}s/edittemplates",
- "director/${type}template",
+ "director/{$type}s/edittemplates",
+ "director/{$type}template",
['name']
);
}
@@ -60,12 +60,12 @@ class TemplatesTable extends ZfQueryBasedTable implements FilterableByUsage
$name,
Html::tag(
'span',
- ['style' => 'font-style: italic'],
+ ['class' => 'font-italic'],
$this->translate(' - not in use -')
)
];
- $url = Url::fromPath("director/${type}template/usage", [
+ $url = Url::fromPath("director/{$type}template/usage", [
'name' => $name
]);
@@ -101,8 +101,8 @@ class TemplatesTable extends ZfQueryBasedTable implements FilterableByUsage
{
$type = $this->getType();
$this->getQuery()->where(
- "(EXISTS (SELECT ${type}_id FROM icinga_${type}_inheritance"
- . " WHERE parent_${type}_id = o.id))"
+ "(EXISTS (SELECT {$type}_id FROM icinga_{$type}_inheritance"
+ . " WHERE parent_{$type}_id = o.id))"
);
}
@@ -110,8 +110,8 @@ class TemplatesTable extends ZfQueryBasedTable implements FilterableByUsage
{
$type = $this->getType();
$this->getQuery()->where(
- "(NOT EXISTS (SELECT ${type}_id FROM icinga_${type}_inheritance"
- . " WHERE parent_${type}_id = o.id))"
+ "(NOT EXISTS (SELECT {$type}_id FROM icinga_{$type}_inheritance"
+ . " WHERE parent_{$type}_id = o.id))"
);
}
@@ -135,8 +135,8 @@ class TemplatesTable extends ZfQueryBasedTable implements FilterableByUsage
protected function prepareQuery()
{
$type = $this->getType();
- $used = "CASE WHEN EXISTS(SELECT 1 FROM icinga_${type}_inheritance oi"
- . " WHERE oi.parent_${type}_id = o.id) THEN 'y' ELSE 'n' END";
+ $used = "CASE WHEN EXISTS(SELECT 1 FROM icinga_{$type}_inheritance oi"
+ . " WHERE oi.parent_{$type}_id = o.id) THEN 'y' ELSE 'n' END";
$columns = [
'object_name' => 'o.object_name',
@@ -145,7 +145,7 @@ class TemplatesTable extends ZfQueryBasedTable implements FilterableByUsage
'is_used' => $used,
];
$query = $this->db()->select()->from(
- ['o' => "icinga_${type}"],
+ ['o' => "icinga_{$type}"],
$columns
)->where(
"o.object_type = 'template'"