summaryrefslogtreecommitdiffstats
path: root/modules/monitoring/library/Monitoring/Backend/Ido/Query
diff options
context:
space:
mode:
Diffstat (limited to 'modules/monitoring/library/Monitoring/Backend/Ido/Query')
-rw-r--r--modules/monitoring/library/Monitoring/Backend/Ido/Query/AllcontactsQuery.php74
-rw-r--r--modules/monitoring/library/Monitoring/Backend/Ido/Query/CommandQuery.php61
-rw-r--r--modules/monitoring/library/Monitoring/Backend/Ido/Query/CommentQuery.php158
-rw-r--r--modules/monitoring/library/Monitoring/Backend/Ido/Query/CommentdeletionhistoryQuery.php179
-rw-r--r--modules/monitoring/library/Monitoring/Backend/Ido/Query/CommenteventQuery.php39
-rw-r--r--modules/monitoring/library/Monitoring/Backend/Ido/Query/CommenthistoryQuery.php179
-rw-r--r--modules/monitoring/library/Monitoring/Backend/Ido/Query/ContactQuery.php139
-rw-r--r--modules/monitoring/library/Monitoring/Backend/Ido/Query/ContactgroupQuery.php214
-rw-r--r--modules/monitoring/library/Monitoring/Backend/Ido/Query/CustomvarQuery.php116
-rw-r--r--modules/monitoring/library/Monitoring/Backend/Ido/Query/DowntimeQuery.php163
-rw-r--r--modules/monitoring/library/Monitoring/Backend/Ido/Query/DowntimeendhistoryQuery.php179
-rw-r--r--modules/monitoring/library/Monitoring/Backend/Ido/Query/DowntimeeventQuery.php42
-rw-r--r--modules/monitoring/library/Monitoring/Backend/Ido/Query/DowntimestarthistoryQuery.php179
-rw-r--r--modules/monitoring/library/Monitoring/Backend/Ido/Query/EmptyhostgroupQuery.php38
-rw-r--r--modules/monitoring/library/Monitoring/Backend/Ido/Query/EmptyservicegroupQuery.php51
-rw-r--r--modules/monitoring/library/Monitoring/Backend/Ido/Query/EventgridQuery.php57
-rw-r--r--modules/monitoring/library/Monitoring/Backend/Ido/Query/EventgridhostsQuery.php16
-rw-r--r--modules/monitoring/library/Monitoring/Backend/Ido/Query/EventgridservicesQuery.php15
-rw-r--r--modules/monitoring/library/Monitoring/Backend/Ido/Query/EventhistoryQuery.php134
-rw-r--r--modules/monitoring/library/Monitoring/Backend/Ido/Query/FlappingendhistoryQuery.php49
-rw-r--r--modules/monitoring/library/Monitoring/Backend/Ido/Query/FlappingeventQuery.php36
-rw-r--r--modules/monitoring/library/Monitoring/Backend/Ido/Query/FlappingstarthistoryQuery.php179
-rw-r--r--modules/monitoring/library/Monitoring/Backend/Ido/Query/GroupsummaryQuery.php131
-rw-r--r--modules/monitoring/library/Monitoring/Backend/Ido/Query/HostcommentQuery.php202
-rw-r--r--modules/monitoring/library/Monitoring/Backend/Ido/Query/HostcommentdeletionhistoryQuery.php44
-rw-r--r--modules/monitoring/library/Monitoring/Backend/Ido/Query/HostcommenthistoryQuery.php197
-rw-r--r--modules/monitoring/library/Monitoring/Backend/Ido/Query/HostcontactQuery.php247
-rw-r--r--modules/monitoring/library/Monitoring/Backend/Ido/Query/HostdowntimeQuery.php208
-rw-r--r--modules/monitoring/library/Monitoring/Backend/Ido/Query/HostdowntimeendhistoryQuery.php40
-rw-r--r--modules/monitoring/library/Monitoring/Backend/Ido/Query/HostdowntimestarthistoryQuery.php204
-rw-r--r--modules/monitoring/library/Monitoring/Backend/Ido/Query/HostflappingendhistoryQuery.php31
-rw-r--r--modules/monitoring/library/Monitoring/Backend/Ido/Query/HostflappingstarthistoryQuery.php200
-rw-r--r--modules/monitoring/library/Monitoring/Backend/Ido/Query/HostgroupQuery.php295
-rw-r--r--modules/monitoring/library/Monitoring/Backend/Ido/Query/HostgroupsummaryQuery.php142
-rw-r--r--modules/monitoring/library/Monitoring/Backend/Ido/Query/HostnotificationQuery.php283
-rw-r--r--modules/monitoring/library/Monitoring/Backend/Ido/Query/HoststatehistoryQuery.php222
-rw-r--r--modules/monitoring/library/Monitoring/Backend/Ido/Query/HoststatusQuery.php338
-rw-r--r--modules/monitoring/library/Monitoring/Backend/Ido/Query/HoststatussummaryQuery.php91
-rw-r--r--modules/monitoring/library/Monitoring/Backend/Ido/Query/IdoQuery.php1599
-rw-r--r--modules/monitoring/library/Monitoring/Backend/Ido/Query/InstanceQuery.php26
-rw-r--r--modules/monitoring/library/Monitoring/Backend/Ido/Query/NotificationQuery.php144
-rw-r--r--modules/monitoring/library/Monitoring/Backend/Ido/Query/NotificationeventQuery.php52
-rw-r--r--modules/monitoring/library/Monitoring/Backend/Ido/Query/NotificationhistoryQuery.php142
-rw-r--r--modules/monitoring/library/Monitoring/Backend/Ido/Query/ProgramstatusQuery.php68
-rw-r--r--modules/monitoring/library/Monitoring/Backend/Ido/Query/RuntimesummaryQuery.php80
-rw-r--r--modules/monitoring/library/Monitoring/Backend/Ido/Query/RuntimevariablesQuery.php18
-rw-r--r--modules/monitoring/library/Monitoring/Backend/Ido/Query/ServicecommentQuery.php218
-rw-r--r--modules/monitoring/library/Monitoring/Backend/Ido/Query/ServicecommentdeletionhistoryQuery.php44
-rw-r--r--modules/monitoring/library/Monitoring/Backend/Ido/Query/ServicecommenthistoryQuery.php195
-rw-r--r--modules/monitoring/library/Monitoring/Backend/Ido/Query/ServicecontactQuery.php235
-rw-r--r--modules/monitoring/library/Monitoring/Backend/Ido/Query/ServicedowntimeQuery.php222
-rw-r--r--modules/monitoring/library/Monitoring/Backend/Ido/Query/ServicedowntimeendhistoryQuery.php40
-rw-r--r--modules/monitoring/library/Monitoring/Backend/Ido/Query/ServicedowntimestarthistoryQuery.php202
-rw-r--r--modules/monitoring/library/Monitoring/Backend/Ido/Query/ServiceflappingendhistoryQuery.php31
-rw-r--r--modules/monitoring/library/Monitoring/Backend/Ido/Query/ServiceflappingstarthistoryQuery.php197
-rw-r--r--modules/monitoring/library/Monitoring/Backend/Ido/Query/ServicegroupQuery.php303
-rw-r--r--modules/monitoring/library/Monitoring/Backend/Ido/Query/ServicegroupsummaryQuery.php113
-rw-r--r--modules/monitoring/library/Monitoring/Backend/Ido/Query/ServicenotificationQuery.php286
-rw-r--r--modules/monitoring/library/Monitoring/Backend/Ido/Query/ServicestatehistoryQuery.php220
-rw-r--r--modules/monitoring/library/Monitoring/Backend/Ido/Query/ServicestatusQuery.php524
-rw-r--r--modules/monitoring/library/Monitoring/Backend/Ido/Query/ServicestatussummaryQuery.php104
-rw-r--r--modules/monitoring/library/Monitoring/Backend/Ido/Query/StatechangeeventQuery.php41
-rw-r--r--modules/monitoring/library/Monitoring/Backend/Ido/Query/StatehistoryQuery.php179
-rw-r--r--modules/monitoring/library/Monitoring/Backend/Ido/Query/StatussummaryQuery.php243
-rw-r--r--modules/monitoring/library/Monitoring/Backend/Ido/Query/UnhandledhostproblemsQuery.php48
-rw-r--r--modules/monitoring/library/Monitoring/Backend/Ido/Query/UnhandledserviceproblemsQuery.php48
66 files changed, 10794 insertions, 0 deletions
diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/AllcontactsQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/AllcontactsQuery.php
new file mode 100644
index 0000000..09779b6
--- /dev/null
+++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/AllcontactsQuery.php
@@ -0,0 +1,74 @@
+<?php
+/* Icinga Web 2 | (c) 2013 Icinga Development Team | GPLv2+ */
+
+namespace Icinga\Module\Monitoring\Backend\Ido\Query;
+
+use Zend_Db_Select;
+
+class AllcontactsQuery extends IdoQuery
+{
+ protected $columnMap = array(
+ 'contacts' => array(
+ 'contact_name' => 'c.contact_name',
+ 'host_object_id' => 'c.host_object_id',
+ 'host_name' => 'c.host_name',
+ 'service_object_id' => 'c.service_object_id',
+ 'service_host_name' => 'c.service_host_name',
+ 'service_description' => 'c.service_description',
+
+ 'contact_alias' => 'c.contact_alias',
+ 'contact_email' => 'c.contact_email',
+ 'contact_pager' => 'c.contact_pager',
+ 'contact_has_host_notfications' => 'c.contact_has_host_notfications',
+ 'contact_has_service_notfications' => 'c.contact_has_service_notfications',
+ 'contact_can_submit_commands' => 'c.contact_can_submit_commands',
+ 'contact_notify_service_recovery' => 'c.notify_service_recovery',
+ 'contact_notify_service_warning' => 'c.notify_service_warning',
+ 'contact_notify_service_critical' => 'c.notify_service_critical',
+ 'contact_notify_service_unknown' => 'c.notify_service_unknown',
+ 'contact_notify_service_flapping' => 'c.notify_service_flapping',
+ 'contact_notify_service_downtime' => 'c.notify_service_downtime',
+ 'contact_notify_host_recovery' => 'c.notify_host_recovery',
+ 'contact_notify_host_down' => 'c.notify_host_down',
+ 'contact_notify_host_unreachable' => 'c.notify_host_unreachable',
+ 'contact_notify_host_flapping' => 'c.notify_host_flapping',
+ 'contact_notify_host_downtime' => 'c.notify_host_downtime',
+
+
+ )
+ );
+
+ protected $contacts;
+ protected $contactgroups;
+ protected $useSubqueryCount = true;
+
+ public function requireColumn($alias)
+ {
+ $this->contacts->addColumn($alias);
+ $this->contactgroups->addColumn($alias);
+ return parent::requireColumn($alias);
+ }
+
+ protected function joinBaseTables()
+ {
+ $this->contacts = $this->createSubQuery(
+ 'contact',
+ array('contact_name')
+ );
+ $this->contactgroups = $this->createSubQuery(
+ 'contactgroup',
+ array('contact_name')
+ );
+ $sub = $this->db->select()->union(
+ array($this->contacts, $this->contactgroups),
+ Zend_Db_Select::SQL_UNION_ALL
+ );
+
+ $this->baseQuery = $this->db->select()->distinct()->from(
+ array('c' => $sub),
+ array()
+ );
+
+ $this->joinedVirtualTables = array('contacts' => true);
+ }
+}
diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/CommandQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/CommandQuery.php
new file mode 100644
index 0000000..59a4ccb
--- /dev/null
+++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/CommandQuery.php
@@ -0,0 +1,61 @@
+<?php
+/* Icinga Web 2 | (c) 2014 Icinga Development Team | GPLv2+ */
+
+namespace Icinga\Module\Monitoring\Backend\Ido\Query;
+
+/**
+ * Query for commands
+ */
+class CommandQuery extends IdoQuery
+{
+ /**
+ * @var array
+ */
+ protected $columnMap = array(
+ 'commands' => array(
+ 'command_id' => 'c.command_id',
+ 'command_instance_id' => 'c.instance_id',
+ 'command_config_type' => 'c.config_type',
+ 'command_line' => 'c.command_line',
+ 'command_name' => 'co.name1'
+ ),
+
+ 'contacts' => array(
+ 'contact_id' => 'con.contact_id',
+ 'contact_alias' => 'con.contact_alias'
+ )
+ );
+
+ /**
+ * Fetch basic information about commands
+ */
+ protected function joinBaseTables()
+ {
+ $this->select->from(
+ array('c' => $this->prefix . 'commands'),
+ array()
+ )->join(
+ array('co' => $this->prefix . 'objects'),
+ 'co.object_id = c.object_id',
+ array()
+ );
+
+ $this->joinedVirtualTables = array('commands' => true);
+ }
+
+ /**
+ * Join contacts
+ */
+ protected function joinContacts()
+ {
+ $this->select->join(
+ array('cnc' => $this->prefix . 'contact_notificationcommands'),
+ 'cnc.command_object_id = co.object_id',
+ array()
+ )->join(
+ array('con' => $this->prefix . 'contacts'),
+ 'con.contact_id = cnc.contact_id',
+ array()
+ );
+ }
+}
diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/CommentQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/CommentQuery.php
new file mode 100644
index 0000000..6c01931
--- /dev/null
+++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/CommentQuery.php
@@ -0,0 +1,158 @@
+<?php
+/* Icinga Web 2 | (c) 2013 Icinga Development Team | GPLv2+ */
+
+namespace Icinga\Module\Monitoring\Backend\Ido\Query;
+
+use Icinga\Data\Filter\FilterExpression;
+use Zend_Db_Expr;
+use Zend_Db_Select;
+use Icinga\Data\Filter\Filter;
+
+/**
+ * Query for host and service comments
+ */
+class CommentQuery extends IdoQuery
+{
+ /**
+ * {@inheritdoc}
+ */
+ protected $columnMap = array(
+ 'comments' => array(
+ 'comment_author' => 'c.comment_author',
+ 'comment_author_name' => 'c.comment_author_name',
+ 'comment_data' => 'c.comment_data',
+ 'comment_expiration' => 'c.comment_expiration',
+ 'comment_internal_id' => 'c.comment_internal_id',
+ 'comment_is_persistent' => 'c.comment_is_persistent',
+ 'comment_name' => 'c.comment_name',
+ 'comment_timestamp' => 'c.comment_timestamp',
+ 'comment_type' => 'c.comment_type',
+ 'instance_name' => 'c.instance_name',
+ 'object_type' => 'c.object_type'
+ ),
+ 'hosts' => array(
+ 'host_display_name' => 'c.host_display_name',
+ 'host_name' => 'c.host_name',
+ 'host_state' => 'c.host_state'
+ ),
+ 'services' => array(
+ 'service_description' => 'c.service_description',
+ 'service_display_name' => 'c.service_display_name',
+ 'service_host_name' => 'c.service_host_name',
+ 'service_state' => 'c.service_state'
+ )
+ );
+
+ /**
+ * The union
+ *
+ * @var Zend_Db_Select
+ */
+ protected $commentQuery;
+
+ /**
+ * Subqueries used for the comment query
+ *
+ * @var IdoQuery[]
+ */
+ protected $subQueries = array();
+
+ /**
+ * {@inheritdoc}
+ */
+ public function allowsCustomVars()
+ {
+ foreach ($this->subQueries as $query) {
+ if (! $query->allowsCustomVars()) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function addFilter(Filter $filter)
+ {
+ foreach ($this->subQueries as $sub) {
+ $sub->applyFilter(clone $filter);
+ }
+ return $this;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function joinBaseTables()
+ {
+ if (version_compare($this->getIdoVersion(), '1.14.0', '<')) {
+ $this->columnMap['comments']['comment_name'] = '(NULL)';
+ }
+ $this->commentQuery = $this->db->select();
+ $this->select->from(
+ array('c' => $this->commentQuery),
+ array()
+ );
+ $this->joinedVirtualTables['comments'] = true;
+ }
+
+ /**
+ * Join hosts
+ */
+ protected function joinHosts()
+ {
+ $columns = array_keys($this->columnMap['comments'] + $this->columnMap['hosts']);
+ foreach (array_keys($this->columnMap['services']) as $column) {
+ $columns[$column] = new Zend_Db_Expr('NULL');
+ }
+ $hosts = $this->createSubQuery('hostcomment', $columns);
+ $this->subQueries[] = $hosts;
+ $this->commentQuery->union(array($hosts), Zend_Db_Select::SQL_UNION_ALL);
+ }
+
+ /**
+ * Join services
+ */
+ protected function joinServices()
+ {
+ $columns = array_keys($this->columnMap['comments'] + $this->columnMap['hosts'] + $this->columnMap['services']);
+ $services = $this->createSubQuery('servicecomment', $columns);
+ $this->subQueries[] = $services;
+ $this->commentQuery->union(array($services), Zend_Db_Select::SQL_UNION_ALL);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function order($columnOrAlias, $dir = null)
+ {
+ foreach ($this->subQueries as $sub) {
+ $sub->requireColumn($columnOrAlias);
+ }
+ return parent::order($columnOrAlias, $dir);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function where($condition, $value = null)
+ {
+ $this->requireColumn($condition);
+ foreach ($this->subQueries as $sub) {
+ $sub->where($condition, $value);
+ }
+ return $this;
+ }
+
+ public function whereEx(FilterExpression $ex)
+ {
+ $this->requireColumn($ex->getColumn());
+ foreach ($this->subQueries as $sub) {
+ $sub->whereEx($ex);
+ }
+
+ return $this;
+ }
+}
diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/CommentdeletionhistoryQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/CommentdeletionhistoryQuery.php
new file mode 100644
index 0000000..8cb4ddb
--- /dev/null
+++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/CommentdeletionhistoryQuery.php
@@ -0,0 +1,179 @@
+<?php
+/* Icinga Web 2 | (c) 2014 Icinga Development Team | GPLv2+ */
+
+namespace Icinga\Module\Monitoring\Backend\Ido\Query;
+
+use Icinga\Data\Filter\FilterExpression;
+use Zend_Db_Expr;
+use Zend_Db_Select;
+use Icinga\Data\Filter\Filter;
+
+/**
+ * Query for host and service comment removal records
+ */
+class CommentdeletionhistoryQuery extends IdoQuery
+{
+ /**
+ * {@inheritdoc}
+ */
+ protected $columnMap = array(
+ 'commenthistory' => array(
+ 'id' => 'cdh.id',
+ 'object_type' => 'cdh.object_type'
+ ),
+ 'history' => array(
+ 'type' => 'cdh.type',
+ 'timestamp' => 'cdh.timestamp',
+ 'object_id' => 'cdh.object_id',
+ 'state' => 'cdh.state',
+ 'output' => 'cdh.output'
+ ),
+ 'hosts' => array(
+ 'host_display_name' => 'cdh.host_display_name',
+ 'host_name' => 'cdh.host_name'
+ ),
+ 'services' => array(
+ 'service_description' => 'cdh.service_description',
+ 'service_display_name' => 'cdh.service_display_name',
+ 'service_host_name' => 'cdh.service_host_name'
+ )
+ );
+
+ /**
+ * The union
+ *
+ * @var Zend_Db_Select
+ */
+ protected $commentDeletionHistoryQuery;
+
+ /**
+ * Subqueries used for the comment history query
+ *
+ * @var IdoQuery[]
+ */
+ protected $subQueries = array();
+
+ /**
+ * Whether to additionally select all history columns
+ *
+ * @var bool
+ */
+ protected $fetchHistoryColumns = false;
+
+ /**
+ * {@inheritdoc}
+ */
+ public function allowsCustomVars()
+ {
+ foreach ($this->subQueries as $query) {
+ if (! $query->allowsCustomVars()) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function joinBaseTables()
+ {
+ $this->commentDeletionHistoryQuery = $this->db->select();
+ $this->select->from(
+ array('cdh' => $this->commentDeletionHistoryQuery),
+ array()
+ );
+ $this->joinedVirtualTables['commenthistory'] = true;
+ }
+
+ /**
+ * Join history related columns and tables
+ */
+ protected function joinHistory()
+ {
+ // TODO: Ensure that one is selecting the history columns first...
+ $this->fetchHistoryColumns = true;
+ $this->requireVirtualTable('hosts');
+ $this->requireVirtualTable('services');
+ }
+
+ /**
+ * Join hosts
+ */
+ protected function joinHosts()
+ {
+ $columns = array_keys(
+ $this->columnMap['commenthistory'] + $this->columnMap['hosts']
+ );
+ foreach ($this->columnMap['services'] as $column => $_) {
+ $columns[$column] = new Zend_Db_Expr('NULL');
+ }
+ if ($this->fetchHistoryColumns) {
+ $columns = array_merge($columns, array_keys($this->columnMap['history']));
+ }
+ $hosts = $this->createSubQuery('Hostcommentdeletionhistory', $columns);
+ $this->subQueries[] = $hosts;
+ $this->commentDeletionHistoryQuery->union(array($hosts), Zend_Db_Select::SQL_UNION_ALL);
+ }
+
+ /**
+ * Join services
+ */
+ protected function joinServices()
+ {
+ $columns = array_keys(
+ $this->columnMap['commenthistory'] + $this->columnMap['hosts'] + $this->columnMap['services']
+ );
+ if ($this->fetchHistoryColumns) {
+ $columns = array_merge($columns, array_keys($this->columnMap['history']));
+ }
+ $services = $this->createSubQuery('Servicecommentdeletionhistory', $columns);
+ $this->subQueries[] = $services;
+ $this->commentDeletionHistoryQuery->union(array($services), Zend_Db_Select::SQL_UNION_ALL);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function order($columnOrAlias, $dir = null)
+ {
+ foreach ($this->subQueries as $sub) {
+ $sub->requireColumn($columnOrAlias);
+ }
+ return parent::order($columnOrAlias, $dir);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function where($condition, $value = null)
+ {
+ $this->requireColumn($condition);
+ foreach ($this->subQueries as $sub) {
+ $sub->where($condition, $value);
+ }
+ return $this;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function addFilter(Filter $filter)
+ {
+ foreach ($this->subQueries as $sub) {
+ $sub->applyFilter(clone $filter);
+ }
+ return $this;
+ }
+
+ public function whereEx(FilterExpression $ex)
+ {
+ $this->requireColumn($ex->getColumn());
+ foreach ($this->subQueries as $sub) {
+ $sub->whereEx($ex);
+ }
+
+ return $this;
+ }
+}
diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/CommenteventQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/CommenteventQuery.php
new file mode 100644
index 0000000..c85adff
--- /dev/null
+++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/CommenteventQuery.php
@@ -0,0 +1,39 @@
+<?php
+/* Icinga Web 2 | (c) 2017 Icinga Development Team | GPLv2+ */
+
+namespace Icinga\Module\Monitoring\Backend\Ido\Query;
+
+/**
+ * Query for host and service comment entry and deletion events
+ */
+class CommenteventQuery extends IdoQuery
+{
+ protected $columnMap = array(
+ 'commentevent' => array(
+ 'commentevent_id' => 'ch.commenthistory_id',
+ 'commentevent_entry_type' => "(CASE ch.entry_type WHEN 1 THEN 'comment' WHEN 2 THEN 'downtime' WHEN 3 THEN 'flapping' WHEN 4 THEN 'ack' ELSE NULL END)",
+ 'commentevent_comment_time' => 'UNIX_TIMESTAMP(ch.comment_time)',
+ 'commentevent_author_name' => 'ch.author_name',
+ 'commentevent_comment_data' => 'ch.comment_data',
+ 'commentevent_is_persistent' => 'ch.is_persistent',
+ 'commentevent_comment_source' => "(CASE ch.comment_source WHEN 0 THEN 'icinga' WHEN 1 THEN 'user' ELSE NULL END)",
+ 'commentevent_expires' => 'ch.expires',
+ 'commentevent_expiration_time' => 'UNIX_TIMESTAMP(ch.expiration_time)',
+ 'commentevent_deletion_time' => 'UNIX_TIMESTAMP(ch.deletion_time)'
+ ),
+ 'object' => array(
+ 'host_name' => 'o.name1',
+ 'service_description' => 'o.name2'
+ )
+ );
+
+ protected function joinBaseTables()
+ {
+ $this->select()
+ ->from(array('ch' => $this->prefix . 'commenthistory'), array())
+ ->join(array('o' => $this->prefix . 'objects'), 'ch.object_id = o.object_id', array());
+
+ $this->joinedVirtualTables['commentevent'] = true;
+ $this->joinedVirtualTables['object'] = true;
+ }
+}
diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/CommenthistoryQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/CommenthistoryQuery.php
new file mode 100644
index 0000000..47dd97c
--- /dev/null
+++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/CommenthistoryQuery.php
@@ -0,0 +1,179 @@
+<?php
+/* Icinga Web 2 | (c) 2013 Icinga Development Team | GPLv2+ */
+
+namespace Icinga\Module\Monitoring\Backend\Ido\Query;
+
+use Icinga\Data\Filter\FilterExpression;
+use Zend_Db_Expr;
+use Zend_Db_Select;
+use Icinga\Data\Filter\Filter;
+
+/**
+ * Query for host and service comment history records
+ */
+class CommenthistoryQuery extends IdoQuery
+{
+ /**
+ * {@inheritdoc}
+ */
+ protected $columnMap = array(
+ 'commenthistory' => array(
+ 'id' => 'ch.id',
+ 'object_type' => 'ch.object_type'
+ ),
+ 'history' => array(
+ 'type' => 'ch.type',
+ 'timestamp' => 'ch.timestamp',
+ 'object_id' => 'ch.object_id',
+ 'state' => 'ch.state',
+ 'output' => 'ch.output'
+ ),
+ 'hosts' => array(
+ 'host_display_name' => 'ch.host_display_name',
+ 'host_name' => 'ch.host_name'
+ ),
+ 'services' => array(
+ 'service_description' => 'ch.service_description',
+ 'service_display_name' => 'ch.service_display_name',
+ 'service_host_name' => 'ch.service_host_name'
+ )
+ );
+
+ /**
+ * The union
+ *
+ * @var Zend_Db_Select
+ */
+ protected $commentHistoryQuery;
+
+ /**
+ * Subqueries used for the comment history query
+ *
+ * @var IdoQuery[]
+ */
+ protected $subQueries = array();
+
+ /**
+ * Whether to additionally select all history columns
+ *
+ * @var bool
+ */
+ protected $fetchHistoryColumns = false;
+
+ /**
+ * {@inheritdoc}
+ */
+ public function allowsCustomVars()
+ {
+ foreach ($this->subQueries as $query) {
+ if (! $query->allowsCustomVars()) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function joinBaseTables()
+ {
+ $this->commentHistoryQuery = $this->db->select();
+ $this->select->from(
+ array('ch' => $this->commentHistoryQuery),
+ array()
+ );
+ $this->joinedVirtualTables['commenthistory'] = true;
+ }
+
+ /**
+ * Join history related columns and tables
+ */
+ protected function joinHistory()
+ {
+ // TODO: Ensure that one is selecting the history columns first...
+ $this->fetchHistoryColumns = true;
+ $this->requireVirtualTable('hosts');
+ $this->requireVirtualTable('services');
+ }
+
+ /**
+ * Join hosts
+ */
+ protected function joinHosts()
+ {
+ $columns = array_keys(
+ $this->columnMap['commenthistory'] + $this->columnMap['hosts']
+ );
+ foreach ($this->columnMap['services'] as $column => $_) {
+ $columns[$column] = new Zend_Db_Expr('NULL');
+ }
+ if ($this->fetchHistoryColumns) {
+ $columns = array_merge($columns, array_keys($this->columnMap['history']));
+ }
+ $hosts = $this->createSubQuery('Hostcommenthistory', $columns);
+ $this->subQueries[] = $hosts;
+ $this->commentHistoryQuery->union(array($hosts), Zend_Db_Select::SQL_UNION_ALL);
+ }
+
+ /**
+ * Join services
+ */
+ protected function joinServices()
+ {
+ $columns = array_keys(
+ $this->columnMap['commenthistory'] + $this->columnMap['hosts'] + $this->columnMap['services']
+ );
+ if ($this->fetchHistoryColumns) {
+ $columns = array_merge($columns, array_keys($this->columnMap['history']));
+ }
+ $services = $this->createSubQuery('Servicecommenthistory', $columns);
+ $this->subQueries[] = $services;
+ $this->commentHistoryQuery->union(array($services), Zend_Db_Select::SQL_UNION_ALL);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function order($columnOrAlias, $dir = null)
+ {
+ foreach ($this->subQueries as $sub) {
+ $sub->requireColumn($columnOrAlias);
+ }
+ return parent::order($columnOrAlias, $dir);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function where($condition, $value = null)
+ {
+ $this->requireColumn($condition);
+ foreach ($this->subQueries as $sub) {
+ $sub->where($condition, $value);
+ }
+ return $this;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function addFilter(Filter $filter)
+ {
+ foreach ($this->subQueries as $sub) {
+ $sub->applyFilter(clone $filter);
+ }
+ return $this;
+ }
+
+ public function whereEx(FilterExpression $ex)
+ {
+ $this->requireColumn($ex->getColumn());
+ foreach ($this->subQueries as $sub) {
+ $sub->whereEx($ex);
+ }
+
+ return $this;
+ }
+}
diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/ContactQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/ContactQuery.php
new file mode 100644
index 0000000..ca10323
--- /dev/null
+++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/ContactQuery.php
@@ -0,0 +1,139 @@
+<?php
+/* Icinga Web 2 | (c) 2013 Icinga Development Team | GPLv2+ */
+
+namespace Icinga\Module\Monitoring\Backend\Ido\Query;
+
+use Icinga\Data\Filter\FilterExpression;
+use Zend_Db_Select;
+use Icinga\Data\Filter\Filter;
+
+/**
+ * Query for contacts
+ */
+class ContactQuery extends IdoQuery
+{
+ protected $columnMap = [
+ 'contacts' => [
+ 'contact_id' => 'c.contact_id',
+ 'contact' => 'c.contact',
+ 'contact_name' => 'c.contact_name',
+ 'contact_alias' => 'c.contact_alias',
+ 'contact_email' => 'c.contact_email',
+ 'contact_pager' => 'c.contact_pager',
+ 'contact_object_id' => 'c.contact_object_id',
+ 'contact_has_host_notfications' => 'c.contact_has_host_notfications',
+ 'contact_has_service_notfications' => 'c.contact_has_service_notfications',
+ 'contact_can_submit_commands' => 'c.contact_can_submit_commands',
+ 'contact_notify_service_recovery' => 'c.contact_notify_service_recovery',
+ 'contact_notify_service_warning' => 'c.contact_notify_service_warning',
+ 'contact_notify_service_critical' => 'c.contact_notify_service_critical',
+ 'contact_notify_service_unknown' => 'c.contact_notify_service_unknown',
+ 'contact_notify_service_flapping' => 'c.contact_notify_service_flapping',
+ 'contact_notify_service_downtime' => 'c.contact_notify_service_downtime',
+ 'contact_notify_host_recovery' => 'c.contact_notify_host_recovery',
+ 'contact_notify_host_down' => 'c.contact_notify_host_down',
+ 'contact_notify_host_unreachable' => 'c.contact_notify_host_unreachable',
+ 'contact_notify_host_flapping' => 'c.contact_notify_host_flapping',
+ 'contact_notify_host_downtime' => 'c.contact_notify_host_downtime',
+ 'contact_notify_host_timeperiod' => 'c.contact_notify_host_timeperiod',
+ 'contact_notify_service_timeperiod' => 'c.contact_notify_service_timeperiod'
+ ]
+ ];
+
+ /** @var Zend_Db_Select The union */
+ protected $contactQuery;
+
+ /** @var IdoQuery[] Subqueries used for the contact query */
+ protected $subQueries = [];
+
+ public function allowsCustomVars()
+ {
+ foreach ($this->subQueries as $query) {
+ if (! $query->allowsCustomVars()) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ public function addFilter(Filter $filter)
+ {
+ $strangers = array_diff(
+ $filter->listFilteredColumns(),
+ array_keys($this->columnMap['contacts'])
+ );
+ if (! empty($strangers)) {
+ $this->transformToUnion();
+ }
+
+ foreach ($this->subQueries as $sub) {
+ $sub->applyFilter(clone $filter);
+ }
+
+ return $this;
+ }
+
+ protected function joinBaseTables()
+ {
+ $this->contactQuery = $this->createSubQuery('Hostcontact', array_keys($this->columnMap['contacts']));
+ $this->contactQuery->setIsSubQuery();
+ $this->subQueries[] = $this->contactQuery;
+
+ $this->select->from(
+ ['c' => $this->contactQuery],
+ []
+ );
+
+ $this->joinedVirtualTables['contacts'] = true;
+ }
+
+ public function order($columnOrAlias, $dir = null)
+ {
+ foreach ($this->subQueries as $sub) {
+ $sub->requireColumn($columnOrAlias);
+ }
+
+ return parent::order($columnOrAlias, $dir);
+ }
+
+ public function where($condition, $value = null)
+ {
+ $this->requireColumn($condition);
+ foreach ($this->subQueries as $sub) {
+ $sub->where($condition, $value);
+ }
+
+ return $this;
+ }
+
+ public function whereEx(FilterExpression $ex)
+ {
+ $this->requireColumn($ex->getColumn());
+ foreach ($this->subQueries as $sub) {
+ $sub->whereEx($ex);
+ }
+
+ return $this;
+ }
+
+ public function transformToUnion()
+ {
+ $this->contactQuery = $this->db->select();
+ $this->select->reset();
+ $this->subQueries = [];
+
+ $this->select->distinct()->from(
+ ['c' => $this->contactQuery],
+ []
+ );
+
+ $hosts = $this->createSubQuery('Hostcontact', array_keys($this->columnMap['contacts']));
+ $this->subQueries[] = $hosts;
+ $this->contactQuery->union([$hosts], Zend_Db_Select::SQL_UNION_ALL);
+
+ $services = $this->createSubQuery('Servicecontact', array_keys($this->columnMap['contacts']));
+ $this->subQueries[] = $services;
+ $this->contactQuery->union([$services], Zend_Db_Select::SQL_UNION_ALL);
+ }
+}
diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/ContactgroupQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/ContactgroupQuery.php
new file mode 100644
index 0000000..7d4cbc1
--- /dev/null
+++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/ContactgroupQuery.php
@@ -0,0 +1,214 @@
+<?php
+/* Icinga Web 2 | (c) 2013 Icinga Development Team | GPLv2+ */
+
+namespace Icinga\Module\Monitoring\Backend\Ido\Query;
+
+/**
+ * Query for contact groups
+ */
+class ContactgroupQuery extends IdoQuery
+{
+ /**
+ * {@inheritdoc}
+ */
+ protected $allowCustomVars = true;
+
+ /**
+ * {@inheritdoc}
+ */
+ protected $groupBase = array('contactgroups' => array('cg.contactgroup_id', 'cgo.object_id'));
+
+ /**
+ * {@inheritdoc}
+ */
+ protected $groupOrigin = array('hosts', 'members', 'services');
+
+ protected $subQueryTargets = array(
+ 'hostgroups' => 'hostgroup',
+ 'servicegroups' => 'servicegroup'
+ );
+
+ /**
+ * {@inheritdoc}
+ */
+ protected $columnMap = array(
+ 'contactgroups' => array(
+ 'contactgroup' => 'cgo.name1 COLLATE latin1_general_ci',
+ 'contactgroup_name' => 'cgo.name1',
+ 'contactgroup_alias' => 'cg.alias COLLATE latin1_general_ci'
+ ),
+ 'members' => array(
+ 'contact_count' => 'SUM(CASE WHEN cgmo.object_id IS NOT NULL THEN 1 ELSE 0 END)'
+ ),
+ 'hostgroups' => array(
+ 'hostgroup' => 'hgo.name1 COLLATE latin1_general_ci',
+ 'hostgroup_alias' => 'hg.alias COLLATE latin1_general_ci',
+ 'hostgroup_name' => 'hgo.name1'
+ ),
+ 'hosts' => array(
+ 'host' => 'ho.name1 COLLATE latin1_general_ci',
+ 'host_name' => 'ho.name1',
+ 'host_alias' => 'h.alias',
+ 'host_display_name' => 'h.display_name COLLATE latin1_general_ci'
+ ),
+ 'instances' => array(
+ 'instance_name' => 'i.instance_name'
+ ),
+ 'servicegroups' => array(
+ 'servicegroup' => 'sgo.name1 COLLATE latin1_general_ci',
+ 'servicegroup_name' => 'sgo.name1',
+ 'servicegroup_alias' => 'sg.alias COLLATE latin1_general_ci'
+ ),
+ 'services' => array(
+ 'service' => 'so.name2 COLLATE latin1_general_ci',
+ 'service_description' => 'so.name2',
+ 'service_display_name' => 's.display_name COLLATE latin1_general_ci',
+ 'service_host_name' => 'so.name1'
+ )
+ );
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function joinBaseTables()
+ {
+ $this->select->from(
+ array('cg' => $this->prefix . 'contactgroups'),
+ array()
+ )->join(
+ array('cgo' => $this->prefix . 'objects'),
+ 'cgo.object_id = cg.contactgroup_object_id AND cgo.is_active = 1 AND cgo.objecttype_id = 11',
+ array()
+ );
+ $this->joinedVirtualTables['contactgroups'] = true;
+ }
+
+ /**
+ * Join contact group members
+ */
+ protected function joinMembers()
+ {
+ $this->select->joinLeft(
+ array('cgm' => $this->prefix . 'contactgroup_members'),
+ 'cgm.contactgroup_id = cg.contactgroup_id',
+ array()
+ )->joinLeft(
+ array('cgmo' => $this->prefix . 'objects'),
+ 'cgmo.object_id = cgm.contact_object_id AND cgmo.is_active = 1 AND cgmo.objecttype_id = 10',
+ array()
+ );
+ }
+
+ /**
+ * Join host groups
+ */
+ protected function joinHostgroups()
+ {
+ $this->requireVirtualTable('hosts');
+ $this->select->joinLeft(
+ array('hgm' => $this->prefix . 'hostgroup_members'),
+ 'hgm.host_object_id = ho.object_id',
+ array()
+ )->joinLeft(
+ array('hg' => $this->prefix . 'hostgroups'),
+ 'hg.hostgroup_id = hgm.hostgroup_id',
+ array()
+ )->joinLeft(
+ array('hgo' => $this->prefix . 'objects'),
+ 'hgo.object_id = hg.hostgroup_object_id AND hgo.is_active = 1 AND hgo.objecttype_id = 3',
+ array()
+ );
+ }
+
+ /**
+ * Join hosts
+ */
+ protected function joinHosts()
+ {
+ $this->select->joinLeft(
+ array('hcg' => $this->prefix . 'host_contactgroups'),
+ 'hcg.contactgroup_object_id = cg.contactgroup_object_id',
+ array()
+ )->joinLeft(
+ array('h' => $this->prefix . 'hosts'),
+ 'h.host_id = hcg.host_id',
+ array()
+ )->joinLeft(
+ array('ho' => $this->prefix . 'objects'),
+ 'ho.object_id = h.host_object_id AND ho.is_active = 1 AND ho.objecttype_id = 1',
+ array()
+ );
+ }
+
+ /**
+ * Join instances
+ */
+ protected function joinInstances()
+ {
+ $this->select->join(
+ array('i' => $this->prefix . 'instances'),
+ 'i.instance_id = cg.instance_id',
+ array()
+ );
+ }
+
+ /**
+ * Join service groups
+ */
+ protected function joinServicegroups()
+ {
+ $this->requireVirtualTable('services');
+ $this->select->joinLeft(
+ array('sgm' => $this->prefix . 'servicegroup_members'),
+ 'sgm.service_object_id = s.service_object_id',
+ array()
+ )->joinLeft(
+ array('sg' => $this->prefix . 'servicegroups'),
+ 'sg.servicegroup_id = sgm.servicegroup_id',
+ array()
+ )->joinLeft(
+ array('sgo' => $this->prefix . 'objects'),
+ 'sgo.object_id = sg.servicegroup_object_id AND sgo.is_active = 1 AND sgo.objecttype_id = 4',
+ array()
+ );
+ }
+
+ /**
+ * Join services
+ */
+ protected function joinServices()
+ {
+ $this->select->joinLeft(
+ array('scg' => $this->prefix . 'service_contactgroups'),
+ 'scg.contactgroup_object_id = cg.contactgroup_object_id',
+ array()
+ )->joinLeft(
+ array('s' => $this->prefix . 'services'),
+ 's.service_id = scg.service_id',
+ array()
+ )->joinLeft(
+ array('so' => $this->prefix . 'objects'),
+ 'so.object_id = s.service_object_id AND so.is_active = 1 AND so.objecttype_id = 2',
+ array()
+ );
+ }
+
+ protected function joinSubQuery(IdoQuery $query, $name, $filter, $and, $negate, &$additionalFilter)
+ {
+ if ($name === 'hostgroup') {
+ $this->requireVirtualTable('hosts');
+
+ $query->joinVirtualTable('members');
+
+ return ['hgm.host_object_id', 'ho.object_id'];
+ } elseif ($name === 'servicegroup') {
+ $this->requireVirtualTable('services');
+
+ $query->joinVirtualTable('members');
+
+ return ['sgm.service_object_id', 'so.object_id'];
+ }
+
+ return parent::joinSubQuery($query, $name, $filter, $and, $negate, $additionalFilter);
+ }
+}
diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/CustomvarQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/CustomvarQuery.php
new file mode 100644
index 0000000..1492894
--- /dev/null
+++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/CustomvarQuery.php
@@ -0,0 +1,116 @@
+<?php
+/* Icinga Web 2 | (c) 2013 Icinga Development Team | GPLv2+ */
+
+namespace Icinga\Module\Monitoring\Backend\Ido\Query;
+
+use Icinga\Application\Config;
+use Icinga\Data\Filter\FilterExpression;
+
+class CustomvarQuery extends IdoQuery
+{
+ protected $columnMap = array(
+ 'instances' => array(
+ 'instance_name' => 'i.instance_name'
+ ),
+ 'customvariablestatus' => array(
+ 'varname' => 'cvs.varname',
+ 'varvalue' => 'cvs.varvalue',
+ 'is_json' => 'cvs.is_json',
+ ),
+ 'objects' => array(
+ 'host' => 'cvo.name1 COLLATE latin1_general_ci',
+ 'host_name' => 'cvo.name1',
+ 'service' => 'cvo.name2 COLLATE latin1_general_ci',
+ 'service_description' => 'cvo.name2',
+ 'contact' => 'cvo.name1 COLLATE latin1_general_ci',
+ 'contact_name' => 'cvo.name1',
+ 'object_type' => "CASE cvo.objecttype_id WHEN 1 THEN 'host' WHEN 2 THEN 'service' WHEN 10 THEN 'contact' ELSE 'invalid' END",
+ 'object_type_id' => 'cvo.objecttype_id'
+// 'object_type' => "CASE cvo.objecttype_id WHEN 1 THEN 'host' WHEN 2 THEN 'service' WHEN 3 THEN 'hostgroup' WHEN 4 THEN 'servicegroup' WHEN 5 THEN 'hostescalation' WHEN 6 THEN 'serviceescalation' WHEN 7 THEN 'hostdependency' WHEN 8 THEN 'servicedependency' WHEN 9 THEN 'timeperiod' WHEN 10 THEN 'contact' WHEN 11 THEN 'contactgroup' WHEN 12 THEN 'command' ELSE 'other' END"
+ ),
+ );
+
+ public function where($expression, $parameters = null)
+ {
+ $types = array('host' => 1, 'service' => 2, 'contact' => 10);
+ if ($expression === 'object_type') {
+ parent::where('object_type_id', $types[$parameters]);
+ } else {
+ parent::where($expression, $parameters);
+ }
+ return $this;
+ }
+
+ public function whereEx(FilterExpression $ex)
+ {
+ $types = ['host' => 1, 'service' => 2, 'contact' => 10];
+ if ($ex->getColumn() === 'object_type') {
+ $ex = clone $ex;
+ $ex->setColumn('object_type_id');
+ $ex->setExpression($types[$ex->getExpression()]);
+ }
+
+ parent::whereEx($ex);
+
+ return $this;
+ }
+
+ protected function joinBaseTables()
+ {
+ if (version_compare($this->getIdoVersion(), '1.12.0', '<')) {
+ $this->columnMap['customvariablestatus']['is_json'] = '(0)';
+ }
+
+ if (! (bool) Config::module('monitoring')->get('ido', 'use_customvar_status_table', true)) {
+ $table = 'customvariables';
+ } else {
+ $table = 'customvariablestatus';
+ }
+
+ $this->select->from(
+ array('cvs' => $this->prefix . $table),
+ array()
+ )->join(
+ array('cvo' => $this->prefix . 'objects'),
+ 'cvs.object_id = cvo.object_id AND cvo.is_active = 1',
+ array()
+ );
+ $this->joinedVirtualTables = array(
+ 'customvariablestatus' => true,
+ 'objects' => true
+ );
+ }
+
+ /**
+ * Join instances
+ */
+ protected function joinInstances()
+ {
+ $this->select->join(
+ array('i' => $this->prefix . 'instances'),
+ 'i.instance_id = cvs.instance_id',
+ array()
+ );
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getGroup()
+ {
+ $group = parent::getGroup();
+ if (! empty($group) && $this->ds->getDbType() === 'pgsql') {
+ foreach ($this->columnMap as $table => $columns) {
+ $pk = ($table === 'objects' ? 'cvo.' : 'cvs.') . $this->getPrimaryKeyColumn($table);
+ foreach ($columns as $alias => $_) {
+ if (! in_array($pk, $group, true) && in_array($alias, $group, true)) {
+ $group[] = $pk;
+ break;
+ }
+ }
+ }
+ }
+
+ return $group;
+ }
+}
diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/DowntimeQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/DowntimeQuery.php
new file mode 100644
index 0000000..9bc1d88
--- /dev/null
+++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/DowntimeQuery.php
@@ -0,0 +1,163 @@
+<?php
+/* Icinga Web 2 | (c) 2013 Icinga Development Team | GPLv2+ */
+
+namespace Icinga\Module\Monitoring\Backend\Ido\Query;
+
+use Icinga\Data\Filter\FilterExpression;
+use Zend_Db_Expr;
+use Zend_Db_Select;
+use Icinga\Data\Filter\Filter;
+
+/**
+ * Query for host and service downtimes
+ */
+class DowntimeQuery extends IdoQuery
+{
+ /**
+ * {@inheritdoc}
+ */
+ protected $columnMap = array(
+ 'downtimes' => array(
+ 'downtime_author' => 'd.downtime_author',
+ 'downtime_author_name' => 'd.downtime_author_name',
+ 'downtime_comment' => 'd.downtime_comment',
+ 'downtime_duration' => 'd.downtime_duration',
+ 'downtime_end' => 'd.downtime_end',
+ 'downtime_entry_time' => 'd.downtime_entry_time',
+ 'downtime_internal_id' => 'd.downtime_internal_id',
+ 'downtime_is_fixed' => 'd.downtime_is_fixed',
+ 'downtime_is_flexible' => 'd.downtime_is_flexible',
+ 'downtime_is_in_effect' => 'd.downtime_is_in_effect',
+ 'downtime_name' => 'd.downtime_name',
+ 'downtime_scheduled_end' => 'd.downtime_scheduled_end',
+ 'downtime_scheduled_start' => 'd.downtime_scheduled_start',
+ 'downtime_start' => 'd.downtime_start',
+ 'object_type' => 'd.object_type',
+ 'instance_name' => 'd.instance_name'
+ ),
+ 'hosts' => array(
+ 'host_display_name' => 'd.host_display_name',
+ 'host_name' => 'd.host_name',
+ 'host_state' => 'd.host_state'
+ ),
+ 'services' => array(
+ 'service_description' => 'd.service_description',
+ 'service_display_name' => 'd.service_display_name',
+ 'service_host_name' => 'd.service_host_name',
+ 'service_state' => 'd.service_state'
+ )
+ );
+
+ /**
+ * The union
+ *
+ * @var Zend_Db_Select
+ */
+ protected $downtimeQuery;
+
+ /**
+ * Subqueries used for the downtime query
+ *
+ * @var IdoQuery[]
+ */
+ protected $subQueries = array();
+
+ /**
+ * {@inheritdoc}
+ */
+ public function allowsCustomVars()
+ {
+ foreach ($this->subQueries as $query) {
+ if (! $query->allowsCustomVars()) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function addFilter(Filter $filter)
+ {
+ foreach ($this->subQueries as $sub) {
+ $sub->applyFilter(clone $filter);
+ }
+ return $this;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function joinBaseTables()
+ {
+ if (version_compare($this->getIdoVersion(), '1.14.0', '<')) {
+ $this->columnMap['downtimes']['downtime_name'] = '(NULL)';
+ }
+ $this->downtimeQuery = $this->db->select();
+ $this->select->from(
+ array('d' => $this->downtimeQuery),
+ array()
+ );
+ $this->joinedVirtualTables['downtimes'] = true;
+ }
+
+ /**
+ * Join hosts
+ */
+ protected function joinHosts()
+ {
+ $columns = array_keys($this->columnMap['downtimes'] + $this->columnMap['hosts']);
+ foreach (array_keys($this->columnMap['services']) as $column) {
+ $columns[$column] = new Zend_Db_Expr('NULL');
+ }
+ $hosts = $this->createSubQuery('hostdowntime', $columns);
+ $this->subQueries[] = $hosts;
+ $this->downtimeQuery->union(array($hosts), Zend_Db_Select::SQL_UNION_ALL);
+ }
+
+ /**
+ * Join services
+ */
+ protected function joinServices()
+ {
+ $columns = array_keys($this->columnMap['downtimes'] + $this->columnMap['hosts'] + $this->columnMap['services']);
+ $services = $this->createSubQuery('servicedowntime', $columns);
+ $this->subQueries[] = $services;
+ $this->downtimeQuery->union(array($services), Zend_Db_Select::SQL_UNION_ALL);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function order($columnOrAlias, $dir = null)
+ {
+ foreach ($this->subQueries as $sub) {
+ $sub->requireColumn($columnOrAlias);
+ }
+ return parent::order($columnOrAlias, $dir);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function where($condition, $value = null)
+ {
+ $this->requireColumn($condition);
+ foreach ($this->subQueries as $sub) {
+ $sub->where($condition, $value);
+ }
+ return $this;
+ }
+
+ public function whereEx(FilterExpression $ex)
+ {
+ $this->requireColumn($ex->getColumn());
+ foreach ($this->subQueries as $sub) {
+ $sub->whereEx($ex);
+ }
+
+ return $this;
+ }
+}
diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/DowntimeendhistoryQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/DowntimeendhistoryQuery.php
new file mode 100644
index 0000000..de47418
--- /dev/null
+++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/DowntimeendhistoryQuery.php
@@ -0,0 +1,179 @@
+<?php
+/* Icinga Web 2 | (c) 2013 Icinga Development Team | GPLv2+ */
+
+namespace Icinga\Module\Monitoring\Backend\Ido\Query;
+
+use Icinga\Data\Filter\FilterExpression;
+use Zend_Db_Expr;
+use Zend_Db_Select;
+use Icinga\Data\Filter\Filter;
+
+/**
+ * Query for host and service downtime end history records
+ */
+class DowntimeendhistoryQuery extends IdoQuery
+{
+ /**
+ * {@inheritdoc}
+ */
+ protected $columnMap = array(
+ 'downtimehistory' => array(
+ 'id' => 'deh.id',
+ 'object_type' => 'deh.object_type'
+ ),
+ 'history' => array(
+ 'type' => 'deh.type',
+ 'timestamp' => 'deh.timestamp',
+ 'object_id' => 'deh.object_id',
+ 'state' => 'deh.state',
+ 'output' => 'deh.output'
+ ),
+ 'hosts' => array(
+ 'host_display_name' => 'deh.host_display_name',
+ 'host_name' => 'deh.host_name'
+ ),
+ 'services' => array(
+ 'service_description' => 'deh.service_description',
+ 'service_display_name' => 'deh.service_display_name',
+ 'service_host_name' => 'deh.service_host_name'
+ )
+ );
+
+ /**
+ * The union
+ *
+ * @var Zend_Db_Select
+ */
+ protected $downtimeEndHistoryQuery;
+
+ /**
+ * Subqueries used for the downtime end history query
+ *
+ * @var IdoQuery[]
+ */
+ protected $subQueries = array();
+
+ /**
+ * Whether to additionally select all history columns
+ *
+ * @var bool
+ */
+ protected $fetchHistoryColumns = false;
+
+ /**
+ * {@inheritdoc}
+ */
+ public function allowsCustomVars()
+ {
+ foreach ($this->subQueries as $query) {
+ if (! $query->allowsCustomVars()) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function joinBaseTables()
+ {
+ $this->downtimeEndHistoryQuery = $this->db->select();
+ $this->select->from(
+ array('deh' => $this->downtimeEndHistoryQuery),
+ array()
+ );
+ $this->joinedVirtualTables['downtimehistory'] = true;
+ }
+
+ /**
+ * Join history related columns and tables
+ */
+ protected function joinHistory()
+ {
+ // TODO: Ensure that one is selecting the history columns first...
+ $this->fetchHistoryColumns = true;
+ $this->requireVirtualTable('hosts');
+ $this->requireVirtualTable('services');
+ }
+
+ /**
+ * Join hosts
+ */
+ protected function joinHosts()
+ {
+ $columns = array_keys(
+ $this->columnMap['downtimehistory'] + $this->columnMap['hosts']
+ );
+ foreach ($this->columnMap['services'] as $column => $_) {
+ $columns[$column] = new Zend_Db_Expr('NULL');
+ }
+ if ($this->fetchHistoryColumns) {
+ $columns = array_merge($columns, array_keys($this->columnMap['history']));
+ }
+ $hosts = $this->createSubQuery('Hostdowntimeendhistory', $columns);
+ $this->subQueries[] = $hosts;
+ $this->downtimeEndHistoryQuery->union(array($hosts), Zend_Db_Select::SQL_UNION_ALL);
+ }
+
+ /**
+ * Join services
+ */
+ protected function joinServices()
+ {
+ $columns = array_keys(
+ $this->columnMap['downtimehistory'] + $this->columnMap['hosts'] + $this->columnMap['services']
+ );
+ if ($this->fetchHistoryColumns) {
+ $columns = array_merge($columns, array_keys($this->columnMap['history']));
+ }
+ $services = $this->createSubQuery('Servicedowntimeendhistory', $columns);
+ $this->subQueries[] = $services;
+ $this->downtimeEndHistoryQuery->union(array($services), Zend_Db_Select::SQL_UNION_ALL);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function order($columnOrAlias, $dir = null)
+ {
+ foreach ($this->subQueries as $sub) {
+ $sub->requireColumn($columnOrAlias);
+ }
+ return parent::order($columnOrAlias, $dir);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function where($condition, $value = null)
+ {
+ $this->requireColumn($condition);
+ foreach ($this->subQueries as $sub) {
+ $sub->where($condition, $value);
+ }
+ return $this;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function addFilter(Filter $filter)
+ {
+ foreach ($this->subQueries as $sub) {
+ $sub->applyFilter(clone $filter);
+ }
+ return $this;
+ }
+
+ public function whereEx(FilterExpression $ex)
+ {
+ $this->requireColumn($ex->getColumn());
+ foreach ($this->subQueries as $sub) {
+ $sub->whereEx($ex);
+ }
+
+ return $this;
+ }
+}
diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/DowntimeeventQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/DowntimeeventQuery.php
new file mode 100644
index 0000000..04e6aa5
--- /dev/null
+++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/DowntimeeventQuery.php
@@ -0,0 +1,42 @@
+<?php
+/* Icinga Web 2 | (c) 2017 Icinga Development Team | GPLv2+ */
+
+namespace Icinga\Module\Monitoring\Backend\Ido\Query;
+
+/**
+ * Query for host and service downtime events
+ */
+class DowntimeeventQuery extends IdoQuery
+{
+ protected $columnMap = array(
+ 'downtimeevent' => array(
+ 'downtimeevent_id' => 'dth.downtimehistory_id',
+ 'downtimeevent_entry_time' => 'UNIX_TIMESTAMP(dth.entry_time)',
+ 'downtimeevent_author_name' => 'dth.author_name',
+ 'downtimeevent_comment_data' => 'dth.comment_data',
+ 'downtimeevent_is_fixed' => 'dth.is_fixed',
+ 'downtimeevent_scheduled_start_time' => 'UNIX_TIMESTAMP(dth.scheduled_start_time)',
+ 'downtimeevent_scheduled_end_time' => 'UNIX_TIMESTAMP(dth.scheduled_end_time)',
+ 'downtimeevent_was_started' => 'dth.was_started',
+ 'downtimeevent_actual_start_time' => 'UNIX_TIMESTAMP(dth.actual_start_time)',
+ 'downtimeevent_actual_end_time' => 'UNIX_TIMESTAMP(dth.actual_end_time)',
+ 'downtimeevent_was_cancelled' => 'dth.was_cancelled',
+ 'downtimeevent_is_in_effect' => 'dth.is_in_effect',
+ 'downtimeevent_trigger_time' => 'UNIX_TIMESTAMP(dth.trigger_time)'
+ ),
+ 'object' => array(
+ 'host_name' => 'o.name1',
+ 'service_description' => 'o.name2'
+ )
+ );
+
+ protected function joinBaseTables()
+ {
+ $this->select()
+ ->from(array('dth' => $this->prefix . 'downtimehistory'), array())
+ ->join(array('o' => $this->prefix . 'objects'), 'dth.object_id = o.object_id', array());
+
+ $this->joinedVirtualTables['downtimeevent'] = true;
+ $this->joinedVirtualTables['object'] = true;
+ }
+}
diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/DowntimestarthistoryQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/DowntimestarthistoryQuery.php
new file mode 100644
index 0000000..3ba600d
--- /dev/null
+++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/DowntimestarthistoryQuery.php
@@ -0,0 +1,179 @@
+<?php
+/* Icinga Web 2 | (c) 2013 Icinga Development Team | GPLv2+ */
+
+namespace Icinga\Module\Monitoring\Backend\Ido\Query;
+
+use Icinga\Data\Filter\FilterExpression;
+use Zend_Db_Expr;
+use Zend_Db_Select;
+use Icinga\Data\Filter\Filter;
+
+/**
+ * Query for host and service downtime start history records
+ */
+class DowntimestarthistoryQuery extends IdoQuery
+{
+ /**
+ * {@inheritdoc}
+ */
+ protected $columnMap = array(
+ 'downtimehistory' => array(
+ 'id' => 'dsh.id',
+ 'object_type' => 'dsh.object_type'
+ ),
+ 'history' => array(
+ 'type' => 'dsh.type',
+ 'timestamp' => 'dsh.timestamp',
+ 'object_id' => 'dsh.object_id',
+ 'state' => 'dsh.state',
+ 'output' => 'dsh.output'
+ ),
+ 'hosts' => array(
+ 'host_display_name' => 'dsh.host_display_name',
+ 'host_name' => 'dsh.host_name'
+ ),
+ 'services' => array(
+ 'service_description' => 'dsh.service_description',
+ 'service_display_name' => 'dsh.service_display_name',
+ 'service_host_name' => 'dsh.service_host_name'
+ )
+ );
+
+ /**
+ * The union
+ *
+ * @var Zend_Db_Select
+ */
+ protected $downtimeStartHistoryQuery;
+
+ /**
+ * Subqueries used for the downtime start history query
+ *
+ * @var IdoQuery[]
+ */
+ protected $subQueries = array();
+
+ /**
+ * Whether to additionally select all history columns
+ *
+ * @var bool
+ */
+ protected $fetchHistoryColumns = false;
+
+ /**
+ * {@inheritdoc}
+ */
+ public function allowsCustomVars()
+ {
+ foreach ($this->subQueries as $query) {
+ if (! $query->allowsCustomVars()) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function joinBaseTables()
+ {
+ $this->downtimeStartHistoryQuery = $this->db->select();
+ $this->select->from(
+ array('dsh' => $this->downtimeStartHistoryQuery),
+ array()
+ );
+ $this->joinedVirtualTables['downtimehistory'] = true;
+ }
+
+ /**
+ * Join history related columns and tables
+ */
+ protected function joinHistory()
+ {
+ // TODO: Ensure that one is selecting the history columns first...
+ $this->fetchHistoryColumns = true;
+ $this->requireVirtualTable('hosts');
+ $this->requireVirtualTable('services');
+ }
+
+ /**
+ * Join hosts
+ */
+ protected function joinHosts()
+ {
+ $columns = array_keys(
+ $this->columnMap['downtimehistory'] + $this->columnMap['hosts']
+ );
+ foreach ($this->columnMap['services'] as $column => $_) {
+ $columns[$column] = new Zend_Db_Expr('NULL');
+ }
+ if ($this->fetchHistoryColumns) {
+ $columns = array_merge($columns, array_keys($this->columnMap['history']));
+ }
+ $hosts = $this->createSubQuery('Hostdowntimestarthistory', $columns);
+ $this->subQueries[] = $hosts;
+ $this->downtimeStartHistoryQuery->union(array($hosts), Zend_Db_Select::SQL_UNION_ALL);
+ }
+
+ /**
+ * Join services
+ */
+ protected function joinServices()
+ {
+ $columns = array_keys(
+ $this->columnMap['downtimehistory'] + $this->columnMap['hosts'] + $this->columnMap['services']
+ );
+ if ($this->fetchHistoryColumns) {
+ $columns = array_merge($columns, array_keys($this->columnMap['history']));
+ }
+ $services = $this->createSubQuery('Servicedowntimestarthistory', $columns);
+ $this->subQueries[] = $services;
+ $this->downtimeStartHistoryQuery->union(array($services), Zend_Db_Select::SQL_UNION_ALL);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function order($columnOrAlias, $dir = null)
+ {
+ foreach ($this->subQueries as $sub) {
+ $sub->requireColumn($columnOrAlias);
+ }
+ return parent::order($columnOrAlias, $dir);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function where($condition, $value = null)
+ {
+ $this->requireColumn($condition);
+ foreach ($this->subQueries as $sub) {
+ $sub->where($condition, $value);
+ }
+ return $this;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function addFilter(Filter $filter)
+ {
+ foreach ($this->subQueries as $sub) {
+ $sub->applyFilter(clone $filter);
+ }
+ return $this;
+ }
+
+ public function whereEx(FilterExpression $ex)
+ {
+ $this->requireColumn($ex->getColumn());
+ foreach ($this->subQueries as $sub) {
+ $sub->whereEx($ex);
+ }
+
+ return $this;
+ }
+}
diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/EmptyhostgroupQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/EmptyhostgroupQuery.php
new file mode 100644
index 0000000..a99d6b7
--- /dev/null
+++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/EmptyhostgroupQuery.php
@@ -0,0 +1,38 @@
+<?php
+/* Icinga Web 2 | (c) 2019 Icinga GmbH | GPLv2+ */
+
+namespace Icinga\Module\Monitoring\Backend\Ido\Query;
+
+class EmptyhostgroupQuery extends HostgroupQuery
+{
+ protected $subQueryTargets = [];
+
+ protected $columnMap = [
+ 'hostgroups' => [
+ 'hostgroup' => 'hgo.name1 COLLATE latin1_general_ci',
+ 'hostgroup_alias' => 'hg.alias COLLATE latin1_general_ci',
+ 'hostgroup_name' => 'hgo.name1',
+ 'host_name' => '(NULL)',
+ 'service_description' => '(NULL)',
+ 'servicegroup_name' => '(NULL)',
+ 'host_contact' => '(NULL)',
+ 'host_contactgroup' => '(NULL)'
+ ],
+ 'instances' => [
+ 'instance_name' => 'i.instance_name'
+ ]
+ ];
+
+ protected function joinBaseTables()
+ {
+ parent::joinBaseTables();
+
+ $this->select->joinLeft(
+ ['ehgm' => $this->prefix . 'hostgroup_members'],
+ 'ehgm.hostgroup_id = hg.hostgroup_id',
+ []
+ );
+ $this->select->group(['hgo.object_id', 'hg.hostgroup_id']);
+ $this->select->having('COUNT(ehgm.hostgroup_member_id) = ?', 0);
+ }
+}
diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/EmptyservicegroupQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/EmptyservicegroupQuery.php
new file mode 100644
index 0000000..88ee4c3
--- /dev/null
+++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/EmptyservicegroupQuery.php
@@ -0,0 +1,51 @@
+<?php
+/* Icinga Web 2 | (c) 2019 Icinga GmbH | GPLv2+ */
+
+namespace Icinga\Module\Monitoring\Backend\Ido\Query;
+
+class EmptyservicegroupQuery extends ServicegroupQuery
+{
+ protected $subQueryTargets = [];
+
+ protected $columnMap = [
+ 'servicegroups' => [
+ 'servicegroup' => 'sgo.name1 COLLATE latin1_general_ci',
+ 'servicegroup_alias' => 'sg.alias COLLATE latin1_general_ci',
+ 'servicegroup_name' => 'sgo.name1',
+ 'host_name' => '(NULL)',
+ 'hostgroup_name' => '(NULL)',
+ 'service_description' => '(NULL)',
+ 'host_contact' => '(NULL)',
+ 'host_contactgroup' => '(NULL)',
+ 'service_contact' => '(NULL)',
+ 'service_contactgroup' => '(NULL)'
+ ],
+ 'instances' => [
+ 'instance_name' => 'i.instance_name'
+ ]
+ ];
+
+ protected function joinBaseTables()
+ {
+ parent::joinBaseTables();
+
+ $this->select->joinLeft(
+ ['esgm' => $this->prefix . 'servicegroup_members'],
+ 'esgm.servicegroup_id = sg.servicegroup_id',
+ []
+ );
+ $this->select->group(['sgo.object_id', 'sg.servicegroup_id']);
+ $this->select->having('COUNT(esgm.servicegroup_member_id) = ?', 0);
+ }
+
+ protected function joinHosts()
+ {
+ parent::joinHosts();
+
+ $this->select->joinLeft(
+ ['h' => 'icinga_hosts'],
+ 'h.host_object_id = s.host_object_id',
+ []
+ );
+ }
+}
diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/EventgridQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/EventgridQuery.php
new file mode 100644
index 0000000..297b20a
--- /dev/null
+++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/EventgridQuery.php
@@ -0,0 +1,57 @@
+<?php
+/* Icinga Web 2 | (c) 2014 Icinga Development Team | GPLv2+ */
+
+namespace Icinga\Module\Monitoring\Backend\Ido\Query;
+
+abstract class EventgridQuery extends StatehistoryQuery
+{
+ /**
+ * The columns additionally provided by this query
+ *
+ * @var array
+ */
+ protected $additionalColumns = array(
+ 'day' => 'DATE(FROM_UNIXTIME(sth.timestamp))',
+ 'cnt_up' => "SUM(CASE WHEN sth.state = 0 THEN 1 ELSE 0 END)",
+ 'cnt_down_hard' => "SUM(CASE WHEN sth.state = 1 AND sth.type = 'hard_state' THEN 1 ELSE 0 END)",
+ 'cnt_down' => "SUM(CASE WHEN sth.state = 1 THEN 1 ELSE 0 END)",
+ 'cnt_unreachable_hard' => "SUM(CASE WHEN sth.state = 2 AND sth.type = 'hard_state' THEN 1 ELSE 0 END)",
+ 'cnt_unreachable' => "SUM(CASE WHEN sth.state = 2 THEN 1 ELSE 0 END)",
+ 'cnt_unknown_hard' => "SUM(CASE WHEN sth.state = 3 AND sth.type = 'hard_state' THEN 1 ELSE 0 END)",
+ 'cnt_unknown' => "SUM(CASE WHEN sth.state = 3 THEN 1 ELSE 0 END)",
+ 'cnt_unknown_hard' => "SUM(CASE WHEN sth.state = 3 AND sth.type = 'hard_state' THEN 1 ELSE 0 END)",
+ 'cnt_critical' => "SUM(CASE WHEN sth.state = 2 THEN 1 ELSE 0 END)",
+ 'cnt_critical_hard' => "SUM(CASE WHEN sth.state = 2 AND sth.type = 'hard_state' THEN 1 ELSE 0 END)",
+ 'cnt_warning' => "SUM(CASE WHEN sth.state = 1 THEN 1 ELSE 0 END)",
+ 'cnt_warning_hard' => "SUM(CASE WHEN sth.state = 1 AND sth.type = 'hard_state' THEN 1 ELSE 0 END)",
+ 'cnt_ok' => "SUM(CASE WHEN sth.state = 0 THEN 1 ELSE 0 END)"
+ );
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function joinBaseTables()
+ {
+ parent::joinBaseTables();
+ $this->requireVirtualTable('history');
+ $this->columnMap['statehistory'] += $this->additionalColumns;
+ $this->select->group(array('DATE(FROM_UNIXTIME(sth.timestamp))'));
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function order($columnOrAlias, $dir = null)
+ {
+ if (array_key_exists($columnOrAlias, $this->additionalColumns)) {
+ $subQueries = $this->subQueries;
+ $this->subQueries = array();
+ parent::order($columnOrAlias, $dir);
+ $this->subQueries = $subQueries;
+ } else {
+ parent::order($columnOrAlias, $dir);
+ }
+
+ return $this;
+ }
+}
diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/EventgridhostsQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/EventgridhostsQuery.php
new file mode 100644
index 0000000..62d92e4
--- /dev/null
+++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/EventgridhostsQuery.php
@@ -0,0 +1,16 @@
+<?php
+
+namespace Icinga\Module\Monitoring\Backend\Ido\Query;
+
+class EventgridhostsQuery extends EventgridQuery
+{
+
+ /**
+ * Join history related columns and tables, hosts only
+ */
+ protected function joinHistory()
+ {
+ $this->fetchHistoryColumns = true;
+ $this->requireVirtualTable('hosts');
+ }
+}
diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/EventgridservicesQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/EventgridservicesQuery.php
new file mode 100644
index 0000000..424de45
--- /dev/null
+++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/EventgridservicesQuery.php
@@ -0,0 +1,15 @@
+<?php
+
+namespace Icinga\Module\Monitoring\Backend\Ido\Query;
+
+class EventgridservicesQuery extends EventgridQuery
+{
+ /**
+ * Join history related columns and tables, services only
+ */
+ protected function joinHistory()
+ {
+ $this->fetchHistoryColumns = true;
+ $this->requireVirtualTable('services');
+ }
+}
diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/EventhistoryQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/EventhistoryQuery.php
new file mode 100644
index 0000000..680e2ca
--- /dev/null
+++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/EventhistoryQuery.php
@@ -0,0 +1,134 @@
+<?php
+/* Icinga Web 2 | (c) 2013 Icinga Development Team | GPLv2+ */
+
+namespace Icinga\Module\Monitoring\Backend\Ido\Query;
+
+use Icinga\Data\Filter\FilterExpression;
+use Zend_Db_Select;
+use Icinga\Data\Filter\Filter;
+
+/**
+ * Query for event history records
+ */
+class EventhistoryQuery extends IdoQuery
+{
+ /**
+ * {@inheritdoc}
+ */
+ protected $useSubqueryCount = true;
+
+ /**
+ * Subqueries used for the event history query
+ *
+ * @type IdoQuery[]
+ */
+ protected $subQueries = array();
+
+ /**
+ * {@inheritdoc}
+ */
+ protected $columnMap = array(
+ 'eventhistory' => array(
+ 'id' => 'eh.id',
+ 'host_name' => 'eh.host_name',
+ 'service_description' => 'eh.service_description',
+ 'object_type' => 'eh.object_type',
+ 'timestamp' => 'eh.timestamp',
+ 'state' => 'eh.state',
+ 'output' => 'eh.output',
+ 'type' => 'eh.type',
+ 'host_display_name' => 'eh.host_display_name',
+ 'service_display_name' => 'eh.service_display_name'
+ )
+ );
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function joinBaseTables()
+ {
+ $columns = array(
+ 'id',
+ 'timestamp',
+ 'output',
+ 'type',
+ 'state',
+ 'object_type',
+ 'host_name',
+ 'service_description',
+ 'host_display_name',
+ 'service_display_name'
+ );
+ $this->subQueries = array(
+ $this->createSubQuery('Notificationhistory', $columns),
+ $this->createSubQuery('Statehistory', $columns),
+ $this->createSubQuery('Downtimestarthistory', $columns),
+ $this->createSubQuery('Downtimeendhistory', $columns),
+ $this->createSubQuery('Commenthistory', $columns),
+ $this->createSubQuery('Commentdeletionhistory', $columns),
+ $this->createSubQuery('Flappingstarthistory', $columns),
+ $this->createSubQuery('Flappingendhistory', $columns)
+ );
+ $sub = $this->db->select()->union($this->subQueries, Zend_Db_Select::SQL_UNION_ALL);
+ $this->select->from(array('eh' => $sub), array());
+ $this->joinedVirtualTables['eventhistory'] = true;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function allowsCustomVars()
+ {
+ foreach ($this->subQueries as $query) {
+ if (! $query->allowsCustomVars()) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function order($columnOrAlias, $dir = null)
+ {
+ foreach ($this->subQueries as $sub) {
+ $sub->requireColumn($columnOrAlias);
+ }
+ return parent::order($columnOrAlias, $dir);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function where($condition, $value = null)
+ {
+ $this->requireColumn($condition);
+ foreach ($this->subQueries as $sub) {
+ $sub->where($condition, $value);
+ }
+ return $this;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function addFilter(Filter $filter)
+ {
+ foreach ($this->subQueries as $sub) {
+ $sub->applyFilter(clone $filter);
+ }
+ return $this;
+ }
+
+ public function whereEx(FilterExpression $ex)
+ {
+ $this->requireColumn($ex->getColumn());
+ foreach ($this->subQueries as $sub) {
+ $sub->whereEx($ex);
+ }
+
+ return $this;
+ }
+}
diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/FlappingendhistoryQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/FlappingendhistoryQuery.php
new file mode 100644
index 0000000..7bdf332
--- /dev/null
+++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/FlappingendhistoryQuery.php
@@ -0,0 +1,49 @@
+<?php
+/* Icinga Web 2 | (c) 2016 Icinga Development Team | GPLv2+ */
+
+namespace Icinga\Module\Monitoring\Backend\Ido\Query;
+
+use Zend_Db_Expr;
+use Zend_Db_Select;
+use Icinga\Data\Filter\Filter;
+
+/**
+ * Query for host and service flapping end history records
+ */
+class FlappingendhistoryQuery extends FlappingstarthistoryQuery
+{
+ /**
+ * Join hosts
+ */
+ protected function joinHosts()
+ {
+ $columns = array_keys(
+ $this->columnMap['flappinghistory'] + $this->columnMap['hosts']
+ );
+ foreach ($this->columnMap['services'] as $column => $_) {
+ $columns[$column] = new Zend_Db_Expr('NULL');
+ }
+ if ($this->fetchHistoryColumns) {
+ $columns = array_merge($columns, array_keys($this->columnMap['history']));
+ }
+ $hosts = $this->createSubQuery('Hostflappingendhistory', $columns);
+ $this->subQueries[] = $hosts;
+ $this->flappingStartHistoryQuery->union(array($hosts), Zend_Db_Select::SQL_UNION_ALL);
+ }
+
+ /**
+ * Join services
+ */
+ protected function joinServices()
+ {
+ $columns = array_keys(
+ $this->columnMap['flappinghistory'] + $this->columnMap['hosts'] + $this->columnMap['services']
+ );
+ if ($this->fetchHistoryColumns) {
+ $columns = array_merge($columns, array_keys($this->columnMap['history']));
+ }
+ $services = $this->createSubQuery('Serviceflappingendhistory', $columns);
+ $this->subQueries[] = $services;
+ $this->flappingStartHistoryQuery->union(array($services), Zend_Db_Select::SQL_UNION_ALL);
+ }
+}
diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/FlappingeventQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/FlappingeventQuery.php
new file mode 100644
index 0000000..d993467
--- /dev/null
+++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/FlappingeventQuery.php
@@ -0,0 +1,36 @@
+<?php
+/* Icinga Web 2 | (c) 2017 Icinga Development Team | GPLv2+ */
+
+namespace Icinga\Module\Monitoring\Backend\Ido\Query;
+
+/**
+ * Query for host and service flapping events
+ */
+class FlappingeventQuery extends IdoQuery
+{
+ protected $columnMap = array(
+ 'flappingevent' => array(
+ 'flappingevent_id' => 'fh.flappinghistory_id',
+ 'flappingevent_event_time' => 'UNIX_TIMESTAMP(fh.event_time)',
+ 'flappingevent_event_type' => "(CASE fh.event_type WHEN 1000 THEN 'flapping' WHEN 1001 THEN 'flapping_deleted' ELSE NULL END)",
+ 'flappingevent_reason_type' => "(CASE fh.reason_type WHEN 1 THEN 'stopped' WHEN 2 THEN 'disabled' ELSE NULL END)",
+ 'flappingevent_percent_state_change' => 'fh.percent_state_change',
+ 'flappingevent_low_threshold' => 'fh.low_threshold',
+ 'flappingevent_high_threshold' => 'fh.high_threshold'
+ ),
+ 'object' => array(
+ 'host_name' => 'o.name1',
+ 'service_description' => 'o.name2'
+ )
+ );
+
+ protected function joinBaseTables()
+ {
+ $this->select()
+ ->from(array('fh' => $this->prefix . 'flappinghistory'), array())
+ ->join(array('o' => $this->prefix . 'objects'), 'fh.object_id = o.object_id', array());
+
+ $this->joinedVirtualTables['flappingevent'] = true;
+ $this->joinedVirtualTables['object'] = true;
+ }
+}
diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/FlappingstarthistoryQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/FlappingstarthistoryQuery.php
new file mode 100644
index 0000000..5c8bec5
--- /dev/null
+++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/FlappingstarthistoryQuery.php
@@ -0,0 +1,179 @@
+<?php
+/* Icinga Web 2 | (c) 2016 Icinga Development Team | GPLv2+ */
+
+namespace Icinga\Module\Monitoring\Backend\Ido\Query;
+
+use Icinga\Data\Filter\FilterExpression;
+use Zend_Db_Expr;
+use Zend_Db_Select;
+use Icinga\Data\Filter\Filter;
+
+/**
+ * Query for host and service flapping start history records
+ */
+class FlappingstarthistoryQuery extends IdoQuery
+{
+ /**
+ * {@inheritdoc}
+ */
+ protected $columnMap = array(
+ 'flappinghistory' => array(
+ 'id' => 'fsh.id',
+ 'object_type' => 'fsh.object_type'
+ ),
+ 'history' => array(
+ 'type' => 'fsh.type',
+ 'timestamp' => 'fsh.timestamp',
+ 'object_id' => 'fsh.object_id',
+ 'state' => 'fsh.state',
+ 'output' => 'fsh.output'
+ ),
+ 'hosts' => array(
+ 'host_display_name' => 'fsh.host_display_name',
+ 'host_name' => 'fsh.host_name'
+ ),
+ 'services' => array(
+ 'service_description' => 'fsh.service_description',
+ 'service_display_name' => 'fsh.service_display_name',
+ 'service_host_name' => 'fsh.service_host_name'
+ )
+ );
+
+ /**
+ * The union
+ *
+ * @var Zend_Db_Select
+ */
+ protected $flappingStartHistoryQuery;
+
+ /**
+ * Subqueries used for the flapping start history query
+ *
+ * @var IdoQuery[]
+ */
+ protected $subQueries = array();
+
+ /**
+ * Whether to additionally select all history columns
+ *
+ * @var bool
+ */
+ protected $fetchHistoryColumns = false;
+
+ /**
+ * {@inheritdoc}
+ */
+ public function allowsCustomVars()
+ {
+ foreach ($this->subQueries as $query) {
+ if (! $query->allowsCustomVars()) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function joinBaseTables()
+ {
+ $this->flappingStartHistoryQuery = $this->db->select();
+ $this->select->from(
+ array('fsh' => $this->flappingStartHistoryQuery),
+ array()
+ );
+ $this->joinedVirtualTables['flappinghistory'] = true;
+ }
+
+ /**
+ * Join history related columns and tables
+ */
+ protected function joinHistory()
+ {
+ // TODO: Ensure that one is selecting the history columns first...
+ $this->fetchHistoryColumns = true;
+ $this->requireVirtualTable('hosts');
+ $this->requireVirtualTable('services');
+ }
+
+ /**
+ * Join hosts
+ */
+ protected function joinHosts()
+ {
+ $columns = array_keys(
+ $this->columnMap['flappinghistory'] + $this->columnMap['hosts']
+ );
+ foreach ($this->columnMap['services'] as $column => $_) {
+ $columns[$column] = new Zend_Db_Expr('NULL');
+ }
+ if ($this->fetchHistoryColumns) {
+ $columns = array_merge($columns, array_keys($this->columnMap['history']));
+ }
+ $hosts = $this->createSubQuery('Hostflappingstarthistory', $columns);
+ $this->subQueries[] = $hosts;
+ $this->flappingStartHistoryQuery->union(array($hosts), Zend_Db_Select::SQL_UNION_ALL);
+ }
+
+ /**
+ * Join services
+ */
+ protected function joinServices()
+ {
+ $columns = array_keys(
+ $this->columnMap['flappinghistory'] + $this->columnMap['hosts'] + $this->columnMap['services']
+ );
+ if ($this->fetchHistoryColumns) {
+ $columns = array_merge($columns, array_keys($this->columnMap['history']));
+ }
+ $services = $this->createSubQuery('Serviceflappingstarthistory', $columns);
+ $this->subQueries[] = $services;
+ $this->flappingStartHistoryQuery->union(array($services), Zend_Db_Select::SQL_UNION_ALL);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function order($columnOrAlias, $dir = null)
+ {
+ foreach ($this->subQueries as $sub) {
+ $sub->requireColumn($columnOrAlias);
+ }
+ return parent::order($columnOrAlias, $dir);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function where($condition, $value = null)
+ {
+ $this->requireColumn($condition);
+ foreach ($this->subQueries as $sub) {
+ $sub->where($condition, $value);
+ }
+ return $this;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function addFilter(Filter $filter)
+ {
+ foreach ($this->subQueries as $sub) {
+ $sub->applyFilter(clone $filter);
+ }
+ return $this;
+ }
+
+ public function whereEx(FilterExpression $ex)
+ {
+ $this->requireColumn($ex->getColumn());
+ foreach ($this->subQueries as $sub) {
+ $sub->whereEx($ex);
+ }
+
+ return $this;
+ }
+}
diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/GroupsummaryQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/GroupsummaryQuery.php
new file mode 100644
index 0000000..60ea5ef
--- /dev/null
+++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/GroupsummaryQuery.php
@@ -0,0 +1,131 @@
+<?php
+/* Icinga Web 2 | (c) 2013 Icinga Development Team | GPLv2+ */
+
+namespace Icinga\Module\Monitoring\Backend\Ido\Query;
+
+use Zend_Db_Select;
+
+/**
+ * Query for host and service group summaries
+ */
+class GroupsummaryQuery extends IdoQuery
+{
+ /**
+ * {@inheritdoc}
+ */
+ protected $columnMap = array(
+ 'hoststatussummary' => array(
+ 'hostgroup' => 'hostgroup COLLATE latin1_general_ci',
+ 'hostgroup_alias' => 'hostgroup_alias COLLATE latin1_general_ci',
+ 'hostgroup_name' => 'hostgroup_name',
+ 'hosts_up' => 'SUM(CASE WHEN object_type = \'host\' AND state = 0 THEN 1 ELSE 0 END)',
+ 'hosts_unreachable' => 'SUM(CASE WHEN object_type = \'host\' AND state = 2 THEN 1 ELSE 0 END)',
+ 'hosts_unreachable_handled' => 'SUM(CASE WHEN object_type = \'host\' AND state = 2 AND acknowledged + in_downtime != 0 THEN 1 ELSE 0 END)',
+ 'hosts_unreachable_unhandled' => 'SUM(CASE WHEN object_type = \'host\' AND state = 2 AND acknowledged + in_downtime = 0 THEN 1 ELSE 0 END)',
+ 'hosts_down' => 'SUM(CASE WHEN object_type = \'host\' AND state = 1 THEN 1 ELSE 0 END)',
+ 'hosts_down_handled' => 'SUM(CASE WHEN object_type = \'host\' AND state = 1 AND acknowledged + in_downtime != 0 THEN 1 ELSE 0 END)',
+ 'hosts_down_last_state_change_handled' => 'MAX(CASE WHEN object_type = \'host\' AND state = 1 AND acknowledged + in_downtime != 0 THEN state_change ELSE 0 END)',
+ 'hosts_down_last_state_change_unhandled' => 'MAX(CASE WHEN object_type = \'host\' AND state = 1 AND acknowledged + in_downtime = 0 THEN state_change ELSE 0 END)',
+ 'hosts_down_unhandled' => 'SUM(CASE WHEN object_type = \'host\' AND state = 1 AND acknowledged + in_downtime = 0 THEN 1 ELSE 0 END)',
+ 'hosts_pending' => 'SUM(CASE WHEN object_type = \'host\' AND state = 99 THEN 1 ELSE 0 END)',
+ 'hosts_pending_last_state_change' => 'MAX(CASE WHEN object_type = \'host\' AND state = 99 THEN state_change ELSE 0 END)',
+ 'hosts_severity' => 'MAX(CASE WHEN object_type = \'host\' THEN severity ELSE 0 END)',
+ 'hosts_total' => 'SUM(CASE WHEN object_type = \'host\' THEN 1 ELSE 0 END)',
+ 'hosts_unreachable_last_state_change_handled' => 'MAX(CASE WHEN object_type = \'host\' AND state = 2 AND acknowledged + in_downtime != 0 THEN state_change ELSE 0 END)',
+ 'hosts_unreachable_last_state_change_unhandled' => 'MAX(CASE WHEN object_type = \'host\' AND state = 2 AND acknowledged + in_downtime = 0 THEN state_change ELSE 0 END)',
+ 'hosts_up_last_state_change' => 'MAX(CASE WHEN object_type = \'host\' AND state = 0 THEN state_change ELSE 0 END)'
+ ),
+ 'servicestatussummary' => array(
+ 'servicegroup' => 'servicegroup COLLATE latin1_general_ci',
+ 'servicegroup_alias' => 'servicegroup_alias COLLATE latin1_general_ci',
+ 'servicegroup_name' => 'servicegroup_name',
+ 'services_critical' => 'SUM(CASE WHEN object_type = \'service\' AND state = 2 THEN 1 ELSE 0 END)',
+ 'services_critical_handled' => 'SUM(CASE WHEN object_type = \'service\' AND state = 2 AND acknowledged + in_downtime + host_state > 0 THEN 1 ELSE 0 END)',
+ 'services_critical_last_state_change_handled' => 'MAX(CASE WHEN object_type = \'service\' AND state = 2 AND acknowledged + in_downtime + host_state > 0 THEN state_change ELSE 0 END)',
+ 'services_critical_last_state_change_unhandled' => 'MAX(CASE WHEN object_type = \'service\' AND state = 2 AND acknowledged + in_downtime + host_state = 0 THEN state_change ELSE 0 END)',
+ 'services_critical_unhandled' => 'SUM(CASE WHEN object_type = \'service\' AND state = 2 AND acknowledged + in_downtime + host_state = 0 THEN 1 ELSE 0 END)',
+ 'services_ok' => 'SUM(CASE WHEN object_type = \'service\' AND state = 0 THEN 1 ELSE 0 END)',
+ 'services_ok_last_state_change' => 'MAX(CASE WHEN object_type = \'service\' AND state = 0 THEN state_change ELSE 0 END)',
+ 'services_pending' => 'SUM(CASE WHEN object_type = \'service\' AND state = 99 THEN 1 ELSE 0 END)',
+ 'services_pending_last_state_change' => 'MAX(CASE WHEN object_type = \'service\' AND state = 99 THEN state_change ELSE 0 END)',
+ 'services_severity' => 'MAX(CASE WHEN object_type = \'service\' THEN severity ELSE 0 END)',
+ 'services_total' => 'SUM(CASE WHEN object_type = \'service\' THEN 1 ELSE 0 END)',
+ 'services_unknown' => 'SUM(CASE WHEN object_type = \'service\' AND state = 3 THEN 1 ELSE 0 END)',
+ 'services_unknown_handled' => 'SUM(CASE WHEN object_type = \'service\' AND state = 3 AND acknowledged + in_downtime + host_state > 0 THEN 1 ELSE 0 END)',
+ 'services_unknown_last_state_change_handled' => 'MAX(CASE WHEN object_type = \'service\' AND state = 3 AND acknowledged + in_downtime + host_state > 0 THEN state_change ELSE 0 END)',
+ 'services_unknown_last_state_change_unhandled' => 'MAX(CASE WHEN object_type = \'service\' AND state = 3 AND acknowledged + in_downtime + host_state = 0 THEN state_change ELSE 0 END)',
+ 'services_unknown_unhandled' => 'SUM(CASE WHEN object_type = \'service\' AND state = 3 AND acknowledged + in_downtime + host_state = 0 THEN 1 ELSE 0 END)',
+ 'services_warning' => 'SUM(CASE WHEN object_type = \'service\' AND state = 1 THEN 1 ELSE 0 END)',
+ 'services_warning_handled' => 'SUM(CASE WHEN object_type = \'service\' AND state = 1 AND acknowledged + in_downtime + host_state > 0 THEN 1 ELSE 0 END)',
+ 'services_warning_last_state_change_handled' => 'MAX(CASE WHEN object_type = \'service\' AND state = 1 AND acknowledged + in_downtime + host_state > 0 THEN state_change ELSE 0 END)',
+ 'services_warning_last_state_change_unhandled' => 'MAX(CASE WHEN object_type = \'service\' AND state = 1 AND acknowledged + in_downtime + host_state = 0 THEN state_change ELSE 0 END)',
+ 'services_warning_unhandled' => 'SUM(CASE WHEN object_type = \'service\' AND state = 1 AND acknowledged + in_downtime + host_state = 0 THEN 1 ELSE 0 END)'
+ )
+ );
+
+ /**
+ * {@inheritdoc}
+ */
+ protected $useSubqueryCount = true;
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function joinBaseTables()
+ {
+ $columns = array(
+ 'object_type',
+ 'host_state'
+ );
+
+ if (in_array('servicegroup', $this->desiredColumns) || in_array('servicegroup_name', $this->desiredColumns)) {
+ $columns[] = 'servicegroup';
+ $columns[] = 'servicegroup_name';
+ $columns[] = 'servicegroup_alias';
+ $groupColumns = array('servicegroup_name', 'servicegroup_alias');
+ } else {
+ $columns[] = 'hostgroup';
+ $columns[] = 'hostgroup_name';
+ $columns[] = 'hostgroup_alias';
+ $groupColumns = array('hostgroup_name', 'hostgroup_alias');
+ }
+ $hosts = $this->createSubQuery(
+ 'Hoststatus',
+ $columns + array(
+ 'state' => 'host_state',
+ 'acknowledged' => 'host_acknowledged',
+ 'in_downtime' => 'host_in_downtime',
+ 'state_change' => 'host_last_state_change',
+ 'severity' => 'host_severity'
+ )
+ );
+ if (in_array('servicegroup_name', $this->desiredColumns)) {
+ $hosts->group(array(
+ 'sgo.name1',
+ 'ho.object_id',
+ 'sg.alias',
+ 'state',
+ 'acknowledged',
+ 'in_downtime',
+ 'state_change',
+ 'severity'
+ ));
+ }
+ $services = $this->createSubQuery(
+ 'Status',
+ $columns + array(
+ 'state' => 'service_state',
+ 'acknowledged' => 'service_acknowledged',
+ 'in_downtime' => 'service_in_downtime',
+ 'state_change' => 'service_last_state_change',
+ 'severity' => 'service_severity'
+ )
+ );
+ $union = $this->db->select()->union(array($hosts, $services), Zend_Db_Select::SQL_UNION_ALL);
+ $this->select->from(array('statussummary' => $union), array())->group($groupColumns);
+ $this->joinedVirtualTables = array(
+ 'servicestatussummary' => true,
+ 'hoststatussummary' => true
+ );
+ }
+}
diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/HostcommentQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/HostcommentQuery.php
new file mode 100644
index 0000000..b388204
--- /dev/null
+++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/HostcommentQuery.php
@@ -0,0 +1,202 @@
+<?php
+/* Icinga Web 2 | (c) 2015 Icinga Development Team | GPLv2+ */
+
+namespace Icinga\Module\Monitoring\Backend\Ido\Query;
+
+/**
+ * Query for host comments
+ */
+class HostcommentQuery extends IdoQuery
+{
+ /**
+ * {@inheritdoc}
+ */
+ protected $allowCustomVars = true;
+
+ /**
+ * {@inheritdoc}
+ */
+ protected $groupBase = array('comments' => array('c.comment_id', 'ho.object_id'));
+
+ /**
+ * {@inheritdoc}
+ */
+ protected $groupOrigin = array('hostgroups', 'services');
+
+ protected $subQueryTargets = array(
+ 'hostgroups' => 'hostgroup',
+ 'servicegroups' => 'servicegroup'
+ );
+
+ /**
+ * {@inheritdoc}
+ */
+ protected $columnMap = array(
+ 'comments' => array(
+ 'comment_author' => 'c.author_name COLLATE latin1_general_ci',
+ 'comment_author_name' => 'c.author_name',
+ 'comment_data' => 'c.comment_data',
+ 'comment_expiration' => 'CASE c.expires WHEN 1 THEN UNIX_TIMESTAMP(c.expiration_time) ELSE NULL END',
+ 'comment_internal_id' => 'c.internal_comment_id',
+ 'comment_is_persistent' => 'c.is_persistent',
+ 'comment_name' => 'c.name',
+ 'comment_timestamp' => 'UNIX_TIMESTAMP(c.comment_time)',
+ 'comment_type' => "CASE c.entry_type WHEN 1 THEN 'comment' WHEN 2 THEN 'downtime' WHEN 3 THEN 'flapping' WHEN 4 THEN 'ack' END",
+ 'host' => 'ho.name1 COLLATE latin1_general_ci',
+ 'host_name' => 'ho.name1',
+ 'object_type' => '(\'host\')'
+ ),
+ 'hostgroups' => array(
+ 'hostgroup' => 'hgo.name1 COLLATE latin1_general_ci',
+ 'hostgroup_alias' => 'hg.alias COLLATE latin1_general_ci',
+ 'hostgroup_name' => 'hgo.name1'
+ ),
+ 'hosts' => array(
+ 'host_alias' => 'h.alias',
+ 'host_display_name' => 'h.display_name COLLATE latin1_general_ci'
+ ),
+ 'hoststatus' => array(
+ 'host_state' => 'CASE WHEN hs.has_been_checked = 0 OR hs.has_been_checked IS NULL THEN 99 ELSE hs.current_state END'
+ ),
+ 'instances' => array(
+ 'instance_name' => 'i.instance_name'
+ ),
+ 'servicegroups' => array(
+ 'servicegroup' => 'sgo.name1 COLLATE latin1_general_ci',
+ 'servicegroup_name' => 'sgo.name1',
+ 'servicegroup_alias' => 'sg.alias COLLATE latin1_general_ci'
+ ),
+ 'services' => array(
+ 'service' => 'so.name2 COLLATE latin1_general_ci',
+ 'service_description' => 'so.name2',
+ 'service_display_name' => 's.display_name COLLATE latin1_general_ci',
+ )
+ );
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function joinBaseTables()
+ {
+ if (version_compare($this->getIdoVersion(), '1.14.0', '<')) {
+ $this->columnMap['comments']['comment_name'] = '(NULL)';
+ }
+ $this->select->from(
+ array('c' => $this->prefix . 'comments'),
+ array()
+ )->join(
+ array('ho' => $this->prefix . 'objects'),
+ 'ho.object_id = c.object_id AND ho.is_active = 1 AND ho.objecttype_id = 1',
+ array()
+ );
+ $this->joinedVirtualTables['comments'] = true;
+ }
+
+ /**
+ * Join host groups
+ */
+ protected function joinHostgroups()
+ {
+ $this->select->joinLeft(
+ array('hgm' => $this->prefix . 'hostgroup_members'),
+ 'hgm.host_object_id = ho.object_id',
+ array()
+ )->joinLeft(
+ array('hg' => $this->prefix . 'hostgroups'),
+ 'hg.hostgroup_id = hgm.hostgroup_id',
+ array()
+ )->joinLeft(
+ array('hgo' => $this->prefix . 'objects'),
+ 'hgo.object_id = hg.hostgroup_object_id AND hgo.is_active = 1 AND hgo.objecttype_id = 3',
+ array()
+ );
+ }
+
+ /**
+ * Join hosts
+ */
+ protected function joinHosts()
+ {
+ $this->select->join(
+ array('h' => $this->prefix . 'hosts'),
+ 'h.host_object_id = ho.object_id',
+ array()
+ );
+ }
+
+ /**
+ * Join host status
+ */
+ protected function joinHoststatus()
+ {
+ $this->select->join(
+ array('hs' => $this->prefix . 'hoststatus'),
+ 'hs.host_object_id = ho.object_id',
+ array()
+ );
+ }
+
+ /**
+ * Join instances
+ */
+ protected function joinInstances()
+ {
+ $this->select->join(
+ array('i' => $this->prefix . 'instances'),
+ 'i.instance_id = c.instance_id',
+ array()
+ );
+ }
+
+ /**
+ * Join service groups
+ */
+ protected function joinServicegroups()
+ {
+ $this->requireVirtualTable('services');
+ $this->select->joinLeft(
+ array('sgm' => $this->prefix . 'servicegroup_members'),
+ 'sgm.service_object_id = s.service_object_id',
+ array()
+ )->joinLeft(
+ array('sg' => $this->prefix . 'servicegroups'),
+ 'sgm.servicegroup_id = sg.' . $this->servicegroup_id,
+ array()
+ )->joinLeft(
+ array('sgo' => $this->prefix . 'objects'),
+ 'sgo.object_id = sg.servicegroup_object_id AND sgo.is_active = 1 AND sgo.objecttype_id = 4',
+ array()
+ );
+ }
+
+ /**
+ * Join services
+ */
+ protected function joinServices()
+ {
+ $this->select->joinLeft(
+ array('s' => $this->prefix . 'services'),
+ 's.host_object_id = ho.object_id',
+ array()
+ )->joinLeft(
+ array('so' => $this->prefix . 'objects'),
+ 'so.object_id = s.service_object_id AND so.is_active = 1 AND so.objecttype_id = 2',
+ array()
+ );
+ }
+
+ protected function joinSubQuery(IdoQuery $query, $name, $filter, $and, $negate, &$additionalFilter)
+ {
+ if ($name === 'hostgroup') {
+ $query->joinVirtualTable('members');
+
+ return ['hgm.host_object_id', 'ho.object_id'];
+ } elseif ($name === 'servicegroup') {
+ $query->joinVirtualTable('services');
+
+ return ['s.host_object_id', 'ho.object_id'];
+ }
+
+ return parent::joinSubQuery($query, $name, $filter, $and, $negate, $additionalFilter);
+ }
+}
diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/HostcommentdeletionhistoryQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/HostcommentdeletionhistoryQuery.php
new file mode 100644
index 0000000..d798d56
--- /dev/null
+++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/HostcommentdeletionhistoryQuery.php
@@ -0,0 +1,44 @@
+<?php
+/* Icinga Web 2 | (c) 2015 Icinga Development Team | GPLv2+ */
+
+namespace Icinga\Module\Monitoring\Backend\Ido\Query;
+
+use Icinga\Data\Filter\Filter;
+use Icinga\Data\Filter\FilterExpression;
+
+/**
+ * Query for host comment removal records
+ */
+class HostcommentdeletionhistoryQuery extends HostcommenthistoryQuery
+{
+ protected function requireFilterColumns(Filter $filter)
+ {
+ if ($filter instanceof FilterExpression && $filter->getColumn() === 'timestamp') {
+ $this->requireColumn('timestamp');
+ $filter->setColumn('hch.deletion_time');
+ $filter->setExpression($this->timestampForSql($this->valueToTimestamp($filter->getExpression())));
+ return null;
+ }
+
+ return parent::requireFilterColumns($filter);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function joinBaseTables()
+ {
+ parent::joinBaseTables();
+ $this->select->where("hch.deletion_time > '1970-01-02 00:00:00'");
+ $this->columnMap['commenthistory']['timestamp'] = str_replace(
+ 'comment_time',
+ 'deletion_time',
+ $this->columnMap['commenthistory']['timestamp']
+ );
+ $this->columnMap['commenthistory']['type'] = str_replace(
+ 'END)',
+ "END || '_deleted')",
+ $this->columnMap['commenthistory']['type']
+ );
+ }
+}
diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/HostcommenthistoryQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/HostcommenthistoryQuery.php
new file mode 100644
index 0000000..b8f166a
--- /dev/null
+++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/HostcommenthistoryQuery.php
@@ -0,0 +1,197 @@
+<?php
+/* Icinga Web 2 | (c) 2015 Icinga Development Team | GPLv2+ */
+
+namespace Icinga\Module\Monitoring\Backend\Ido\Query;
+
+use Icinga\Data\Filter\Filter;
+use Icinga\Data\Filter\FilterExpression;
+
+/**
+ * Query for host comment history records
+ */
+class HostcommenthistoryQuery extends IdoQuery
+{
+ /**
+ * {@inheritdoc}
+ */
+ protected $allowCustomVars = true;
+
+ /**
+ * {@inheritdoc}
+ */
+ protected $groupBase = array('commenthistory' => array('hch.commenthistory_id', 'ho.object_id'));
+
+ /**
+ * {@inheritdoc}
+ */
+ protected $groupOrigin = array('hostgroups', 'services');
+
+ protected $subQueryTargets = array(
+ 'hostgroups' => 'hostgroup',
+ 'servicegroups' => 'servicegroup'
+ );
+
+ /**
+ * {@inheritdoc}
+ */
+ protected $columnMap = array(
+ 'commenthistory' => array(
+ 'id' => 'hch.commenthistory_id',
+ 'host' => 'ho.name1 COLLATE latin1_general_ci',
+ 'host_name' => 'ho.name1',
+ 'object_id' => 'hch.object_id',
+ 'object_type' => '(\'host\')',
+ 'output' => "('[' || hch.author_name || '] ' || hch.comment_data)",
+ 'state' => '(-1)',
+ 'timestamp' => 'UNIX_TIMESTAMP(hch.comment_time)',
+ 'type' => "(CASE hch.entry_type WHEN 1 THEN 'comment' WHEN 2 THEN 'dt_comment' WHEN 3 THEN 'flapping' WHEN 4 THEN 'ack' END)"
+ ),
+ 'hostgroups' => array(
+ 'hostgroup' => 'hgo.name1 COLLATE latin1_general_ci',
+ 'hostgroup_alias' => 'hg.alias COLLATE latin1_general_ci',
+ 'hostgroup_name' => 'hgo.name1'
+ ),
+ 'hosts' => array(
+ 'host_alias' => 'h.alias',
+ 'host_display_name' => 'h.display_name COLLATE latin1_general_ci'
+ ),
+ 'instances' => array(
+ 'instance_name' => 'i.instance_name'
+ ),
+ 'servicegroups' => array(
+ 'servicegroup' => 'sgo.name1 COLLATE latin1_general_ci',
+ 'servicegroup_name' => 'sgo.name1',
+ 'servicegroup_alias' => 'sg.alias COLLATE latin1_general_ci'
+ ),
+ 'services' => array(
+ 'service' => 'so.name2 COLLATE latin1_general_ci',
+ 'service_description' => 'so.name2',
+ 'service_display_name' => 's.display_name COLLATE latin1_general_ci',
+ 'service_host_name' => 'so.name1'
+ )
+ );
+
+ protected function requireFilterColumns(Filter $filter)
+ {
+ if ($filter instanceof FilterExpression && $filter->getColumn() === 'timestamp') {
+ $this->requireColumn('timestamp');
+ $filter->setColumn('hch.comment_time');
+ $filter->setExpression($this->timestampForSql($this->valueToTimestamp($filter->getExpression())));
+ return null;
+ }
+
+ return parent::requireFilterColumns($filter);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function joinBaseTables()
+ {
+ $this->select->from(
+ array('hch' => $this->prefix . 'commenthistory'),
+ array()
+ )->join(
+ array('ho' => $this->prefix . 'objects'),
+ 'ho.object_id = hch.object_id AND ho.is_active = 1 AND ho.objecttype_id = 1',
+ array()
+ );
+ $this->joinedVirtualTables['commenthistory'] = true;
+ }
+
+ /**
+ * Join host groups
+ */
+ protected function joinHostgroups()
+ {
+ $this->select->joinLeft(
+ array('hgm' => $this->prefix . 'hostgroup_members'),
+ 'hgm.host_object_id = ho.object_id',
+ array()
+ )->joinLeft(
+ array('hg' => $this->prefix . 'hostgroups'),
+ 'hg.hostgroup_id = hgm.hostgroup_id',
+ array()
+ )->joinLeft(
+ array('hgo' => $this->prefix . 'objects'),
+ 'hgo.object_id = hg.hostgroup_object_id AND hgo.is_active = 1 AND hgo.objecttype_id = 3',
+ array()
+ );
+ }
+
+ /**
+ * Join hosts
+ */
+ protected function joinHosts()
+ {
+ $this->select->join(
+ array('h' => $this->prefix . 'hosts'),
+ 'h.host_object_id = ho.object_id',
+ array()
+ );
+ }
+
+ /**
+ * Join instances
+ */
+ protected function joinInstances()
+ {
+ $this->select->join(
+ array('i' => $this->prefix . 'instances'),
+ 'i.instance_id = hch.instance_id',
+ array()
+ );
+ }
+
+ /**
+ * Join service groups
+ */
+ protected function joinServicegroups()
+ {
+ $this->requireVirtualTable('services');
+ $this->select->joinLeft(
+ array('sgm' => $this->prefix . 'servicegroup_members'),
+ 'sgm.service_object_id = s.service_object_id',
+ array()
+ )->joinLeft(
+ array('sg' => $this->prefix . 'servicegroups'),
+ 'sg.' . $this->servicegroup_id . ' = sgm.servicegroup_id',
+ array()
+ )->joinLeft(
+ array('sgo' => $this->prefix . 'objects'),
+ 'sgo.object_id = sg.servicegroup_object_id AND sgo.is_active = 1 AND sgo.objecttype_id = 4',
+ array()
+ );
+ }
+
+ /**
+ * Join services
+ */
+ protected function joinServices()
+ {
+ $this->select->joinLeft(
+ array('s' => $this->prefix . 'services'),
+ 's.host_object_id = ho.object_id',
+ array()
+ )->joinLeft(
+ array('so' => $this->prefix . 'objects'),
+ 'so.object_id = s.service_object_id AND so.is_active = 1 AND so.objecttype_id = 2',
+ array()
+ );
+ }
+
+ protected function joinSubQuery(IdoQuery $query, $name, $filter, $and, $negate, &$additionalFilter)
+ {
+ if ($name === 'hostgroup') {
+ $query->joinVirtualTable('members');
+
+ return ['hgm.host_object_id', 'ho.object_id'];
+ } elseif ($name === 'servicegroup') {
+ $query->joinVirtualTable('services');
+
+ return ['s.host_object_id', 'ho.object_id'];
+ }
+
+ return parent::joinSubQuery($query, $name, $filter, $and, $negate, $additionalFilter);
+ }
+}
diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/HostcontactQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/HostcontactQuery.php
new file mode 100644
index 0000000..23b0e90
--- /dev/null
+++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/HostcontactQuery.php
@@ -0,0 +1,247 @@
+<?php
+/* Icinga Web 2 | (c) 2018 Icinga Development Team | GPLv2+ */
+
+namespace Icinga\Module\Monitoring\Backend\Ido\Query;
+
+/**
+ * Query for host contacts
+ */
+class HostcontactQuery extends IdoQuery
+{
+ protected $allowCustomVars = true;
+
+ protected $groupBase = [
+ 'contacts' => ['co.object_id', 'c.contact_id'],
+ 'timeperiods' => ['ht.timeperiod_id', 'st.timeperiod_id']
+ ];
+
+ protected $groupOrigin = ['contactgroups', 'hosts', 'services'];
+
+ protected $subQueryTargets = [
+ 'hostgroups' => 'hostgroup',
+ 'servicegroups' => 'servicegroup'
+ ];
+
+ protected $columnMap = [
+ 'contactgroups' => [
+ 'contactgroup' => 'cgo.name1 COLLATE latin1_general_ci',
+ 'contactgroup_name' => 'cgo.name1',
+ 'contactgroup_alias' => 'cg.alias COLLATE latin1_general_ci'
+ ],
+ 'contacts' => [
+ 'contact_id' => 'c.contact_id',
+ 'contact' => 'co.name1 COLLATE latin1_general_ci',
+ 'contact_name' => 'co.name1',
+ 'contact_alias' => 'c.alias COLLATE latin1_general_ci',
+ 'contact_email' => 'c.email_address COLLATE latin1_general_ci',
+ 'contact_pager' => 'c.pager_address',
+ 'contact_object_id' => 'c.contact_object_id',
+ 'contact_has_host_notfications' => 'c.host_notifications_enabled',
+ 'contact_has_service_notfications' => 'c.service_notifications_enabled',
+ 'contact_can_submit_commands' => 'c.can_submit_commands',
+ 'contact_notify_service_recovery' => 'c.notify_service_recovery',
+ 'contact_notify_service_warning' => 'c.notify_service_warning',
+ 'contact_notify_service_critical' => 'c.notify_service_critical',
+ 'contact_notify_service_unknown' => 'c.notify_service_unknown',
+ 'contact_notify_service_flapping' => 'c.notify_service_flapping',
+ 'contact_notify_service_downtime' => 'c.notify_service_downtime',
+ 'contact_notify_host_recovery' => 'c.notify_host_recovery',
+ 'contact_notify_host_down' => 'c.notify_host_down',
+ 'contact_notify_host_unreachable' => 'c.notify_host_unreachable',
+ 'contact_notify_host_flapping' => 'c.notify_host_flapping',
+ 'contact_notify_host_downtime' => 'c.notify_host_downtime'
+ ],
+ 'hostgroups' => [
+ 'hostgroup' => 'hgo.name1 COLLATE latin1_general_ci',
+ 'hostgroup_alias' => 'hg.alias COLLATE latin1_general_ci',
+ 'hostgroup_name' => 'hgo.name1'
+ ],
+ 'hosts' => [
+ 'host' => 'ho.name1 COLLATE latin1_general_ci',
+ 'host_name' => 'ho.name1',
+ 'host_alias' => 'h.alias',
+ 'host_display_name' => 'h.display_name COLLATE latin1_general_ci'
+ ],
+ 'instances' => [
+ 'instance_name' => 'i.instance_name'
+ ],
+ 'servicegroups' => [
+ 'servicegroup' => 'sgo.name1 COLLATE latin1_general_ci',
+ 'servicegroup_name' => 'sgo.name1',
+ 'servicegroup_alias' => 'sg.alias COLLATE latin1_general_ci'
+ ],
+ 'services' => [
+ 'service' => 'so.name2 COLLATE latin1_general_ci',
+ 'service_description' => 'so.name2',
+ 'service_display_name' => 's.display_name COLLATE latin1_general_ci',
+ 'service_host_name' => 'so.name1'
+ ],
+ 'timeperiods' => [
+ 'contact_notify_host_timeperiod' => 'ht.alias COLLATE latin1_general_ci',
+ 'contact_notify_service_timeperiod' => 'st.alias COLLATE latin1_general_ci'
+ ]
+ ];
+
+ protected function joinBaseTables()
+ {
+ $this->select->from(
+ ['c' => $this->prefix . 'contacts'],
+ []
+ )->join(
+ ['co' => $this->prefix . 'objects'],
+ 'co.object_id = c.contact_object_id AND co.is_active = 1 AND co.objecttype_id = 10',
+ []
+ );
+
+ $this->joinedVirtualTables = array('contacts' => true);
+ }
+
+ /**
+ * Join contact groups
+ */
+ protected function joinContactgroups()
+ {
+ $this->select->joinLeft(
+ ['cgm' => $this->prefix . 'contactgroup_members'],
+ 'co.object_id = cgm.contact_object_id',
+ []
+ )->joinLeft(
+ ['cg' => $this->prefix . 'contactgroups'],
+ 'cgm.contactgroup_id = cg.contactgroup_id',
+ []
+ )->joinLeft(
+ ['cgo' => $this->prefix . 'objects'],
+ 'cg.contactgroup_object_id = cgo.object_id AND cgo.is_active = 1 AND cgo.objecttype_id = 11',
+ []
+ );
+ }
+
+ /**
+ * Join host groups
+ */
+ protected function joinHostgroups()
+ {
+ $this->requireVirtualTable('hosts');
+
+ $this->select->joinLeft(
+ ['hgm' => $this->prefix . 'hostgroup_members'],
+ 'hgm.host_object_id = ho.object_id',
+ []
+ )->joinLeft(
+ ['hg' => $this->prefix . 'hostgroups'],
+ 'hg.hostgroup_id = hgm.hostgroup_id',
+ []
+ )->joinLeft(
+ ['hgo' => $this->prefix . 'objects'],
+ 'hgo.object_id = hg.hostgroup_object_id AND hgo.is_active = 1 AND hgo.objecttype_id = 3',
+ []
+ );
+ }
+
+ /**
+ * Join hosts
+ */
+ protected function joinHosts()
+ {
+ $this->select->joinLeft(
+ ['hc' => $this->prefix . 'host_contacts'],
+ 'hc.contact_object_id = c.contact_object_id',
+ []
+ )->joinLeft(
+ ['h' => $this->prefix . 'hosts'],
+ 'h.host_id = hc.host_id',
+ []
+ )->joinLeft(
+ ['ho' => $this->prefix . 'objects'],
+ 'ho.object_id = h.host_object_id AND ho.is_active = 1 AND ho.objecttype_id = 1',
+ []
+ );
+ }
+
+ /**
+ * Join instances
+ */
+ protected function joinInstances()
+ {
+ $this->select->join(
+ ['i' => $this->prefix . 'instances'],
+ 'i.instance_id = c.instance_id',
+ []
+ );
+ }
+
+ /**
+ * Join service groups
+ */
+ protected function joinServicegroups()
+ {
+ $this->requireVirtualTable('services');
+ $this->select->joinLeft(
+ ['sgm' => $this->prefix . 'servicegroup_members'],
+ 'sgm.service_object_id = s.service_object_id',
+ []
+ )->joinLeft(
+ ['sg' => $this->prefix . 'servicegroups'],
+ 'sg.servicegroup_id = sgm.servicegroup_id',
+ []
+ )->joinLeft(
+ ['sgo' => $this->prefix . 'objects'],
+ 'sgo.object_id = sg.servicegroup_object_id AND sgo.is_active = 1 AND sgo.objecttype_id = 4',
+ []
+ );
+ }
+
+ /**
+ * Join services
+ */
+ protected function joinServices()
+ {
+ $this->requireVirtualTable('hosts');
+
+ $this->select->joinLeft(
+ ['s' => $this->prefix . 'services'],
+ 's.host_object_id = ho.object_id',
+ []
+ )->joinLeft(
+ ['so' => $this->prefix . 'objects'],
+ 'so.object_id = s.service_object_id AND so.is_active = 1 AND so.objecttype_id = 2',
+ []
+ );
+ }
+
+ /**
+ * Join time periods
+ */
+ protected function joinTimeperiods()
+ {
+ $this->select->joinLeft(
+ ['ht' => $this->prefix . 'timeperiods'],
+ 'ht.timeperiod_object_id = c.host_timeperiod_object_id',
+ []
+ );
+ $this->select->joinLeft(
+ ['st' => $this->prefix . 'timeperiods'],
+ 'st.timeperiod_object_id = c.service_timeperiod_object_id',
+ []
+ );
+ }
+
+ protected function joinSubQuery(IdoQuery $query, $name, $filter, $and, $negate, &$additionalFilter)
+ {
+ if ($name === 'hostgroup') {
+ $this->requireVirtualTable('hosts');
+
+ $query->joinVirtualTable('members');
+
+ return ['hgm.host_object_id', 'ho.object_id'];
+ } elseif ($name === 'servicegroup') {
+ $this->requireVirtualTable('services');
+
+ $query->joinVirtualTable('members');
+
+ return ['sgm.service_object_id', 'so.object_id'];
+ }
+
+ return parent::joinSubQuery($query, $name, $filter, $and, $negate, $additionalFilter);
+ }
+}
diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/HostdowntimeQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/HostdowntimeQuery.php
new file mode 100644
index 0000000..62f5ceb
--- /dev/null
+++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/HostdowntimeQuery.php
@@ -0,0 +1,208 @@
+<?php
+/* Icinga Web 2 | (c) 2015 Icinga Development Team | GPLv2+ */
+
+namespace Icinga\Module\Monitoring\Backend\Ido\Query;
+
+/**
+ * Query for host downtimes
+ */
+class HostdowntimeQuery extends IdoQuery
+{
+ /**
+ * {@inheritdoc}
+ */
+ protected $allowCustomVars = true;
+
+ /**
+ * {@inheritdoc}
+ */
+ protected $groupBase = array('downtimes' => array('sd.scheduleddowntime_id', 'ho.object_id'));
+
+ /**
+ * {@inheritdoc}
+ */
+ protected $groupOrigin = array('hostgroups', 'servicegroups', 'services');
+
+ protected $subQueryTargets = array(
+ 'hostgroups' => 'hostgroup',
+ 'servicegroups' => 'servicegroup'
+ );
+
+ /**
+ * {@inheritdoc}
+ */
+ protected $columnMap = array(
+ 'downtimes' => array(
+ 'downtime_author' => 'sd.author_name COLLATE latin1_general_ci',
+ 'downtime_author_name' => 'sd.author_name',
+ 'downtime_comment' => 'sd.comment_data',
+ 'downtime_duration' => 'sd.duration',
+ 'downtime_end' => 'CASE WHEN sd.is_fixed > 0 THEN UNIX_TIMESTAMP(sd.scheduled_end_time) ELSE UNIX_TIMESTAMP(sd.trigger_time) + sd.duration END',
+ 'downtime_entry_time' => 'UNIX_TIMESTAMP(sd.entry_time)',
+ 'downtime_internal_id' => 'sd.internal_downtime_id',
+ 'downtime_is_fixed' => 'sd.is_fixed',
+ 'downtime_is_flexible' => 'CASE WHEN sd.is_fixed = 0 THEN 1 ELSE 0 END',
+ 'downtime_is_in_effect' => 'sd.is_in_effect',
+ 'downtime_name' => 'sd.name',
+ 'downtime_scheduled_end' => 'UNIX_TIMESTAMP(sd.scheduled_end_time)',
+ 'downtime_scheduled_start' => 'UNIX_TIMESTAMP(sd.scheduled_start_time)',
+ 'downtime_start' => 'UNIX_TIMESTAMP(CASE WHEN UNIX_TIMESTAMP(sd.trigger_time) > 0 then sd.trigger_time ELSE sd.scheduled_start_time END)',
+ 'downtime_triggered_by_id' => 'sd.triggered_by_id',
+ 'host' => 'ho.name1 COLLATE latin1_general_ci',
+ 'host_name' => 'ho.name1',
+ 'object_type' => '(\'host\')'
+ ),
+ 'hostgroups' => array(
+ 'hostgroup' => 'hgo.name1 COLLATE latin1_general_ci',
+ 'hostgroup_alias' => 'hg.alias COLLATE latin1_general_ci',
+ 'hostgroup_name' => 'hgo.name1'
+ ),
+ 'hosts' => array(
+ 'host_alias' => 'h.alias',
+ 'host_display_name' => 'h.display_name COLLATE latin1_general_ci'
+ ),
+ 'hoststatus' => array(
+ 'host_state' => 'CASE WHEN hs.has_been_checked = 0 OR hs.has_been_checked IS NULL THEN 99 ELSE hs.current_state END'
+ ),
+ 'instances' => array(
+ 'instance_name' => 'i.instance_name'
+ ),
+ 'servicegroups' => array(
+ 'servicegroup' => 'sgo.name1 COLLATE latin1_general_ci',
+ 'servicegroup_name' => 'sgo.name1',
+ 'servicegroup_alias' => 'sg.alias COLLATE latin1_general_ci'
+ ),
+ 'services' => array(
+ 'service' => 'so.name2 COLLATE latin1_general_ci',
+ 'service_description' => 'so.name2',
+ 'service_display_name' => 's.display_name COLLATE latin1_general_ci',
+ )
+ );
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function joinBaseTables()
+ {
+ if (version_compare($this->getIdoVersion(), '1.14.0', '<')) {
+ $this->columnMap['downtimes']['downtime_name'] = '(NULL)';
+ }
+ $this->select->from(
+ array('sd' => $this->prefix . 'scheduleddowntime'),
+ array()
+ )->join(
+ array('ho' => $this->prefix . 'objects'),
+ 'sd.object_id = ho.object_id AND ho.is_active = 1 AND ho.objecttype_id = 1',
+ array()
+ );
+ $this->joinedVirtualTables['downtimes'] = true;
+ }
+
+ /**
+ * Join host groups
+ */
+ protected function joinHostgroups()
+ {
+ $this->select->joinLeft(
+ array('hgm' => $this->prefix . 'hostgroup_members'),
+ 'hgm.host_object_id = ho.object_id',
+ array()
+ )->joinLeft(
+ array('hg' => $this->prefix . 'hostgroups'),
+ 'hg.hostgroup_id = hgm.hostgroup_id',
+ array()
+ )->joinLeft(
+ array('hgo' => $this->prefix . 'objects'),
+ 'hgo.object_id = hg.hostgroup_object_id AND hgo.is_active = 1 AND hgo.objecttype_id = 3',
+ array()
+ );
+ }
+
+ /**
+ * Join hosts
+ */
+ protected function joinHosts()
+ {
+ $this->select->join(
+ array('h' => $this->prefix . 'hosts'),
+ 'h.host_object_id = ho.object_id',
+ array()
+ );
+ }
+
+ /**
+ * Join host status
+ */
+ protected function joinHoststatus()
+ {
+ $this->select->join(
+ array('hs' => $this->prefix . 'hoststatus'),
+ 'hs.host_object_id = ho.object_id',
+ array()
+ );
+ }
+
+ /**
+ * Join instances
+ */
+ protected function joinInstances()
+ {
+ $this->select->join(
+ array('i' => $this->prefix . 'instances'),
+ 'i.instance_id = sd.instance_id',
+ array()
+ );
+ }
+
+ /**
+ * Join service groups
+ */
+ protected function joinServicegroups()
+ {
+ $this->requireVirtualTable('services');
+ $this->select->joinLeft(
+ array('sgm' => $this->prefix . 'servicegroup_members'),
+ 'sgm.service_object_id = s.service_object_id',
+ array()
+ )->joinLeft(
+ array('sg' => $this->prefix . 'servicegroups'),
+ 'sgm.servicegroup_id = sg.' . $this->servicegroup_id,
+ array()
+ )->joinLeft(
+ array('sgo' => $this->prefix . 'objects'),
+ 'sgo.object_id = sg.servicegroup_object_id AND sgo.is_active = 1 AND sgo.objecttype_id = 4',
+ array()
+ );
+ }
+
+ /**
+ * Join services
+ */
+ protected function joinServices()
+ {
+ $this->select->joinLeft(
+ array('s' => $this->prefix . 'services'),
+ 's.host_object_id = ho.object_id',
+ array()
+ )->joinLeft(
+ array('so' => $this->prefix . 'objects'),
+ 'so.object_id = s.service_object_id AND so.is_active = 1 AND so.objecttype_id = 2',
+ array()
+ );
+ }
+
+ protected function joinSubQuery(IdoQuery $query, $name, $filter, $and, $negate, &$additionalFilter)
+ {
+ if ($name === 'hostgroup') {
+ $query->joinVirtualTable('members');
+
+ return ['hgm.host_object_id', 'ho.object_id'];
+ } elseif ($name === 'servicegroup') {
+ $query->joinVirtualTable('services');
+
+ return ['s.host_object_id', 'ho.object_id'];
+ }
+
+ return parent::joinSubQuery($query, $name, $filter, $and, $negate, $additionalFilter);
+ }
+}
diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/HostdowntimeendhistoryQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/HostdowntimeendhistoryQuery.php
new file mode 100644
index 0000000..77d91e5
--- /dev/null
+++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/HostdowntimeendhistoryQuery.php
@@ -0,0 +1,40 @@
+<?php
+/* Icinga Web 2 | (c) 2015 Icinga Development Team | GPLv2+ */
+
+namespace Icinga\Module\Monitoring\Backend\Ido\Query;
+
+use Icinga\Data\Filter\Filter;
+use Icinga\Data\Filter\FilterExpression;
+
+/**
+ * Query for host downtime end history records
+ */
+class HostdowntimeendhistoryQuery extends HostdowntimestarthistoryQuery
+{
+ protected function requireFilterColumns(Filter $filter)
+ {
+ if ($filter instanceof FilterExpression && $filter->getColumn() === 'timestamp') {
+ $this->requireColumn('timestamp');
+ $filter->setColumn('hdh.actual_end_time');
+ $filter->setExpression($this->timestampForSql($this->valueToTimestamp($filter->getExpression())));
+ return null;
+ }
+
+ return parent::requireFilterColumns($filter);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function joinBaseTables()
+ {
+ parent::joinBaseTables(true);
+ $this->select->where("hdh.actual_end_time > '1970-01-02 00:00:00'");
+ $this->columnMap['downtimehistory']['type'] = "('dt_end')";
+ $this->columnMap['downtimehistory']['timestamp'] = str_replace(
+ 'actual_start_time',
+ 'actual_end_time',
+ $this->columnMap['downtimehistory']['timestamp']
+ );
+ }
+}
diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/HostdowntimestarthistoryQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/HostdowntimestarthistoryQuery.php
new file mode 100644
index 0000000..54ac6a1
--- /dev/null
+++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/HostdowntimestarthistoryQuery.php
@@ -0,0 +1,204 @@
+<?php
+/* Icinga Web 2 | (c) 2015 Icinga Development Team | GPLv2+ */
+
+namespace Icinga\Module\Monitoring\Backend\Ido\Query;
+
+use Icinga\Data\Filter\Filter;
+use Icinga\Data\Filter\FilterExpression;
+
+/**
+ * Query for host downtime start history records
+ */
+class HostdowntimestarthistoryQuery extends IdoQuery
+{
+ /**
+ * {@inheritdoc}
+ */
+ protected $allowCustomVars = true;
+
+ /**
+ * {@inheritdoc}
+ */
+ protected $groupBase = array('downtimehistory' => array('hdh.downtimehistory_id', 'ho.object_id'));
+
+ /**
+ * {@inheritdoc}
+ */
+ protected $groupOrigin = array('hostgroups', 'services');
+
+ protected $subQueryTargets = array(
+ 'hostgroups' => 'hostgroup',
+ 'servicegroups' => 'servicegroup'
+ );
+
+ /**
+ * {@inheritdoc}
+ */
+ protected $columnMap = array(
+ 'downtimehistory' => array(
+ 'id' => 'hdh.downtimehistory_id',
+ 'host' => 'ho.name1 COLLATE latin1_general_ci',
+ 'host_name' => 'ho.name1',
+ 'object_id' => 'hdh.object_id',
+ 'object_type' => '(\'host\')',
+ 'output' => "('[' || hdh.author_name || '] ' || hdh.comment_data)",
+ 'state' => '(-1)',
+ 'timestamp' => 'UNIX_TIMESTAMP(hdh.actual_start_time)',
+ 'type' => "('dt_start')"
+ ),
+ 'hostgroups' => array(
+ 'hostgroup' => 'hgo.name1 COLLATE latin1_general_ci',
+ 'hostgroup_alias' => 'hg.alias COLLATE latin1_general_ci',
+ 'hostgroup_name' => 'hgo.name1'
+ ),
+ 'hosts' => array(
+ 'host_alias' => 'h.alias',
+ 'host_display_name' => 'h.display_name COLLATE latin1_general_ci'
+ ),
+ 'instances' => array(
+ 'instance_name' => 'i.instance_name'
+ ),
+ 'servicegroups' => array(
+ 'servicegroup' => 'sgo.name1 COLLATE latin1_general_ci',
+ 'servicegroup_name' => 'sgo.name1',
+ 'servicegroup_alias' => 'sg.alias COLLATE latin1_general_ci'
+ ),
+ 'services' => array(
+ 'service' => 'so.name2 COLLATE latin1_general_ci',
+ 'service_description' => 'so.name2',
+ 'service_display_name' => 's.display_name COLLATE latin1_general_ci',
+ 'service_host_name' => 'so.name1'
+ )
+ );
+
+ protected function requireFilterColumns(Filter $filter)
+ {
+ if ($filter instanceof FilterExpression && $filter->getColumn() === 'timestamp') {
+ $this->requireColumn('timestamp');
+ $filter->setColumn('hdh.actual_start_time');
+ $filter->setExpression($this->timestampForSql($this->valueToTimestamp($filter->getExpression())));
+ return null;
+ }
+
+ return parent::requireFilterColumns($filter);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function joinBaseTables()
+ {
+ $this->select->from(
+ array('hdh' => $this->prefix . 'downtimehistory'),
+ array()
+ )->join(
+ array('ho' => $this->prefix . 'objects'),
+ 'ho.object_id = hdh.object_id AND ho.is_active = 1 AND ho.objecttype_id = 1',
+ array()
+ );
+
+ if (func_num_args() === 0 || func_get_arg(0) === false) {
+ $this->select->where(
+ "hdh.actual_start_time > '1970-01-02 00:00:00'"
+ );
+ }
+
+ $this->joinedVirtualTables['downtimehistory'] = true;
+ }
+
+ /**
+ * Join host groups
+ */
+ protected function joinHostgroups()
+ {
+ $this->select->joinLeft(
+ array('hgm' => $this->prefix . 'hostgroup_members'),
+ 'hgm.host_object_id = ho.object_id',
+ array()
+ )->joinLeft(
+ array('hg' => $this->prefix . 'hostgroups'),
+ 'hg.hostgroup_id = hgm.hostgroup_id',
+ array()
+ )->joinLeft(
+ array('hgo' => $this->prefix . 'objects'),
+ 'hgo.object_id = hg.hostgroup_object_id AND hgo.is_active = 1 AND hgo.objecttype_id = 3',
+ array()
+ );
+ }
+
+ /**
+ * Join hosts
+ */
+ protected function joinHosts()
+ {
+ $this->select->join(
+ array('h' => $this->prefix . 'hosts'),
+ 'h.host_object_id = ho.object_id',
+ array()
+ );
+ }
+
+ /**
+ * Join instances
+ */
+ protected function joinInstances()
+ {
+ $this->select->join(
+ array('i' => $this->prefix . 'instances'),
+ 'i.instance_id = hdh.instance_id',
+ array()
+ );
+ }
+
+ /**
+ * Join service groups
+ */
+ protected function joinServicegroups()
+ {
+ $this->requireVirtualTable('services');
+ $this->select->joinLeft(
+ array('sgm' => $this->prefix . 'servicegroup_members'),
+ 'sgm.service_object_id = s.service_object_id',
+ array()
+ )->joinLeft(
+ array('sg' => $this->prefix . 'servicegroups'),
+ 'sg.' . $this->servicegroup_id . ' = sgm.servicegroup_id',
+ array()
+ )->joinLeft(
+ array('sgo' => $this->prefix . 'objects'),
+ 'sgo.object_id = sg.servicegroup_object_id AND sgo.is_active = 1 AND sgo.objecttype_id = 4',
+ array()
+ );
+ }
+
+ /**
+ * Join services
+ */
+ protected function joinServices()
+ {
+ $this->select->joinLeft(
+ array('s' => $this->prefix . 'services'),
+ 's.host_object_id = ho.object_id',
+ array()
+ )->joinLeft(
+ array('so' => $this->prefix . 'objects'),
+ 'so.object_id = s.service_object_id AND so.is_active = 1 AND so.objecttype_id = 2',
+ array()
+ );
+ }
+
+ protected function joinSubQuery(IdoQuery $query, $name, $filter, $and, $negate, &$additionalFilter)
+ {
+ if ($name === 'hostgroup') {
+ $query->joinVirtualTable('members');
+
+ return ['hgm.host_object_id', 'ho.object_id'];
+ } elseif ($name === 'servicegroup') {
+ $query->joinVirtualTable('services');
+
+ return ['s.host_object_id', 'ho.object_id'];
+ }
+
+ return parent::joinSubQuery($query, $name, $filter, $and, $negate, $additionalFilter);
+ }
+}
diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/HostflappingendhistoryQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/HostflappingendhistoryQuery.php
new file mode 100644
index 0000000..ebc346b
--- /dev/null
+++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/HostflappingendhistoryQuery.php
@@ -0,0 +1,31 @@
+<?php
+/* Icinga Web 2 | (c) 2016 Icinga Development Team | GPLv2+ */
+
+namespace Icinga\Module\Monitoring\Backend\Ido\Query;
+
+/**
+ * Query for host flapping end history records
+ */
+class HostflappingendhistoryQuery extends HostflappingstarthistoryQuery
+{
+ /**
+ * {@inheritdoc}
+ */
+ protected function joinBaseTables()
+ {
+ $this->select->from(
+ array('hfh' => $this->prefix . 'flappinghistory'),
+ array()
+ )->join(
+ array('ho' => $this->prefix . 'objects'),
+ 'ho.object_id = hfh.object_id AND ho.is_active = 1 AND ho.objecttype_id = 1',
+ array()
+ );
+
+ $this->select->where('hfh.event_type = 1001');
+
+ $this->joinedVirtualTables['flappinghistory'] = true;
+
+ $this->columnMap['flappinghistory']['type'] = '(\'flapping_deleted\')';
+ }
+}
diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/HostflappingstarthistoryQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/HostflappingstarthistoryQuery.php
new file mode 100644
index 0000000..497a493
--- /dev/null
+++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/HostflappingstarthistoryQuery.php
@@ -0,0 +1,200 @@
+<?php
+/* Icinga Web 2 | (c) 2016 Icinga Development Team | GPLv2+ */
+
+namespace Icinga\Module\Monitoring\Backend\Ido\Query;
+
+use Icinga\Data\Filter\Filter;
+use Icinga\Data\Filter\FilterExpression;
+
+/**
+ * Query for host flapping start history records
+ */
+class HostflappingstarthistoryQuery extends IdoQuery
+{
+ /**
+ * {@inheritdoc}
+ */
+ protected $allowCustomVars = true;
+
+ /**
+ * {@inheritdoc}
+ */
+ protected $groupBase = array('flappinghistory' => array('hfh.flappinghistory_id', 'ho.object_id'));
+
+ /**
+ * {@inheritdoc}
+ */
+ protected $groupOrigin = array('hostgroups', 'services');
+
+ protected $subQueryTargets = array(
+ 'hostgroups' => 'hostgroup',
+ 'servicegroups' => 'servicegroup'
+ );
+
+ /**
+ * {@inheritdoc}
+ */
+ protected $columnMap = array(
+ 'flappinghistory' => array(
+ 'id' => 'hfh.flappinghistory_id',
+ 'host' => 'ho.name1 COLLATE latin1_general_ci',
+ 'host_name' => 'ho.name1',
+ 'object_id' => 'hfh.object_id',
+ 'object_type' => '(\'host\')',
+ 'output' => '(hfh.percent_state_change || \'\')',
+ 'state' => '(-1)',
+ 'timestamp' => 'UNIX_TIMESTAMP(hfh.event_time)',
+ 'type' => '(\'flapping\')'
+ ),
+ 'hostgroups' => array(
+ 'hostgroup' => 'hgo.name1 COLLATE latin1_general_ci',
+ 'hostgroup_alias' => 'hg.alias COLLATE latin1_general_ci',
+ 'hostgroup_name' => 'hgo.name1'
+ ),
+ 'hosts' => array(
+ 'host_alias' => 'h.alias',
+ 'host_display_name' => 'h.display_name COLLATE latin1_general_ci'
+ ),
+ 'instances' => array(
+ 'instance_name' => 'i.instance_name'
+ ),
+ 'servicegroups' => array(
+ 'servicegroup_name' => 'sgo.name1',
+ 'servicegroup' => 'sgo.name1 COLLATE latin1_general_ci',
+ 'servicegroup_alias' => 'sg.alias COLLATE latin1_general_ci'
+ ),
+ 'services' => array(
+ 'service' => 'so.name2 COLLATE latin1_general_ci',
+ 'service_description' => 'so.name2',
+ 'service_display_name' => 's.display_name COLLATE latin1_general_ci',
+ 'service_host_name' => 'so.name1'
+ )
+ );
+
+ protected function requireFilterColumns(Filter $filter)
+ {
+ if ($filter instanceof FilterExpression && $filter->getColumn() === 'timestamp') {
+ $this->requireColumn('timestamp');
+ $filter->setColumn('hfh.event_time');
+ $filter->setExpression($this->timestampForSql($this->valueToTimestamp($filter->getExpression())));
+ return null;
+ }
+
+ return parent::requireFilterColumns($filter);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function joinBaseTables()
+ {
+ $this->select->from(
+ array('hfh' => $this->prefix . 'flappinghistory'),
+ array()
+ )->join(
+ array('ho' => $this->prefix . 'objects'),
+ 'ho.object_id = hfh.object_id AND ho.is_active = 1 AND ho.objecttype_id = 1',
+ array()
+ );
+
+ $this->select->where('hfh.event_type = 1000');
+
+ $this->joinedVirtualTables['flappinghistory'] = true;
+ }
+
+ /**
+ * Join host groups
+ */
+ protected function joinHostgroups()
+ {
+ $this->select->joinLeft(
+ array('hgm' => $this->prefix . 'hostgroup_members'),
+ 'hgm.host_object_id = ho.object_id',
+ array()
+ )->joinLeft(
+ array('hg' => $this->prefix . 'hostgroups'),
+ 'hg.hostgroup_id = hgm.hostgroup_id',
+ array()
+ )->joinLeft(
+ array('hgo' => $this->prefix . 'objects'),
+ 'hgo.object_id = hg.hostgroup_object_id AND hgo.is_active = 1 AND hgo.objecttype_id = 3',
+ array()
+ );
+ }
+
+ /**
+ * Join hosts
+ */
+ protected function joinHosts()
+ {
+ $this->select->join(
+ array('h' => $this->prefix . 'hosts'),
+ 'h.host_object_id = ho.object_id',
+ array()
+ );
+ }
+
+ /**
+ * Join instances
+ */
+ protected function joinInstances()
+ {
+ $this->select->join(
+ array('i' => $this->prefix . 'instances'),
+ 'i.instance_id = hfh.instance_id',
+ array()
+ );
+ }
+
+ /**
+ * Join service groups
+ */
+ protected function joinServicegroups()
+ {
+ $this->requireVirtualTable('services');
+ $this->select->joinLeft(
+ array('sgm' => $this->prefix . 'servicegroup_members'),
+ 'sgm.service_object_id = s.service_object_id',
+ array()
+ )->joinLeft(
+ array('sg' => $this->prefix . 'servicegroups'),
+ 'sg.' . $this->servicegroup_id . ' = sgm.servicegroup_id',
+ array()
+ )->joinLeft(
+ array('sgo' => $this->prefix . 'objects'),
+ 'sgo.object_id = sg.servicegroup_object_id AND sgo.is_active = 1 AND sgo.objecttype_id = 4',
+ array()
+ );
+ }
+
+ /**
+ * Join services
+ */
+ protected function joinServices()
+ {
+ $this->select->joinLeft(
+ array('s' => $this->prefix . 'services'),
+ 's.host_object_id = ho.object_id',
+ array()
+ )->joinLeft(
+ array('so' => $this->prefix . 'objects'),
+ 'so.object_id = s.service_object_id AND so.is_active = 1 AND so.objecttype_id = 2',
+ array()
+ );
+ }
+
+ protected function joinSubQuery(IdoQuery $query, $name, $filter, $and, $negate, &$additionalFilter)
+ {
+ if ($name === 'hostgroup') {
+ $query->joinVirtualTable('members');
+
+ return ['hgm.host_object_id', 'ho.object_id'];
+ } elseif ($name === 'servicegroup') {
+ $query->joinVirtualTable('services');
+
+ return ['s.host_object_id', 'ho.object_id'];
+ }
+
+ return parent::joinSubQuery($query, $name, $filter, $and, $negate, $additionalFilter);
+ }
+}
diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/HostgroupQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/HostgroupQuery.php
new file mode 100644
index 0000000..463fba9
--- /dev/null
+++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/HostgroupQuery.php
@@ -0,0 +1,295 @@
+<?php
+/* Icinga Web 2 | (c) 2013 Icinga Development Team | GPLv2+ */
+
+namespace Icinga\Module\Monitoring\Backend\Ido\Query;
+
+/**
+ * Query for host groups
+ */
+class HostgroupQuery extends IdoQuery
+{
+ protected $allowCustomVars = true;
+
+ protected $groupBase = array(
+ 'hostgroups' => array('hgo.object_id', 'hg.hostgroup_id'),
+ 'hoststatus' => array('hs.hoststatus_id'),
+ 'servicestatus' => array('ss.servicestatus_id')
+ );
+
+ protected $groupOrigin = array('members');
+
+ protected $subQueryTargets = array(
+ 'hostgroups' => 'hostgroup',
+ 'servicegroups' => 'servicegroup'
+ );
+
+ protected $columnMap = array(
+ 'contacts' => [
+ 'host_contact' => 'hco.name1'
+ ],
+ 'contactgroups' => [
+ 'host_contactgroup' => 'hcgo.name1'
+ ],
+ 'hostgroups' => array(
+ 'hostgroup' => 'hgo.name1 COLLATE latin1_general_ci',
+ 'hostgroup_alias' => 'hg.alias COLLATE latin1_general_ci',
+ 'hostgroup_name' => 'hgo.name1'
+ ),
+ 'hoststatus' => array(
+ 'host_handled' => 'CASE WHEN (hs.problem_has_been_acknowledged + hs.scheduled_downtime_depth) > 0 THEN 1 ELSE 0 END',
+ 'host_severity' => '
+ CASE
+ WHEN hs.has_been_checked = 0 OR hs.has_been_checked IS NULL
+ THEN 16
+ ELSE
+ CASE
+ WHEN hs.current_state = 0
+ THEN 1
+ ELSE
+ CASE
+ WHEN hs.current_state = 1 THEN 64
+ WHEN hs.current_state = 2 THEN 32
+ ELSE 256
+ END
+ +
+ CASE
+ WHEN hs.problem_has_been_acknowledged = 1 THEN 2
+ WHEN hs.scheduled_downtime_depth > 0 THEN 1
+ ELSE 256
+ END
+ END
+ END',
+ 'host_state' => 'CASE WHEN hs.has_been_checked = 0 OR hs.has_been_checked IS NULL THEN 99 ELSE hs.current_state END'
+ ),
+ 'instances' => array(
+ 'instance_name' => 'i.instance_name'
+ ),
+ 'members' => array(
+ 'host_name' => 'ho.name1'
+ ),
+ 'servicegroups' => array(
+ 'servicegroup_name' => 'sgo.name1'
+ ),
+ 'services' => array(
+ 'service_description' => 'so.name2'
+ ),
+ 'servicestatus' => array(
+ 'service_handled' => 'CASE WHEN (ss.problem_has_been_acknowledged + ss.scheduled_downtime_depth + COALESCE(hs.current_state, 0)) > 0 THEN 1 ELSE 0 END',
+ 'service_severity' => '
+ CASE WHEN ss.current_state = 0
+ THEN
+ CASE WHEN ss.has_been_checked = 0 OR ss.has_been_checked IS NULL
+ THEN 16
+ ELSE 0
+ END
+ +
+ CASE WHEN ss.problem_has_been_acknowledged = 1
+ THEN 2
+ ELSE
+ CASE WHEN ss.scheduled_downtime_depth > 0
+ THEN 1
+ ELSE 4
+ END
+ END
+ ELSE
+ CASE WHEN ss.has_been_checked = 0 OR ss.has_been_checked IS NULL THEN 16
+ WHEN ss.current_state = 1 THEN 32
+ WHEN ss.current_state = 2 THEN 128
+ WHEN ss.current_state = 3 THEN 64
+ ELSE 256
+ END
+ +
+ CASE WHEN hs.current_state > 0
+ THEN 1024
+ ELSE
+ CASE WHEN ss.problem_has_been_acknowledged = 1
+ THEN 512
+ ELSE
+ CASE WHEN ss.scheduled_downtime_depth > 0
+ THEN 256
+ ELSE 2048
+ END
+ END
+ END
+ END',
+ 'service_state' => 'CASE WHEN ss.has_been_checked = 0 OR ss.has_been_checked IS NULL THEN 99 ELSE ss.current_state END'
+ )
+ );
+
+ protected function joinBaseTables()
+ {
+ $this->select->from(
+ array('hgo' => $this->prefix . 'objects'),
+ array()
+ )->join(
+ array('hg' => $this->prefix . 'hostgroups'),
+ 'hg.hostgroup_object_id = hgo.object_id AND hgo.is_active = 1 AND hgo.objecttype_id = 3',
+ array()
+ );
+ $this->joinedVirtualTables['hostgroups'] = true;
+ }
+
+ /**
+ * Join contacts
+ */
+ protected function joinContacts()
+ {
+ $this->requireVirtualTable('hosts');
+
+ $this->select->joinLeft(
+ ['hc' => 'icinga_host_contacts'],
+ 'hc.host_id = h.host_id',
+ []
+ )->joinLeft(
+ ['hco' => 'icinga_objects'],
+ 'hco.object_id = hc.contact_object_id AND hco.is_active = 1 AND hco.objecttype_id = 10',
+ []
+ );
+ }
+
+ /**
+ * Join contact groups
+ */
+ protected function joinContactgroups()
+ {
+ $this->requireVirtualTable('hosts');
+
+ $this->select->joinLeft(
+ ['hcg' => 'icinga_host_contactgroups'],
+ 'hcg.host_id = h.host_id',
+ []
+ )->joinLeft(
+ ['hcgo' => 'icinga_objects'],
+ 'hcgo.object_id = hcg.contactgroup_object_id AND hcgo.is_active = 1 AND hcgo.objecttype_id = 11',
+ []
+ );
+ }
+
+ /**
+ * Join hosts
+ */
+ protected function joinHosts()
+ {
+ $this->requireVirtualTable('members');
+ $this->select->join(
+ array('h' => $this->prefix . 'hosts'),
+ 'h.host_object_id = ho.object_id',
+ array()
+ );
+ }
+
+ /**
+ * Join host status
+ */
+ protected function joinHoststatus()
+ {
+ $this->requireVirtualTable('members');
+ $this->select->join(
+ array('hs' => $this->prefix . 'hoststatus'),
+ 'hs.host_object_id = ho.object_id',
+ array()
+ );
+ }
+
+ /**
+ * Join instances
+ */
+ protected function joinInstances()
+ {
+ $this->select->join(
+ array('i' => $this->prefix . 'instances'),
+ 'i.instance_id = hg.instance_id',
+ array()
+ );
+ }
+
+ /**
+ * Join members
+ */
+ protected function joinMembers()
+ {
+ $this->select->join(
+ array('hgm' => $this->prefix . 'hostgroup_members'),
+ 'hgm.hostgroup_id = hg.hostgroup_id',
+ array()
+ )->join(
+ array('ho' => $this->prefix . 'objects'),
+ 'hgm.host_object_id = ho.object_id AND ho.is_active = 1 AND ho.objecttype_id = 1',
+ array()
+ );
+ }
+
+ /**
+ * Join service groups
+ */
+ protected function joinServicegroups()
+ {
+ $this->requireVirtualTable('services');
+ $this->select->joinLeft(
+ array('sgm' => $this->prefix . 'servicegroup_members'),
+ 'sgm.service_object_id = s.service_object_id',
+ array()
+ )->joinLeft(
+ array('sg' => $this->prefix . 'servicegroups'),
+ 'sgm.servicegroup_id = sg.servicegroup_id',
+ array()
+ )->joinLeft(
+ array('sgo' => $this->prefix . 'objects'),
+ 'sgo.object_id = sg.servicegroup_object_id AND sgo.is_active = 1 AND sgo.objecttype_id = 4',
+ array()
+ );
+ }
+
+ /**
+ * Join services
+ */
+ protected function joinServices()
+ {
+ $this->requireVirtualTable('hosts');
+ $this->select->joinLeft(
+ array('s' => $this->prefix . 'services'),
+ 's.host_object_id = h.host_object_id',
+ array()
+ )->joinLeft(
+ array('so' => $this->prefix . 'objects'),
+ 'so.object_id = s.service_object_id AND so.is_active = 1 AND so.objecttype_id = 2',
+ array()
+ );
+ }
+
+ /**
+ * Join service status
+ */
+ protected function joinServicestatus()
+ {
+ $this->requireVirtualTable('services');
+ $this->requireVirtualTable('hoststatus');
+ $this->select->join(
+ array('ss' => $this->prefix . 'servicestatus'),
+ 'ss.service_object_id = so.object_id',
+ array()
+ );
+ }
+
+ protected function joinSubQuery(IdoQuery $query, $name, $filter, $and, $negate, &$additionalFilter)
+ {
+ if ($name === 'hostgroup') {
+ // Propagate that the "parent" query has to be filtered as well
+ $additionalFilter = clone $filter;
+
+ $this->requireVirtualTable('members');
+
+ $query->joinVirtualTable('members');
+
+ return ['hgm.host_object_id', 'ho.object_id'];
+ } elseif ($name === 'servicegroup') {
+ $this->requireVirtualTable('members');
+
+ $query->joinVirtualTable('services');
+
+ return ['s.host_object_id', 'ho.object_id'];
+ }
+
+ return parent::joinSubQuery($query, $name, $filter, $and, $negate, $additionalFilter);
+ }
+}
diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/HostgroupsummaryQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/HostgroupsummaryQuery.php
new file mode 100644
index 0000000..a1b7182
--- /dev/null
+++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/HostgroupsummaryQuery.php
@@ -0,0 +1,142 @@
+<?php
+/* Icinga Web 2 | (c) 2015 Icinga Development Team | GPLv2+ */
+
+namespace Icinga\Module\Monitoring\Backend\Ido\Query;
+
+use Zend_Db_Expr;
+use Zend_Db_Select;
+
+use Icinga\Data\Filter\Filter;
+
+/**
+ * Query for host group summary
+ */
+class HostgroupsummaryQuery extends IdoQuery
+{
+ protected $allowCustomVars = true;
+
+ protected $columnMap = array(
+ 'hostgroupsummary' => array(
+ 'hostgroup_alias' => 'hostgroup_alias',
+ 'hostgroup_name' => 'hostgroup_name',
+ 'hosts_down' => 'SUM(CASE WHEN host_state = 1 THEN 1 ELSE 0 END)',
+ 'hosts_down_handled' => 'SUM(CASE WHEN host_state = 1 AND host_handled = 1 THEN 1 ELSE 0 END)',
+ 'hosts_down_unhandled' => 'SUM(CASE WHEN host_state = 1 AND host_handled = 0 THEN 1 ELSE 0 END)',
+ 'hosts_pending' => 'SUM(CASE WHEN host_state = 99 THEN 1 ELSE 0 END)',
+ 'hosts_severity' => 'MAX(host_severity)',
+ 'hosts_total' => 'SUM(CASE WHEN host_state IS NOT NULL THEN 1 ELSE 0 END)',
+ 'hosts_unreachable' => 'SUM(CASE WHEN host_state = 2 THEN 1 ELSE 0 END)',
+ 'hosts_unreachable_handled' => 'SUM(CASE WHEN host_state = 2 AND host_handled = 1 THEN 1 ELSE 0 END)',
+ 'hosts_unreachable_unhandled' => 'SUM(CASE WHEN host_state = 2 AND host_handled = 0 THEN 1 ELSE 0 END)',
+ 'hosts_up' => 'SUM(CASE WHEN host_state = 0 THEN 1 ELSE 0 END)',
+ 'services_critical' => 'SUM(CASE WHEN service_state = 2 THEN 1 ELSE 0 END)',
+ 'services_critical_handled' => 'SUM(CASE WHEN service_state = 2 AND service_handled = 1 THEN 1 ELSE 0 END)',
+ 'services_critical_unhandled' => 'SUM(CASE WHEN service_state = 2 AND service_handled = 0 THEN 1 ELSE 0 END)',
+ 'services_ok' => 'SUM(CASE WHEN service_state = 0 THEN 1 ELSE 0 END)',
+ 'services_pending' => 'SUM(CASE WHEN service_state = 99 THEN 1 ELSE 0 END)',
+ 'services_total' => 'SUM(CASE WHEN service_state IS NOT NULL THEN 1 ELSE 0 END)',
+ 'services_unknown' => 'SUM(CASE WHEN service_state = 3 THEN 1 ELSE 0 END)',
+ 'services_unknown_handled' => 'SUM(CASE WHEN service_state = 3 AND service_handled = 1 THEN 1 ELSE 0 END)',
+ 'services_unknown_unhandled' => 'SUM(CASE WHEN service_state = 3 AND service_handled = 0 THEN 1 ELSE 0 END)',
+ 'services_warning' => 'SUM(CASE WHEN service_state = 1 THEN 1 ELSE 0 END)',
+ 'services_warning_handled' => 'SUM(CASE WHEN service_state = 1 AND service_handled = 1 THEN 1 ELSE 0 END)',
+ 'services_warning_unhandled' => 'SUM(CASE WHEN service_state = 1 AND service_handled = 0 THEN 1 ELSE 0 END)',
+ )
+ );
+
+ /**
+ * The union
+ *
+ * @var Zend_Db_Select
+ */
+ protected $summaryQuery;
+
+ /**
+ * Subqueries used for the summary query
+ *
+ * @var IdoQuery[]
+ */
+ protected $subQueries = array();
+
+ /**
+ * Count query
+ *
+ * @var IdoQuery
+ */
+ protected $countQuery;
+
+ public function addFilter(Filter $filter)
+ {
+ foreach ($this->subQueries as $sub) {
+ $sub->applyFilter(clone $filter);
+ }
+ $this->countQuery->applyFilter(clone $filter);
+ return $this;
+ }
+
+ protected function joinBaseTables()
+ {
+ $this->countQuery = $this->createSubQuery(
+ 'Hostgroup',
+ array()
+ );
+ $hosts = $this->createSubQuery(
+ 'Hostgroup',
+ array(
+ 'hostgroup_alias',
+ 'hostgroup_name',
+ 'host_handled',
+ 'host_severity',
+ 'host_state',
+ 'service_handled' => new Zend_Db_Expr('NULL'),
+ 'service_severity' => new Zend_Db_Expr('0'),
+ 'service_state' => new Zend_Db_Expr('NULL'),
+ )
+ );
+ $this->subQueries[] = $hosts;
+ $services = $this->createSubQuery(
+ 'Hostgroup',
+ array(
+ 'hostgroup_alias',
+ 'hostgroup_name',
+ 'host_handled' => new Zend_Db_Expr('NULL'),
+ 'host_severity' => new Zend_Db_Expr('0'),
+ 'host_state' => new Zend_Db_Expr('NULL'),
+ 'service_handled',
+ 'service_severity',
+ 'service_state'
+ )
+ );
+ $this->subQueries[] = $services;
+ $emptyGroups = $this->createSubQuery(
+ 'Emptyhostgroup',
+ [
+ 'hostgroup_alias',
+ 'hostgroup_name',
+ 'host_handled' => new Zend_Db_Expr('NULL'),
+ 'host_severity' => new Zend_Db_Expr('0'),
+ 'host_state' => new Zend_Db_Expr('NULL'),
+ 'service_handled' => new Zend_Db_Expr('NULL'),
+ 'service_severity' => new Zend_Db_Expr('0'),
+ 'service_state' => new Zend_Db_Expr('NULL'),
+ ]
+ );
+ $this->subQueries[] = $emptyGroups;
+ $this->summaryQuery = $this->db->select()->union(
+ [$hosts, $services, $emptyGroups],
+ Zend_Db_Select::SQL_UNION_ALL
+ );
+ $this->select->from(array('hostgroupsummary' => $this->summaryQuery), array());
+ $this->group(array('hostgroup_name', 'hostgroup_alias'));
+ $this->joinedVirtualTables['hostgroupsummary'] = true;
+ }
+
+ public function getCountQuery()
+ {
+ $count = $this->countQuery->select();
+ $this->countQuery->applyFilterSql($count);
+ $count->columns(array('hgo.object_id'));
+ $count->group(array('hgo.object_id'));
+ return $this->db->select()->from($count, array('cnt' => 'COUNT(*)'));
+ }
+}
diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/HostnotificationQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/HostnotificationQuery.php
new file mode 100644
index 0000000..284468e
--- /dev/null
+++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/HostnotificationQuery.php
@@ -0,0 +1,283 @@
+<?php
+/* Icinga Web 2 | (c) 2015 Icinga Development Team | GPLv2+ */
+
+namespace Icinga\Module\Monitoring\Backend\Ido\Query;
+
+use Icinga\Data\Filter\Filter;
+use Icinga\Data\Filter\FilterExpression;
+
+/**
+ * Query for host notifications
+ */
+class HostnotificationQuery extends IdoQuery
+{
+ /**
+ * {@inheritdoc}
+ */
+ protected $allowCustomVars = true;
+
+ protected $subQueryTargets = array(
+ 'hostgroups' => 'hostgroup',
+ 'servicegroups' => 'servicegroup'
+ );
+
+ /**
+ * {@inheritdoc}
+ */
+ protected $columnMap = array(
+ 'contactnotifications' => array(
+ 'notification_contact_name' => 'co.name1'
+ ),
+ 'hostgroups' => array(
+ 'hostgroup' => 'hgo.name1 COLLATE latin1_general_ci',
+ 'hostgroup_alias' => 'hg.alias COLLATE latin1_general_ci',
+ 'hostgroup_name' => 'hgo.name1'
+ ),
+ 'hosts' => array(
+ 'host_display_name' => 'h.display_name COLLATE latin1_general_ci',
+ 'host_alias' => 'h.alias COLLATE latin1_general_ci',
+ ),
+ 'history' => array(
+ 'output' => null,
+ 'state' => 'hn.state',
+ 'timestamp' => 'UNIX_TIMESTAMP(hn.start_time)',
+ 'type' => '
+ CASE hn.notification_reason
+ WHEN 1 THEN \'notification_ack\'
+ WHEN 2 THEN \'notification_flapping\'
+ WHEN 3 THEN \'notification_flapping_end\'
+ WHEN 5 THEN \'notification_dt_start\'
+ WHEN 6 THEN \'notification_dt_end\'
+ WHEN 7 THEN \'notification_dt_end\'
+ WHEN 8 THEN \'notification_custom\'
+ ELSE \'notification_state\'
+ END',
+ ),
+ 'instances' => array(
+ 'instance_name' => 'i.instance_name'
+ ),
+ 'notifications' => array(
+ 'id' => 'hn.notification_id',
+ 'host' => 'ho.name1 COLLATE latin1_general_ci',
+ 'host_name' => 'ho.name1',
+ 'notification_output' => 'hn.output',
+ 'notification_reason' => 'hn.notification_reason',
+ 'notification_state' => 'hn.state',
+ 'notification_timestamp' => 'UNIX_TIMESTAMP(hn.start_time)',
+ 'object_type' => '(\'host\')'
+ ),
+ 'servicegroups' => array(
+ 'servicegroup_name' => 'sgo.name1',
+ 'servicegroup' => 'sgo.name1 COLLATE latin1_general_ci',
+ 'servicegroup_alias' => 'sg.alias COLLATE latin1_general_ci'
+ ),
+ 'services' => array(
+ 'service' => 'so.name2 COLLATE latin1_general_ci',
+ 'service_description' => 'so.name2',
+ 'service_display_name' => 's.display_name COLLATE latin1_general_ci',
+ 'service_host_name' => 'so.name1'
+ )
+ );
+
+ protected function requireFilterColumns(Filter $filter)
+ {
+ if ($filter instanceof FilterExpression) {
+ switch ($filter->getColumn()) {
+ case 'output':
+ $this->requireColumn('output');
+ $filter->setColumn('hn.output');
+ return null;
+ case 'timestamp':
+ case 'notification_timestamp':
+ $this->requireColumn($filter->getColumn());
+ $filter->setColumn('hn.start_time');
+ $filter->setExpression($this->timestampForSql($this->valueToTimestamp($filter->getExpression())));
+ return null;
+ }
+ }
+
+ return parent::requireFilterColumns($filter);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function joinBaseTables()
+ {
+ switch ($this->ds->getDbType()) {
+ case 'mysql':
+ $concattedContacts = "GROUP_CONCAT("
+ . "DISTINCT co.name1 ORDER BY co.name1 SEPARATOR ', '"
+ . ") COLLATE latin1_general_ci";
+ break;
+ case 'pgsql':
+ // TODO: Find a way to order the contact alias list:
+ $concattedContacts = "ARRAY_TO_STRING(ARRAY_AGG(DISTINCT co.name1), ', ')";
+ break;
+ }
+ $this->columnMap['history']['output'] = "('[' || $concattedContacts || '] ' || hn.output)";
+
+ $this->select->from(
+ array('hn' => $this->prefix . 'notifications'),
+ array()
+ )->join(
+ array('ho' => $this->prefix . 'objects'),
+ 'ho.object_id = hn.object_id AND ho.is_active = 1 AND ho.objecttype_id = 1',
+ array()
+ );
+ $this->joinedVirtualTables['notifications'] = true;
+ }
+
+ /**
+ * Join virtual table history
+ */
+ protected function joinHistory()
+ {
+ $this->requireVirtualTable('contactnotifications');
+ }
+
+ /**
+ * Join contact notifications
+ */
+ protected function joinContactnotifications()
+ {
+ $this->select->joinLeft(
+ array('cn' => $this->prefix . 'contactnotifications'),
+ 'cn.notification_id = hn.notification_id',
+ array()
+ );
+ $this->select->joinLeft(
+ array('co' => $this->prefix . 'objects'),
+ 'co.object_id = cn.contact_object_id AND co.is_active = 1 AND co.objecttype_id = 10',
+ array()
+ );
+ }
+
+ /**
+ * Join host groups
+ */
+ protected function joinHostgroups()
+ {
+ $this->select->joinLeft(
+ array('hgm' => $this->prefix . 'hostgroup_members'),
+ 'hgm.host_object_id = ho.object_id',
+ array()
+ )->joinLeft(
+ array('hg' => $this->prefix . 'hostgroups'),
+ 'hg.hostgroup_id = hgm.hostgroup_id',
+ array()
+ )->joinLeft(
+ array('hgo' => $this->prefix . 'objects'),
+ 'hgo.object_id = hg.hostgroup_object_id AND hgo.is_active = 1 AND hgo.objecttype_id = 3',
+ array()
+ );
+ }
+
+ /**
+ * Join hosts
+ */
+ protected function joinHosts()
+ {
+ $this->select->join(
+ array('h' => $this->prefix . 'hosts'),
+ 'h.host_object_id = ho.object_id',
+ array()
+ );
+ }
+
+ /**
+ * Join service groups
+ */
+ protected function joinServicegroups()
+ {
+ $this->requireVirtualTable('services');
+ $this->select->joinLeft(
+ array('sgm' => $this->prefix . 'servicegroup_members'),
+ 'sgm.service_object_id = s.service_object_id',
+ array()
+ )->joinLeft(
+ array('sg' => $this->prefix . 'servicegroups'),
+ 'sg.' . $this->servicegroup_id . ' = sgm.servicegroup_id',
+ array()
+ )->joinLeft(
+ array('sgo' => $this->prefix . 'objects'),
+ 'sgo.object_id = sg.servicegroup_object_id AND sgo.is_active = 1 AND sgo.objecttype_id = 4',
+ array()
+ );
+ }
+
+ /**
+ * Join services
+ */
+ protected function joinServices()
+ {
+ $this->select->joinLeft(
+ array('s' => $this->prefix . 'services'),
+ 's.host_object_id = ho.object_id',
+ array()
+ )->joinLeft(
+ array('so' => $this->prefix . 'objects'),
+ 'so.object_id = s.service_object_id AND so.is_active = 1 AND so.objecttype_id = 2',
+ array()
+ );
+ }
+
+ /**
+ * Join instances
+ */
+ protected function joinInstances()
+ {
+ $this->select->join(
+ array('i' => $this->prefix . 'instances'),
+ 'i.instance_id = hn.instance_id',
+ array()
+ );
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getGroup()
+ {
+ $group = array();
+
+ if ($this->hasJoinedVirtualTable('history')
+ || $this->hasJoinedVirtualTable('services')
+ || $this->hasJoinedVirtualTable('hostgroups')
+ ) {
+ $group = array('hn.notification_id', 'ho.object_id');
+ if ($this->hasJoinedVirtualTable('contactnotifications') && !$this->hasJoinedVirtualTable('history')) {
+ $group[] = 'co.object_id';
+ }
+ } elseif ($this->hasJoinedVirtualTable('contactnotifications')) {
+ $group = array('hn.notification_id', 'co.object_id', 'ho.object_id');
+ }
+
+ if (! empty($group)) {
+ if ($this->hasJoinedVirtualTable('hosts')) {
+ $group[] = 'h.host_id';
+ }
+
+ if ($this->hasJoinedVirtualTable('instances')) {
+ $group[] = 'i.instance_id';
+ }
+ }
+
+ return $group;
+ }
+
+ protected function joinSubQuery(IdoQuery $query, $name, $filter, $and, $negate, &$additionalFilter)
+ {
+ if ($name === 'hostgroup') {
+ $query->joinVirtualTable('members');
+
+ return ['hgm.host_object_id', 'ho.object_id'];
+ } elseif ($name === 'servicegroup') {
+ $query->joinVirtualTable('services');
+
+ return ['s.host_object_id', 'ho.object_id'];
+ }
+
+ return parent::joinSubQuery($query, $name, $filter, $and, $negate, $additionalFilter);
+ }
+}
diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/HoststatehistoryQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/HoststatehistoryQuery.php
new file mode 100644
index 0000000..ac85c1f
--- /dev/null
+++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/HoststatehistoryQuery.php
@@ -0,0 +1,222 @@
+<?php
+/* Icinga Web 2 | (c) 2015 Icinga Development Team | GPLv2+ */
+
+namespace Icinga\Module\Monitoring\Backend\Ido\Query;
+
+use Icinga\Data\Filter\Filter;
+use Icinga\Data\Filter\FilterExpression;
+
+/**
+ * Query for host state history records
+ */
+class HoststatehistoryQuery extends IdoQuery
+{
+ /**
+ * {@inheritdoc}
+ */
+ protected $allowCustomVars = true;
+
+ /**
+ * {@inheritdoc}
+ */
+ protected $groupBase = array('statehistory' => array('hh.statehistory_id', 'ho.object_id'));
+
+ /**
+ * {@inheritdoc}
+ */
+ protected $groupOrigin = array('hostgroups', 'services');
+
+ /**
+ * Array to map type names to type ids for query optimization
+ *
+ * @var array
+ */
+ protected $types = array(
+ 'soft_state' => 0,
+ 'hard_state' => 1
+ );
+
+ protected $subQueryTargets = array(
+ 'hostgroups' => 'hostgroup',
+ 'servicegroups' => 'servicegroup'
+ );
+
+ /**
+ * {@inheritdoc}
+ */
+ protected $columnMap = array(
+ 'hostgroups' => array(
+ 'hostgroup' => 'hgo.name1 COLLATE latin1_general_ci',
+ 'hostgroup_alias' => 'hg.alias COLLATE latin1_general_ci',
+ 'hostgroup_name' => 'hgo.name1'
+ ),
+ 'hosts' => array(
+ 'host_alias' => 'h.alias',
+ 'host_display_name' => 'h.display_name COLLATE latin1_general_ci'
+ ),
+ 'instances' => array(
+ 'instance_name' => 'i.instance_name'
+ ),
+ 'servicegroups' => array(
+ 'servicegroup' => 'sgo.name1 COLLATE latin1_general_ci',
+ 'servicegroup_name' => 'sgo.name1',
+ 'servicegroup_alias' => 'sg.alias COLLATE latin1_general_ci'
+ ),
+ 'services' => array(
+ 'service' => 'so.name2 COLLATE latin1_general_ci',
+ 'service_description' => 'so.name2',
+ 'service_display_name' => 's.display_name COLLATE latin1_general_ci',
+ 'service_host_name' => 'so.name1'
+ ),
+ 'statehistory' => array(
+ 'id' => 'hh.statehistory_id',
+ 'host' => 'ho.name1 COLLATE latin1_general_ci',
+ 'host_name' => 'ho.name1',
+ 'object_id' => 'hh.object_id',
+ 'object_type' => '(\'host\')',
+ 'output' => '(CASE WHEN hh.state_type = 1 THEN hh.output ELSE \'[ \' || hh.current_check_attempt || \'/\' || hh.max_check_attempts || \' ] \' || hh.output END)',
+ 'state' => 'hh.state',
+ 'timestamp' => 'UNIX_TIMESTAMP(hh.state_time)',
+ 'type' => "(CASE WHEN hh.state_type = 1 THEN 'hard_state' ELSE 'soft_state' END)"
+ ),
+ );
+
+ protected function requireFilterColumns(Filter $filter)
+ {
+ if ($filter instanceof FilterExpression) {
+ switch ($filter->getColumn()) {
+ case 'timestamp':
+ $this->requireColumn('timestamp');
+ $filter->setColumn('hh.state_time');
+ $filter->setExpression($this->timestampForSql($this->valueToTimestamp($filter->getExpression())));
+ return null;
+ case 'type':
+ if (! is_array($filter->getExpression())) {
+ $this->requireColumn('type');
+ $filter->setColumn('hh.state_type');
+ if (isset($this->types[$filter->getExpression()])) {
+ $filter->setExpression($this->types[$filter->getExpression()]);
+ } else {
+ $filter->setExpression(-1);
+ }
+
+ return null;
+ }
+ }
+ }
+
+ return parent::requireFilterColumns($filter);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function joinBaseTables()
+ {
+ $this->select->from(
+ array('hh' => $this->prefix . 'statehistory'),
+ array()
+ )->join(
+ array('ho' => $this->prefix . 'objects'),
+ 'ho.object_id = hh.object_id AND ho.is_active = 1 AND ho.objecttype_id = 1',
+ array()
+ );
+ $this->joinedVirtualTables['statehistory'] = true;
+ }
+
+ /**
+ * Join host groups
+ */
+ protected function joinHostgroups()
+ {
+ $this->select->joinLeft(
+ array('hgm' => $this->prefix . 'hostgroup_members'),
+ 'hgm.host_object_id = ho.object_id',
+ array()
+ )->joinLeft(
+ array('hg' => $this->prefix . 'hostgroups'),
+ 'hg.hostgroup_id = hgm.hostgroup_id',
+ array()
+ )->joinLeft(
+ array('hgo' => $this->prefix . 'objects'),
+ 'hgo.object_id = hg.hostgroup_object_id AND hgo.is_active = 1 AND hgo.objecttype_id = 3',
+ array()
+ );
+ }
+
+ /**
+ * Join hosts
+ */
+ protected function joinHosts()
+ {
+ $this->select->join(
+ array('h' => $this->prefix . 'hosts'),
+ 'h.host_object_id = ho.object_id',
+ array()
+ );
+ }
+
+ /**
+ * Join instances
+ */
+ protected function joinInstances()
+ {
+ $this->select->join(
+ array('i' => $this->prefix . 'instances'),
+ 'i.instance_id = hh.instance_id',
+ array()
+ );
+ }
+
+ /**
+ * Join service groups
+ */
+ protected function joinServicegroups()
+ {
+ $this->requireVirtualTable('services');
+ $this->select->joinLeft(
+ array('sgm' => $this->prefix . 'servicegroup_members'),
+ 'sgm.service_object_id = s.service_object_id',
+ array()
+ )->joinLeft(
+ array('sg' => $this->prefix . 'servicegroups'),
+ 'sg.' . $this->servicegroup_id . ' = sgm.servicegroup_id',
+ array()
+ )->joinLeft(
+ array('sgo' => $this->prefix . 'objects'),
+ 'sgo.object_id = sg.servicegroup_object_id AND sgo.is_active = 1 AND sgo.objecttype_id = 4',
+ array()
+ );
+ }
+
+ /**
+ * Join services
+ */
+ protected function joinServices()
+ {
+ $this->select->joinLeft(
+ array('s' => $this->prefix . 'services'),
+ 's.host_object_id = ho.object_id',
+ array()
+ )->joinLeft(
+ array('so' => $this->prefix . 'objects'),
+ 'so.object_id = s.service_object_id AND so.is_active = 1 AND so.objecttype_id = 2',
+ array()
+ );
+ }
+
+ protected function joinSubQuery(IdoQuery $query, $name, $filter, $and, $negate, &$additionalFilter)
+ {
+ if ($name === 'hostgroup') {
+ $query->joinVirtualTable('members');
+
+ return ['hgm.host_object_id', 'ho.object_id'];
+ } elseif ($name === 'servicegroup') {
+ $query->joinVirtualTable('services');
+
+ return ['s.host_object_id', 'ho.object_id'];
+ }
+
+ return parent::joinSubQuery($query, $name, $filter, $and, $negate, $additionalFilter);
+ }
+}
diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/HoststatusQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/HoststatusQuery.php
new file mode 100644
index 0000000..e1b5480
--- /dev/null
+++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/HoststatusQuery.php
@@ -0,0 +1,338 @@
+<?php
+/* Icinga Web 2 | (c) 2013 Icinga Development Team | GPLv2+ */
+
+namespace Icinga\Module\Monitoring\Backend\Ido\Query;
+
+class HoststatusQuery extends IdoQuery
+{
+ /**
+ * {@inheritdoc}
+ */
+ protected $allowCustomVars = true;
+
+ /**
+ * {@inheritdoc}
+ */
+ protected $groupBase = array('hosts' => array('ho.object_id', 'h.host_id'));
+
+ /**
+ * {@inheritdoc}
+ */
+ protected $groupOrigin = array('hostgroups', 'servicegroups', 'services');
+
+ protected $subQueryTargets = array(
+ 'hostgroups' => 'hostgroup',
+ 'servicegroups' => 'servicegroup'
+ );
+
+ /**
+ * {@inheritdoc}
+ */
+ protected $columnMap = array(
+ 'checktimeperiods' => array(
+ 'host_check_timeperiod' => 'ctp.alias COLLATE latin1_general_ci'
+ ),
+ 'contacts' => [
+ 'host_contact' => 'hco.name1'
+ ],
+ 'contactgroups' => [
+ 'host_contactgroup' => 'hcgo.name1'
+ ],
+ 'hostgroups' => array(
+ 'hostgroup' => 'hgo.name1 COLLATE latin1_general_ci',
+ 'hostgroup_alias' => 'hg.alias COLLATE latin1_general_ci',
+ 'hostgroup_name' => 'hgo.name1'
+ ),
+ 'hosts' => array(
+ 'host' => 'ho.name1 COLLATE latin1_general_ci',
+ 'host_action_url' => 'h.action_url',
+ 'host_address' => 'h.address',
+ 'host_address6' => 'h.address6',
+ 'host_alias' => 'h.alias',
+ 'host_check_interval' => '(h.check_interval * 60)',
+ 'host_display_name' => 'h.display_name COLLATE latin1_general_ci',
+ 'host_icon_image' => 'h.icon_image',
+ 'host_icon_image_alt' => 'h.icon_image_alt',
+ 'host_ipv4' => 'INET_ATON(h.address)',
+ 'host_name' => 'ho.name1',
+ 'host_notes' => 'h.notes',
+ 'host_notes_url' => 'h.notes_url',
+ 'object_type' => '(\'host\')',
+ 'object_id' => 'ho.object_id'
+ ),
+ 'hoststatus' => array(
+ 'host_acknowledged' => 'hs.problem_has_been_acknowledged',
+ 'host_acknowledgement_type' => 'hs.acknowledgement_type',
+ 'host_active_checks_enabled' => 'hs.active_checks_enabled',
+ 'host_active_checks_enabled_changed' => 'CASE WHEN hs.active_checks_enabled = h.active_checks_enabled THEN 0 ELSE 1 END',
+ 'host_attempt' => 'hs.current_check_attempt || \'/\' || hs.max_check_attempts',
+ 'host_check_command' => 'hs.check_command',
+ 'host_check_execution_time' => 'hs.execution_time',
+ 'host_check_latency' => 'hs.latency',
+ 'host_check_source' => 'hs.check_source',
+ 'host_check_type' => 'hs.check_type',
+ 'host_current_check_attempt' => 'hs.current_check_attempt',
+ 'host_current_notification_number' => 'hs.current_notification_number',
+ 'host_event_handler' => 'hs.event_handler',
+ 'host_event_handler_enabled' => 'hs.event_handler_enabled',
+ 'host_event_handler_enabled_changed' => 'CASE WHEN hs.event_handler_enabled = h.event_handler_enabled THEN 0 ELSE 1 END',
+ 'host_failure_prediction_enabled' => 'hs.failure_prediction_enabled',
+ 'host_flap_detection_enabled' => 'hs.flap_detection_enabled',
+ 'host_flap_detection_enabled_changed' => 'CASE WHEN hs.flap_detection_enabled = h.flap_detection_enabled THEN 0 ELSE 1 END',
+ 'host_handled' => 'CASE WHEN (hs.problem_has_been_acknowledged + hs.scheduled_downtime_depth) > 0 THEN 1 ELSE 0 END',
+ 'host_hard_state' => 'CASE WHEN hs.has_been_checked = 0 OR hs.has_been_checked IS NULL THEN 99 ELSE CASE WHEN hs.state_type = 1 THEN hs.current_state ELSE hs.last_hard_state END END',
+ 'host_in_downtime' => 'CASE WHEN (hs.scheduled_downtime_depth = 0) THEN 0 ELSE 1 END',
+ 'host_is_flapping' => 'hs.is_flapping',
+ 'host_is_passive_checked' => 'CASE WHEN hs.active_checks_enabled = 0 AND hs.passive_checks_enabled = 1 THEN 1 ELSE 0 END',
+ 'host_is_reachable' => 'hs.is_reachable',
+ 'host_last_check' => 'UNIX_TIMESTAMP(hs.last_check)',
+ 'host_last_hard_state' => 'hs.last_hard_state',
+ 'host_last_hard_state_change' => 'UNIX_TIMESTAMP(hs.last_hard_state_change)',
+ 'host_last_notification' => 'UNIX_TIMESTAMP(hs.last_notification)',
+ 'host_last_state_change' => 'UNIX_TIMESTAMP(hs.last_state_change)',
+ 'host_last_state_change_ts' => 'hs.last_state_change',
+ 'host_last_time_down' => 'UNIX_TIMESTAMP(hs.last_time_down)',
+ 'host_last_time_unreachable' => 'UNIX_TIMESTAMP(hs.last_time_unreachable)',
+ 'host_last_time_up' => 'UNIX_TIMESTAMP(hs.last_time_up)',
+ 'host_long_output' => 'hs.long_output',
+ 'host_max_check_attempts' => 'hs.max_check_attempts',
+ 'host_modified_host_attributes' => 'hs.modified_host_attributes',
+ 'host_next_check' => 'CASE hs.should_be_scheduled WHEN 1 THEN UNIX_TIMESTAMP(hs.next_check) ELSE NULL END',
+ 'host_next_notification' => 'UNIX_TIMESTAMP(hs.next_notification)',
+ 'host_next_update' => 'CASE WHEN hs.has_been_checked = 0 OR hs.has_been_checked IS NULL
+ THEN
+ CASE hs.should_be_scheduled WHEN 1 THEN UNIX_TIMESTAMP(hs.next_check) + (hs.normal_check_interval * 60) ELSE NULL END
+ ELSE
+ UNIX_TIMESTAMP(hs.next_check)
+ + (CASE WHEN
+ COALESCE(hs.current_state, 0) > 0 AND hs.state_type = 0
+ THEN
+ hs.retry_check_interval
+ ELSE
+ hs.normal_check_interval
+ END * 60)
+ + (CEIL(hs.execution_time + hs.latency) * 2)
+ END',
+ 'host_no_more_notifications' => 'hs.no_more_notifications',
+ 'host_normal_check_interval' => 'hs.normal_check_interval',
+ 'host_notifications_enabled' => 'hs.notifications_enabled',
+ 'host_notifications_enabled_changed' => 'CASE WHEN hs.notifications_enabled = h.notifications_enabled THEN 0 ELSE 1 END',
+ 'host_obsessing' => 'hs.obsess_over_host',
+ 'host_obsessing_changed' => 'CASE WHEN hs.obsess_over_host = h.obsess_over_host THEN 0 ELSE 1 END',
+ 'host_output' => 'hs.output',
+ 'host_passive_checks_enabled' => 'hs.passive_checks_enabled',
+ 'host_passive_checks_enabled_changed' => 'CASE WHEN hs.passive_checks_enabled = h.passive_checks_enabled THEN 0 ELSE 1 END',
+ 'host_percent_state_change' => 'hs.percent_state_change',
+ 'host_perfdata' => 'hs.perfdata',
+ 'host_problem' => 'CASE WHEN COALESCE(hs.current_state, 0) = 0 THEN 0 ELSE 1 END',
+ 'host_problem_has_been_acknowledged' => 'hs.problem_has_been_acknowledged',
+ 'host_process_performance_data' => 'hs.process_performance_data',
+ 'host_retry_check_interval' => 'hs.retry_check_interval',
+ 'host_scheduled_downtime_depth' => 'hs.scheduled_downtime_depth',
+ 'host_severity' => '
+ CASE
+ WHEN hs.has_been_checked = 0 OR hs.has_been_checked IS NULL
+ THEN 16
+ ELSE
+ CASE
+ WHEN hs.current_state = 0
+ THEN 1
+ ELSE
+ CASE
+ WHEN hs.current_state = 1 THEN 64
+ WHEN hs.current_state = 2 THEN 32
+ ELSE 256
+ END
+ +
+ CASE
+ WHEN hs.problem_has_been_acknowledged = 1 THEN 2
+ WHEN hs.scheduled_downtime_depth > 0 THEN 1
+ ELSE 256
+ END
+ END
+ END',
+ 'host_state' => 'CASE WHEN hs.has_been_checked = 0 OR hs.has_been_checked IS NULL THEN 99 ELSE hs.current_state END',
+ 'host_state_type' => 'hs.state_type',
+ 'host_status_update_time' => 'hs.status_update_time',
+ 'host_unhandled' => 'CASE WHEN (hs.problem_has_been_acknowledged + hs.scheduled_downtime_depth) = 0 THEN 1 ELSE 0 END',
+ 'problems' => 'CASE WHEN COALESCE(hs.current_state, 0) = 0 THEN 0 ELSE 1 END'
+ ),
+ 'instances' => array(
+ 'instance_name' => 'i.instance_name'
+ ),
+ 'servicegroups' => array(
+ 'servicegroup' => 'sgo.name1 COLLATE latin1_general_ci',
+ 'servicegroup_name' => 'sgo.name1',
+ 'servicegroup_alias' => 'sg.alias COLLATE latin1_general_ci'
+ ),
+ 'services' => array(
+ 'service' => 'so.name2 COLLATE latin1_general_ci',
+ 'service_description' => 'so.name2',
+ 'service_display_name' => 's.display_name COLLATE latin1_general_ci',
+ )
+ );
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function joinBaseTables()
+ {
+ if (version_compare($this->getIdoVersion(), '1.10.0', '<')) {
+ $this->columnMap['hoststatus']['host_check_source'] = '(NULL)';
+ }
+ if (version_compare($this->getIdoVersion(), '1.13.0', '<')) {
+ $this->columnMap['hoststatus']['host_is_reachable'] = '(NULL)';
+ }
+
+ $this->select->from(
+ array('ho' => $this->prefix . 'objects'),
+ array()
+ )->join(
+ array('h' => $this->prefix . 'hosts'),
+ 'h.host_object_id = ho.object_id AND ho.is_active = 1 AND ho.objecttype_id = 1',
+ array()
+ );
+ $this->joinedVirtualTables['hosts'] = true;
+ }
+
+ /**
+ * Join check time periods
+ */
+ protected function joinChecktimeperiods()
+ {
+ $this->select->joinLeft(
+ array('ctp' => $this->prefix . 'timeperiods'),
+ 'ctp.timeperiod_object_id = h.check_timeperiod_object_id',
+ array()
+ );
+ }
+
+ /**
+ * Join contacts
+ */
+ protected function joinContacts()
+ {
+ $this->select->joinLeft(
+ ['hc' => 'icinga_host_contacts'],
+ 'hc.host_id = h.host_id',
+ []
+ )->joinLeft(
+ ['hco' => 'icinga_objects'],
+ 'hco.object_id = hc.contact_object_id AND hco.is_active = 1 AND hco.objecttype_id = 10',
+ []
+ );
+ }
+
+ /**
+ * Join contact groups
+ */
+ protected function joinContactgroups()
+ {
+ $this->select->joinLeft(
+ ['hcg' => 'icinga_host_contactgroups'],
+ 'hcg.host_id = h.host_id',
+ []
+ )->joinLeft(
+ ['hcgo' => 'icinga_objects'],
+ 'hcgo.object_id = hcg.contactgroup_object_id AND hcgo.is_active = 1 AND hcgo.objecttype_id = 11',
+ []
+ );
+ }
+
+ /**
+ * Join host groups
+ */
+ protected function joinHostgroups()
+ {
+ $this->select->joinLeft(
+ array('hgm' => $this->prefix . 'hostgroup_members'),
+ 'hgm.host_object_id = ho.object_id',
+ array()
+ )->joinLeft(
+ array('hg' => $this->prefix . 'hostgroups'),
+ 'hg.hostgroup_id = hgm.hostgroup_id',
+ array()
+ )->joinLeft(
+ array('hgo' => $this->prefix . 'objects'),
+ 'hgo.object_id = hg.hostgroup_object_id AND hgo.is_active = 1 AND hgo.objecttype_id = 3',
+ array()
+ );
+ }
+
+ /**
+ * Join host status
+ */
+ protected function joinHoststatus()
+ {
+ $this->select->join(
+ array('hs' => $this->prefix . 'hoststatus'),
+ 'hs.host_object_id = ho.object_id',
+ array()
+ );
+ }
+
+ /**
+ * Join instances
+ */
+ protected function joinInstances()
+ {
+ $this->select->join(
+ array('i' => $this->prefix . 'instances'),
+ 'i.instance_id = ho.instance_id',
+ array()
+ );
+ }
+
+ /**
+ * Join service groups
+ */
+ protected function joinServicegroups()
+ {
+ $this->requireVirtualTable('services');
+ $this->select->joinLeft(
+ array('sgm' => $this->prefix . 'servicegroup_members'),
+ 'sgm.service_object_id = s.service_object_id',
+ array()
+ )->joinLeft(
+ array('sg' => $this->prefix . 'servicegroups'),
+ 'sgm.servicegroup_id = sg.' . $this->servicegroup_id,
+ array()
+ )->joinLeft(
+ array('sgo' => $this->prefix . 'objects'),
+ 'sgo.object_id = sg.servicegroup_object_id AND sgo.is_active = 1 AND sgo.objecttype_id = 4',
+ array()
+ );
+ }
+
+ /**
+ * Join services
+ */
+ protected function joinServices()
+ {
+ $this->requireVirtualTable('hosts');
+ $this->select->joinLeft(
+ array('s' => $this->prefix . 'services'),
+ 's.host_object_id = h.host_object_id',
+ array()
+ )->joinLeft(
+ array('so' => $this->prefix . 'objects'),
+ 'so.object_id = s.service_object_id AND so.is_active = 1 AND so.objecttype_id = 2',
+ array()
+ );
+ }
+
+ protected function joinSubQuery(IdoQuery $query, $name, $filter, $and, $negate, &$additionalFilter)
+ {
+ if ($name === 'hostgroup') {
+ $query->joinVirtualTable('members');
+
+ return ['hgm.host_object_id', 'ho.object_id'];
+ } elseif ($name === 'servicegroup') {
+ $query->joinVirtualTable('services');
+
+ return ['s.host_object_id', 'ho.object_id'];
+ }
+
+ return parent::joinSubQuery($query, $name, $filter, $and, $negate, $additionalFilter);
+ }
+}
diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/HoststatussummaryQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/HoststatussummaryQuery.php
new file mode 100644
index 0000000..5d79143
--- /dev/null
+++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/HoststatussummaryQuery.php
@@ -0,0 +1,91 @@
+<?php
+/* Icinga Web 2 | (c) 2015 Icinga Development Team | GPLv2+ */
+
+namespace Icinga\Module\Monitoring\Backend\Ido\Query;
+
+use Icinga\Data\Filter\Filter;
+use Icinga\Data\Filter\FilterExpression;
+
+/**
+ * Query for host group summaries
+ */
+class HoststatussummaryQuery extends IdoQuery
+{
+ /**
+ * {@inheritdoc}
+ */
+ protected $columnMap = array(
+ 'hoststatussummary' => array(
+ 'hosts_down' => 'SUM(CASE WHEN state = 1 THEN 1 ELSE 0 END)',
+ 'hosts_down_handled' => 'SUM(CASE WHEN state = 1 AND handled = 1 THEN 1 ELSE 0 END)',
+ 'hosts_down_unhandled' => 'SUM(CASE WHEN state = 1 AND handled = 0 THEN 1 ELSE 0 END)',
+ 'hosts_pending' => 'SUM(CASE WHEN state = 99 THEN 1 ELSE 0 END)',
+ 'hosts_total' => 'SUM(1)',
+ 'hosts_unreachable' => 'SUM(CASE WHEN state = 2 THEN 1 ELSE 0 END)',
+ 'hosts_unreachable_handled' => 'SUM(CASE WHEN state = 2 AND handled = 1 THEN 1 ELSE 0 END)',
+ 'hosts_unreachable_unhandled' => 'SUM(CASE WHEN state = 2 AND handled = 0 THEN 1 ELSE 0 END)',
+ 'hosts_up' => 'SUM(CASE WHEN state = 0 THEN 1 ELSE 0 END)'
+ )
+ );
+
+ /**
+ * The host status sub select
+ *
+ * @var HostStatusQuery
+ */
+ protected $subSelect;
+
+ /**
+ * {@inheritdoc}
+ */
+ public function allowsCustomVars()
+ {
+ return $this->subSelect->allowsCustomVars();
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function addFilter(Filter $filter)
+ {
+ $this->subSelect->applyFilter(clone $filter);
+ return $this;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function joinBaseTables()
+ {
+ // TODO(el): Allow to switch between hard and soft states
+ $this->subSelect = $this->createSubQuery(
+ 'Hoststatus',
+ array(
+ 'handled' => 'host_handled',
+ 'state' => 'host_state',
+ 'state_change' => 'host_last_state_change'
+ )
+ );
+ $this->select->from(
+ array('hoststatussummary' => $this->subSelect->setIsSubQuery(true)),
+ array()
+ );
+ $this->joinedVirtualTables['hoststatussummary'] = true;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function where($condition, $value = null)
+ {
+ $this->subSelect->where($condition, $value);
+ return $this;
+ }
+
+ public function whereEx(FilterExpression $ex)
+ {
+ $this->subSelect->whereEx($ex);
+
+ return $this;
+ }
+}
diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/IdoQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/IdoQuery.php
new file mode 100644
index 0000000..bd7a077
--- /dev/null
+++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/IdoQuery.php
@@ -0,0 +1,1599 @@
+<?php
+/* Icinga Web 2 | (c) 2013 Icinga Development Team | GPLv2+ */
+
+namespace Icinga\Module\Monitoring\Backend\Ido\Query;
+
+use Icinga\Data\Filter\FilterNot;
+use Zend_Db_Expr;
+use Icinga\Application\Icinga;
+use Icinga\Application\Hook;
+use Icinga\Application\Logger;
+use Icinga\Data\Db\DbQuery;
+use Icinga\Data\Filter\Filter;
+use Icinga\Data\Filter\FilterExpression;
+use Icinga\Exception\IcingaException;
+use Icinga\Exception\NotImplementedError;
+use Icinga\Exception\ProgrammingError;
+use Icinga\Exception\QueryException;
+use Icinga\Web\Session;
+use Icinga\Module\Monitoring\Data\ColumnFilterIterator;
+use Zend_Db_Select;
+
+/**
+ * Base class for Ido Queries
+ *
+ * This is the base class for all Ido queries and should be extended for new queries
+ * The starting point for implementations is the columnMap attribute. This is an asscociative array in the
+ * following form:
+ *
+ * <pre>
+ * <code>
+ * array(
+ * 'virtualTable' => array(
+ * 'fieldalias1' => 'queryColumn1',
+ * 'fieldalias2' => 'queryColumn2',
+ * ....
+ * ),
+ * 'virtualTable2' => array(
+ * 'host' => 'host_name1'
+ * )
+ * )
+ * </code>
+ * </pre>
+ *
+ * This allows you to select e.g. fieldalias1, which automatically calls the query code for joining 'virtualTable'. If
+ * you afterwards select 'host', 'virtualTable2' will be joined. The joining logic is up to you, in order to make the
+ * above example work you need to implement the joinVirtualTable() method which contain your
+ * custom (Zend_Db) logic for joining, filtering and querying the data you want.
+ *
+ */
+abstract class IdoQuery extends DbQuery
+{
+ /**
+ * The prefix to use
+ *
+ * @var string
+ */
+ protected $prefix;
+
+ /**
+ * An array to map aliases to column names
+ *
+ * @var array
+ */
+ protected $idxAliasColumn;
+
+ /**
+ * An array to map aliases to table names
+ *
+ * @var array
+ */
+ protected $idxAliasTable;
+
+ /**
+ * An array to map custom aliases to aliases
+ *
+ * @var array
+ */
+ protected $idxCustomAliases;
+
+ /**
+ * The column map containing all filterable columns
+ *
+ * This must be overwritten by child classes, in the format
+ * array(
+ * 'virtualTable' => array(
+ * 'fieldalias1' => 'queryColumn1',
+ * 'fieldalias2' => 'queryColumn2',
+ * ....
+ * )
+ * )
+ *
+ * @var array
+ */
+ protected $columnMap = array();
+
+ /**
+ * Custom vars available for this query
+ *
+ * @var array
+ */
+ protected $customVars = array();
+
+ /**
+ * Printf compatible string to joins custom vars
+ *
+ * - %1$s Source field, contain the object_id
+ * - %2$s Alias used for the relation
+ * - %3$s Name of the CustomVariable
+ *
+ * @var string
+ */
+ private $customVarsJoinTemplate = '%1$s = %2$s.object_id AND %2$s.varname = %3$s';
+
+ /**
+ * An array with all 'virtual' tables that are already joined
+ *
+ * Virtual tables are the keys of the columnMap array and require a
+ * join%VirtualTableName%() method to be defined in the concrete
+ * query
+ *
+ * @var array
+ */
+ protected $joinedVirtualTables = array();
+
+ /**
+ * A map of virtual table names and corresponding hook instances
+ *
+ * Joins for those tables will be delegated to them
+ *
+ * @var array
+ */
+ protected $hookedVirtualTables = array();
+
+ /**
+ * List of column aliases used for sorting the result
+ *
+ * @var array
+ */
+ protected $orderColumns = array();
+
+ /**
+ * Table to columns map which have to be added to the GROUP BY list if the query is grouped
+ *
+ * @var array
+ */
+ protected $groupBase = array();
+
+ /**
+ * List of table names which initiate grouping if one of them is joined
+ *
+ * @var array
+ */
+ protected $groupOrigin = array();
+
+ /**
+ * Map of table names to query names for which to create subquery filters
+ *
+ * @var array
+ */
+ protected $subQueryTargets = array();
+
+ /**
+ * The primary key column for the instances table
+ *
+ * @var string
+ */
+ protected $instance_id = 'instance_id';
+
+ /**
+ * The primary key column for the objects table
+ *
+ * @var string
+ */
+ protected $object_id = 'object_id';
+
+ /**
+ * The primary key column for the acknowledgements table
+ *
+ * @var string
+ */
+ protected $acknowledgement_id = 'acknowledgement_id';
+
+ /**
+ * The primary key column for the commenthistory table
+ *
+ * @var string
+ */
+ protected $commenthistory_id = 'commenthistory_id';
+
+ /**
+ * The primary key column for the contactnotifications table
+ *
+ * @var string
+ */
+ protected $contactnotification_id = 'contactnotification_id';
+
+ /**
+ * The primary key column for the downtimehistory table
+ *
+ * @var string
+ */
+ protected $downtimehistory_id = 'downtimehistory_id';
+
+ /**
+ * The primary key column for the flappinghistory table
+ *
+ * @var string
+ */
+ protected $flappinghistory_id = 'flappinghistory_id';
+
+ /**
+ * The primary key column for the notifications table
+ *
+ * @var string
+ */
+ protected $notification_id = 'notification_id';
+
+ /**
+ * The primary key column for the statehistory table
+ *
+ * @var string
+ */
+ protected $statehistory_id = 'statehistory_id';
+
+ /**
+ * The primary key column for the comments table
+ *
+ * @var string
+ */
+ protected $comment_id = 'comment_id';
+
+ /**
+ * The primary key column for the customvariablestatus table
+ *
+ * @var string
+ */
+ protected $customvariablestatus_id = 'customvariablestatus_id';
+
+ /**
+ * The primary key column for the hoststatus table
+ *
+ * @var string
+ */
+ protected $hoststatus_id = 'hoststatus_id';
+
+ /**
+ * The primary key column for the programstatus table
+ *
+ * @var string
+ */
+ protected $programstatus_id = 'programstatus_id';
+
+ /**
+ * The primary key column for the runtimevariables table
+ *
+ * @var string
+ */
+ protected $runtimevariable_id = 'runtimevariable_id';
+
+ /**
+ * The primary key column for the scheduleddowntime table
+ *
+ * @var string
+ */
+ protected $scheduleddowntime_id = 'scheduleddowntime_id';
+
+ /**
+ * The primary key column for the servicestatus table
+ *
+ * @var string
+ */
+ protected $servicestatus_id = 'servicestatus_id';
+
+ /**
+ * The primary key column for the contactstatus table
+ *
+ * @var string
+ */
+ protected $contactstatus_id = 'contactstatus_id';
+
+ /**
+ * The primary key column for the commands table
+ *
+ * @var string
+ */
+ protected $command_id = 'command_id';
+
+ /**
+ * The primary key column for the contactgroup_members table
+ *
+ * @var string
+ */
+ protected $contactgroup_member_id = 'contactgroup_member_id';
+
+ /**
+ * The primary key column for the contactgroups table
+ *
+ * @var string
+ */
+ protected $contactgroup_id = 'contactgroup_id';
+
+ /**
+ * The primary key column for the contacts table
+ *
+ * @var string
+ */
+ protected $contact_id = 'contact_id';
+
+ /**
+ * The primary key column for the customvariables table
+ *
+ * @var string
+ */
+ protected $customvariable_id = 'customvariable_id';
+
+ /**
+ * The primary key column for the host_contactgroups table
+ *
+ * @var string
+ */
+ protected $host_contactgroup_id = 'host_contactgroup_id';
+
+ /**
+ * The primary key column for the host_contacts table
+ *
+ * @var string
+ */
+ protected $host_contact_id = 'host_contact_id';
+
+ /**
+ * The primary key column for the hostgroup_members table
+ *
+ * @var string
+ */
+ protected $hostgroup_member_id = 'hostgroup_member_id';
+
+ /**
+ * The primary key column for the hostgroups table
+ *
+ * @var string
+ */
+ protected $hostgroup_id = 'hostgroup_id';
+
+ /**
+ * The primary key column for the hosts table
+ *
+ * @var string
+ */
+ protected $host_id = 'host_id';
+
+ /**
+ * The primary key column for the service_contactgroup table
+ *
+ * @var string
+ */
+ protected $service_contactgroup_id = 'service_contactgroup_id';
+
+ /**
+ * The primary key column for the service_contact table
+ *
+ * @var string
+ */
+ protected $service_contact_id = 'service_contact_id';
+
+ /**
+ * The primary key column for the servicegroup_members table
+ *
+ * @var string
+ */
+ protected $servicegroup_member_id = 'servicegroup_member_id';
+
+ /**
+ * The primary key column for the servicegroups table
+ *
+ * @var string
+ */
+ protected $servicegroup_id = 'servicegroup_id';
+
+ /**
+ * The primary key column for the services table
+ *
+ * @var string
+ */
+ protected $service_id = 'service_id';
+
+ /**
+ * The primary key column for the timeperiods table
+ *
+ * @var string
+ */
+ protected $timeperiod_id = 'timeperiod_id';
+
+ /**
+ * An array containing Column names that cause an aggregation of the query
+ *
+ * @var array
+ */
+ protected $aggregateColumnIdx = array();
+
+ /**
+ * True to allow customvar filters and queries
+ *
+ * @var bool
+ */
+ protected $allowCustomVars = false;
+
+ /**
+ * Current IDO version. This is bullshit and needs to be moved somewhere
+ * else. As someone decided that we need no Backend-specific connection
+ * class unfortunately there is no better place right now. And as of the
+ * 'check_source' patch we need a quick fix immediately. So here you go.
+ *
+ * TODO: Fix this.
+ *
+ * @var string
+ */
+ protected static $idoVersion;
+
+ /**
+ * List of column aliases mapped to their table where the COLLATE SQL-instruction has been removed
+ *
+ * This list is being populated in case of a PostgreSQL backend only,
+ * to ensure case-insensitive string comparison in WHERE clauses.
+ *
+ * @var array
+ */
+ protected $caseInsensitiveColumns;
+
+ /**
+ * Return true when the column is an aggregate column
+ *
+ * @param String $column The column to test
+ * @return bool True when the column is an aggregate column
+ */
+ public function isAggregateColumn($column)
+ {
+ return array_key_exists($column, $this->aggregateColumnIdx);
+ }
+
+ /**
+ * Order the result by the given alias
+ *
+ * @param string $alias The column alias to order by
+ * @param int $dir The sort direction or null to use the default direction
+ *
+ * @return $this
+ */
+ public function order($alias, $dir = null)
+ {
+ $this->requireColumn($alias);
+
+ if ($this->isCustomvar($alias)) {
+ $column = $this->getCustomvarColumnName($alias);
+ } elseif ($this->hasAliasName($alias)) {
+ $column = $this->aliasToColumnName($alias);
+ $table = $this->aliasToTableName($alias);
+ if (isset($this->caseInsensitiveColumns[$table][$alias])) {
+ $column = 'LOWER(' . $column . ')';
+ }
+ } else {
+ Logger::info('Can\'t order by column ' . $alias);
+ return $this;
+ }
+
+ $this->orderColumns[] = $alias;
+ return parent::order($column, $dir);
+ }
+
+ /**
+ * Return true when the given field can be used for filtering
+ *
+ * @param String $field The field to test
+ * @return bool True when the field can be used for querying, otherwise false
+ */
+ public function isValidFilterTarget($field)
+ {
+ return $this->getMappedField($field) !== null;
+ }
+
+ /**
+ * Return the resolved field for an alias
+ *
+ * @param String $field The alias to resolve
+ * @return String The resolved alias or null if unknown
+ */
+ public function getMappedField($field)
+ {
+ foreach ($this->columnMap as $columnSource => $columnSet) {
+ if (isset($columnSet[$field])) {
+ return $columnSet[$field];
+ }
+ }
+ if ($this->isCustomVar($field)) {
+ return $this->getCustomvarColumnName($field);
+ }
+ return null;
+ }
+
+ public function distinct()
+ {
+ $this->select->distinct();
+ return $this;
+ }
+
+ /**
+ * Prepare the given query so that it can be linked to the parent
+ *
+ * @param IdoQuery $query
+ * @param string $name
+ * @param FilterExpression $filter The filter which initiated the sub query
+ * @param bool $and Whether it's an AND filter
+ * @param bool $negate Whether it's an != filter
+ * @param FilterExpression $additionalFilter Filters which should be applied to the "parent" query
+ *
+ * @return array The first value is their, the second our key column
+ *
+ * @throws NotImplementedError In case the given query is unknown
+ */
+ protected function joinSubQuery(IdoQuery $query, $name, $filter, $and, $negate, &$additionalFilter)
+ {
+ throw new NotImplementedError('Query "%s" is unknown', $name);
+ }
+
+ /**
+ * Create and return a sub-query filter for the given filter expression
+ *
+ * @param FilterExpression $filter
+ * @param string $queryName
+ *
+ * @return Filter
+ *
+ * @throws QueryException
+ */
+ protected function createSubQueryFilter(FilterExpression $filter, $queryName)
+ {
+ $expr = $filter->getExpression();
+ $op = $filter->getSign();
+
+ if ($op === '=' && ! is_array($expr) && $op !== '!=') {
+ // We're joining a subquery only if the filter is enclosed in parentheses or if it's a != filter,
+ // e.g. hostgroup_name=(linux...), hostgroup_name!=linux, hostgroup_name!=(linux...)
+ throw new NotImplementedError('');
+ }
+
+ $subQuery = $this->createSubQuery($queryName);
+ $subQuery->setIsSubQuery();
+
+ $subQueryFilter = clone $filter;
+
+ if ($op === '!=') {
+ $negate = true;
+ if (! is_array($expr)) {
+ // We assume that expression is an array later on but we'll support subquery joins for != filters
+ // which are not enclosed in parentheses
+ $expr = [$expr];
+ }
+ } else {
+ $negate = false;
+ }
+
+ if (count($expr) === 1 && strpos($expr[0], '&') !== false) {
+ // Our current filter implementation does not specify & as a control character so the count of the
+ // expression array is always one in this case
+ $expr = array_unique(explode('&', $expr[0]));
+ $subQueryFilter->setExpression($expr);
+ $and = true;
+ } else {
+ // Or filters are respected by our filter implementation. No special handling needed here
+ $and = false;
+ }
+
+ $alias = $filter->getColumn();
+ $column = $subQuery->aliasToColumnName($alias);
+ if (isset($this->caseInsensitiveColumns[$subQuery->aliasToTableName($alias)][$alias])) {
+ $column = 'LOWER( ' . $column . ' )';
+ $subQueryFilter->setColumn($column);
+ $subQueryFilter->setExpression(array_map('strtolower', (array) $subQueryFilter->getExpression()));
+ } else {
+ $subQueryFilter->setColumn($column);
+ }
+
+ $additional = null;
+
+ list($theirs, $ours) = $this->joinSubQuery($subQuery, $queryName, $subQueryFilter, $and, $negate, $additional);
+
+ $zendSelect = $subQuery->select();
+ $fromPart = $zendSelect->getPart($zendSelect::FROM);
+ $zendSelect->reset($zendSelect::FROM);
+
+ foreach ($fromPart as $correlationName => $joinOptions) {
+ if (isset($joinOptions['joinCondition'])) {
+ $joinOptions['joinCondition'] = preg_replace(
+ '/(?<=^|\s)\w+(?=\.)/',
+ 'sub_$0',
+ $joinOptions['joinCondition']
+ );
+ }
+
+ $name = ['sub_' . $correlationName => $joinOptions['tableName']];
+ switch ($joinOptions['joinType']) {
+ case $zendSelect::FROM:
+ $zendSelect->from($name);
+ break;
+ case $zendSelect::INNER_JOIN:
+ $zendSelect->joinInner($name, $joinOptions['joinCondition'], null);
+ break;
+ case $zendSelect::LEFT_JOIN:
+ $zendSelect->joinLeft($name, $joinOptions['joinCondition'], null);
+ break;
+ default:
+ // TODO: Add support for other join types if required?
+ throw new QueryException(
+ 'Unsupported join type %s. Cannot create subquery filter.',
+ $joinOptions['joinType']
+ );
+ }
+ }
+
+ if ($and || $negate) {
+ // Having is only required for AND and != filters,
+ // e.g. hostgroup_name=(ping&linux), hostgroup_name!=ping, hostgroup_name!=(ping|linux)
+ $groups = $subQuery->getGroup();
+ if (! empty($groups)) {
+ $group = $groups[0];
+ $group = preg_replace('/(?<=^|\s)\w+(?=\.)/', 'sub_$0', $group);
+
+ $cnt = count($expr);
+
+ $subQuery->select()->having("COUNT(DISTINCT $group) >= $cnt");
+ }
+ }
+
+ $subQueryFilter->setColumn(preg_replace(
+ '/(?<=^|\s)\w+(?=\.)/',
+ 'sub_$0',
+ $column
+ ));
+
+ if ($negate) {
+ // != will be NOT EXISTS later
+ $subQueryFilter = $subQueryFilter->setSign('=');
+ }
+
+ $subQueryFilter = $subQueryFilter->andFilter(Filter::where(
+ preg_replace('/(?<=^|\s)\w+(?=\.)/', 'sub_$0', $theirs),
+ new Zend_Db_Expr($ours)
+ ));
+
+ $subQuery
+ ->setFilter($subQueryFilter)
+ ->clearGroupingRules()
+ ->select()
+ ->reset('columns')
+ ->columns([new Zend_Db_Expr('1')]);
+
+ // EXISTS is the column name because without any column $this->isCustomVar() fails badly otherwise.
+ // Additionally it bypasses the non-required optimizations made by our filter rendering implementation.
+ $exists = new FilterExpression($negate ? 'NOT EXISTS' : 'EXISTS', '', new Zend_Db_Expr($subQuery));
+
+ if ($additional !== null) {
+ return Filter::matchAll($exists, $additional);
+ }
+
+ return $exists;
+ }
+
+ protected function requireFilterColumns(Filter $filter)
+ {
+ if ($filter instanceof FilterExpression) {
+ $alias = $filter->getColumn();
+
+ $virtualTable = $this->aliasToTableName($alias);
+ if (isset($this->subQueryTargets[$virtualTable])) {
+ try {
+ return $this->createSubQueryFilter($filter, $this->subQueryTargets[$virtualTable]);
+ } catch (NotImplementedError $e) {
+ // We don't want to create subquery filters in all cases
+ }
+ }
+
+ $this->requireColumn($alias);
+
+ if ($this->isCustomvar($alias)) {
+ $column = $this->getCustomvarColumnName($alias);
+ } else {
+ $column = $this->aliasToColumnName($alias);
+ if (isset($this->caseInsensitiveColumns[$this->aliasToTableName($alias)][$alias])) {
+ $column = 'LOWER(' . $column . ')';
+ $expression = $filter->getExpression();
+ if (is_array($expression)) {
+ $filter->setExpression(array_map('strtolower', $expression));
+ } else {
+ $filter->setExpression(strtolower($expression));
+ }
+ }
+ }
+
+ $filter->setColumn($column);
+ } else {
+ if (! $filter instanceof FilterNot) {
+ // Allow subquery filters in a filter chain
+ $columns = $filter->listFilteredColumns();
+ if (count($columns) === 1) {
+ $column = $columns[0];
+ $virtualTable = $this->aliasToTableName($column);
+ if (isset($this->subQueryTargets[$virtualTable])) {
+ $lastSign = null;
+ $filters = [];
+ $expressions = [];
+ foreach ($filter->filters() as $child) {
+ switch (true) {
+ case $child instanceof FilterExpression:
+ $expression = $child->getExpression();
+ if (! is_array($expression)) {
+ break;
+ }
+ // Move to default
+ default:
+ $filters[] = $child;
+ continue 2;
+ }
+ if ($lastSign === null) {
+ $lastSign = $child->getSign();
+ } else {
+ $sign = $child->getSign();
+ if ($sign !== $lastSign) {
+ $filters[] = new FilterExpression(
+ $column,
+ $lastSign,
+ $filter->getOperatorSymbol() === '&'
+ ? [implode('&', $expressions)]
+ : $expressions
+ );
+ $expressions = [];
+ $lastSign = $sign;
+ }
+ }
+ $expressions[] = $expression;
+ }
+ if (! empty($expressions)) {
+ $filters[] = new FilterExpression(
+ $column,
+ $lastSign,
+ $filter->getOperatorSymbol() === '&'
+ ? [implode('&', $expressions)]
+ : $expressions
+ );
+ }
+ $filter->setFilters($filters);
+ }
+ }
+ }
+
+ foreach ($filter->filters() as $child) {
+ $replacement = $this->requireFilterColumns($child);
+ if ($replacement !== null) {
+ // setId($child->getId()) is performed because replaceById() doesn't already do it
+ $filter->replaceById($child->getId(), $replacement->setId($child->getId()));
+ }
+ }
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function addFilter(Filter $filter)
+ {
+ $filter = clone $filter;
+ return parent::addFilter($this->requireFilterColumns($filter) ?: $filter);
+ }
+
+ public function where($condition, $value = null)
+ {
+ $this->requireColumn($condition);
+ $col = $this->getMappedField($condition);
+ if ($col === null) {
+ throw new IcingaException(
+ 'No such field: %s',
+ $condition
+ );
+ }
+ return parent::where($col, $value);
+ }
+
+ /**
+ * Add a filter expression, with as less validation as possible
+ *
+ * @param FilterExpression $ex
+ *
+ * @internal If you use this outside the monitoring module, it's your fault if something breaks
+ * @return $this
+ */
+ public function whereEx(FilterExpression $ex)
+ {
+ $this->requireColumn($ex->getColumn());
+ $col = $this->getMappedField($ex->getColumn());
+ if ($col === null) {
+ throw new IcingaException(
+ 'No such field: %s',
+ $ex->getColumn()
+ );
+ }
+
+ parent::addFilter((clone $ex)->setColumn($col));
+
+ return $this;
+ }
+
+ /**
+ * Return true if an field contains an explicit timestamp
+ *
+ * @param string $field The field to test for containing an timestamp
+ *
+ * @return bool True when the field represents an timestamp
+ */
+ public function isTimestamp($field)
+ {
+ if ($this->isCustomVar($field)) {
+ return false;
+ }
+
+ return stripos($this->getMappedField($field) ?: $field, 'UNIX_TIMESTAMP') !== false;
+ }
+
+ /**
+ * Return whether the given alias provides case insensitive value comparison
+ *
+ * @param string $alias
+ *
+ * @return bool
+ */
+ public function isCaseInsensitive($alias)
+ {
+ if ($this->isCustomVar($alias)) {
+ return false;
+ }
+
+ $column = $this->getMappedField($alias);
+ if (! $column) {
+ return false;
+ }
+
+ if (empty($this->caseInsensitiveColumns)) {
+ return preg_match('/ COLLATE .+$/', $column) === 1;
+ }
+
+ if (strpos($column, 'LOWER') === 0) {
+ return true;
+ }
+
+ $table = $this->aliasToTableName($alias);
+ if (! $table) {
+ return false;
+ }
+
+ return isset($this->caseInsensitiveColumns[$table][$alias]);
+ }
+
+ /**
+ * Return our column map
+ *
+ * Might be useful for hooks
+ *
+ * @return array
+ */
+ public function getColumnMap()
+ {
+ return $this->columnMap;
+ }
+
+ /**
+ * Apply oracle specific query initialization
+ */
+ private function initializeForOracle()
+ {
+ // Oracle uses the reserved field 'id' for primary keys, so
+ // these must be used instead of the normally defined ids
+ $this->object_id = $this->host_id = $this->service_id
+ = $this->hostgroup_id = $this->servicegroup_id
+ = $this->contact_id = $this->contactgroup_id = 'id';
+ $this->customVarsJoinTemplate =
+ '%1$s = %2$s.object_id AND LOWER(%2$s.varname) = %3$s';
+ foreach ($this->columnMap as &$columns) {
+ foreach ($columns as &$value) {
+ $value = preg_replace('/UNIX_TIMESTAMP/', 'localts2unixts', $value);
+ $value = preg_replace('/ COLLATE .+$/', '', $value);
+ }
+ }
+ }
+
+ /**
+ * Apply PostgreSQL specific query initialization
+ */
+ private function initializeForPostgres()
+ {
+ $this->customVarsJoinTemplate =
+ '%1$s = %2$s.object_id AND LOWER(%2$s.varname) = %3$s';
+ foreach ($this->columnMap as $table => & $columns) {
+ foreach ($columns as $alias => & $column) {
+ if ($column === null) {
+ continue;
+ }
+
+ // Using a regex here because COLLATE may occur anywhere in the string
+ $column = preg_replace('/ COLLATE .+$/', '', $column, -1, $count);
+ if ($count > 0) {
+ $this->caseInsensitiveColumns[$table][$alias] = true;
+ }
+
+ $column = preg_replace(
+ '/inet_aton\(([[:word:].]+)\)/i',
+ '(CASE WHEN $1 ~ \'(?:[0-9]{1,3}\\\\.){3}[0-9]{1,3}\' THEN $1::inet - \'0.0.0.0\' ELSE NULL END)',
+ $column
+ );
+ if (version_compare($this->getIdoVersion(), '1.14.2', '>=')) {
+ $column = str_replace('NOW()', 'NOW() AT TIME ZONE \'UTC\'', $column);
+ } else {
+ $column = preg_replace(
+ '/UNIX_TIMESTAMP(\((?>[^()]|(?-1))*\))/i',
+ 'CASE WHEN ($1 < \'1970-01-03 00:00:00+00\'::timestamp with time zone) THEN 0 ELSE UNIX_TIMESTAMP($1) END',
+ $column
+ );
+ }
+ }
+ }
+ }
+
+ /**
+ * Set up this query and join the initial tables
+ *
+ * @see IdoQuery::initializeForPostgres For postgresql specific setup
+ */
+ protected function init()
+ {
+ parent::init();
+ $this->prefix = $this->ds->getTablePrefix();
+
+ foreach (Hook::all('monitoring/idoQueryExtension') as $hook) {
+ $extensions = $hook->extendColumnMap($this);
+ if (! is_array($extensions)) {
+ continue;
+ }
+
+ foreach ($extensions as $vTable => $cols) {
+ if (! array_key_exists($vTable, $this->columnMap)) {
+ $this->hookedVirtualTables[$vTable] = $hook;
+ $this->columMap[$vTable] = array();
+ }
+
+ foreach ($cols as $k => $v) {
+ $this->columnMap[$vTable][$k] = $v;
+ }
+ }
+ }
+
+ $dbType = $this->ds->getDbType();
+ if ($dbType === 'oracle') {
+ $this->initializeForOracle();
+ } elseif ($dbType === 'pgsql') {
+ $this->initializeForPostgres();
+ } else {
+ $charset = $this->ds->getConfig()->get('charset') ?: 'latin1';
+ $this->customVarsJoinTemplate .= " COLLATE {$charset}_general_ci";
+ }
+ $this->joinBaseTables();
+ $this->select->columns($this->columns);
+ $this->prepareAliasIndexes();
+ }
+
+ /**
+ * Join the base tables for this query
+ */
+ protected function joinBaseTables()
+ {
+ reset($this->columnMap);
+ $table = key($this->columnMap);
+
+ $this->select->from(
+ array($table => $this->prefix . $table),
+ array()
+ );
+
+ $this->joinedVirtualTables = array($table => true);
+ }
+
+ /**
+ * Populates the idxAliasTAble and idxAliasColumn properties
+ */
+ protected function prepareAliasIndexes()
+ {
+ foreach ($this->columnMap as $tbl => & $cols) {
+ foreach ($cols as $alias => $col) {
+ $this->idxAliasTable[$alias] = $tbl;
+ $this->idxAliasColumn[$alias] = preg_replace('~\n\s*~', ' ', $col);
+ }
+ }
+ }
+
+ /**
+ * Resolve columns aliases to their database field using the columnMap
+ *
+ * @param array $columns
+ *
+ * @return array
+ */
+ public function resolveColumns($columns)
+ {
+ $resolvedColumns = array();
+
+ foreach ($columns as $alias => $col) {
+ if ($col instanceof Zend_Db_Expr) {
+ // Support selecting NULL as column for example
+ $resolvedColumns[$alias] = $col;
+ continue;
+ }
+ $this->requireColumn($col);
+ if ($this->isCustomvar($col)) {
+ $name = $this->getCustomvarColumnName($col);
+ } else {
+ $name = $this->aliasToColumnName($col);
+ }
+ if (is_int($alias)) {
+ $alias = $col;
+ } else {
+ $this->idxCustomAliases[$alias] = $col;
+ }
+
+ $resolvedColumns[$alias] = preg_replace('|\n|', ' ', $name);
+ }
+
+ return $resolvedColumns;
+ }
+
+ /**
+ * Return all columns that will be selected when no columns are given in the constructor or from
+ *
+ * @return array An array of column aliases
+ */
+ public function getDefaultColumns()
+ {
+ reset($this->columnMap);
+ $table = key($this->columnMap);
+ return array_keys($this->columnMap[$table]);
+ }
+
+ /**
+ * Modify the query to the given alias can be used in the result set or queries
+ *
+ * This calls requireVirtualTable if needed
+ *
+ * @param string $alias The alias of the column to require
+ *
+ * @return $this Fluent interface
+ * @see IdoQuery::requireVirtualTable The method initializing required joins
+ * @throws \Icinga\Exception\ProgrammingError When an unknown column is requested
+ */
+ public function requireColumn($alias)
+ {
+ if ($this->hasAliasName($alias)) {
+ $this->requireVirtualTable($this->aliasToTableName($alias));
+ } elseif ($this->isCustomVar($alias)) {
+ $this->requireCustomvar($alias);
+ } else {
+ throw new ProgrammingError(
+ '%s : Got invalid column: %s',
+ get_called_class(),
+ $alias
+ );
+ }
+ return $this;
+ }
+
+ /**
+ * Return true if the given alias exists
+ *
+ * @param String $alias The alias to test for
+ * @return bool True when the alias exists, otherwise false
+ */
+ protected function hasAliasName($alias)
+ {
+ return array_key_exists($alias, $this->idxAliasColumn);
+ }
+
+ /**
+ * Require a virtual table for the given table name if not already required
+ *
+ * @param String $name The table name to require
+ * @return $this Fluent interface
+ */
+ protected function requireVirtualTable($name)
+ {
+ if ($this->hasJoinedVirtualTable($name)) {
+ return $this;
+ }
+
+ if ($this->virtualTableIsHooked($name)) {
+ return $this->joinHookedVirtualTable($name);
+ } else {
+ return $this->joinVirtualTable($name);
+ }
+ }
+
+ /**
+ * Whether a given virtual table name has been provided by a hook
+ *
+ * @param string $name Virtual table name
+ *
+ * @return boolean
+ */
+ protected function virtualTableIsHooked($name)
+ {
+ return array_key_exists($name, $this->hookedVirtualTables);
+ }
+
+ protected function conflictsWithVirtualTable($name)
+ {
+ if ($this->hasJoinedVirtualTable($name)) {
+ throw new ProgrammingError(
+ 'IDO query virtual table conflict with "%s"',
+ $name
+ );
+ }
+ return $this;
+ }
+
+ /**
+ * Call the method for joining a virtual table
+ *
+ * This requires a join$Table() method to exist
+ *
+ * @param String $table The table to join by calling join$Table() in the concrete implementation
+ * @return $this Fluent interface
+ *
+ * @throws \Icinga\Exception\ProgrammingError If the join method for this table does not exist
+ */
+ protected function joinVirtualTable($table)
+ {
+ $func = 'join' . ucfirst($table);
+ if (method_exists($this, $func)) {
+ $this->$func();
+ } else {
+ throw new ProgrammingError(
+ 'Cannot join "%s", no such table found',
+ $table
+ );
+ }
+ $this->joinedVirtualTables[$table] = true;
+ return $this;
+ }
+
+ /**
+ * Tell a hook to join a virtual table
+ *
+ * @param String $table
+ * @return $this
+ */
+ protected function joinHookedVirtualTable($table)
+ {
+ $this->hookedVirtualTables[$table]->joinVirtualTable($this, $table);
+ $this->joinedVirtualTables[$table] = true;
+ return $this;
+ }
+
+ /**
+ * Get the table for a specific alias
+ *
+ * @param String $alias The alias to request the table for
+ * @return String The table for the alias or null if it doesn't exist
+ */
+ protected function aliasToTableName($alias)
+ {
+ return isset($this->idxAliasTable[$alias]) ? $this->idxAliasTable[$alias] : null;
+ }
+
+ /**
+ * Return whether this query allows to join custom variables
+ *
+ * @return bool
+ */
+ public function allowsCustomVars()
+ {
+ return $this->allowCustomVars;
+ }
+
+ /**
+ * Return true if the given alias denotes a custom variable
+ *
+ * @param String $alias The alias to test for being a customvariable
+ * @return bool True if the alias is a customvariable, otherwise false
+ */
+ protected function isCustomVar($alias)
+ {
+ return $this->allowCustomVars && $alias[0] === '_';
+ }
+
+ protected function requireCustomvar($customvar)
+ {
+ if (! $this->hasCustomvar($customvar)) {
+ $this->joinCustomvar($customvar);
+ }
+ return $this;
+ }
+
+ protected function hasCustomvar($customvar)
+ {
+ return array_key_exists(strtolower($customvar), $this->customVars);
+ }
+
+ protected function joinCustomvar($customvar)
+ {
+ // TODO: This is not generic enough yet
+ list($type, $name) = $this->customvarNameToTypeName($customvar);
+ $alias = ($type === 'host' ? 'hcv_' : 'scv_') . preg_replace('~[^a-zA-Z0-9_]~', '_', $name);
+
+ // We're replacing any problematic char with an underscore, which will lead to duplicates, this avoids them
+ $from = $this->select->getPart(Zend_Db_Select::FROM);
+ for ($i = 2; array_key_exists($alias, $from); $i++) {
+ $alias = $alias . '_' . $i;
+ }
+
+ $this->customVars[strtolower($customvar)] = $alias;
+
+ if ($type === 'host') {
+ if ($this instanceof ServicecommentQuery
+ || $this instanceof ServicedowntimeQuery
+ || $this instanceof ServicecommenthistoryQuery
+ || $this instanceof ServicedowntimestarthistoryQuery
+ || $this instanceof ServiceflappingstarthistoryQuery
+ || $this instanceof ServicegroupQuery
+ || $this instanceof ServicenotificationQuery
+ || $this instanceof ServicestatehistoryQuery
+ || $this instanceof ServicestatusQuery
+ ) {
+ $this->requireVirtualTable('services');
+ $leftcol = 's.host_object_id';
+ } else {
+ $leftcol = 'ho.object_id';
+ if (! $this->hasJoinedTable('ho')) {
+ $this->requireVirtualTable('hosts');
+ }
+ }
+ } else { // $type === 'service'
+ $leftcol = 'so.object_id';
+ if (! $this->hasJoinedTable('so')) {
+ $this->requireVirtualTable('services');
+ }
+ }
+
+ $mapped = $this->getMappedField($leftcol);
+ if ($mapped !== null) {
+ $this->requireColumn($leftcol);
+ $leftcol = $mapped;
+ }
+
+ $joinOn = sprintf(
+ $this->customVarsJoinTemplate,
+ $leftcol,
+ $alias,
+ $this->db->quote($name)
+ );
+
+ $this->select->joinLeft(
+ array($alias => $this->prefix . 'customvariablestatus'),
+ $joinOn,
+ array()
+ );
+
+ return $this;
+ }
+
+ protected function customvarNameToTypeName($customvar)
+ {
+ $customvar = strtolower($customvar);
+ if (! preg_match('~^_(host|service)_(.+)$~', $customvar, $m)) {
+ throw new ProgrammingError(
+ 'Got invalid custom var: "%s"',
+ $customvar
+ );
+ }
+ return array($m[1], $m[2]);
+ }
+
+ protected function hasJoinedVirtualTable($name)
+ {
+ return array_key_exists($name, $this->joinedVirtualTables);
+ }
+
+ /**
+ * Get the query column of a already joined custom variable
+ *
+ * @param string $customvar
+ *
+ * @return string
+ * @throws QueryException If the custom variable has not been joined
+ */
+ protected function getCustomvarColumnName($customvar)
+ {
+ if (! isset($this->customVars[($customvar = strtolower($customvar))])) {
+ throw new QueryException('Custom variable %s has not been joined', $customvar);
+ }
+ return $this->customVars[$customvar] . '.varvalue';
+ }
+
+ public function aliasToColumnName($alias)
+ {
+ return $this->idxAliasColumn[$alias];
+ }
+
+ /**
+ * Get the alias of a column expression as defined in the {@link $columnMap} property.
+ *
+ * @param string $alias Potential custom alias
+ *
+ * @return string
+ */
+ public function customAliasToAlias($alias)
+ {
+ if (isset($this->idxCustomAliases[$alias])) {
+ return $this->idxCustomAliases[$alias];
+ }
+ return $alias;
+ }
+
+ /**
+ * Create a sub query
+ *
+ * @param string $queryName
+ * @param array $columns
+ *
+ * @return static
+ */
+ protected function createSubQuery($queryName, $columns = array())
+ {
+ $class = '\\'
+ . substr(__CLASS__, 0, strrpos(__CLASS__, '\\') + 1)
+ . ucfirst($queryName) . 'Query';
+ $query = new $class($this->ds, $columns);
+ return $query;
+ }
+
+ /**
+ * Set columns to select
+ *
+ * @param array $columns
+ *
+ * @return $this
+ */
+ public function columns(array $columns)
+ {
+ $this->idxCustomAliases = array();
+ $this->columns = $this->resolveColumns($columns);
+ // TODO: we need to refresh our select!
+ // $this->select->columns($columns);
+ return $this;
+ }
+
+ public function clearGroupingRules()
+ {
+ $this->groupBase = array();
+ $this->groupOrigin = array();
+ return $this;
+ }
+
+ /**
+ * Register the GROUP BY columns required for the given alias
+ *
+ * @param string $alias The alias to register columns for
+ * @param string $table The table the given alias is associated with
+ * @param array $groupedColumns The grouping columns registered so far
+ * @param array $groupedTables The tables for which columns were registered so far
+ */
+ protected function registerGroupColumns($alias, $table, array &$groupedColumns, array &$groupedTables)
+ {
+ switch ($table) {
+ case 'checktimeperiods':
+ $groupedColumns[] = 'ctp.timeperiod_id';
+ break;
+ case 'contacts':
+ $groupedColumns[] = 'co.object_id';
+ $groupedColumns[] = 'c.contact_id';
+ break;
+ case 'hostobjects':
+ $groupedColumns[] = 'ho.object_id';
+ break;
+ case 'hosts':
+ $groupedColumns[] = 'h.host_id';
+ break;
+ case 'hostgroups':
+ $groupedColumns[] = 'hgo.object_id';
+ $groupedColumns[] = 'hg.hostgroup_id';
+ break;
+ case 'hoststatus':
+ $groupedColumns[] = 'hs.hoststatus_id';
+ break;
+ case 'instances':
+ $groupedColumns[] = 'i.instance_id';
+ break;
+ case 'servicegroups':
+ $groupedColumns[] = 'sgo.object_id';
+ $groupedColumns[] = 'sg.servicegroup_id';
+ break;
+ case 'serviceobjects':
+ $groupedColumns[] = 'so.object_id';
+ break;
+ case 'serviceproblemsummary':
+ $groupedColumns[] = 'sps.unhandled_services_count';
+ break;
+ case 'services':
+ $groupedColumns[] = 'so.object_id';
+ $groupedColumns[] = 's.service_id';
+ break;
+ case 'servicestatus':
+ $groupedColumns[] = 'ss.servicestatus_id';
+ break;
+ default:
+ return;
+ }
+
+ $groupedTables[$table] = true;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getGroup()
+ {
+ $group = parent::getGroup() ?: array();
+ if (! is_array($group)) {
+ $group = array($group);
+ }
+
+ $joinedOrigins = array_filter($this->groupOrigin, array($this, 'hasJoinedVirtualTable'));
+ if (empty($joinedOrigins)) {
+ return $group;
+ }
+
+ $groupedTables = array();
+ foreach ($this->groupBase as $baseTable => $aliasedPks) {
+ if (! $this->hasJoinedVirtualTable($baseTable)) {
+ continue;
+ }
+ $groupedTables[$baseTable] = true;
+ foreach ($aliasedPks as $aliasedPk) {
+ $group[] = $aliasedPk;
+ }
+ }
+
+ foreach (new ColumnFilterIterator($this->columns) as $desiredAlias => $desiredColumn) {
+ $alias = is_string($desiredAlias) ? $this->customAliasToAlias($desiredAlias) : $desiredColumn;
+ if ($this->isCustomVar($alias) && $this->getDatasource()->getDbType() === 'pgsql') {
+ $table = $this->customVars[$alias];
+ if (! isset($groupedTables[$table])) {
+ $group[] = $this->getCustomvarColumnName($alias);
+ $groupedTables[$table] = true;
+ }
+ continue;
+ }
+ $table = $this->aliasToTableName($alias);
+ if ($table && !isset($groupedTables[$table]) && (
+ in_array($table, $joinedOrigins, true) || $this->getDatasource()->getDbType() === 'pgsql')
+ ) {
+ $this->registerGroupColumns($alias, $table, $group, $groupedTables);
+ }
+ }
+
+ if (! empty($group) && $this->getDatasource()->getDbType() === 'pgsql') {
+ foreach (new ColumnFilterIterator($this->orderColumns) as $alias) {
+ if ($this->isCustomVar($alias)) {
+ $table = $this->customVars[$alias];
+ if (! isset($groupedTables[$table])) {
+ $group[] = $this->getCustomvarColumnName($alias);
+ $groupedTables[$table] = true;
+ }
+ continue;
+ }
+ $table = $this->aliasToTableName($alias);
+ if ($table && !isset($groupedTables[$table])
+ && !in_array($this->getMappedField($alias), $this->columns, true)
+ ) {
+ $this->registerGroupColumns($alias, $table, $group, $groupedTables);
+ }
+ }
+ }
+
+ return array_unique($group);
+ }
+
+ // TODO: Move this away, see note related to $idoVersion var
+ protected function getIdoVersion()
+ {
+ if (self::$idoVersion === null) {
+ $dbconf = $this->db->getConfig();
+ $id = $dbconf['host'] . '/' . $dbconf['dbname'];
+ $session = null;
+ if (Icinga::app()->isWeb()) {
+ // TODO: Once we have version per connection we should choose a
+ // namespace based on resource name
+ $session = Session::getSession()->getNamespace('monitoring/ido/' . $id);
+ if (isset($session->version)) {
+ self::$idoVersion = $session->version;
+ return self::$idoVersion;
+ }
+ }
+ self::$idoVersion = $this->db->fetchOne(
+ $this->db->select()->from($this->prefix . 'dbversion', 'version')
+ );
+ if ($session !== null) {
+ $session->version = self::$idoVersion;
+ }
+ }
+ return self::$idoVersion;
+ }
+
+ /**
+ * Return the name of the primary key column for the given table name
+ *
+ * @param string $table
+ *
+ * @return string
+ *
+ * @throws ProgrammingError In case $table is unknown
+ */
+ protected function getPrimaryKeyColumn($table)
+ {
+ // TODO: For god's sake, make this being a mapping
+ // (instead of matching a ton of properties using a ridiculous long switch case)
+ switch ($table) {
+ case 'instances':
+ return $this->instance_id;
+ case 'objects':
+ return $this->object_id;
+ case 'acknowledgements':
+ return $this->acknowledgement_id;
+ case 'commenthistory':
+ return $this->commenthistory_id;
+ case 'contactnotifiations':
+ return $this->contactnotification_id;
+ case 'downtimehistory':
+ return $this->downtimehistory_id;
+ case 'flappinghistory':
+ return $this->flappinghistory_id;
+ case 'notifications':
+ return $this->notification_id;
+ case 'statehistory':
+ return $this->statehistory_id;
+ case 'comments':
+ return $this->comment_id;
+ case 'customvariablestatus':
+ return $this->customvariablestatus_id;
+ case 'hoststatus':
+ return $this->hoststatus_id;
+ case 'programstatus':
+ return $this->programstatus_id;
+ case 'runtimevariables':
+ return $this->runtimevariable_id;
+ case 'scheduleddowntime':
+ return $this->scheduleddowntime_id;
+ case 'servicestatus':
+ return $this->servicestatus_id;
+ case 'contactstatus':
+ return $this->contactstatus_id;
+ case 'commands':
+ return $this->command_id;
+ case 'contactgroup_members':
+ return $this->contactgroup_member_id;
+ case 'contactgroups':
+ return $this->contactgroup_id;
+ case 'contacts':
+ return $this->contact_id;
+ case 'customvariables':
+ return $this->customvariable_id;
+ case 'host_contactgroups':
+ return $this->host_contactgroup_id;
+ case 'host_contacts':
+ return $this->host_contact_id;
+ case 'hostgroup_members':
+ return $this->hostgroup_member_id;
+ case 'hostgroups':
+ return $this->hostgroup_id;
+ case 'hosts':
+ return $this->host_id;
+ case 'service_contactgroups':
+ return $this->service_contactgroup_id;
+ case 'service_contacts':
+ return $this->service_contact_id;
+ case 'servicegroup_members':
+ return $this->servicegroup_member_id;
+ case 'servicegroups':
+ return $this->servicegroup_id;
+ case 'services':
+ return $this->service_id;
+ case 'timeperiods':
+ return $this->timeperiod_id;
+ default:
+ throw new ProgrammingError('Cannot provide a primary key column. Table "%s" is unknown', $table);
+ }
+ }
+}
diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/InstanceQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/InstanceQuery.php
new file mode 100644
index 0000000..ac538ec
--- /dev/null
+++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/InstanceQuery.php
@@ -0,0 +1,26 @@
+<?php
+/* Icinga Web 2 | (c) 2015 Icinga Development Team | GPLv2+ */
+
+namespace Icinga\Module\Monitoring\Backend\Ido\Query;
+
+class InstanceQuery extends IdoQuery
+{
+ /**
+ * {@inheritdoc}
+ */
+ protected $columnMap = array(
+ 'instances' => array(
+ 'instance_id' => 'i.instance_id',
+ 'instance_name' => 'i.instance_name'
+ )
+ );
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function joinBaseTables()
+ {
+ $this->select()->from(array('i' => $this->prefix . 'instances'), array());
+ $this->joinedVirtualTables['instances'] = true;
+ }
+}
diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/NotificationQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/NotificationQuery.php
new file mode 100644
index 0000000..8bfb725
--- /dev/null
+++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/NotificationQuery.php
@@ -0,0 +1,144 @@
+<?php
+/* Icinga Web 2 | (c) 2013 Icinga Development Team | GPLv2+ */
+
+namespace Icinga\Module\Monitoring\Backend\Ido\Query;
+
+use Icinga\Data\Filter\FilterExpression;
+use Zend_Db_Expr;
+use Zend_Db_Select;
+use Icinga\Data\Filter\Filter;
+
+/**
+ * Query for host and service notifications
+ */
+class NotificationQuery extends IdoQuery
+{
+ /**
+ * {@inheritdoc}
+ */
+ protected $allowCustomVars = true;
+
+ /**
+ * {@inheritdoc}
+ */
+ protected $columnMap = array(
+ 'notifications' => array(
+ 'id' => 'n.id',
+ 'instance_name' => 'n.instance_name',
+ 'notification_contact_name' => 'n.notification_contact_name',
+ 'notification_output' => 'n.notification_output',
+ 'notification_reason' => 'n.notification_reason',
+ 'notification_state' => 'n.notification_state',
+ 'notification_timestamp' => 'n.notification_timestamp'
+ ),
+ 'hosts' => array(
+ 'host_display_name' => 'n.host_display_name',
+ 'host_name' => 'n.host_name'
+ ),
+ 'services' => array(
+ 'service_description' => 'n.service_description',
+ 'service_display_name' => 'n.service_display_name',
+ 'service_host_name' => 'n.service_host_name'
+ )
+ );
+
+ /**
+ * The union
+ *
+ * @var Zend_Db_Select
+ */
+ protected $notificationQuery;
+
+ /**
+ * Subqueries used for the notification query
+ *
+ * @var IdoQuery[]
+ */
+ protected $subQueries = array();
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function joinBaseTables()
+ {
+ $this->notificationQuery = $this->db->select();
+ $this->select->from(
+ array('n' => $this->notificationQuery),
+ array()
+ );
+ $this->joinedVirtualTables['notifications'] = true;
+ }
+
+ /**
+ * Join hosts
+ */
+ protected function joinHosts()
+ {
+ $columns = $this->desiredColumns;
+ $columns = array_combine($columns, $columns);
+ foreach ($this->columnMap['services'] as $column => $_) {
+ if (isset($columns[$column])) {
+ $columns[$column] = new Zend_Db_Expr('NULL');
+ }
+ }
+ $hosts = $this->createSubQuery('hostnotification', $columns);
+ $hosts->setIsSubQuery(true);
+ $this->subQueries[] = $hosts;
+ $this->notificationQuery->union(array($hosts), Zend_Db_Select::SQL_UNION_ALL);
+ }
+
+ /**
+ * Join services
+ */
+ protected function joinServices()
+ {
+ $services = $this->createSubQuery('servicenotification', $this->desiredColumns);
+ $services->setIsSubQuery(true);
+ $this->subQueries[] = $services;
+ $this->notificationQuery->union(array($services), Zend_Db_Select::SQL_UNION_ALL);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function addFilter(Filter $filter)
+ {
+ foreach ($this->subQueries as $sub) {
+ $sub->applyFilter(clone $filter);
+ }
+ return $this;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function order($columnOrAlias, $dir = null)
+ {
+ foreach ($this->subQueries as $sub) {
+ $sub->requireColumn($columnOrAlias);
+ }
+ return parent::order($columnOrAlias, $dir);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function where($condition, $value = null)
+ {
+ $this->requireColumn($condition);
+ foreach ($this->subQueries as $sub) {
+ $sub->where($condition, $value);
+ }
+ return $this;
+ }
+
+ public function whereEx(FilterExpression $ex)
+ {
+ $this->requireColumn($ex->getColumn());
+ foreach ($this->subQueries as $sub) {
+ $sub->whereEx($ex);
+ }
+
+ return $this;
+ }
+}
diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/NotificationeventQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/NotificationeventQuery.php
new file mode 100644
index 0000000..87a71f6
--- /dev/null
+++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/NotificationeventQuery.php
@@ -0,0 +1,52 @@
+<?php
+/* Icinga Web 2 | (c) 2017 Icinga Development Team | GPLv2+ */
+
+namespace Icinga\Module\Monitoring\Backend\Ido\Query;
+
+/**
+ * Query for host and service notification events
+ */
+class NotificationeventQuery extends IdoQuery
+{
+ protected $columnMap = array(
+ 'notificationevent' => array(
+ 'notificationevent_id' => 'n.notification_id',
+ 'notificationevent_reason' => <<<EOF
+(CASE n.notification_reason
+ WHEN 0 THEN 'normal_notification'
+ WHEN 1 THEN 'ack'
+ WHEN 2 THEN 'flapping_started'
+ WHEN 3 THEN 'flapping_stopped'
+ WHEN 4 THEN 'flapping_disabled'
+ WHEN 5 THEN 'dt_start'
+ WHEN 6 THEN 'dt_end'
+ WHEN 7 THEN 'dt_cancel'
+ WHEN 99 THEN 'custom_notification'
+ ELSE NULL
+END)
+EOF
+ ,
+ 'notificationevent_start_time' => 'UNIX_TIMESTAMP(n.start_time)',
+ 'notificationevent_end_time' => 'UNIX_TIMESTAMP(n.end_time)',
+ 'notificationevent_state' => 'n.state',
+ 'notificationevent_output' => 'n.output',
+ 'notificationevent_long_output' => 'n.long_output',
+ 'notificationevent_escalated' => 'n.escalated',
+ 'notificationevent_contacts_notified' => 'n.contacts_notified'
+ ),
+ 'object' => array(
+ 'host_name' => 'o.name1',
+ 'service_description' => 'o.name2'
+ )
+ );
+
+ protected function joinBaseTables()
+ {
+ $this->select()
+ ->from(array('n' => $this->prefix . 'notifications'), array())
+ ->join(array('o' => $this->prefix . 'objects'), 'n.object_id = o.object_id', array());
+
+ $this->joinedVirtualTables['notificationevent'] = true;
+ $this->joinedVirtualTables['object'] = true;
+ }
+}
diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/NotificationhistoryQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/NotificationhistoryQuery.php
new file mode 100644
index 0000000..f629115
--- /dev/null
+++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/NotificationhistoryQuery.php
@@ -0,0 +1,142 @@
+<?php
+/* Icinga Web 2 | (c) 2013 Icinga Development Team | GPLv2+ */
+
+namespace Icinga\Module\Monitoring\Backend\Ido\Query;
+
+use Icinga\Data\Filter\FilterExpression;
+use Zend_Db_Expr;
+use Zend_Db_Select;
+use Icinga\Data\Filter\Filter;
+
+/**
+ * Query for host and service notification history
+ */
+class NotificationhistoryQuery extends IdoQuery
+{
+ /**
+ * {@inheritdoc}
+ */
+ protected $allowCustomVars = true;
+
+ /**
+ * {@inheritdoc}
+ */
+ protected $columnMap = array(
+ 'history' => array(
+ 'id' => 'n.id',
+ 'object_type' => 'n.object_type',
+ 'output' => 'n.output',
+ 'state' => 'n.state',
+ 'timestamp' => 'n.timestamp',
+ 'type' => 'n.type'
+ ),
+ 'hosts' => array(
+ 'host_display_name' => 'n.host_display_name',
+ 'host_name' => 'n.host_name'
+ ),
+ 'services' => array(
+ 'service_description' => 'n.service_description',
+ 'service_display_name' => 'n.service_display_name',
+ 'service_host_name' => 'n.service_host_name'
+ )
+ );
+
+ /**
+ * The union
+ *
+ * @var Zend_Db_Select
+ */
+ protected $notificationQuery;
+
+ /**
+ * Subqueries used for the notification query
+ *
+ * @var IdoQuery[]
+ */
+ protected $subQueries = array();
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function joinBaseTables()
+ {
+ $this->notificationQuery = $this->db->select();
+ $this->select->from(
+ array('n' => $this->notificationQuery),
+ array()
+ );
+ $this->joinedVirtualTables['history'] = true;
+ }
+
+ /**
+ * Join hosts
+ */
+ protected function joinHosts()
+ {
+ $columns = $this->desiredColumns;
+ $columns = array_combine($columns, $columns);
+ foreach ($this->columnMap['services'] as $column => $_) {
+ if (isset($columns[$column])) {
+ $columns[$column] = new Zend_Db_Expr('NULL');
+ }
+ }
+ $hosts = $this->createSubQuery('hostnotification', $columns);
+ $this->subQueries[] = $hosts;
+ $this->notificationQuery->union(array($hosts), Zend_Db_Select::SQL_UNION_ALL);
+ }
+
+ /**
+ * Join services
+ */
+ protected function joinServices()
+ {
+ $columns = array_flip($this->desiredColumns);
+ $services = $this->createSubQuery('servicenotification', array_flip($columns));
+ $this->subQueries[] = $services;
+ $this->notificationQuery->union(array($services), Zend_Db_Select::SQL_UNION_ALL);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function addFilter(Filter $filter)
+ {
+ foreach ($this->subQueries as $sub) {
+ $sub->applyFilter(clone $filter);
+ }
+ return $this;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function order($columnOrAlias, $dir = null)
+ {
+ foreach ($this->subQueries as $sub) {
+ $sub->requireColumn($columnOrAlias);
+ }
+ return parent::order($columnOrAlias, $dir);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function where($condition, $value = null)
+ {
+ $this->requireColumn($condition);
+ foreach ($this->subQueries as $sub) {
+ $sub->where($condition, $value);
+ }
+ return $this;
+ }
+
+ public function whereEx(FilterExpression $ex)
+ {
+ $this->requireColumn($ex->getColumn());
+ foreach ($this->subQueries as $sub) {
+ $sub->whereEx($ex);
+ }
+
+ return $this;
+ }
+}
diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/ProgramstatusQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/ProgramstatusQuery.php
new file mode 100644
index 0000000..9e9f5f6
--- /dev/null
+++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/ProgramstatusQuery.php
@@ -0,0 +1,68 @@
+<?php
+/* Icinga Web 2 | (c) 2013 Icinga Development Team | GPLv2+ */
+
+namespace Icinga\Module\Monitoring\Backend\Ido\Query;
+
+/**
+ * Program status query
+ */
+class ProgramstatusQuery extends IdoQuery
+{
+ /**
+ * {@inheritdoc}
+ */
+ protected $columnMap = array(
+ 'programstatus' => array(
+ 'id' => 'programstatus_id',
+ 'status_update_time' => 'UNIX_TIMESTAMP(programstatus.status_update_time)',
+ 'program_version' => 'program_version',
+ 'program_start_time' => 'UNIX_TIMESTAMP(programstatus.program_start_time)',
+ 'program_end_time' => 'UNIX_TIMESTAMP(programstatus.program_end_time)',
+ 'is_currently_running' => 'CASE WHEN (UNIX_TIMESTAMP(programstatus.status_update_time) + 60 > UNIX_TIMESTAMP(NOW()))
+ THEN
+ 1
+ ELSE
+ 0
+ END',
+ 'process_id' => 'process_id',
+ 'endpoint_name' => 'endpoint_name',
+ 'daemon_mode' => 'daemon_mode',
+ 'last_command_check' => 'UNIX_TIMESTAMP(programstatus.last_command_check)',
+ 'last_log_rotation' => 'UNIX_TIMESTAMP(programstatus.last_log_rotation)',
+ 'notifications_enabled' => 'notifications_enabled',
+ 'disable_notif_expire_time' => 'UNIX_TIMESTAMP(programstatus.disable_notif_expire_time)',
+ 'active_service_checks_enabled' => 'active_service_checks_enabled',
+ 'passive_service_checks_enabled' => 'passive_service_checks_enabled',
+ 'active_host_checks_enabled' => 'active_host_checks_enabled',
+ 'passive_host_checks_enabled' => 'passive_host_checks_enabled',
+ 'event_handlers_enabled' => 'event_handlers_enabled',
+ 'flap_detection_enabled' => 'flap_detection_enabled',
+ 'failure_prediction_enabled' => 'failure_prediction_enabled',
+ 'process_performance_data' => 'process_performance_data',
+ 'obsess_over_hosts' => 'obsess_over_hosts',
+ 'obsess_over_services' => 'obsess_over_services',
+ 'modified_host_attributes' => 'modified_host_attributes',
+ 'modified_service_attributes' => 'modified_service_attributes',
+ 'global_host_event_handler' => 'global_host_event_handler',
+ 'global_service_event_handler' => 'global_service_event_handler',
+ )
+ );
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function joinBaseTables()
+ {
+ parent::joinBaseTables();
+
+ if (version_compare($this->getIdoVersion(), '1.11.7', '<')) {
+ $this->columnMap['programstatus']['endpoint_name'] = '(0)';
+ }
+ if (version_compare($this->getIdoVersion(), '1.11.8', '<')) {
+ $this->columnMap['programstatus']['program_version'] = '(NULL)';
+ }
+ if (version_compare($this->getIdoVersion(), '1.8', '<')) {
+ $this->columnMap['programstatus']['disable_notif_expire_time'] = '(NULL)';
+ }
+ }
+}
diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/RuntimesummaryQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/RuntimesummaryQuery.php
new file mode 100644
index 0000000..1aa2257
--- /dev/null
+++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/RuntimesummaryQuery.php
@@ -0,0 +1,80 @@
+<?php
+/* Icinga Web 2 | (c) 2013 Icinga Development Team | GPLv2+ */
+
+namespace Icinga\Module\Monitoring\Backend\Ido\Query;
+
+use Zend_Db_Select;
+
+/**
+ * Query check summaries out of database
+ */
+class RuntimesummaryQuery extends IdoQuery
+{
+ protected $columnMap = array(
+ 'runtimesummary' => array(
+ 'check_type' => 'check_type',
+ 'active_checks_enabled' => 'active_checks_enabled',
+ 'passive_checks_enabled' => 'passive_checks_enabled',
+ 'execution_time' => 'execution_time',
+ 'latency' => 'latency',
+ 'object_count' => 'object_count',
+ 'object_type' => 'object_type'
+ )
+ );
+
+ protected function joinBaseTables()
+ {
+ $hosts = $this->db->select()->from(
+ array('ho' => $this->prefix . 'objects'),
+ array()
+ )->join(
+ array('hs' => $this->prefix . 'hoststatus'),
+ 'ho.object_id = hs.host_object_id AND ho.is_active = 1 AND ho.objecttype_id = 1',
+ array()
+ )->columns(
+ array(
+ 'check_type' => 'CASE '
+ . 'WHEN hs.active_checks_enabled = 0 AND hs.passive_checks_enabled = 1 THEN \'passive\' '
+ . 'WHEN hs.active_checks_enabled = 1 THEN \'active\' '
+ . 'END',
+ 'active_checks_enabled' => 'hs.active_checks_enabled',
+ 'passive_checks_enabled' => 'hs.passive_checks_enabled',
+ 'execution_time' => 'SUM(hs.execution_time)',
+ 'latency' => 'SUM(hs.latency)',
+ 'object_count' => 'COUNT(*)',
+ 'object_type' => "('host')"
+ )
+ )->group('check_type')->group('active_checks_enabled')->group('passive_checks_enabled');
+
+ $services = $this->db->select()->from(
+ array('so' => $this->prefix . 'objects'),
+ array()
+ )->join(
+ array('ss' => $this->prefix . 'servicestatus'),
+ 'so.object_id = ss.service_object_id AND so.is_active = 1 AND so.objecttype_id = 2',
+ array()
+ )->columns(
+ array(
+ 'check_type' => 'CASE '
+ . 'WHEN ss.active_checks_enabled = 0 AND ss.passive_checks_enabled = 1 THEN \'passive\' '
+ . 'WHEN ss.active_checks_enabled = 1 THEN \'active\' '
+ . 'END',
+ 'active_checks_enabled' => 'ss.active_checks_enabled',
+ 'passive_checks_enabled' => 'ss.passive_checks_enabled',
+ 'execution_time' => 'SUM(ss.execution_time)',
+ 'latency' => 'SUM(ss.latency)',
+ 'object_count' => 'COUNT(*)',
+ 'object_type' => "('service')"
+ )
+ )->group('check_type')->group('active_checks_enabled')->group('passive_checks_enabled');
+
+ $union = $this->db->select()->union(
+ array('s' => $services, 'h' => $hosts),
+ Zend_Db_Select::SQL_UNION_ALL
+ );
+
+ $this->select->from(array('hs' => $union));
+
+ $this->joinedVirtualTables = array('runtimesummary' => true);
+ }
+}
diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/RuntimevariablesQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/RuntimevariablesQuery.php
new file mode 100644
index 0000000..494744a
--- /dev/null
+++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/RuntimevariablesQuery.php
@@ -0,0 +1,18 @@
+<?php
+/* Icinga Web 2 | (c) 2013 Icinga Development Team | GPLv2+ */
+
+namespace Icinga\Module\Monitoring\Backend\Ido\Query;
+
+/**
+ * Query for runtimevariables table
+ */
+class RuntimevariablesQuery extends IdoQuery
+{
+ protected $columnMap = array(
+ 'runtimevariables' => array(
+ 'id' => 'runtimevariable_id',
+ 'varname' => 'varname',
+ 'varvalue' => 'varvalue'
+ )
+ );
+}
diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/ServicecommentQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/ServicecommentQuery.php
new file mode 100644
index 0000000..cae11bc
--- /dev/null
+++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/ServicecommentQuery.php
@@ -0,0 +1,218 @@
+<?php
+/* Icinga Web 2 | (c) 2015 Icinga Development Team | GPLv2+ */
+
+namespace Icinga\Module\Monitoring\Backend\Ido\Query;
+
+/**
+ * Query for service comments
+ */
+class ServicecommentQuery extends IdoQuery
+{
+ /**
+ * {@inheritdoc}
+ */
+ protected $allowCustomVars = true;
+
+ /**
+ * {@inheritdoc}
+ */
+ protected $groupBase = array('comments' => array('c.comment_id', 'so.object_id'));
+
+ /**
+ * {@inheritdoc}
+ */
+ protected $groupOrigin = array('hostgroups', 'servicegroups');
+
+ protected $subQueryTargets = array(
+ 'hostgroups' => 'hostgroup',
+ 'servicegroups' => 'servicegroup'
+ );
+
+ /**
+ * {@inheritdoc}
+ */
+ protected $columnMap = array(
+ 'comments' => array(
+ 'comment_author' => 'c.author_name COLLATE latin1_general_ci',
+ 'comment_author_name' => 'c.author_name',
+ 'comment_data' => 'c.comment_data',
+ 'comment_expiration' => 'CASE c.expires WHEN 1 THEN UNIX_TIMESTAMP(c.expiration_time) ELSE NULL END',
+ 'comment_internal_id' => 'c.internal_comment_id',
+ 'comment_is_persistent' => 'c.is_persistent',
+ 'comment_name' => 'c.name',
+ 'comment_timestamp' => 'UNIX_TIMESTAMP(c.comment_time)',
+ 'comment_type' => "CASE c.entry_type WHEN 1 THEN 'comment' WHEN 2 THEN 'downtime' WHEN 3 THEN 'flapping' WHEN 4 THEN 'ack' END",
+ 'host' => 'so.name1 COLLATE latin1_general_ci',
+ 'host_name' => 'so.name1',
+ 'object_type' => '(\'service\')',
+ 'service' => 'so.name2 COLLATE latin1_general_ci',
+ 'service_description' => 'so.name2',
+ 'service_host' => 'so.name1 COLLATE latin1_general_ci',
+ 'service_host_name' => 'so.name1'
+ ),
+ 'hostgroups' => array(
+ 'hostgroup' => 'hgo.name1 COLLATE latin1_general_ci',
+ 'hostgroup_alias' => 'hg.alias COLLATE latin1_general_ci',
+ 'hostgroup_name' => 'hgo.name1'
+ ),
+ 'hosts' => array(
+ 'host_alias' => 'h.alias',
+ 'host_display_name' => 'h.display_name COLLATE latin1_general_ci'
+ ),
+ 'instances' => array(
+ 'instance_name' => 'i.instance_name'
+ ),
+ 'hoststatus' => array(
+ 'host_state' => 'CASE WHEN hs.has_been_checked = 0 OR hs.has_been_checked IS NULL THEN 99 ELSE hs.current_state END'
+ ),
+ 'servicegroups' => array(
+ 'servicegroup' => 'sgo.name1 COLLATE latin1_general_ci',
+ 'servicegroup_name' => 'sgo.name1',
+ 'servicegroup_alias' => 'sg.alias COLLATE latin1_general_ci'
+ ),
+ 'services' => array(
+ 'service_display_name' => 's.display_name COLLATE latin1_general_ci'
+ ),
+ 'servicestatus' => array(
+ 'service_state' => 'CASE WHEN ss.has_been_checked = 0 OR ss.has_been_checked IS NULL THEN 99 ELSE ss.current_state END'
+ )
+ );
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function joinBaseTables()
+ {
+ if (version_compare($this->getIdoVersion(), '1.14.0', '<')) {
+ $this->columnMap['comments']['comment_name'] = '(NULL)';
+ }
+ $this->select->from(
+ array('c' => $this->prefix . 'comments'),
+ array()
+ )->join(
+ array('so' => $this->prefix . 'objects'),
+ 'so.object_id = c.object_id AND so.is_active = 1 AND so.objecttype_id = 2',
+ array()
+ );
+ $this->joinedVirtualTables['comments'] = true;
+ }
+ /**
+ * Join host groups
+ */
+ protected function joinHostgroups()
+ {
+ $this->requireVirtualTable('services');
+ $this->select->joinLeft(
+ array('hgm' => $this->prefix . 'hostgroup_members'),
+ 'hgm.host_object_id = s.host_object_id',
+ array()
+ )->joinLeft(
+ array('hg' => $this->prefix . 'hostgroups'),
+ 'hg.hostgroup_id = hgm.hostgroup_id',
+ array()
+ )->joinLeft(
+ array('hgo' => $this->prefix . 'objects'),
+ 'hgo.object_id = hg.hostgroup_object_id AND hgo.is_active = 1 AND hgo.objecttype_id = 3',
+ array()
+ );
+ }
+
+ /**
+ * Join hosts
+ */
+ protected function joinHosts()
+ {
+ $this->requireVirtualTable('services');
+ $this->select->join(
+ array('h' => $this->prefix . 'hosts'),
+ 'h.host_object_id = s.host_object_id',
+ array()
+ );
+ }
+
+ /**
+ * Join host status
+ */
+ protected function joinHoststatus()
+ {
+ $this->requireVirtualTable('services');
+ $this->select->join(
+ array('hs' => $this->prefix . 'hoststatus'),
+ 'hs.host_object_id = s.host_object_id',
+ array()
+ );
+ }
+
+ /**
+ * Join service groups
+ */
+ protected function joinServicegroups()
+ {
+ $this->select->joinLeft(
+ array('sgm' => $this->prefix . 'servicegroup_members'),
+ 'sgm.service_object_id = so.object_id',
+ array()
+ )->joinLeft(
+ array('sg' => $this->prefix . 'servicegroups'),
+ 'sgm.servicegroup_id = sg.' . $this->servicegroup_id,
+ array()
+ )->joinLeft(
+ array('sgo' => $this->prefix . 'objects'),
+ 'sgo.object_id = sg.servicegroup_object_id AND sgo.is_active = 1 AND sgo.objecttype_id = 4',
+ array()
+ );
+ }
+
+ /**
+ * Join instances
+ */
+ protected function joinInstances()
+ {
+ $this->select->join(
+ array('i' => $this->prefix . 'instances'),
+ 'i.instance_id = c.instance_id',
+ array()
+ );
+ }
+
+ /**
+ * Join services
+ */
+ protected function joinServices()
+ {
+ $this->select->join(
+ array('s' => $this->prefix . 'services'),
+ 's.service_object_id = so.object_id',
+ array()
+ );
+ }
+
+ /**
+ * Join service status
+ */
+ protected function joinServicestatus()
+ {
+ $this->select->join(
+ array('ss' => $this->prefix . 'servicestatus'),
+ 'ss.service_object_id = so.object_id',
+ array()
+ );
+ }
+
+ protected function joinSubQuery(IdoQuery $query, $name, $filter, $and, $negate, &$additionalFilter)
+ {
+ if ($name === 'hostgroup') {
+ $this->requireVirtualTable('services');
+
+ $query->joinVirtualTable('members');
+
+ return ['hgm.host_object_id', 's.host_object_id'];
+ } elseif ($name === 'servicegroup') {
+ $query->joinVirtualTable('members');
+
+ return ['sgm.service_object_id', 'so.object_id'];
+ }
+
+ return parent::joinSubQuery($query, $name, $filter, $and, $negate, $additionalFilter);
+ }
+}
diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/ServicecommentdeletionhistoryQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/ServicecommentdeletionhistoryQuery.php
new file mode 100644
index 0000000..33aaa25
--- /dev/null
+++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/ServicecommentdeletionhistoryQuery.php
@@ -0,0 +1,44 @@
+<?php
+/* Icinga Web 2 | (c) 2015 Icinga Development Team | GPLv2+ */
+
+namespace Icinga\Module\Monitoring\Backend\Ido\Query;
+
+use Icinga\Data\Filter\Filter;
+use Icinga\Data\Filter\FilterExpression;
+
+/**
+ * Query for service comment removal records
+ */
+class ServicecommentdeletionhistoryQuery extends ServicecommenthistoryQuery
+{
+ protected function requireFilterColumns(Filter $filter)
+ {
+ if ($filter instanceof FilterExpression && $filter->getColumn() === 'timestamp') {
+ $this->requireColumn('timestamp');
+ $filter->setColumn('sch.deletion_time');
+ $filter->setExpression($this->timestampForSql($this->valueToTimestamp($filter->getExpression())));
+ return null;
+ }
+
+ return parent::requireFilterColumns($filter);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function joinBaseTables()
+ {
+ parent::joinBaseTables();
+ $this->select->where("sch.deletion_time > '1970-01-02 00:00:00'");
+ $this->columnMap['commenthistory']['timestamp'] = str_replace(
+ 'comment_time',
+ 'deletion_time',
+ $this->columnMap['commenthistory']['timestamp']
+ );
+ $this->columnMap['commenthistory']['type'] = str_replace(
+ 'END)',
+ "END || '_deleted')",
+ $this->columnMap['commenthistory']['type']
+ );
+ }
+}
diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/ServicecommenthistoryQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/ServicecommenthistoryQuery.php
new file mode 100644
index 0000000..b3e9c16
--- /dev/null
+++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/ServicecommenthistoryQuery.php
@@ -0,0 +1,195 @@
+<?php
+/* Icinga Web 2 | (c) 2015 Icinga Development Team | GPLv2+ */
+
+namespace Icinga\Module\Monitoring\Backend\Ido\Query;
+
+use Icinga\Data\Filter\Filter;
+use Icinga\Data\Filter\FilterExpression;
+
+/**
+ * Query for service comment history records
+ */
+class ServicecommenthistoryQuery extends IdoQuery
+{
+ /**
+ * {@inheritdoc}
+ */
+ protected $allowCustomVars = true;
+
+ /**
+ * {@inheritdoc}
+ */
+ protected $groupBase = array('commenthistory' => array('sch.commenthistory_id', 'so.object_id'));
+
+ /**
+ * {@inheritdoc}
+ */
+ protected $groupOrigin = array('hostgroups', 'servicegroups', 'services');
+
+ protected $subQueryTargets = array(
+ 'hostgroups' => 'hostgroup',
+ 'servicegroups' => 'servicegroup'
+ );
+
+ /**
+ * {@inheritdoc}
+ */
+ protected $columnMap = array(
+ 'commenthistory' => array(
+ 'id' => 'sch.commenthistory_id',
+ 'host' => 'so.name1 COLLATE latin1_general_ci',
+ 'host_name' => 'so.name1',
+ 'object_id' => 'sch.object_id',
+ 'object_type' => '(\'service\')',
+ 'output' => "('[' || sch.author_name || '] ' || sch.comment_data)",
+ 'service' => 'so.name2 COLLATE latin1_general_ci',
+ 'service_description' => 'so.name2',
+ 'service_host' => 'so.name1 COLLATE latin1_general_ci',
+ 'service_host_name' => 'so.name1',
+ 'state' => '(-1)',
+ 'timestamp' => 'UNIX_TIMESTAMP(sch.comment_time)',
+ 'type' => "(CASE sch.entry_type WHEN 1 THEN 'comment' WHEN 2 THEN 'dt_comment' WHEN 3 THEN 'flapping' WHEN 4 THEN 'ack' END)"
+ ),
+ 'hostgroups' => array(
+ 'hostgroup' => 'hgo.name1 COLLATE latin1_general_ci',
+ 'hostgroup_alias' => 'hg.alias COLLATE latin1_general_ci',
+ 'hostgroup_name' => 'hgo.name1'
+ ),
+ 'hosts' => array(
+ 'host_alias' => 'h.alias',
+ 'host_display_name' => 'h.display_name COLLATE latin1_general_ci'
+ ),
+ 'instances' => array(
+ 'instance_name' => 'i.instance_name'
+ ),
+ 'servicegroups' => array(
+ 'servicegroup' => 'sgo.name1 COLLATE latin1_general_ci',
+ 'servicegroup_name' => 'sgo.name1',
+ 'servicegroup_alias' => 'sg.alias COLLATE latin1_general_ci'
+ ),
+ 'services' => array(
+ 'service_display_name' => 's.display_name COLLATE latin1_general_ci'
+ )
+ );
+
+ protected function requireFilterColumns(Filter $filter)
+ {
+ if ($filter instanceof FilterExpression && $filter->getColumn() === 'timestamp') {
+ $this->requireColumn('timestamp');
+ $filter->setColumn('sch.comment_time');
+ $filter->setExpression($this->timestampForSql($this->valueToTimestamp($filter->getExpression())));
+ return null;
+ }
+
+ return parent::requireFilterColumns($filter);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function joinBaseTables()
+ {
+ $this->select->from(
+ array('sch' => $this->prefix . 'commenthistory'),
+ array()
+ )->join(
+ array('so' => $this->prefix . 'objects'),
+ 'so.object_id = sch.object_id AND so.is_active = 1 AND so.objecttype_id = 2',
+ array()
+ );
+ $this->joinedVirtualTables['commenthistory'] = true;
+ }
+
+ /**
+ * Join host groups
+ */
+ protected function joinHostgroups()
+ {
+ $this->requireVirtualTable('services');
+ $this->select->joinLeft(
+ array('hgm' => $this->prefix . 'hostgroup_members'),
+ 'hgm.host_object_id = s.host_object_id',
+ array()
+ )->joinLeft(
+ array('hg' => $this->prefix . 'hostgroups'),
+ 'hg.hostgroup_id = hgm.hostgroup_id',
+ array()
+ )->joinLeft(
+ array('hgo' => $this->prefix . 'objects'),
+ 'hgo.object_id = hg.hostgroup_object_id AND hgo.is_active = 1 AND hgo.objecttype_id = 3',
+ array()
+ );
+ }
+
+ /**
+ * Join hosts
+ */
+ protected function joinHosts()
+ {
+ $this->requireVirtualTable('services');
+ $this->select->join(
+ array('h' => $this->prefix . 'hosts'),
+ 'h.host_object_id = s.host_object_id',
+ array()
+ );
+ }
+
+ /**
+ * Join instances
+ */
+ protected function joinInstances()
+ {
+ $this->select->join(
+ array('i' => $this->prefix . 'instances'),
+ 'i.instance_id = sch.instance_id',
+ array()
+ );
+ }
+
+ /**
+ * Join service groups
+ */
+ protected function joinServicegroups()
+ {
+ $this->select->joinLeft(
+ array('sgm' => $this->prefix . 'servicegroup_members'),
+ 'sgm.service_object_id = so.object_id',
+ array()
+ )->joinLeft(
+ array('sg' => $this->prefix . 'servicegroups'),
+ 'sg.' . $this->servicegroup_id . ' = sgm.servicegroup_id',
+ array()
+ )->joinLeft(
+ array('sgo' => $this->prefix . 'objects'),
+ 'sgo.object_id = sg.servicegroup_object_id AND sgo.is_active = 1 AND sgo.objecttype_id = 4',
+ array()
+ );
+ }
+
+ /**
+ * Join services
+ */
+ protected function joinServices()
+ {
+ $this->select->join(
+ array('s' => $this->prefix . 'services'),
+ 's.service_object_id = so.object_id',
+ array()
+ );
+ }
+
+ protected function joinSubQuery(IdoQuery $query, $name, $filter, $and, $negate, &$additionalFilter)
+ {
+ if ($name === 'hostgroup') {
+ $query->joinVirtualTable('services');
+
+ return ['so.object_id', 'so.object_id'];
+ } elseif ($name === 'servicegroup') {
+ $query->joinVirtualTable('members');
+
+ return ['sgm.service_object_id', 'so.object_id'];
+ }
+
+ return parent::joinSubQuery($query, $name, $filter, $and, $negate, $additionalFilter);
+ }
+}
diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/ServicecontactQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/ServicecontactQuery.php
new file mode 100644
index 0000000..0a46709
--- /dev/null
+++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/ServicecontactQuery.php
@@ -0,0 +1,235 @@
+<?php
+/* Icinga Web 2 | (c) 2018 Icinga Development Team | GPLv2+ */
+
+namespace Icinga\Module\Monitoring\Backend\Ido\Query;
+
+/**
+ * Query for service contacts
+ */
+class ServicecontactQuery extends IdoQuery
+{
+ protected $allowCustomVars = true;
+
+ protected $groupBase = [
+ 'contacts' => ['co.object_id', 'c.contact_id'],
+ 'timeperiods' => ['ht.timeperiod_id', 'st.timeperiod_id']
+ ];
+
+ protected $groupOrigin = ['contactgroups', 'hosts', 'services'];
+
+ protected $subQueryTargets = [
+ 'hostgroups' => 'hostgroup',
+ 'servicegroups' => 'servicegroup'
+ ];
+
+ protected $columnMap = [
+ 'contactgroups' => [
+ 'contactgroup' => 'cgo.name1 COLLATE latin1_general_ci',
+ 'contactgroup_name' => 'cgo.name1',
+ 'contactgroup_alias' => 'cg.alias COLLATE latin1_general_ci'
+ ],
+ 'contacts' => [
+ 'contact_id' => 'c.contact_id',
+ 'contact' => 'co.name1 COLLATE latin1_general_ci',
+ 'contact_name' => 'co.name1',
+ 'contact_alias' => 'c.alias COLLATE latin1_general_ci',
+ 'contact_email' => 'c.email_address COLLATE latin1_general_ci',
+ 'contact_pager' => 'c.pager_address',
+ 'contact_object_id' => 'c.contact_object_id',
+ 'contact_has_host_notfications' => 'c.host_notifications_enabled',
+ 'contact_has_service_notfications' => 'c.service_notifications_enabled',
+ 'contact_can_submit_commands' => 'c.can_submit_commands',
+ 'contact_notify_service_recovery' => 'c.notify_service_recovery',
+ 'contact_notify_service_warning' => 'c.notify_service_warning',
+ 'contact_notify_service_critical' => 'c.notify_service_critical',
+ 'contact_notify_service_unknown' => 'c.notify_service_unknown',
+ 'contact_notify_service_flapping' => 'c.notify_service_flapping',
+ 'contact_notify_service_downtime' => 'c.notify_service_downtime',
+ 'contact_notify_host_recovery' => 'c.notify_host_recovery',
+ 'contact_notify_host_down' => 'c.notify_host_down',
+ 'contact_notify_host_unreachable' => 'c.notify_host_unreachable',
+ 'contact_notify_host_flapping' => 'c.notify_host_flapping',
+ 'contact_notify_host_downtime' => 'c.notify_host_downtime'
+ ],
+ 'hostgroups' => [
+ 'hostgroup' => 'hgo.name1 COLLATE latin1_general_ci',
+ 'hostgroup_alias' => 'hg.alias COLLATE latin1_general_ci',
+ 'hostgroup_name' => 'hgo.name1'
+ ],
+ 'hosts' => [
+ 'host' => 'ho.name1 COLLATE latin1_general_ci',
+ 'host_name' => 'ho.name1',
+ 'host_alias' => 'h.alias',
+ 'host_display_name' => 'h.display_name COLLATE latin1_general_ci'
+ ],
+ 'instances' => [
+ 'instance_name' => 'i.instance_name'
+ ],
+ 'servicegroups' => [
+ 'servicegroup' => 'sgo.name1 COLLATE latin1_general_ci',
+ 'servicegroup_name' => 'sgo.name1',
+ 'servicegroup_alias' => 'sg.alias COLLATE latin1_general_ci'
+ ],
+ 'services' => [
+ 'service' => 'so.name2 COLLATE latin1_general_ci',
+ 'service_description' => 'so.name2',
+ 'service_display_name' => 's.display_name COLLATE latin1_general_ci',
+ 'service_host_name' => 'so.name1'
+ ],
+ 'timeperiods' => [
+ 'contact_notify_host_timeperiod' => 'ht.alias COLLATE latin1_general_ci',
+ 'contact_notify_service_timeperiod' => 'st.alias COLLATE latin1_general_ci'
+ ]
+ ];
+
+ protected function joinBaseTables()
+ {
+ $this->select->from(
+ ['c' => $this->prefix . 'contacts'],
+ []
+ )->join(
+ ['co' => $this->prefix . 'objects'],
+ 'co.object_id = c.contact_object_id AND co.is_active = 1 AND co.objecttype_id = 10',
+ []
+ );
+
+ $this->select->joinLeft(
+ ['sc' => $this->prefix . 'service_contacts'],
+ 'sc.contact_object_id = c.contact_object_id',
+ []
+ )->joinLeft(
+ ['s' => $this->prefix . 'services'],
+ 's.service_id = sc.service_id',
+ []
+ )->joinLeft(
+ ['so' => $this->prefix . 'objects'],
+ 'so.object_id = s.service_object_id AND so.is_active = 1 AND so.objecttype_id = 2',
+ []
+ );
+
+ $this->joinedVirtualTables['contacts'] = true;
+ $this->joinedVirtualTables['services'] = true;
+ }
+
+ /**
+ * Join contact groups
+ */
+ protected function joinContactgroups()
+ {
+ $this->select->joinLeft(
+ ['cgm' => $this->prefix . 'contactgroup_members'],
+ 'co.object_id = cgm.contact_object_id',
+ []
+ )->joinLeft(
+ ['cg' => $this->prefix . 'contactgroups'],
+ 'cgm.contactgroup_id = cg.contactgroup_id',
+ []
+ )->joinLeft(
+ ['cgo' => $this->prefix . 'objects'],
+ 'cg.contactgroup_object_id = cgo.object_id AND cgo.is_active = 1 AND cgo.objecttype_id = 11',
+ []
+ );
+ }
+
+ /**
+ * Join host groups
+ */
+ protected function joinHostgroups()
+ {
+ $this->requireVirtualTable('hosts');
+ $this->select->joinLeft(
+ ['hgm' => $this->prefix . 'hostgroup_members'],
+ 'hgm.host_object_id = ho.object_id',
+ []
+ )->joinLeft(
+ ['hg' => $this->prefix . 'hostgroups'],
+ 'hg.hostgroup_id = hgm.hostgroup_id',
+ []
+ )->joinLeft(
+ ['hgo' => $this->prefix . 'objects'],
+ 'hgo.object_id = hg.hostgroup_object_id AND hgo.is_active = 1 AND hgo.objecttype_id = 3',
+ []
+ );
+ }
+
+ /**
+ * Join hosts
+ */
+ protected function joinHosts()
+ {
+ $this->select->joinLeft(
+ ['h' => $this->prefix . 'hosts'],
+ 'h.host_object_id = s.host_object_id',
+ []
+ )->joinLeft(
+ ['ho' => $this->prefix . 'objects'],
+ 'ho.object_id = h.host_object_id AND ho.is_active = 1 AND ho.objecttype_id = 1',
+ []
+ );
+ }
+
+ /**
+ * Join instances
+ */
+ protected function joinInstances()
+ {
+ $this->select->join(
+ ['i' => $this->prefix . 'instances'],
+ 'i.instance_id = c.instance_id',
+ []
+ );
+ }
+
+ /**
+ * Join service groups
+ */
+ protected function joinServicegroups()
+ {
+ $this->requireVirtualTable('services');
+ $this->select->joinLeft(
+ ['sgm' => $this->prefix . 'servicegroup_members'],
+ 'sgm.service_object_id = s.service_object_id',
+ []
+ )->joinLeft(
+ ['sg' => $this->prefix . 'servicegroups'],
+ 'sg.servicegroup_id = sgm.servicegroup_id',
+ []
+ )->joinLeft(
+ ['sgo' => $this->prefix . 'objects'],
+ 'sgo.object_id = sg.servicegroup_object_id AND sgo.is_active = 1 AND sgo.objecttype_id = 4',
+ []
+ );
+ }
+
+ /**
+ * Join time periods
+ */
+ protected function joinTimeperiods()
+ {
+ $this->select->joinLeft(
+ ['ht' => $this->prefix . 'timeperiods'],
+ 'ht.timeperiod_object_id = c.host_timeperiod_object_id',
+ []
+ );
+ $this->select->joinLeft(
+ ['st' => $this->prefix . 'timeperiods'],
+ 'st.timeperiod_object_id = c.service_timeperiod_object_id',
+ []
+ );
+ }
+
+ protected function joinSubQuery(IdoQuery $query, $name, $filter, $and, $negate, &$additionalFilter)
+ {
+ if ($name === 'hostgroup') {
+ $query->joinVirtualTable('members');
+
+ return ['hgm.host_object_id', 's.host_object_id'];
+ } elseif ($name === 'servicegroup') {
+ $query->joinVirtualTable('members');
+
+ return ['sgm.service_object_id', 'so.object_id'];
+ }
+
+ return parent::joinSubQuery($query, $name, $filter, $and, $negate, $additionalFilter);
+ }
+}
diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/ServicedowntimeQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/ServicedowntimeQuery.php
new file mode 100644
index 0000000..feea061
--- /dev/null
+++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/ServicedowntimeQuery.php
@@ -0,0 +1,222 @@
+<?php
+/* Icinga Web 2 | (c) 2015 Icinga Development Team | GPLv2+ */
+
+namespace Icinga\Module\Monitoring\Backend\Ido\Query;
+
+/**
+ * Query for service downtimes
+ */
+class ServicedowntimeQuery extends IdoQuery
+{
+ /**
+ * {@inheritdoc}
+ */
+ protected $allowCustomVars = true;
+
+ /**
+ * {@inheritdoc}
+ */
+ protected $groupBase = array('downtimes' => array('sd.scheduleddowntime_id', 'so.object_id'));
+
+ /**
+ * {@inheritdoc}
+ */
+ protected $groupOrigin = array('hostgroups', 'servicegroups');
+
+ protected $subQueryTargets = array(
+ 'hostgroups' => 'hostgroup',
+ 'servicegroups' => 'servicegroup'
+ );
+
+ /**
+ * {@inheritdoc}
+ */
+ protected $columnMap = array(
+ 'downtimes' => array(
+ 'downtime_author' => 'sd.author_name COLLATE latin1_general_ci',
+ 'downtime_author_name' => 'sd.author_name',
+ 'downtime_comment' => 'sd.comment_data',
+ 'downtime_duration' => 'sd.duration',
+ 'downtime_end' => 'CASE WHEN sd.is_fixed > 0 THEN UNIX_TIMESTAMP(sd.scheduled_end_time) ELSE UNIX_TIMESTAMP(sd.trigger_time) + sd.duration END',
+ 'downtime_entry_time' => 'UNIX_TIMESTAMP(sd.entry_time)',
+ 'downtime_internal_id' => 'sd.internal_downtime_id',
+ 'downtime_is_fixed' => 'sd.is_fixed',
+ 'downtime_is_flexible' => 'CASE WHEN sd.is_fixed = 0 THEN 1 ELSE 0 END',
+ 'downtime_is_in_effect' => 'sd.is_in_effect',
+ 'downtime_name' => 'sd.name',
+ 'downtime_scheduled_end' => 'UNIX_TIMESTAMP(sd.scheduled_end_time)',
+ 'downtime_scheduled_start' => 'UNIX_TIMESTAMP(sd.scheduled_start_time)',
+ 'downtime_start' => 'UNIX_TIMESTAMP(CASE WHEN UNIX_TIMESTAMP(sd.trigger_time) > 0 then sd.trigger_time ELSE sd.scheduled_start_time END)',
+ 'downtime_triggered_by_id' => 'sd.triggered_by_id',
+ 'host' => 'so.name1 COLLATE latin1_general_ci',
+ 'host_name' => 'so.name1',
+ 'object_type' => '(\'service\')',
+ 'service' => 'so.name2 COLLATE latin1_general_ci',
+ 'service_description' => 'so.name2',
+ 'service_host' => 'so.name1 COLLATE latin1_general_ci',
+ 'service_host_name' => 'so.name1'
+ ),
+ 'hostgroups' => array(
+ 'hostgroup' => 'hgo.name1 COLLATE latin1_general_ci',
+ 'hostgroup_alias' => 'hg.alias COLLATE latin1_general_ci',
+ 'hostgroup_name' => 'hgo.name1'
+ ),
+ 'hosts' => array(
+ 'host_alias' => 'h.alias',
+ 'host_display_name' => 'h.display_name COLLATE latin1_general_ci'
+ ),
+ 'hoststatus' => array(
+ 'host_state' => 'CASE WHEN hs.has_been_checked = 0 OR hs.has_been_checked IS NULL THEN 99 ELSE hs.current_state END'
+ ),
+ 'instances' => array(
+ 'instance_name' => 'i.instance_name'
+ ),
+ 'servicegroups' => array(
+ 'servicegroup' => 'sgo.name1 COLLATE latin1_general_ci',
+ 'servicegroup_name' => 'sgo.name1',
+ 'servicegroup_alias' => 'sg.alias COLLATE latin1_general_ci'
+ ),
+ 'services' => array(
+ 'service_display_name' => 's.display_name COLLATE latin1_general_ci'
+ ),
+ 'servicestatus' => array(
+ 'service_state' => 'CASE WHEN ss.has_been_checked = 0 OR ss.has_been_checked IS NULL THEN 99 ELSE ss.current_state END'
+ )
+ );
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function joinBaseTables()
+ {
+ if (version_compare($this->getIdoVersion(), '1.14.0', '<')) {
+ $this->columnMap['downtimes']['downtime_name'] = '(NULL)';
+ }
+ $this->select->from(
+ array('sd' => $this->prefix . 'scheduleddowntime'),
+ array()
+ )->join(
+ array('so' => $this->prefix . 'objects'),
+ 'sd.object_id = so.object_id AND so.is_active = 1 AND so.objecttype_id = 2',
+ array()
+ );
+ $this->joinedVirtualTables['downtimes'] = true;
+ }
+ /**
+ * Join host groups
+ */
+ protected function joinHostgroups()
+ {
+ $this->requireVirtualTable('services');
+ $this->select->joinLeft(
+ array('hgm' => $this->prefix . 'hostgroup_members'),
+ 'hgm.host_object_id = s.host_object_id',
+ array()
+ )->joinLeft(
+ array('hg' => $this->prefix . 'hostgroups'),
+ 'hg.hostgroup_id = hgm.hostgroup_id',
+ array()
+ )->joinLeft(
+ array('hgo' => $this->prefix . 'objects'),
+ 'hgo.object_id = hg.hostgroup_object_id AND hgo.is_active = 1 AND hgo.objecttype_id = 3',
+ array()
+ );
+ }
+
+ /**
+ * Join hosts
+ */
+ protected function joinHosts()
+ {
+ $this->requireVirtualTable('services');
+ $this->select->join(
+ array('h' => $this->prefix . 'hosts'),
+ 'h.host_object_id = s.host_object_id',
+ array()
+ );
+ }
+
+ /**
+ * Join host status
+ */
+ protected function joinHoststatus()
+ {
+ $this->requireVirtualTable('services');
+ $this->select->join(
+ array('hs' => $this->prefix . 'hoststatus'),
+ 'hs.host_object_id = s.host_object_id',
+ array()
+ );
+ }
+
+ /**
+ * Join instances
+ */
+ protected function joinInstances()
+ {
+ $this->select->join(
+ array('i' => $this->prefix . 'instances'),
+ 'i.instance_id = sd.instance_id',
+ array()
+ );
+ }
+
+ /**
+ * Join service groups
+ */
+ protected function joinServicegroups()
+ {
+ $this->select->joinLeft(
+ array('sgm' => $this->prefix . 'servicegroup_members'),
+ 'sgm.service_object_id = so.object_id',
+ array()
+ )->joinLeft(
+ array('sg' => $this->prefix . 'servicegroups'),
+ 'sgm.servicegroup_id = sg.' . $this->servicegroup_id,
+ array()
+ )->joinLeft(
+ array('sgo' => $this->prefix . 'objects'),
+ 'sgo.object_id = sg.servicegroup_object_id AND sgo.is_active = 1 AND sgo.objecttype_id = 4',
+ array()
+ );
+ }
+
+ /**
+ * Join services
+ */
+ protected function joinServices()
+ {
+ $this->select->join(
+ array('s' => $this->prefix . 'services'),
+ 's.service_object_id = so.object_id',
+ array()
+ );
+ }
+
+ /**
+ * Join service status
+ */
+ protected function joinServicestatus()
+ {
+ $this->select->join(
+ array('ss' => $this->prefix . 'servicestatus'),
+ 'ss.service_object_id = so.object_id',
+ array()
+ );
+ }
+
+ protected function joinSubQuery(IdoQuery $query, $name, $filter, $and, $negate, &$additionalFilter)
+ {
+ if ($name === 'hostgroup') {
+ $query->joinVirtualTable('services');
+
+ return ['so.object_id', 'so.object_id'];
+ } elseif ($name === 'servicegroup') {
+ $query->joinVirtualTable('members');
+
+ return ['sgm.service_object_id', 'so.object_id'];
+ }
+
+ return parent::joinSubQuery($query, $name, $filter, $and, $negate, $additionalFilter);
+ }
+}
diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/ServicedowntimeendhistoryQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/ServicedowntimeendhistoryQuery.php
new file mode 100644
index 0000000..2d592c8
--- /dev/null
+++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/ServicedowntimeendhistoryQuery.php
@@ -0,0 +1,40 @@
+<?php
+/* Icinga Web 2 | (c) 2015 Icinga Development Team | GPLv2+ */
+
+namespace Icinga\Module\Monitoring\Backend\Ido\Query;
+
+use Icinga\Data\Filter\Filter;
+use Icinga\Data\Filter\FilterExpression;
+
+/**
+ * Query for host downtime end history records
+ */
+class ServicedowntimeendhistoryQuery extends ServicedowntimestarthistoryQuery
+{
+ protected function requireFilterColumns(Filter $filter)
+ {
+ if ($filter instanceof FilterExpression && $filter->getColumn() === 'timestamp') {
+ $this->requireColumn('timestamp');
+ $filter->setColumn('sdh.actual_end_time');
+ $filter->setExpression($this->timestampForSql($this->valueToTimestamp($filter->getExpression())));
+ return null;
+ }
+
+ return parent::requireFilterColumns($filter);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function joinBaseTables()
+ {
+ parent::joinBaseTables(true);
+ $this->select->where("sdh.actual_end_time > '1970-01-02 00:00:00'");
+ $this->columnMap['downtimehistory']['type'] = "('dt_end')";
+ $this->columnMap['downtimehistory']['timestamp'] = str_replace(
+ 'actual_start_time',
+ 'actual_end_time',
+ $this->columnMap['downtimehistory']['timestamp']
+ );
+ }
+}
diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/ServicedowntimestarthistoryQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/ServicedowntimestarthistoryQuery.php
new file mode 100644
index 0000000..f22e265
--- /dev/null
+++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/ServicedowntimestarthistoryQuery.php
@@ -0,0 +1,202 @@
+<?php
+/* Icinga Web 2 | (c) 2015 Icinga Development Team | GPLv2+ */
+
+namespace Icinga\Module\Monitoring\Backend\Ido\Query;
+
+use Icinga\Data\Filter\Filter;
+use Icinga\Data\Filter\FilterExpression;
+
+/**
+ * Query for service downtime start history records
+ */
+class ServicedowntimestarthistoryQuery extends IdoQuery
+{
+ /**
+ * {@inheritdoc}
+ */
+ protected $allowCustomVars = true;
+
+ /**
+ * {@inheritdoc}
+ */
+ protected $groupBase = array('downtimehistory' => array('sdh.downtimehistory_id', 'so.object_id'));
+
+ /**
+ * {@inheritdoc}
+ */
+ protected $groupOrigin = array('hostgroups', 'servicegroups');
+
+ protected $subQueryTargets = array(
+ 'hostgroups' => 'hostgroup',
+ 'servicegroups' => 'servicegroup'
+ );
+
+ /**
+ * {@inheritdoc}
+ */
+ protected $columnMap = array(
+ 'downtimehistory' => array(
+ 'id' => 'sdh.downtimehistory_id',
+ 'host' => 'so.name1 COLLATE latin1_general_ci',
+ 'host_name' => 'so.name1',
+ 'object_id' => 'sdh.object_id',
+ 'object_type' => '(\'service\')',
+ 'output' => "('[' || sdh.author_name || '] ' || sdh.comment_data)",
+ 'service' => 'so.name2 COLLATE latin1_general_ci',
+ 'service_description' => 'so.name2',
+ 'service_host' => 'so.name1 COLLATE latin1_general_ci',
+ 'service_host_name' => 'so.name1',
+ 'state' => '(-1)',
+ 'timestamp' => 'UNIX_TIMESTAMP(sdh.actual_start_time)',
+ 'type' => "('dt_start')"
+ ),
+ 'hostgroups' => array(
+ 'hostgroup' => 'hgo.name1 COLLATE latin1_general_ci',
+ 'hostgroup_alias' => 'hg.alias COLLATE latin1_general_ci',
+ 'hostgroup_name' => 'hgo.name1'
+ ),
+ 'hosts' => array(
+ 'host_alias' => 'h.alias',
+ 'host_display_name' => 'h.display_name COLLATE latin1_general_ci'
+ ),
+ 'instances' => array(
+ 'instance_name' => 'i.instance_name'
+ ),
+ 'servicegroups' => array(
+ 'servicegroup' => 'sgo.name1 COLLATE latin1_general_ci',
+ 'servicegroup_name' => 'sgo.name1',
+ 'servicegroup_alias' => 'sg.alias COLLATE latin1_general_ci'
+ ),
+ 'services' => array(
+ 'service_display_name' => 's.display_name COLLATE latin1_general_ci'
+ )
+ );
+
+ protected function requireFilterColumns(Filter $filter)
+ {
+ if ($filter instanceof FilterExpression && $filter->getColumn() === 'timestamp') {
+ $this->requireColumn('timestamp');
+ $filter->setColumn('sdh.actual_start_time');
+ $filter->setExpression($this->timestampForSql($this->valueToTimestamp($filter->getExpression())));
+ return null;
+ }
+
+ return parent::requireFilterColumns($filter);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function joinBaseTables()
+ {
+ $this->select->from(
+ array('sdh' => $this->prefix . 'downtimehistory'),
+ array()
+ )->join(
+ array('so' => $this->prefix . 'objects'),
+ 'so.object_id = sdh.object_id AND so.is_active = 1 AND so.objecttype_id = 2',
+ array()
+ );
+
+ if (func_num_args() === 0 || func_get_arg(0) === false) {
+ $this->select->where(
+ "sdh.actual_start_time > '1970-01-02 00:00:00'"
+ );
+ }
+
+ $this->joinedVirtualTables['downtimehistory'] = true;
+ }
+
+ /**
+ * Join host groups
+ */
+ protected function joinHostgroups()
+ {
+ $this->requireVirtualTable('services');
+ $this->select->joinLeft(
+ array('hgm' => $this->prefix . 'hostgroup_members'),
+ 'hgm.host_object_id = s.host_object_id',
+ array()
+ )->joinLeft(
+ array('hg' => $this->prefix . 'hostgroups'),
+ 'hg.hostgroup_id = hgm.hostgroup_id',
+ array()
+ )->joinLeft(
+ array('hgo' => $this->prefix . 'objects'),
+ 'hgo.object_id = hg.hostgroup_object_id AND hgo.is_active = 1 AND hgo.objecttype_id = 3',
+ array()
+ );
+ }
+
+ /**
+ * Join hosts
+ */
+ protected function joinHosts()
+ {
+ $this->requireVirtualTable('services');
+ $this->select->join(
+ array('h' => $this->prefix . 'hosts'),
+ 'h.host_object_id = s.host_object_id',
+ array()
+ );
+ }
+
+ /**
+ * Join instances
+ */
+ protected function joinInstances()
+ {
+ $this->select->join(
+ array('i' => $this->prefix . 'instances'),
+ 'i.instance_id = sdh.instance_id',
+ array()
+ );
+ }
+
+ /**
+ * Join service groups
+ */
+ protected function joinServicegroups()
+ {
+ $this->select->joinLeft(
+ array('sgm' => $this->prefix . 'servicegroup_members'),
+ 'sgm.service_object_id = so.object_id',
+ array()
+ )->joinLeft(
+ array('sg' => $this->prefix . 'servicegroups'),
+ 'sg.' . $this->servicegroup_id . ' = sgm.servicegroup_id',
+ array()
+ )->joinLeft(
+ array('sgo' => $this->prefix . 'objects'),
+ 'sgo.object_id = sg.servicegroup_object_id AND sgo.is_active = 1 AND sgo.objecttype_id = 4',
+ array()
+ );
+ }
+
+ /**
+ * Join services
+ */
+ protected function joinServices()
+ {
+ $this->select->join(
+ array('s' => $this->prefix . 'services'),
+ 's.service_object_id = so.object_id',
+ array()
+ );
+ }
+
+ protected function joinSubQuery(IdoQuery $query, $name, $filter, $and, $negate, &$additionalFilter)
+ {
+ if ($name === 'hostgroup') {
+ $query->joinVirtualTable('services');
+
+ return ['so.object_id', 'so.object_id'];
+ } elseif ($name === 'servicegroup') {
+ $query->joinVirtualTable('members');
+
+ return ['sgm.service_object_id', 'so.object_id'];
+ }
+
+ return parent::joinSubQuery($query, $name, $filter, $and, $negate, $additionalFilter);
+ }
+}
diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/ServiceflappingendhistoryQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/ServiceflappingendhistoryQuery.php
new file mode 100644
index 0000000..48fb0bc
--- /dev/null
+++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/ServiceflappingendhistoryQuery.php
@@ -0,0 +1,31 @@
+<?php
+/* Icinga Web 2 | (c) 2016 Icinga Development Team | GPLv2+ */
+
+namespace Icinga\Module\Monitoring\Backend\Ido\Query;
+
+/**
+ * Query for service flapping end history records
+ */
+class ServiceflappingendhistoryQuery extends ServiceflappingstarthistoryQuery
+{
+ /**
+ * {@inheritdoc}
+ */
+ protected function joinBaseTables()
+ {
+ $this->select->from(
+ array('sfh' => $this->prefix . 'flappinghistory'),
+ array()
+ )->join(
+ array('so' => $this->prefix . 'objects'),
+ 'so.object_id = sfh.object_id AND so.is_active = 1 AND so.objecttype_id = 2',
+ array()
+ );
+
+ $this->select->where('sfh.event_type = 1001');
+
+ $this->joinedVirtualTables['flappinghistory'] = true;
+
+ $this->columnMap['flappinghistory']['type'] = '(\'flapping_deleted\')';
+ }
+}
diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/ServiceflappingstarthistoryQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/ServiceflappingstarthistoryQuery.php
new file mode 100644
index 0000000..f068681
--- /dev/null
+++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/ServiceflappingstarthistoryQuery.php
@@ -0,0 +1,197 @@
+<?php
+/* Icinga Web 2 | (c) 2016 Icinga Development Team | GPLv2+ */
+
+namespace Icinga\Module\Monitoring\Backend\Ido\Query;
+
+use Icinga\Data\Filter\Filter;
+use Icinga\Data\Filter\FilterExpression;
+
+/**
+ * Query for service flapping start history records
+ */
+class ServiceflappingstarthistoryQuery extends IdoQuery
+{
+ /**
+ * {@inheritdoc}
+ */
+ protected $allowCustomVars = true;
+
+ /**
+ * {@inheritdoc}
+ */
+ protected $groupBase = array('flappinghistory' => array('sfh.flappinghistory_id', 'so.object_id'));
+
+ /**
+ * {@inheritdoc}
+ */
+ protected $groupOrigin = array('hostgroups', 'servicegroups');
+
+ protected $subQueryTargets = array(
+ 'hostgroups' => 'hostgroup',
+ 'servicegroups' => 'servicegroup'
+ );
+
+ /**
+ * {@inheritdoc}
+ */
+ protected $columnMap = array(
+ 'flappinghistory' => array(
+ 'id' => 'sfh.flappinghistory_id',
+ 'host' => 'so.name1 COLLATE latin1_general_ci',
+ 'host_name' => 'so.name1',
+ 'object_id' => 'sfh.object_id',
+ 'object_type' => '(\'service\')',
+ 'output' => '(sfh.percent_state_change || \'\')',
+ 'service' => 'so.name2 COLLATE latin1_general_ci',
+ 'service_description' => 'so.name2',
+ 'service_host_name' => 'so.name1',
+ 'state' => '(-1)',
+ 'timestamp' => 'UNIX_TIMESTAMP(sfh.event_time)',
+ 'type' => "('flapping')"
+ ),
+ 'hostgroups' => array(
+ 'hostgroup' => 'hgo.name1 COLLATE latin1_general_ci',
+ 'hostgroup_alias' => 'hg.alias COLLATE latin1_general_ci',
+ 'hostgroup_name' => 'hgo.name1'
+ ),
+ 'hosts' => array(
+ 'host_alias' => 'h.alias',
+ 'host_display_name' => 'h.display_name COLLATE latin1_general_ci'
+ ),
+ 'instances' => array(
+ 'instance_name' => 'i.instance_name'
+ ),
+ 'servicegroups' => array(
+ 'servicegroup_name' => 'sgo.name1',
+ 'servicegroup' => 'sgo.name1 COLLATE latin1_general_ci',
+ 'servicegroup_alias' => 'sg.alias COLLATE latin1_general_ci'
+ ),
+ 'services' => array(
+ 'service_display_name' => 's.display_name COLLATE latin1_general_ci'
+ )
+ );
+
+ protected function requireFilterColumns(Filter $filter)
+ {
+ if ($filter instanceof FilterExpression && $filter->getColumn() === 'timestamp') {
+ $this->requireColumn('timestamp');
+ $filter->setColumn('sfh.event_time');
+ $filter->setExpression($this->timestampForSql($this->valueToTimestamp($filter->getExpression())));
+ return null;
+ }
+
+ return parent::requireFilterColumns($filter);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function joinBaseTables()
+ {
+ $this->select->from(
+ array('sfh' => $this->prefix . 'flappinghistory'),
+ array()
+ )->join(
+ array('so' => $this->prefix . 'objects'),
+ 'so.object_id = sfh.object_id AND so.is_active = 1 AND so.objecttype_id = 2',
+ array()
+ );
+
+ $this->select->where('sfh.event_type = 1000');
+
+ $this->joinedVirtualTables['flappinghistory'] = true;
+ }
+
+ /**
+ * Join host groups
+ */
+ protected function joinHostgroups()
+ {
+ $this->requireVirtualTable('services');
+ $this->select->joinLeft(
+ array('hgm' => $this->prefix . 'hostgroup_members'),
+ 'hgm.host_object_id = s.host_object_id',
+ array()
+ )->joinLeft(
+ array('hg' => $this->prefix . 'hostgroups'),
+ 'hg.hostgroup_id = hgm.hostgroup_id',
+ array()
+ )->joinLeft(
+ array('hgo' => $this->prefix . 'objects'),
+ 'hgo.object_id = hg.hostgroup_object_id AND hgo.is_active = 1 AND hgo.objecttype_id = 3',
+ array()
+ );
+ }
+
+ /**
+ * Join hosts
+ */
+ protected function joinHosts()
+ {
+ $this->requireVirtualTable('services');
+ $this->select->join(
+ array('h' => $this->prefix . 'hosts'),
+ 'h.host_object_id = s.host_object_id',
+ array()
+ );
+ }
+
+ /**
+ * Join instances
+ */
+ protected function joinInstances()
+ {
+ $this->select->join(
+ array('i' => $this->prefix . 'instances'),
+ 'i.instance_id = sfh.instance_id',
+ array()
+ );
+ }
+
+ /**
+ * Join service groups
+ */
+ protected function joinServicegroups()
+ {
+ $this->select->joinLeft(
+ array('sgm' => $this->prefix . 'servicegroup_members'),
+ 'sgm.service_object_id = so.object_id',
+ array()
+ )->joinLeft(
+ array('sg' => $this->prefix . 'servicegroups'),
+ 'sg.' . $this->servicegroup_id . ' = sgm.servicegroup_id',
+ array()
+ )->joinLeft(
+ array('sgo' => $this->prefix . 'objects'),
+ 'sgo.object_id = sg.servicegroup_object_id AND sgo.is_active = 1 AND sgo.objecttype_id = 4',
+ array()
+ );
+ }
+
+ /**
+ * Join services
+ */
+ protected function joinServices()
+ {
+ $this->select->join(
+ array('s' => $this->prefix . 'services'),
+ 's.service_object_id = so.object_id',
+ array()
+ );
+ }
+
+ protected function joinSubQuery(IdoQuery $query, $name, $filter, $and, $negate, &$additionalFilter)
+ {
+ if ($name === 'hostgroup') {
+ $query->joinVirtualTable('services');
+
+ return ['so.object_id', 'so.object_id'];
+ } elseif ($name === 'servicegroup') {
+ $query->joinVirtualTable('members');
+
+ return ['sgm.service_object_id', 'so.object_id'];
+ }
+
+ return parent::joinSubQuery($query, $name, $filter, $and, $negate, $additionalFilter);
+ }
+}
diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/ServicegroupQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/ServicegroupQuery.php
new file mode 100644
index 0000000..7f7be50
--- /dev/null
+++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/ServicegroupQuery.php
@@ -0,0 +1,303 @@
+<?php
+/* Icinga Web 2 | (c) 2013 Icinga Development Team | GPLv2+ */
+
+namespace Icinga\Module\Monitoring\Backend\Ido\Query;
+
+class ServicegroupQuery extends IdoQuery
+{
+ protected $groupBase = array(
+ 'servicegroups' => array('sgo.object_id', 'sg.servicegroup_id'),
+ 'servicestatus' => array('ss.servicestatus_id', 'hs.hoststatus_id')
+ );
+
+ protected $groupOrigin = array('members');
+
+ protected $allowCustomVars = true;
+
+ protected $subQueryTargets = array(
+ 'hostgroups' => 'hostgroup',
+ 'servicegroups' => 'servicegroup'
+ );
+
+ protected $columnMap = array(
+ 'contacts' => [
+ 'service_contact' => 'sco.name1'
+ ],
+ 'contactgroups' => [
+ 'service_contactgroup' => 'scgo.name1'
+ ],
+ 'hostcontacts' => [
+ 'host_contact' => 'hco.name1'
+ ],
+ 'hostcontactgroups' => [
+ 'host_contactgroup' => 'hcgo.name1'
+ ],
+ 'hostgroups' => array(
+ 'hostgroup_name' => 'hgo.name1'
+ ),
+ 'hosts' => array(
+ 'h.host_object_id' => 's.host_object_id'
+ ),
+ 'instances' => array(
+ 'instance_name' => 'i.instance_name'
+ ),
+ 'members' => array(
+ 'host_name' => 'so.name1',
+ 'service_description' => 'so.name2'
+ ),
+ 'servicegroups' => array(
+ 'servicegroup' => 'sgo.name1 COLLATE latin1_general_ci',
+ 'servicegroup_alias' => 'sg.alias COLLATE latin1_general_ci',
+ 'servicegroup_name' => 'sgo.name1'
+ ),
+ 'servicestatus' => array(
+ 'service_handled' => 'CASE WHEN (ss.problem_has_been_acknowledged + ss.scheduled_downtime_depth + COALESCE(hs.current_state, 0)) > 0 THEN 1 ELSE 0 END',
+ 'service_severity' => '
+ CASE WHEN ss.current_state = 0
+ THEN
+ CASE WHEN ss.has_been_checked = 0 OR ss.has_been_checked IS NULL
+ THEN 16
+ ELSE 0
+ END
+ +
+ CASE WHEN ss.problem_has_been_acknowledged = 1
+ THEN 2
+ ELSE
+ CASE WHEN ss.scheduled_downtime_depth > 0
+ THEN 1
+ ELSE 4
+ END
+ END
+ ELSE
+ CASE WHEN ss.has_been_checked = 0 OR ss.has_been_checked IS NULL THEN 16
+ WHEN ss.current_state = 1 THEN 32
+ WHEN ss.current_state = 2 THEN 128
+ WHEN ss.current_state = 3 THEN 64
+ ELSE 256
+ END
+ +
+ CASE WHEN hs.current_state > 0
+ THEN 1024
+ ELSE
+ CASE WHEN ss.problem_has_been_acknowledged = 1
+ THEN 512
+ ELSE
+ CASE WHEN ss.scheduled_downtime_depth > 0
+ THEN 256
+ ELSE 2048
+ END
+ END
+ END
+ END',
+ 'service_state' => 'CASE WHEN ss.has_been_checked = 0 OR ss.has_been_checked IS NULL THEN 99 ELSE ss.current_state END'
+ )
+ );
+
+ protected function joinBaseTables()
+ {
+ $this->select->from(
+ array('sgo' => $this->prefix . 'objects'),
+ array()
+ )->join(
+ array('sg' => $this->prefix . 'servicegroups'),
+ 'sg.servicegroup_object_id = sgo.object_id AND sgo.objecttype_id = 4 AND sgo.is_active = 1',
+ array()
+ );
+ $this->joinedVirtualTables = array('servicegroups' => true);
+ }
+
+ /**
+ * Join contacts
+ */
+ protected function joinContacts()
+ {
+ $this->requireVirtualTable('services');
+
+ $this->select->joinLeft(
+ ['sc' => 'icinga_service_contacts'],
+ 'sc.service_id = s.service_id',
+ []
+ )->joinLeft(
+ ['sco' => 'icinga_objects'],
+ 'sco.object_id = sc.contact_object_id AND sco.is_active = 1 AND sco.objecttype_id = 10',
+ []
+ );
+ }
+
+ /**
+ * Join contact groups
+ */
+ protected function joinContactgroups()
+ {
+ $this->requireVirtualTable('services');
+
+ $this->select->joinLeft(
+ ['scg' => 'icinga_service_contactgroups'],
+ 'scg.service_id = s.service_id',
+ []
+ )->joinLeft(
+ ['scgo' => 'icinga_objects'],
+ 'scgo.object_id = scg.contactgroup_object_id AND scgo.is_active = 1 AND scgo.objecttype_id = 11',
+ []
+ );
+ }
+
+ /**
+ * Join host contacts
+ */
+ protected function joinHostcontacts()
+ {
+ $this->requireVirtualTable('services');
+
+ $this->select->joinLeft(
+ ['h' => 'icinga_hosts'],
+ 'h.host_object_id = s.host_object_id',
+ []
+ )->joinLeft(
+ ['hc' => 'icinga_host_contacts'],
+ 'hc.host_id = h.host_id',
+ []
+ )->joinLeft(
+ ['hco' => 'icinga_objects'],
+ 'hco.object_id = hc.contact_object_id AND hco.is_active = 1 AND hco.objecttype_id = 10',
+ []
+ );
+ }
+
+ /**
+ * Join host contact groups
+ */
+ protected function joinHostcontactgroups()
+ {
+ $this->requireVirtualTable('services');
+
+ $this->select->joinLeft(
+ ['h' => 'icinga_hosts'],
+ 'h.host_object_id = s.host_object_id',
+ []
+ )->joinLeft(
+ ['hcg' => 'icinga_host_contactgroups'],
+ 'hcg.host_id = h.host_id',
+ []
+ )->joinLeft(
+ ['hcgo' => 'icinga_objects'],
+ 'hcgo.object_id = hcg.contactgroup_object_id AND hcgo.is_active = 1 AND hcgo.objecttype_id = 11',
+ []
+ );
+ }
+
+ /**
+ * Join host groups
+ */
+ protected function joinHostgroups()
+ {
+ $this->requireVirtualTable('services');
+ $this->select->joinLeft(
+ array('hgm' => $this->prefix . 'hostgroup_members'),
+ 'hgm.host_object_id = s.host_object_id',
+ array()
+ )->joinLeft(
+ array('hg' => $this->prefix . 'hostgroups'),
+ 'hg.hostgroup_id = hgm.hostgroup_id',
+ array()
+ )->joinLeft(
+ array('hgo' => $this->prefix . 'objects'),
+ 'hgo.object_id = hg.hostgroup_object_id AND hgo.objecttype_id = 3 AND hgo.is_active = 1',
+ array()
+ );
+ }
+
+ /**
+ * Join hosts
+ *
+ * This is required to make filters work which filter by host custom variables.
+ */
+ protected function joinHosts()
+ {
+ $this->requireVirtualTable('services');
+
+ // Host custom var filters work w/o any host related table. If a host table join is necessary here some day,
+ // please adjust `joinHostcontact*()` where we explicitly do this already
+ }
+
+ /**
+ * Join instances
+ */
+ protected function joinInstances()
+ {
+ $this->select->join(
+ array('i' => $this->prefix . 'instances'),
+ 'i.instance_id = sg.instance_id',
+ array()
+ );
+ }
+
+ /**
+ * Join service objects
+ */
+ protected function joinMembers()
+ {
+ $this->select->join(
+ array('sgm' => $this->prefix . 'servicegroup_members'),
+ 'sgm.servicegroup_id = sg.servicegroup_id',
+ array()
+ )->join(
+ array('so' => $this->prefix . 'objects'),
+ 'so.object_id = sgm.service_object_id AND so.objecttype_id = 2 AND so.is_active = 1',
+ array()
+ );
+ }
+
+ /**
+ * Join services
+ */
+ protected function joinServices()
+ {
+ $this->requireVirtualTable('members');
+ $this->select->join(
+ array('s' => $this->prefix . 'services'),
+ 's.service_object_id = so.object_id',
+ array()
+ );
+ }
+
+ /**
+ * Join service status
+ */
+ protected function joinServicestatus()
+ {
+ $this->requireVirtualTable('services');
+ $this->select->join(
+ array('hs' => $this->prefix . 'hoststatus'),
+ 'hs.host_object_id = s.host_object_id',
+ array()
+ );
+ $this->select->join(
+ array('ss' => $this->prefix . 'servicestatus'),
+ 'ss.service_object_id = so.object_id',
+ array()
+ );
+ }
+
+ protected function joinSubQuery(IdoQuery $query, $name, $filter, $and, $negate, &$additionalFilter)
+ {
+ if ($name === 'hostgroup') {
+ $this->requireVirtualTable('members');
+
+ $query->joinVirtualTable('services');
+
+ return ['so.object_id', 'so.object_id'];
+ } elseif ($name === 'servicegroup') {
+ // Propagate that the "parent" query has to be filtered as well
+ $additionalFilter = clone $filter;
+
+ $this->requireVirtualTable('members');
+
+ $query->joinVirtualTable('members');
+
+ return ['sgm.service_object_id', 'so.object_id'];
+ }
+
+ return parent::joinSubQuery($query, $name, $filter, $and, $negate, $additionalFilter);
+ }
+}
diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/ServicegroupsummaryQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/ServicegroupsummaryQuery.php
new file mode 100644
index 0000000..11b62d0
--- /dev/null
+++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/ServicegroupsummaryQuery.php
@@ -0,0 +1,113 @@
+<?php
+/* Icinga Web 2 | (c) 2015 Icinga Development Team | GPLv2+ */
+
+namespace Icinga\Module\Monitoring\Backend\Ido\Query;
+
+use Icinga\Data\Filter\Filter;
+use Zend_Db_Expr;
+use Zend_Db_Select;
+
+/**
+ * Query for service group summary
+ */
+class ServicegroupsummaryQuery extends IdoQuery
+{
+
+ protected $allowCustomVars = true;
+
+ protected $columnMap = array(
+ 'servicegroupsummary' => array(
+ 'servicegroup_alias' => 'servicegroup_alias',
+ 'servicegroup_name' => 'servicegroup_name',
+ 'services_critical' => 'SUM(CASE WHEN service_state = 2 THEN 1 ELSE 0 END)',
+ 'services_critical_handled' => 'SUM(CASE WHEN service_state = 2 AND service_handled = 1 THEN 1 ELSE 0 END)',
+ 'services_critical_unhandled' => 'SUM(CASE WHEN service_state = 2 AND service_handled = 0 THEN 1 ELSE 0 END)',
+ 'services_ok' => 'SUM(CASE WHEN service_state = 0 THEN 1 ELSE 0 END)',
+ 'services_pending' => 'SUM(CASE WHEN service_state = 99 THEN 1 ELSE 0 END)',
+ 'services_severity' => 'MAX(service_severity)',
+ 'services_total' => 'SUM(1)',
+ 'services_unknown' => 'SUM(CASE WHEN service_state = 3 THEN 1 ELSE 0 END)',
+ 'services_unknown_handled' => 'SUM(CASE WHEN service_state = 3 AND service_handled = 1 THEN 1 ELSE 0 END)',
+ 'services_unknown_unhandled' => 'SUM(CASE WHEN service_state = 3 AND service_handled = 0 THEN 1 ELSE 0 END)',
+ 'services_warning' => 'SUM(CASE WHEN service_state = 1 THEN 1 ELSE 0 END)',
+ 'services_warning_handled' => 'SUM(CASE WHEN service_state = 1 AND service_handled = 1 THEN 1 ELSE 0 END)',
+ 'services_warning_unhandled' => 'SUM(CASE WHEN service_state = 1 AND service_handled = 0 THEN 1 ELSE 0 END)',
+ )
+ );
+
+ /**
+ * The union
+ *
+ * @var Zend_Db_Select
+ */
+ protected $summaryQuery;
+
+ /**
+ * Subqueries used for the summary query
+ *
+ * @var IdoQuery[]
+ */
+ protected $subQueries = [];
+
+ /**
+ * Count query
+ *
+ * @var IdoQuery
+ */
+ protected $countQuery;
+
+ public function addFilter(Filter $filter)
+ {
+ foreach ($this->subQueries as $sub) {
+ $sub->applyFilter(clone $filter);
+ }
+ $this->countQuery->applyFilter(clone $filter);
+ return $this;
+ }
+
+ protected function joinBaseTables()
+ {
+ $this->countQuery = $this->createSubQuery(
+ 'Servicegroup',
+ array()
+ );
+ $subQuery = $this->createSubQuery(
+ 'Servicegroup',
+ array(
+ 'servicegroup_alias',
+ 'servicegroup_name',
+ 'service_handled',
+ 'service_severity',
+ 'service_state'
+ )
+ );
+ $this->subQueries[] = $subQuery;
+ $emptyGroups = $this->createSubQuery(
+ 'Emptyservicegroup',
+ [
+ 'servicegroup_alias',
+ 'servicegroup_name',
+ 'service_handled' => new Zend_Db_Expr('NULL'),
+ 'service_severity' => new Zend_Db_Expr('0'),
+ 'service_state' => new Zend_Db_Expr('NULL'),
+ ]
+ );
+ $this->subQueries[] = $emptyGroups;
+ $this->summaryQuery = $this->db->select()->union(
+ [$subQuery, $emptyGroups],
+ Zend_Db_Select::SQL_UNION_ALL
+ );
+ $this->select->from(['servicesgroupsummary' => $this->summaryQuery], []);
+ $this->group(['servicegroup_name', 'servicegroup_alias']);
+ $this->joinedVirtualTables['servicegroupsummary'] = true;
+ }
+
+ public function getCountQuery()
+ {
+ $count = $this->countQuery->select();
+ $this->countQuery->applyFilterSql($count);
+ $count->columns(array('sgo.object_id'));
+ $count->group(array('sgo.object_id'));
+ return $this->db->select()->from($count, array('cnt' => 'COUNT(*)'));
+ }
+}
diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/ServicenotificationQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/ServicenotificationQuery.php
new file mode 100644
index 0000000..d3fccf0
--- /dev/null
+++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/ServicenotificationQuery.php
@@ -0,0 +1,286 @@
+<?php
+/* Icinga Web 2 | (c) 2015 Icinga Development Team | GPLv2+ */
+
+namespace Icinga\Module\Monitoring\Backend\Ido\Query;
+
+use Icinga\Data\Filter\Filter;
+use Icinga\Data\Filter\FilterExpression;
+
+/**
+ * Query for service notifications
+ */
+class ServicenotificationQuery extends IdoQuery
+{
+ /**
+ * {@inheritdoc}
+ */
+ protected $allowCustomVars = true;
+
+ protected $subQueryTargets = array(
+ 'hostgroups' => 'hostgroup',
+ 'servicegroups' => 'servicegroup'
+ );
+
+ /**
+ * {@inheritdoc}
+ */
+ protected $columnMap = array(
+ 'contactnotifications' => array(
+ 'notification_contact_name' => 'co.name1'
+ ),
+ 'history' => array(
+ 'output' => null,
+ 'state' => 'sn.state',
+ 'timestamp' => 'UNIX_TIMESTAMP(sn.start_time)',
+ 'type' => '
+ CASE sn.notification_reason
+ WHEN 1 THEN \'notification_ack\'
+ WHEN 2 THEN \'notification_flapping\'
+ WHEN 3 THEN \'notification_flapping_end\'
+ WHEN 5 THEN \'notification_dt_start\'
+ WHEN 6 THEN \'notification_dt_end\'
+ WHEN 7 THEN \'notification_dt_end\'
+ WHEN 8 THEN \'notification_custom\'
+ ELSE \'notification_state\'
+ END',
+ ),
+ 'hostgroups' => array(
+ 'hostgroup_name' => 'hgo.name1',
+ 'hostgroup' => 'hgo.name1 COLLATE latin1_general_ci',
+ 'hostgroup_alias' => 'hg.alias COLLATE latin1_general_ci',
+ ),
+ 'hosts' => array(
+ 'host_display_name' => 'h.display_name COLLATE latin1_general_ci',
+ 'host_alias' => 'h.alias COLLATE latin1_general_ci',
+ ),
+ 'instances' => array(
+ 'instance_name' => 'i.instance_name'
+ ),
+ 'notifications' => array(
+ 'id' => 'sn.notification_id',
+ 'host' => 'so.name1 COLLATE latin1_general_ci',
+ 'host_name' => 'so.name1',
+ 'notification_output' => 'sn.output',
+ 'notification_reason' => 'sn.notification_reason',
+ 'notification_state' => 'sn.state',
+ 'notification_timestamp' => 'UNIX_TIMESTAMP(sn.start_time)',
+ 'object_type' => '(\'service\')',
+ 'service' => 'so.name2 COLLATE latin1_general_ci',
+ 'service_description' => 'so.name2',
+ 'service_host_name' => 'so.name1'
+ ),
+ 'servicegroups' => array(
+ 'servicegroup_name' => 'sgo.name1',
+ 'servicegroup' => 'sgo.name1 COLLATE latin1_general_ci',
+ 'servicegroup_alias' => 'sg.alias COLLATE latin1_general_ci'
+ ),
+ 'services' => array(
+ 'service_display_name' => 's.display_name COLLATE latin1_general_ci'
+ )
+ );
+
+ protected function requireFilterColumns(Filter $filter)
+ {
+ if ($filter instanceof FilterExpression) {
+ switch ($filter->getColumn()) {
+ case 'output':
+ $this->requireColumn('output');
+ $filter->setColumn('sn.output');
+ return null;
+ case 'timestamp':
+ case 'notification_timestamp':
+ $this->requireColumn($filter->getColumn());
+ $filter->setColumn('sn.start_time');
+ $filter->setExpression($this->timestampForSql($this->valueToTimestamp($filter->getExpression())));
+ return null;
+ }
+ }
+
+ return parent::requireFilterColumns($filter);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function joinBaseTables()
+ {
+ switch ($this->ds->getDbType()) {
+ case 'mysql':
+ $concattedContacts = "GROUP_CONCAT("
+ . "DISTINCT co.name1 ORDER BY co.name1 SEPARATOR ', '"
+ . ") COLLATE latin1_general_ci";
+ break;
+ case 'pgsql':
+ // TODO: Find a way to order the contact alias list:
+ $concattedContacts = "ARRAY_TO_STRING(ARRAY_AGG(DISTINCT co.name1), ', ')";
+ break;
+ }
+ $this->columnMap['history']['output'] = "('[' || $concattedContacts || '] ' || sn.output)";
+
+ $this->select->from(
+ array('sn' => $this->prefix . 'notifications'),
+ array()
+ )->join(
+ array('so' => $this->prefix . 'objects'),
+ 'so.object_id = sn.object_id AND so.is_active = 1 AND so.objecttype_id = 2',
+ array()
+ );
+ $this->joinedVirtualTables['notifications'] = true;
+ }
+
+ /**
+ * Join virtual table history
+ */
+ protected function joinHistory()
+ {
+ $this->requireVirtualTable('contactnotifications');
+ }
+
+ /**
+ * Join contact notifications
+ */
+ protected function joinContactnotifications()
+ {
+ $this->select->joinLeft(
+ array('cn' => $this->prefix . 'contactnotifications'),
+ 'cn.notification_id = sn.notification_id',
+ array()
+ );
+ $this->select->joinLeft(
+ array('co' => $this->prefix . 'objects'),
+ 'co.object_id = cn.contact_object_id AND co.is_active = 1 AND co.objecttype_id = 10',
+ array()
+ );
+ }
+
+ /**
+ * Join host groups
+ */
+ protected function joinHostgroups()
+ {
+ $this->requireVirtualTable('services');
+ $this->select->joinLeft(
+ array('hgm' => $this->prefix . 'hostgroup_members'),
+ 'hgm.host_object_id = s.host_object_id',
+ array()
+ )->joinLeft(
+ array('hg' => $this->prefix . 'hostgroups'),
+ 'hg.hostgroup_id = hgm.hostgroup_id',
+ array()
+ )->joinLeft(
+ array('hgo' => $this->prefix . 'objects'),
+ 'hgo.object_id = hg.hostgroup_object_id AND hgo.is_active = 1 AND hgo.objecttype_id = 3',
+ array()
+ );
+ }
+
+ /**
+ * Join hosts
+ */
+ protected function joinHosts()
+ {
+ $this->requireVirtualTable('services');
+ $this->select->join(
+ array('h' => $this->prefix . 'hosts'),
+ 'h.host_object_id = s.host_object_id',
+ array()
+ );
+ }
+
+ /**
+ * Join service groups
+ */
+ protected function joinServicegroups()
+ {
+ $this->select->joinLeft(
+ array('sgm' => $this->prefix . 'servicegroup_members'),
+ 'sgm.service_object_id = so.object_id',
+ array()
+ )->joinLeft(
+ array('sg' => $this->prefix . 'servicegroups'),
+ 'sg.' . $this->servicegroup_id . ' = sgm.servicegroup_id',
+ array()
+ )->joinLeft(
+ array('sgo' => $this->prefix . 'objects'),
+ 'sgo.object_id = sg.servicegroup_object_id AND sgo.is_active = 1 AND sgo.objecttype_id = 4',
+ array()
+ );
+ }
+
+ /**
+ * Join services
+ */
+ protected function joinServices()
+ {
+ $this->select->join(
+ array('s' => $this->prefix . 'services'),
+ 's.service_object_id = so.object_id',
+ array()
+ );
+ }
+
+ /**
+ * Join instances
+ */
+ protected function joinInstances()
+ {
+ $this->select->join(
+ array('i' => $this->prefix . 'instances'),
+ 'i.instance_id = sn.instance_id',
+ array()
+ );
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getGroup()
+ {
+ $group = array();
+
+ if ($this->hasJoinedVirtualTable('history')
+ || $this->hasJoinedVirtualTable('hostgroups')
+ || $this->hasJoinedVirtualTable('servicegroups')
+ ) {
+ $group = array('sn.notification_id', 'so.object_id');
+ if ($this->hasJoinedVirtualTable('contactnotifications') && !$this->hasJoinedVirtualTable('history')) {
+ $group[] = 'co.object_id';
+ }
+ } elseif ($this->hasJoinedVirtualTable('contactnotifications')) {
+ $group = array('sn.notification_id', 'co.object_id', 'so.object_id');
+ }
+
+ if (! empty($group)) {
+ if ($this->hasJoinedVirtualTable('hosts')) {
+ $group[] = 'h.host_id';
+ }
+
+ if ($this->hasJoinedVirtualTable('services')) {
+ $group[] = 's.service_id';
+ }
+
+ if ($this->hasJoinedVirtualTable('instances')) {
+ $group[] = 'i.instance_id';
+ }
+ }
+
+ return $group;
+ }
+
+ protected function joinSubQuery(IdoQuery $query, $name, $filter, $and, $negate, &$additionalFilter)
+ {
+ if ($name === 'hostgroup') {
+ $this->requireVirtualTable('services');
+
+ $query->joinVirtualTable('members');
+
+ return ['hgm.host_object_id', 's.host_object_id'];
+ } elseif ($name === 'servicegroup') {
+ $query->joinVirtualTable('members');
+
+ return ['sgm.service_object_id', 'so.object_id'];
+ }
+
+ return parent::joinSubQuery($query, $name, $filter, $and, $negate, $additionalFilter);
+ }
+}
diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/ServicestatehistoryQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/ServicestatehistoryQuery.php
new file mode 100644
index 0000000..f93ca8a
--- /dev/null
+++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/ServicestatehistoryQuery.php
@@ -0,0 +1,220 @@
+<?php
+/* Icinga Web 2 | (c) 2015 Icinga Development Team | GPLv2+ */
+
+namespace Icinga\Module\Monitoring\Backend\Ido\Query;
+
+use Icinga\Data\Filter\Filter;
+use Icinga\Data\Filter\FilterExpression;
+
+/**
+ * Query for service state history records
+ */
+class ServicestatehistoryQuery extends IdoQuery
+{
+ /**
+ * {@inheritdoc}
+ */
+ protected $allowCustomVars = true;
+
+ /**
+ * {@inheritdoc}
+ */
+ protected $groupBase = array('statehistory' => array('sh.statehistory_id', 'so.object_id'));
+
+ /**
+ * {@inheritdoc}
+ */
+ protected $groupOrigin = array('hostgroups', 'servicegroups');
+
+ /**
+ * Array to map type names to type ids for query optimization
+ *
+ * @var array
+ */
+ protected $types = array(
+ 'soft_state' => 0,
+ 'hard_state' => 1
+ );
+
+ protected $subQueryTargets = array(
+ 'hostgroups' => 'hostgroup',
+ 'servicegroups' => 'servicegroup'
+ );
+
+ /**
+ * {@inheritdoc}
+ */
+ protected $columnMap = array(
+ 'hostgroups' => array(
+ 'hostgroup' => 'hgo.name1 COLLATE latin1_general_ci',
+ 'hostgroup_alias' => 'hg.alias COLLATE latin1_general_ci',
+ 'hostgroup_name' => 'hgo.name1'
+ ),
+ 'hosts' => array(
+ 'host_alias' => 'h.alias',
+ 'host_display_name' => 'h.display_name COLLATE latin1_general_ci'
+ ),
+ 'instances' => array(
+ 'instance_name' => 'i.instance_name'
+ ),
+ 'servicegroups' => array(
+ 'servicegroup' => 'sgo.name1 COLLATE latin1_general_ci',
+ 'servicegroup_name' => 'sgo.name1',
+ 'servicegroup_alias' => 'sg.alias COLLATE latin1_general_ci'
+ ),
+ 'services' => array(
+ 'service_display_name' => 's.display_name COLLATE latin1_general_ci'
+ ),
+ 'statehistory' => array(
+ 'id' => 'sh.statehistory_id',
+ 'host' => 'so.name1 COLLATE latin1_general_ci',
+ 'host_name' => 'so.name1',
+ 'object_id' => 'sh.object_id',
+ 'object_type' => '(\'service\')',
+ 'output' => '(CASE WHEN sh.state_type = 1 THEN sh.output ELSE \'[ \' || sh.current_check_attempt || \'/\' || sh.max_check_attempts || \' ] \' || sh.output END)',
+ 'service' => 'so.name2 COLLATE latin1_general_ci',
+ 'service_description' => 'so.name2',
+ 'service_host' => 'so.name1 COLLATE latin1_general_ci',
+ 'service_host_name' => 'so.name1',
+ 'state' => 'sh.state',
+ 'timestamp' => 'UNIX_TIMESTAMP(sh.state_time)',
+ 'type' => "(CASE WHEN sh.state_type = 1 THEN 'hard_state' ELSE 'soft_state' END)"
+ ),
+ );
+
+ protected function requireFilterColumns(Filter $filter)
+ {
+ if ($filter instanceof FilterExpression) {
+ switch ($filter->getColumn()) {
+ case 'timestamp':
+ $this->requireColumn('timestamp');
+ $filter->setColumn('sh.state_time');
+ $filter->setExpression($this->timestampForSql($this->valueToTimestamp($filter->getExpression())));
+ return null;
+ case 'type':
+ if (! is_array($filter->getExpression())) {
+ $this->requireColumn('type');
+ $filter->setColumn('sh.state_type');
+ if (isset($this->types[$filter->getExpression()])) {
+ $filter->setExpression($this->types[$filter->getExpression()]);
+ } else {
+ $filter->setExpression(-1);
+ }
+
+ return null;
+ }
+ }
+ }
+
+ return parent::requireFilterColumns($filter);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function joinBaseTables()
+ {
+ $this->select->from(
+ array('sh' => $this->prefix . 'statehistory'),
+ array()
+ )->join(
+ array('so' => $this->prefix . 'objects'),
+ 'so.object_id = sh.object_id AND so.is_active = 1 AND so.objecttype_id = 2',
+ array()
+ );
+ $this->joinedVirtualTables['statehistory'] = true;
+ }
+
+ /**
+ * Join host groups
+ */
+ protected function joinHostgroups()
+ {
+ $this->requireVirtualTable('services');
+ $this->select->joinLeft(
+ array('hgm' => $this->prefix . 'hostgroup_members'),
+ 'hgm.host_object_id = s.host_object_id',
+ array()
+ )->joinLeft(
+ array('hg' => $this->prefix . 'hostgroups'),
+ 'hg.hostgroup_id = hgm.hostgroup_id',
+ array()
+ )->joinLeft(
+ array('hgo' => $this->prefix . 'objects'),
+ 'hgo.object_id = hg.hostgroup_object_id AND hgo.is_active = 1 AND hgo.objecttype_id = 3',
+ array()
+ );
+ }
+
+ /**
+ * Join hosts
+ */
+ protected function joinHosts()
+ {
+ $this->requireVirtualTable('services');
+ $this->select->join(
+ array('h' => $this->prefix . 'hosts'),
+ 'h.host_object_id = s.host_object_id',
+ array()
+ );
+ }
+
+ /**
+ * Join instances
+ */
+ protected function joinInstances()
+ {
+ $this->select->join(
+ array('i' => $this->prefix . 'instances'),
+ 'i.instance_id = sh.instance_id',
+ array()
+ );
+ }
+
+ /**
+ * Join service groups
+ */
+ protected function joinServicegroups()
+ {
+ $this->select->joinLeft(
+ array('sgm' => $this->prefix . 'servicegroup_members'),
+ 'sgm.service_object_id = so.object_id',
+ array()
+ )->joinLeft(
+ array('sg' => $this->prefix . 'servicegroups'),
+ 'sg.' . $this->servicegroup_id . ' = sgm.servicegroup_id',
+ array()
+ )->joinLeft(
+ array('sgo' => $this->prefix . 'objects'),
+ 'sgo.object_id = sg.servicegroup_object_id AND sgo.is_active = 1 AND sgo.objecttype_id = 4',
+ array()
+ );
+ }
+
+ /**
+ * Join services
+ */
+ protected function joinServices()
+ {
+ $this->select->join(
+ array('s' => $this->prefix . 'services'),
+ 's.service_object_id = so.object_id',
+ array()
+ );
+ }
+
+ protected function joinSubQuery(IdoQuery $query, $name, $filter, $and, $negate, &$additionalFilter)
+ {
+ if ($name === 'hostgroup') {
+ $query->joinVirtualTable('services');
+
+ return ['so.object_id', 'so.object_id'];
+ } elseif ($name === 'servicegroup') {
+ $query->joinVirtualTable('members');
+
+ return ['sgm.service_object_id', 'so.object_id'];
+ }
+
+ return parent::joinSubQuery($query, $name, $filter, $and, $negate, $additionalFilter);
+ }
+}
diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/ServicestatusQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/ServicestatusQuery.php
new file mode 100644
index 0000000..fafa03b
--- /dev/null
+++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/ServicestatusQuery.php
@@ -0,0 +1,524 @@
+<?php
+/* Icinga Web 2 | (c) 2013 Icinga Development Team | GPLv2+ */
+
+namespace Icinga\Module\Monitoring\Backend\Ido\Query;
+
+/**
+ * Query for service status
+ */
+class ServicestatusQuery extends IdoQuery
+{
+ /**
+ * {@inheritdoc}
+ */
+ protected $allowCustomVars = true;
+
+ /**
+ * {@inheritdoc}
+ */
+ protected $groupBase = array('services' => array('so.object_id', 's.service_id'));
+
+ /**
+ * {@inheritdoc}
+ */
+ protected $groupOrigin = array('hostgroups', 'servicegroups', 'contacts', 'contactgroups');
+
+ protected $subQueryTargets = array(
+ 'hostgroups' => 'hostgroup',
+ 'servicegroups' => 'servicegroup'
+ );
+
+ /**
+ * {@inheritdoc}
+ */
+ protected $columnMap = array(
+ 'checktimeperiods' => array(
+ 'service_check_timeperiod' => 'ctp.alias COLLATE latin1_general_ci'
+ ),
+ 'contacts' => [
+ 'service_contact' => 'sco.name1'
+ ],
+ 'contactgroups' => [
+ 'service_contactgroup' => 'scgo.name1'
+ ],
+ 'hostcontacts' => [
+ 'host_contact' => 'hco.name1'
+ ],
+ 'hostcontactgroups' => [
+ 'host_contactgroup' => 'hcgo.name1'
+ ],
+ 'hostgroups' => array(
+ 'hostgroup' => 'hgo.name1 COLLATE latin1_general_ci',
+ 'hostgroup_alias' => 'hg.alias COLLATE latin1_general_ci',
+ 'hostgroup_name' => 'hgo.name1'
+ ),
+ 'hosts' => array(
+ 'host_action_url' => 'h.action_url',
+ 'host_address' => 'h.address',
+ 'host_address6' => 'h.address6',
+ 'host_alias' => 'h.alias COLLATE latin1_general_ci',
+ 'host_display_name' => 'h.display_name COLLATE latin1_general_ci',
+ 'host_icon_image' => 'h.icon_image',
+ 'host_icon_image_alt' => 'h.icon_image_alt',
+ 'host_ipv4' => 'INET_ATON(h.address)',
+ 'host_notes' => 'h.notes',
+ 'host_notes_url' => 'h.notes_url'
+ ),
+ 'hoststatus' => array(
+ 'host_acknowledged' => 'hs.problem_has_been_acknowledged',
+ 'host_acknowledgement_type' => 'hs.acknowledgement_type',
+ 'host_active_checks_enabled' => 'hs.active_checks_enabled',
+ 'host_active_checks_enabled_changed' => 'CASE WHEN hs.active_checks_enabled = h.active_checks_enabled THEN 0 ELSE 1 END',
+ 'host_attempt' => 'hs.current_check_attempt || \'/\' || hs.max_check_attempts',
+ 'host_check_command' => 'hs.check_command',
+ 'host_check_execution_time' => 'hs.execution_time',
+ 'host_check_latency' => 'hs.latency',
+ 'host_check_source' => 'hs.check_source',
+ 'host_check_timeperiod_object_id' => 'hs.check_timeperiod_object_id',
+ 'host_check_type' => 'hs.check_type',
+ 'host_current_check_attempt' => 'hs.current_check_attempt',
+ 'host_current_notification_number' => 'hs.current_notification_number',
+ 'host_event_handler' => 'hs.event_handler',
+ 'host_event_handler_enabled' => 'hs.event_handler_enabled',
+ 'host_event_handler_enabled_changed' => 'CASE WHEN hs.event_handler_enabled = h.event_handler_enabled THEN 0 ELSE 1 END',
+ 'host_failure_prediction_enabled' => 'hs.failure_prediction_enabled',
+ 'host_flap_detection_enabled' => 'hs.flap_detection_enabled',
+ 'host_flap_detection_enabled_changed' => 'CASE WHEN hs.flap_detection_enabled = h.flap_detection_enabled THEN 0 ELSE 1 END',
+ 'host_handled' => 'CASE WHEN (hs.problem_has_been_acknowledged + hs.scheduled_downtime_depth) > 0 THEN 1 ELSE 0 END',
+ 'host_hard_state' => 'CASE WHEN hs.has_been_checked = 0 OR hs.has_been_checked IS NULL THEN 99 ELSE CASE WHEN hs.state_type = 1 THEN hs.current_state ELSE hs.last_hard_state END END',
+ 'host_in_downtime' => 'CASE WHEN (hs.scheduled_downtime_depth = 0) THEN 0 ELSE 1 END',
+ 'host_is_flapping' => 'hs.is_flapping',
+ 'host_is_reachable' => 'hs.is_reachable',
+ 'host_last_check' => 'UNIX_TIMESTAMP(hs.last_check)',
+ 'host_last_hard_state' => 'hs.last_hard_state',
+ 'host_last_hard_state_change' => 'UNIX_TIMESTAMP(hs.last_hard_state_change)',
+ 'host_last_notification' => 'UNIX_TIMESTAMP(hs.last_notification)',
+ 'host_last_state_change' => 'UNIX_TIMESTAMP(hs.last_state_change)',
+ 'host_last_time_down' => 'UNIX_TIMESTAMP(hs.last_time_down)',
+ 'host_last_time_unreachable' => 'UNIX_TIMESTAMP(hs.last_time_unreachable)',
+ 'host_last_time_up' => 'UNIX_TIMESTAMP(hs.last_time_up)',
+ 'host_long_output' => 'hs.long_output',
+ 'host_max_check_attempts' => 'hs.max_check_attempts',
+ 'host_modified_host_attributes' => 'hs.modified_host_attributes',
+ 'host_next_check' => 'CASE hs.should_be_scheduled WHEN 1 THEN UNIX_TIMESTAMP(hs.next_check) ELSE NULL END',
+ 'host_next_notification' => 'UNIX_TIMESTAMP(hs.next_notification)',
+ 'host_no_more_notifications' => 'hs.no_more_notifications',
+ 'host_normal_check_interval' => 'hs.normal_check_interval',
+ 'host_notifications_enabled' => 'hs.notifications_enabled',
+ 'host_notifications_enabled_changed' => 'CASE WHEN hs.notifications_enabled = h.notifications_enabled THEN 0 ELSE 1 END',
+ 'host_obsessing' => 'hs.obsess_over_host',
+ 'host_obsessing_changed' => 'CASE WHEN hs.obsess_over_host = h.obsess_over_host THEN 0 ELSE 1 END',
+ 'host_output' => 'hs.output',
+ 'host_passive_checks_enabled' => 'hs.passive_checks_enabled',
+ 'host_passive_checks_enabled_changed' => 'CASE WHEN hs.passive_checks_enabled = h.passive_checks_enabled THEN 0 ELSE 1 END',
+ 'host_percent_state_change' => 'hs.percent_state_change',
+ 'host_perfdata' => 'hs.perfdata',
+ 'host_problem' => 'CASE WHEN COALESCE(hs.current_state, 0) = 0 THEN 0 ELSE 1 END',
+ 'host_problem_has_been_acknowledged' => 'hs.problem_has_been_acknowledged',
+ 'host_process_performance_data' => 'hs.process_performance_data',
+ 'host_retry_check_interval' => 'hs.retry_check_interval',
+ 'host_scheduled_downtime_depth' => 'hs.scheduled_downtime_depth',
+ 'host_severity' => '
+ CASE
+ WHEN hs.has_been_checked = 0 OR hs.has_been_checked IS NULL
+ THEN 16
+ ELSE
+ CASE
+ WHEN hs.current_state = 0
+ THEN 1
+ ELSE
+ CASE
+ WHEN hs.current_state = 1 THEN 64
+ WHEN hs.current_state = 2 THEN 32
+ ELSE 256
+ END
+ +
+ CASE
+ WHEN hs.problem_has_been_acknowledged = 1 THEN 2
+ WHEN hs.scheduled_downtime_depth > 0 THEN 1
+ ELSE 256
+ END
+ END
+ END',
+ 'host_state' => 'CASE WHEN hs.has_been_checked = 0 OR hs.has_been_checked IS NULL THEN 99 ELSE hs.current_state END',
+ 'host_state_type' => 'hs.state_type',
+ 'host_status_update_time' => 'hs.status_update_time',
+ 'host_unhandled' => 'CASE WHEN (hs.problem_has_been_acknowledged + hs.scheduled_downtime_depth) = 0 THEN 1 ELSE 0 END'
+
+ ),
+ 'instances' => array(
+ 'instance_name' => 'i.instance_name'
+ ),
+ 'services' => array(
+ 'host' => 'so.name1 COLLATE latin1_general_ci',
+ 'host_name' => 'so.name1',
+ 'object_type' => '(\'service\')',
+ 'service' => 'so.name2 COLLATE latin1_general_ci',
+ 'service_action_url' => 's.action_url',
+ 'service_check_interval' => '(s.check_interval * 60)',
+ 'service_description' => 'so.name2',
+ 'service_display_name' => 's.display_name COLLATE latin1_general_ci',
+ 'service_host' => 'so.name1 COLLATE latin1_general_ci',
+ 'service_host_name' => 'so.name1',
+ 'service_icon_image' => 's.icon_image',
+ 'service_icon_image_alt' => 's.icon_image_alt',
+ 'service_notes_url' => 's.notes_url',
+ 'service_notes' => 's.notes'
+ ),
+ 'servicegroups' => array(
+ 'servicegroup' => 'sgo.name1 COLLATE latin1_general_ci',
+ 'servicegroup_name' => 'sgo.name1',
+ 'servicegroup_alias' => 'sg.alias COLLATE latin1_general_ci'
+ ),
+ 'servicestatus' => array(
+ 'service_acknowledged' => 'ss.problem_has_been_acknowledged',
+ 'service_acknowledgement_type' => 'ss.acknowledgement_type',
+ 'service_active_checks_enabled' => 'ss.active_checks_enabled',
+ 'service_active_checks_enabled_changed' => 'CASE WHEN ss.active_checks_enabled=s.active_checks_enabled THEN 0 ELSE 1 END',
+ 'service_attempt' => 'ss.current_check_attempt || \'/\' || ss.max_check_attempts',
+ 'service_check_command' => 'ss.check_command',
+ 'service_check_execution_time' => 'ss.execution_time',
+ 'service_check_latency' => 'ss.latency',
+ 'service_check_source' => 'ss.check_source',
+ 'service_check_timeperiod_object_id' => 'ss.check_timeperiod_object_id',
+ 'service_check_type' => 'ss.check_type',
+ 'service_current_check_attempt' => 'ss.current_check_attempt',
+ 'service_current_notification_number' => 'ss.current_notification_number',
+ 'service_event_handler' => 'ss.event_handler',
+ 'service_event_handler_enabled' => 'ss.event_handler_enabled',
+ 'service_event_handler_enabled_changed' => 'CASE WHEN ss.event_handler_enabled=s.event_handler_enabled THEN 0 ELSE 1 END',
+ 'service_failure_prediction_enabled' => 'ss.failure_prediction_enabled',
+ 'service_flap_detection_enabled' => 'ss.flap_detection_enabled',
+ 'service_flap_detection_enabled_changed' => 'CASE WHEN ss.flap_detection_enabled=s.flap_detection_enabled THEN 0 ELSE 1 END',
+ 'service_handled' => 'CASE WHEN (ss.problem_has_been_acknowledged + ss.scheduled_downtime_depth + COALESCE(hs.current_state, 0)) > 0 THEN 1 ELSE 0 END',
+ 'service_hard_state' => 'CASE WHEN ss.has_been_checked = 0 OR ss.has_been_checked IS NULL THEN 99 ELSE CASE WHEN ss.state_type = 1 THEN ss.current_state ELSE ss.last_hard_state END END',
+ 'service_in_downtime' => 'CASE WHEN (ss.scheduled_downtime_depth = 0 OR ss.scheduled_downtime_depth IS NULL) THEN 0 ELSE 1 END',
+ 'service_is_flapping' => 'ss.is_flapping',
+ 'service_is_passive_checked' => 'CASE WHEN ss.active_checks_enabled = 0 AND ss.passive_checks_enabled = 1 THEN 1 ELSE 0 END',
+ 'service_is_reachable' => 'ss.is_reachable',
+ 'service_last_check' => 'UNIX_TIMESTAMP(ss.last_check)',
+ 'service_last_hard_state' => 'ss.last_hard_state',
+ 'service_last_hard_state_change' => 'UNIX_TIMESTAMP(ss.last_hard_state_change)',
+ 'service_last_notification' => 'UNIX_TIMESTAMP(ss.last_notification)',
+ 'service_last_state_change' => 'UNIX_TIMESTAMP(ss.last_state_change)',
+ 'service_last_state_change_ts' => 'ss.last_state_change',
+ 'service_last_time_critical' => 'ss.last_time_critical',
+ 'service_last_time_ok' => 'ss.last_time_ok',
+ 'service_last_time_unknown' => 'ss.last_time_unknown',
+ 'service_last_time_warning' => 'ss.last_time_warning',
+ 'service_long_output' => 'ss.long_output',
+ 'service_max_check_attempts' => 'ss.max_check_attempts',
+ 'service_modified_service_attributes' => 'ss.modified_service_attributes',
+ 'service_next_check' => 'UNIX_TIMESTAMP(ss.next_check)',
+ 'service_next_notification' => 'UNIX_TIMESTAMP(ss.next_notification)',
+ 'service_next_update' => 'CASE WHEN ss.has_been_checked = 0 OR ss.has_been_checked IS NULL
+ THEN
+ CASE ss.should_be_scheduled WHEN 1 THEN UNIX_TIMESTAMP(ss.next_check) + (ss.normal_check_interval * 60) ELSE NULL END
+ ELSE
+ UNIX_TIMESTAMP(ss.next_check)
+ + (CASE WHEN
+ COALESCE(ss.current_state, 0) > 0 AND ss.state_type = 0
+ THEN
+ ss.retry_check_interval
+ ELSE
+ ss.normal_check_interval
+ END * 60)
+ + (CEIL(ss.execution_time + ss.latency) * 2)
+ END',
+ 'service_no_more_notifications' => 'ss.no_more_notifications',
+ 'service_normal_check_interval' => 'ss.normal_check_interval',
+ 'service_notifications_enabled' => 'ss.notifications_enabled',
+ 'service_notifications_enabled_changed' => 'CASE WHEN ss.notifications_enabled=s.notifications_enabled THEN 0 ELSE 1 END',
+ 'service_obsessing' => 'ss.obsess_over_service',
+ 'service_obsessing_changed' => 'CASE WHEN ss.obsess_over_service=s.obsess_over_service THEN 0 ELSE 1 END',
+ 'service_output' => 'ss.output',
+ 'service_passive_checks_enabled' => 'ss.passive_checks_enabled',
+ 'service_passive_checks_enabled_changed' => 'CASE WHEN ss.passive_checks_enabled=s.passive_checks_enabled THEN 0 ELSE 1 END',
+ 'service_percent_state_change' => 'ss.percent_state_change',
+ 'service_perfdata' => 'ss.perfdata',
+ 'service_problem' => 'CASE WHEN COALESCE(ss.current_state, 0) = 0 THEN 0 ELSE 1 END',
+ 'service_problem_has_been_acknowledged' => 'ss.problem_has_been_acknowledged',
+ 'service_process_performance_data' => 'ss.process_performance_data',
+ 'service_retry_check_interval' => 'ss.retry_check_interval',
+ 'service_scheduled_downtime_depth' => 'ss.scheduled_downtime_depth',
+ 'service_severity' => 'CASE WHEN ss.current_state = 0
+ THEN
+ CASE WHEN ss.has_been_checked = 0 OR ss.has_been_checked IS NULL
+ THEN 16
+ ELSE 0
+ END
+ +
+ CASE WHEN ss.problem_has_been_acknowledged = 1
+ THEN 2
+ ELSE
+ CASE WHEN ss.scheduled_downtime_depth > 0
+ THEN 1
+ ELSE 4
+ END
+ END
+ ELSE
+ CASE WHEN ss.has_been_checked = 0 OR ss.has_been_checked IS NULL THEN 16
+ WHEN ss.current_state = 1 THEN 32
+ WHEN ss.current_state = 2 THEN 128
+ WHEN ss.current_state = 3 THEN 64
+ ELSE 256
+ END
+ +
+ CASE WHEN hs.current_state > 0
+ THEN 1024
+ ELSE
+ CASE WHEN ss.problem_has_been_acknowledged = 1
+ THEN 512
+ ELSE
+ CASE WHEN ss.scheduled_downtime_depth > 0
+ THEN 256
+ ELSE 2048
+ END
+ END
+ END
+ END',
+ 'service_state' => 'CASE WHEN ss.has_been_checked = 0 OR ss.has_been_checked IS NULL THEN 99 ELSE ss.current_state END',
+ 'service_state_type' => 'ss.state_type',
+ 'service_status_update_time' => 'ss.status_update_time',
+ 'service_unhandled' => 'CASE WHEN (ss.problem_has_been_acknowledged + ss.scheduled_downtime_depth + COALESCE(hs.current_state, 0)) = 0 THEN 1 ELSE 0 END',
+ 'problems' => 'CASE WHEN COALESCE(ss.current_state, 0) = 0 THEN 0 ELSE 1 END'
+ )
+ );
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function joinBaseTables()
+ {
+ if (version_compare($this->getIdoVersion(), '1.10.0', '<')) {
+ $this->columnMap['hoststatus']['host_check_source'] = '(NULL)';
+ $this->columnMap['servicestatus']['service_check_source'] = '(NULL)';
+ }
+ if (version_compare($this->getIdoVersion(), '1.13.0', '<')) {
+ $this->columnMap['hoststatus']['host_is_reachable'] = '(NULL)';
+ $this->columnMap['servicestatus']['service_is_reachable'] = '(NULL)';
+ }
+
+ $this->select->from(
+ array('so' => $this->prefix . 'objects'),
+ array()
+ )->join(
+ array('s' => $this->prefix . 'services'),
+ 's.service_object_id = so.object_id AND so.is_active = 1 AND so.objecttype_id = 2',
+ array()
+ );
+ $this->joinedVirtualTables['services'] = true;
+ }
+
+ /**
+ * Join check time periods
+ */
+ protected function joinChecktimeperiods()
+ {
+ $this->select->joinLeft(
+ array('ctp' => $this->prefix . 'timeperiods'),
+ 'ctp.timeperiod_object_id = s.check_timeperiod_object_id',
+ array()
+ );
+ }
+
+ /**
+ * Join contacts
+ */
+ protected function joinContacts()
+ {
+ $this->select->joinLeft(
+ ['sc' => 'icinga_service_contacts'],
+ 'sc.service_id = s.service_id',
+ []
+ )->joinLeft(
+ ['sco' => 'icinga_objects'],
+ 'sco.object_id = sc.contact_object_id AND sco.is_active = 1 AND sco.objecttype_id = 10',
+ []
+ );
+ }
+
+ /**
+ * Join contact groups
+ */
+ protected function joinContactgroups()
+ {
+ $this->select->joinLeft(
+ ['scg' => 'icinga_service_contactgroups'],
+ 'scg.service_id = s.service_id',
+ []
+ )->joinLeft(
+ ['scgo' => 'icinga_objects'],
+ 'scgo.object_id = scg.contactgroup_object_id AND scgo.is_active = 1 AND scgo.objecttype_id = 11',
+ []
+ );
+ }
+
+ /**
+ * Join host contacts
+ */
+ protected function joinHostcontacts()
+ {
+ $this->requireVirtualTable('hosts');
+
+ $this->select->joinLeft(
+ ['hc' => 'icinga_host_contacts'],
+ 'hc.host_id = h.host_id',
+ []
+ )->joinLeft(
+ ['hco' => 'icinga_objects'],
+ 'hco.object_id = hc.contact_object_id AND hco.is_active = 1 AND hco.objecttype_id = 10',
+ []
+ );
+ }
+
+ /**
+ * Join host contact groups
+ */
+ protected function joinHostcontactgroups()
+ {
+ $this->requireVirtualTable('hosts');
+
+ $this->select->joinLeft(
+ ['hcg' => 'icinga_host_contactgroups'],
+ 'hcg.host_id = h.host_id',
+ []
+ )->joinLeft(
+ ['hcgo' => 'icinga_objects'],
+ 'hcgo.object_id = hcg.contactgroup_object_id AND hcgo.is_active = 1 AND hcgo.objecttype_id = 11',
+ []
+ );
+ }
+
+ /**
+ * Join host groups
+ */
+ protected function joinHostgroups()
+ {
+ $this->select->joinLeft(
+ array('hgm' => $this->prefix . 'hostgroup_members'),
+ 'hgm.host_object_id = s.host_object_id',
+ array()
+ )->joinLeft(
+ array('hg' => $this->prefix . 'hostgroups'),
+ 'hg.hostgroup_id = hgm.hostgroup_id',
+ array()
+ )->joinLeft(
+ array('hgo' => $this->prefix . 'objects'),
+ 'hgo.object_id = hg.hostgroup_object_id AND hgo.is_active = 1 AND hgo.objecttype_id = 3',
+ array()
+ );
+ }
+
+ /**
+ * Join hosts
+ */
+ protected function joinHosts()
+ {
+ $this->select->join(
+ array('h' => $this->prefix . 'hosts'),
+ 'h.host_object_id = s.host_object_id',
+ array()
+ );
+ }
+
+ /**
+ * Join host status
+ */
+ protected function joinHoststatus()
+ {
+ $this->select->join(
+ array('hs' => $this->prefix . 'hoststatus'),
+ 'hs.host_object_id = s.host_object_id',
+ array()
+ );
+ }
+
+ /**
+ * Join instances
+ */
+ protected function joinInstances()
+ {
+ $this->select->join(
+ array('i' => $this->prefix . 'instances'),
+ 'i.instance_id = so.instance_id',
+ array()
+ );
+ }
+
+ /**
+ * Join service groups
+ */
+ protected function joinServicegroups()
+ {
+ $this->select->joinLeft(
+ array('sgm' => $this->prefix . 'servicegroup_members'),
+ 'sgm.service_object_id = so.object_id',
+ array()
+ )->joinLeft(
+ array('sg' => $this->prefix . 'servicegroups'),
+ 'sg.servicegroup_id = sgm.servicegroup_id',
+ array()
+ )->joinLeft(
+ array('sgo' => $this->prefix . 'objects'),
+ 'sgo.object_id = sg.servicegroup_object_id AND sgo.is_active = 1 AND sgo.objecttype_id = 4',
+ array()
+ );
+ }
+
+ /**
+ * Join service status
+ */
+ protected function joinServicestatus()
+ {
+ $this->requireVirtualTable('hoststatus');
+ $this->select->join(
+ array('ss' => $this->prefix . 'servicestatus'),
+ 'ss.service_object_id = so.object_id',
+ array()
+ );
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function registerGroupColumns($alias, $table, array &$groupedColumns, array &$groupedTables)
+ {
+ if ($alias === 'service_handled' || $alias === 'service_severity' || $alias === 'service_unhandled') {
+ if (! isset($groupedTables['hoststatus'])) {
+ $groupedColumns[] = 'hs.hoststatus_id';
+ $groupedTables['hoststatus'] = true;
+ }
+
+ if (! isset($groupedTables['servicestatus'])) {
+ $groupedColumns[] = 'ss.servicestatus_id';
+ $groupedTables['servicestatus'] = true;
+ }
+ } elseif ($table === 'contacts') {
+ $groupedColumns[] = 'sc.service_contact_id';
+ $groupedColumns[] = 'sco.object_id';
+ $groupedTables[$table] = true;
+ } elseif ($table === 'contactgroups') {
+ $groupedColumns[] = 'scg.service_contactgroup_id';
+ $groupedColumns[] = 'scgo.object_id';
+ $groupedTables[$table] = true;
+ } else {
+ parent::registerGroupColumns($alias, $table, $groupedColumns, $groupedTables);
+ }
+ }
+
+ protected function joinSubQuery(IdoQuery $query, $name, $filter, $and, $negate, &$additionalFilter)
+ {
+ if ($name === 'hostgroup') {
+ $query->joinVirtualTable('members');
+
+ return ['hgm.host_object_id', 's.host_object_id'];
+ } elseif ($name === 'servicegroup') {
+ $query->joinVirtualTable('members');
+
+ return ['sgm.service_object_id', 'so.object_id'];
+ }
+
+ return parent::joinSubQuery($query, $name, $filter, $and, $negate, $additionalFilter);
+ }
+}
diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/ServicestatussummaryQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/ServicestatussummaryQuery.php
new file mode 100644
index 0000000..cf59cf3
--- /dev/null
+++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/ServicestatussummaryQuery.php
@@ -0,0 +1,104 @@
+<?php
+/* Icinga Web 2 | (c) 2015 Icinga Development Team | GPLv2+ */
+
+namespace Icinga\Module\Monitoring\Backend\Ido\Query;
+
+use Icinga\Data\Filter\Filter;
+use Icinga\Data\Filter\FilterExpression;
+
+/**
+ * Query for service status summary
+ *
+ * TODO(el): Allow to switch between hard and soft states
+ */
+class ServicestatussummaryQuery extends IdoQuery
+{
+ /**
+ * {@inheritdoc}
+ */
+ protected $columnMap = array(
+ 'servicestatussummary' => array(
+ 'services_critical' => 'SUM(CASE WHEN state = 2 THEN 1 ELSE 0 END)',
+ 'services_critical_handled' => 'SUM(CASE WHEN state = 2 AND handled = 1 THEN 1 ELSE 0 END)',
+// 'services_critical_handled_last_state_change' => 'MAX(CASE WHEN state = 2 AND handled = 1 THEN UNIX_TIMESTAMP(last_state_change) ELSE NULL END)',
+ 'services_critical_unhandled' => 'SUM(CASE WHEN state = 2 AND handled = 0 THEN 1 ELSE 0 END)',
+// 'services_critical_unhandled_last_state_change' => 'MAX(CASE WHEN state = 2 AND handled = 0 THEN UNIX_TIMESTAMP(last_state_change) ELSE NULL END)',
+ 'services_ok' => 'SUM(CASE WHEN state = 0 THEN 1 ELSE 0 END)',
+// 'services_ok_last_state_change' => 'MAX(CASE WHEN state = 0 THEN UNIX_TIMESTAMP(last_state_change) ELSE NULL END)',
+ 'services_pending' => 'SUM(CASE WHEN state = 99 THEN 1 ELSE 0 END)',
+// 'services_pending_last_state_change' => 'MAX(CASE WHEN state = 99 THEN UNIX_TIMESTAMP(last_state_change) ELSE NULL END)',
+ 'services_total' => 'SUM(1)',
+ 'services_unknown' => 'SUM(CASE WHEN state = 3 THEN 1 ELSE 0 END)',
+ 'services_unknown_handled' => 'SUM(CASE WHEN state = 3 AND handled = 1 THEN 1 ELSE 0 END)',
+// 'services_unknown_handled_last_state_change' => 'MAX(CASE WHEN state = 3 AND handled = 1 THEN UNIX_TIMESTAMP(last_state_change) ELSE NULL END)',
+ 'services_unknown_unhandled' => 'SUM(CASE WHEN state = 3 AND handled = 0 THEN 1 ELSE 0 END)',
+// 'services_unknown_unhandled_last_state_change' => 'MAX(CASE WHEN state = 3 AND handled = 0 THEN UNIX_TIMESTAMP(last_state_change) ELSE NULL END)',
+ 'services_warning' => 'SUM(CASE WHEN state = 1 THEN 1 ELSE 0 END)',
+ 'services_warning_handled' => 'SUM(CASE WHEN state = 1 AND handled = 1 THEN 1 ELSE 0 END)',
+// 'services_warning_handled_last_state_change' => 'MAX(CASE WHEN state = 1 AND handled = 1 THEN UNIX_TIMESTAMP(last_state_change) ELSE NULL END)',
+ 'services_warning_unhandled' => 'SUM(CASE WHEN state = 1 AND handled = 0 THEN 1 ELSE 0 END)',
+// 'services_warning_unhandled_last_state_change' => 'MAX(CASE WHEN state = 1 AND handled = 0 THEN UNIX_TIMESTAMP(last_state_change) ELSE NULL END)'
+ )
+ );
+
+ /**
+ * The service status sub select
+ *
+ * @var ServiceStatusQuery
+ */
+ protected $subSelect;
+
+ /**
+ * {@inheritdoc}
+ */
+ public function allowsCustomVars()
+ {
+ return $this->subSelect->allowsCustomVars();
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function addFilter(Filter $filter)
+ {
+ $this->subSelect->applyFilter(clone $filter);
+ return $this;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function joinBaseTables()
+ {
+ // TODO(el): Allow to switch between hard and soft states
+ $this->subSelect = $this->createSubQuery(
+ 'servicestatus',
+ array(
+ 'handled' => 'service_handled',
+ 'state' => 'service_state',
+ 'state_change' => 'service_last_state_change'
+ )
+ );
+ $this->select->from(
+ array('servicestatussummary' => $this->subSelect->setIsSubQuery(true)),
+ array()
+ );
+ $this->joinedVirtualTables['servicestatussummary'] = true;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function where($condition, $value = null)
+ {
+ $this->subSelect->where($condition, $value);
+ return $this;
+ }
+
+ public function whereEx(FilterExpression $ex)
+ {
+ $this->subSelect->whereEx($ex);
+
+ return $this;
+ }
+}
diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/StatechangeeventQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/StatechangeeventQuery.php
new file mode 100644
index 0000000..18d893f
--- /dev/null
+++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/StatechangeeventQuery.php
@@ -0,0 +1,41 @@
+<?php
+/* Icinga Web 2 | (c) 2017 Icinga Development Team | GPLv2+ */
+
+namespace Icinga\Module\Monitoring\Backend\Ido\Query;
+
+/**
+ * Query for host and service state change events
+ */
+class StatechangeeventQuery extends IdoQuery
+{
+ protected $columnMap = array(
+ 'statechangeevent' => array(
+ 'statechangeevent_id' => 'sh.statehistory_id',
+ 'statechangeevent_state_time' => 'UNIX_TIMESTAMP(sh.state_time)',
+ 'statechangeevent_state_change' => 'sh.state_change',
+ 'statechangeevent_state' => 'sh.state',
+ 'statechangeevent_state_type' => "(CASE sh.state_type WHEN 0 THEN 'soft_state' WHEN 1 THEN 'hard_state' ELSE NULL END)",
+ 'statechangeevent_current_check_attempt' => 'sh.current_check_attempt',
+ 'statechangeevent_max_check_attempts' => 'sh.max_check_attempts',
+ 'statechangeevent_last_state' => 'sh.last_state',
+ 'statechangeevent_last_hard_state' => 'sh.last_hard_state',
+ 'statechangeevent_output' => 'sh.output',
+ 'statechangeevent_long_output' => 'sh.long_output',
+ 'statechangeevent_check_source' => 'sh.check_source'
+ ),
+ 'object' => array(
+ 'host_name' => 'o.name1',
+ 'service_description' => 'o.name2'
+ )
+ );
+
+ protected function joinBaseTables()
+ {
+ $this->select()
+ ->from(array('sh' => $this->prefix . 'statehistory'), array())
+ ->join(array('o' => $this->prefix . 'objects'), 'sh.object_id = o.object_id', array());
+
+ $this->joinedVirtualTables['statechangeevent'] = true;
+ $this->joinedVirtualTables['object'] = true;
+ }
+}
diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/StatehistoryQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/StatehistoryQuery.php
new file mode 100644
index 0000000..56d1e3b
--- /dev/null
+++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/StatehistoryQuery.php
@@ -0,0 +1,179 @@
+<?php
+/* Icinga Web 2 | (c) 2013 Icinga Development Team | GPLv2+ */
+
+namespace Icinga\Module\Monitoring\Backend\Ido\Query;
+
+use Icinga\Data\Filter\FilterExpression;
+use Zend_Db_Expr;
+use Zend_Db_Select;
+use Icinga\Data\Filter\Filter;
+
+/**
+ * Query for host and service state history records
+ */
+class StatehistoryQuery extends IdoQuery
+{
+ /**
+ * {@inheritdoc}
+ */
+ protected $columnMap = array(
+ 'statehistory' => array(
+ 'id' => 'sth.id',
+ 'object_type' => 'sth.object_type'
+ ),
+ 'history' => array(
+ 'type' => 'sth.type',
+ 'timestamp' => 'sth.timestamp',
+ 'object_id' => 'sth.object_id',
+ 'state' => 'sth.state',
+ 'output' => 'sth.output'
+ ),
+ 'hosts' => array(
+ 'host_display_name' => 'sth.host_display_name',
+ 'host_name' => 'sth.host_name'
+ ),
+ 'services' => array(
+ 'service_description' => 'sth.service_description',
+ 'service_display_name' => 'sth.service_display_name',
+ 'service_host_name' => 'sth.service_host_name'
+ )
+ );
+
+ /**
+ * The union
+ *
+ * @var Zend_Db_Select
+ */
+ protected $stateHistoryQuery;
+
+ /**
+ * Subqueries used for the state history query
+ *
+ * @var IdoQuery[]
+ */
+ protected $subQueries = array();
+
+ /**
+ * Whether to additionally select all history columns
+ *
+ * @var bool
+ */
+ protected $fetchHistoryColumns = false;
+
+ /**
+ * {@inheritdoc}
+ */
+ public function allowsCustomVars()
+ {
+ foreach ($this->subQueries as $query) {
+ if (! $query->allowsCustomVars()) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function joinBaseTables()
+ {
+ $this->stateHistoryQuery = $this->db->select();
+ $this->select->from(
+ array('sth' => $this->stateHistoryQuery),
+ array()
+ );
+ $this->joinedVirtualTables['statehistory'] = true;
+ }
+
+ /**
+ * Join history related columns and tables
+ */
+ protected function joinHistory()
+ {
+ // TODO: Ensure that one is selecting the history columns first...
+ $this->fetchHistoryColumns = true;
+ $this->requireVirtualTable('hosts');
+ $this->requireVirtualTable('services');
+ }
+
+ /**
+ * Join hosts
+ */
+ protected function joinHosts()
+ {
+ $columns = array_keys(
+ $this->columnMap['statehistory'] + $this->columnMap['hosts']
+ );
+ foreach ($this->columnMap['services'] as $column => $_) {
+ $columns[$column] = new Zend_Db_Expr('NULL');
+ }
+ if ($this->fetchHistoryColumns) {
+ $columns = array_merge($columns, array_keys($this->columnMap['history']));
+ }
+ $hosts = $this->createSubQuery('Hoststatehistory', $columns);
+ $this->subQueries[] = $hosts;
+ $this->stateHistoryQuery->union(array($hosts), Zend_Db_Select::SQL_UNION_ALL);
+ }
+
+ /**
+ * Join services
+ */
+ protected function joinServices()
+ {
+ $columns = array_keys(
+ $this->columnMap['statehistory'] + $this->columnMap['hosts'] + $this->columnMap['services']
+ );
+ if ($this->fetchHistoryColumns) {
+ $columns = array_merge($columns, array_keys($this->columnMap['history']));
+ }
+ $services = $this->createSubQuery('Servicestatehistory', $columns);
+ $this->subQueries[] = $services;
+ $this->stateHistoryQuery->union(array($services), Zend_Db_Select::SQL_UNION_ALL);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function order($columnOrAlias, $dir = null)
+ {
+ foreach ($this->subQueries as $sub) {
+ $sub->requireColumn($columnOrAlias);
+ }
+ return parent::order($columnOrAlias, $dir);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function where($condition, $value = null)
+ {
+ $this->requireColumn($condition);
+ foreach ($this->subQueries as $sub) {
+ $sub->where($condition, $value);
+ }
+ return $this;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function addFilter(Filter $filter)
+ {
+ foreach ($this->subQueries as $sub) {
+ $sub->applyFilter(clone $filter);
+ }
+ return $this;
+ }
+
+ public function whereEx(FilterExpression $ex)
+ {
+ $this->requireColumn($ex->getColumn());
+ foreach ($this->subQueries as $sub) {
+ $sub->whereEx($ex);
+ }
+
+ return $this;
+ }
+}
diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/StatussummaryQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/StatussummaryQuery.php
new file mode 100644
index 0000000..b1ee9e2
--- /dev/null
+++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/StatussummaryQuery.php
@@ -0,0 +1,243 @@
+<?php
+/* Icinga Web 2 | (c) 2013 Icinga Development Team | GPLv2+ */
+
+namespace Icinga\Module\Monitoring\Backend\Ido\Query;
+
+use Icinga\Data\Filter\FilterExpression;
+use Zend_Db_Expr;
+use Zend_Db_Select;
+use Icinga\Data\Filter\Filter;
+
+/**
+ * Query for host and service status summary
+ */
+class StatussummaryQuery extends IdoQuery
+{
+ /**
+ * {@inheritdoc}
+ */
+ protected $columnMap = array(
+ 'hoststatussummary' => array(
+ 'hosts_total' => 'SUM(CASE WHEN object_type = \'host\' THEN 1 ELSE 0 END)',
+ 'hosts_up' => 'SUM(CASE WHEN object_type = \'host\' AND state = 0 THEN 1 ELSE 0 END)',
+ 'hosts_up_not_checked' => 'SUM(CASE WHEN object_type = \'host\' AND state = 0 AND is_active_checked = 0 AND is_passive_checked = 0 THEN 1 ELSE 0 END)',
+ 'hosts_pending' => 'SUM(CASE WHEN object_type = \'host\' AND state = 99 THEN 1 ELSE 0 END)',
+ 'hosts_pending_not_checked' => 'SUM(CASE WHEN object_type = \'host\' AND state = 99 AND is_active_checked = 0 AND is_passive_checked = 0 THEN 1 ELSE 0 END)',
+ 'hosts_down' => 'SUM(CASE WHEN object_type = \'host\' AND state = 1 THEN 1 ELSE 0 END)',
+ 'hosts_down_handled' => 'SUM(CASE WHEN object_type = \'host\' AND state = 1 AND handled > 0 THEN 1 ELSE 0 END)',
+ 'hosts_down_unhandled' => 'SUM(CASE WHEN object_type = \'host\' AND state = 1 AND handled = 0 THEN 1 ELSE 0 END)',
+ 'hosts_down_passive' => 'SUM(CASE WHEN object_type = \'host\' AND state = 1 AND is_passive_checked = 1 THEN 1 ELSE 0 END)',
+ 'hosts_down_not_checked' => 'SUM(CASE WHEN object_type = \'host\' AND state = 1 AND is_active_checked = 0 AND is_passive_checked = 0 THEN 1 ELSE 0 END)',
+ 'hosts_unreachable' => 'SUM(CASE WHEN object_type = \'host\' AND state = 2 THEN 1 ELSE 0 END)',
+ 'hosts_unreachable_handled' => 'SUM(CASE WHEN object_type = \'host\' AND state = 2 AND handled > 0 THEN 1 ELSE 0 END)',
+ 'hosts_unreachable_unhandled' => 'SUM(CASE WHEN object_type = \'host\' AND state = 2 AND handled = 0 THEN 1 ELSE 0 END)',
+ 'hosts_unreachable_passive' => 'SUM(CASE WHEN object_type = \'host\' AND state = 2 AND is_passive_checked = 1 THEN 1 ELSE 0 END)',
+ 'hosts_unreachable_not_checked' => 'SUM(CASE WHEN object_type = \'host\' AND state = 2 AND is_active_checked = 0 AND is_passive_checked = 0 THEN 1 ELSE 0 END)',
+ 'hosts_active' => 'SUM(CASE WHEN object_type = \'host\' AND is_active_checked = 1 THEN 1 ELSE 0 END)',
+ 'hosts_passive' => 'SUM(CASE WHEN object_type = \'host\' AND is_passive_checked = 1 THEN 1 ELSE 0 END)',
+ 'hosts_not_checked' => 'SUM(CASE WHEN object_type = \'host\' AND is_active_checked = 0 AND is_passive_checked = 0 THEN 1 ELSE 0 END)',
+ 'hosts_not_processing_event_handlers' => 'SUM(CASE WHEN object_type = \'host\' AND is_processing_events = 0 THEN 1 ELSE 0 END)',
+ 'hosts_not_triggering_notifications' => 'SUM(CASE WHEN object_type = \'host\' AND is_triggering_notifications = 0 THEN 1 ELSE 0 END)',
+ 'hosts_without_flap_detection' => 'SUM(CASE WHEN object_type = \'host\' AND is_allowed_to_flap = 0 THEN 1 ELSE 0 END)',
+ 'hosts_flapping' => 'SUM(CASE WHEN object_type = \'host\' AND is_flapping = 1 THEN 1 ELSE 0 END)'
+ ),
+ 'servicestatussummary' => array(
+ 'services_total' => 'SUM(CASE WHEN object_type = \'service\' THEN 1 ELSE 0 END)',
+ 'services_problem' => 'SUM(CASE WHEN object_type = \'service\' AND state > 0 THEN 1 ELSE 0 END)',
+ 'services_problem_handled' => 'SUM(CASE WHEN object_type = \'service\' AND state > 0 AND handled + host_problem > 0 THEN 1 ELSE 0 END)',
+ 'services_problem_unhandled' => 'SUM(CASE WHEN object_type = \'service\' AND state > 0 AND handled + host_problem = 0 THEN 1 ELSE 0 END)',
+ 'services_ok' => 'SUM(CASE WHEN object_type = \'service\' AND state = 0 THEN 1 ELSE 0 END)',
+ 'services_ok_not_checked' => 'SUM(CASE WHEN object_type = \'service\' AND state = 0 AND is_active_checked = 0 AND is_passive_checked = 0 THEN 1 ELSE 0 END)',
+ 'services_pending' => 'SUM(CASE WHEN object_type = \'service\' AND state = 99 THEN 1 ELSE 0 END)',
+ 'services_pending_not_checked' => 'SUM(CASE WHEN object_type = \'service\' AND state = 99 AND is_active_checked = 0 AND is_passive_checked = 0 THEN 1 ELSE 0 END)',
+ 'services_warning' => 'SUM(CASE WHEN object_type = \'service\' AND state = 1 THEN 1 ELSE 0 END)',
+ 'services_warning_handled' => 'SUM(CASE WHEN object_type = \'service\' AND state = 1 AND handled + host_problem > 0 THEN 1 ELSE 0 END)',
+ 'services_warning_unhandled' => 'SUM(CASE WHEN object_type = \'service\' AND state = 1 AND handled + host_problem = 0 THEN 1 ELSE 0 END)',
+ 'services_warning_passive' => 'SUM(CASE WHEN object_type = \'service\' AND state = 1 AND is_passive_checked = 1 THEN 1 ELSE 0 END)',
+ 'services_warning_not_checked' => 'SUM(CASE WHEN object_type = \'service\' AND state = 1 AND is_active_checked = 0 AND is_passive_checked = 0 THEN 1 ELSE 0 END)',
+ 'services_critical' => 'SUM(CASE WHEN object_type = \'service\' AND state = 2 THEN 1 ELSE 0 END)',
+ 'services_critical_handled' => 'SUM(CASE WHEN object_type = \'service\' AND state = 2 AND handled + host_problem > 0 THEN 1 ELSE 0 END)',
+ 'services_critical_unhandled' => 'SUM(CASE WHEN object_type = \'service\' AND state = 2 AND handled + host_problem = 0 THEN 1 ELSE 0 END)',
+ 'services_critical_passive' => 'SUM(CASE WHEN object_type = \'service\' AND state = 2 AND is_passive_checked = 1 THEN 1 ELSE 0 END)',
+ 'services_critical_not_checked' => 'SUM(CASE WHEN object_type = \'service\' AND state = 2 AND is_active_checked = 0 AND is_passive_checked = 0 THEN 1 ELSE 0 END)',
+ 'services_unknown' => 'SUM(CASE WHEN object_type = \'service\' AND state = 3 THEN 1 ELSE 0 END)',
+ 'services_unknown_handled' => 'SUM(CASE WHEN object_type = \'service\' AND state = 3 AND handled + host_problem > 0 THEN 1 ELSE 0 END)',
+ 'services_unknown_unhandled' => 'SUM(CASE WHEN object_type = \'service\' AND state = 3 AND handled + host_problem = 0 THEN 1 ELSE 0 END)',
+ 'services_unknown_passive' => 'SUM(CASE WHEN object_type = \'service\' AND state = 3 AND is_passive_checked = 1 THEN 1 ELSE 0 END)',
+ 'services_unknown_not_checked' => 'SUM(CASE WHEN object_type = \'service\' AND state = 3 AND is_active_checked = 0 AND is_passive_checked = 0 THEN 1 ELSE 0 END)',
+ 'services_active' => 'SUM(CASE WHEN object_type = \'service\' AND is_active_checked = 1 THEN 1 ELSE 0 END)',
+ 'services_passive' => 'SUM(CASE WHEN object_type = \'service\' AND is_passive_checked = 1 THEN 1 ELSE 0 END)',
+ 'services_not_checked' => 'SUM(CASE WHEN object_type = \'service\' AND is_active_checked = 0 AND is_passive_checked = 0 THEN 1 ELSE 0 END)',
+ 'services_not_processing_event_handlers' => 'SUM(CASE WHEN object_type = \'service\' AND is_processing_events = 0 THEN 1 ELSE 0 END)',
+ 'services_not_triggering_notifications' => 'SUM(CASE WHEN object_type = \'service\' AND is_triggering_notifications = 0 THEN 1 ELSE 0 END)',
+ 'services_without_flap_detection' => 'SUM(CASE WHEN object_type = \'service\' AND is_allowed_to_flap = 0 THEN 1 ELSE 0 END)',
+ 'services_flapping' => 'SUM(CASE WHEN object_type = \'service\' AND is_flapping = 1 THEN 1 ELSE 0 END)',
+
+/*
+NOTE: in case you might wonder, please see #7303. As a quickfix I did:
+
+:%s/(host_state = 0 OR host_state = 99)/host_state != 1 AND host_state != 2/g
+:%s/(host_state = 1 OR host_state = 2)/host_state != 0 AND host_state != 99/g
+
+We have to find a better solution here.
+
+*/
+ 'services_ok_on_ok_hosts' => 'SUM(CASE WHEN object_type = \'service\' AND host_state != 1 AND host_state != 2 AND state = 0 THEN 1 ELSE 0 END)',
+ 'services_ok_not_checked_on_ok_hosts' => 'SUM(CASE WHEN object_type = \'service\' AND host_state != 1 AND host_state != 2 AND state = 0 AND is_active_checked = 0 AND is_passive_checked = 0 THEN 1 ELSE 0 END)',
+ 'services_pending_on_ok_hosts' => 'SUM(CASE WHEN object_type = \'service\' AND host_state != 1 AND host_state != 2 AND state = 99 THEN 1 ELSE 0 END)',
+ 'services_pending_not_checked_on_ok_hosts' => 'SUM(CASE WHEN object_type = \'service\' AND host_state != 1 AND host_state != 2 AND state = 99 AND is_active_checked = 0 AND is_passive_checked = 0 THEN 1 ELSE 0 END)',
+ 'services_warning_handled_on_ok_hosts' => 'SUM(CASE WHEN object_type = \'service\' AND host_state != 1 AND host_state != 2 AND state = 1 AND handled > 0 THEN 1 ELSE 0 END)',
+ 'services_warning_unhandled_on_ok_hosts' => 'SUM(CASE WHEN object_type = \'service\' AND host_state != 1 AND host_state != 2 AND state = 1 AND handled = 0 THEN 1 ELSE 0 END)',
+ 'services_warning_passive_on_ok_hosts' => 'SUM(CASE WHEN object_type = \'service\' AND host_state != 1 AND host_state != 2 AND state = 1 AND is_passive_checked = 1 THEN 1 ELSE 0 END)',
+ 'services_warning_not_checked_on_ok_hosts' => 'SUM(CASE WHEN object_type = \'service\' AND host_state != 1 AND host_state != 2 AND state = 1 AND is_active_checked = 0 AND is_passive_checked = 0 THEN 1 ELSE 0 END)',
+ 'services_critical_handled_on_ok_hosts' => 'SUM(CASE WHEN object_type = \'service\' AND host_state != 1 AND host_state != 2 AND state = 2 AND handled > 0 THEN 1 ELSE 0 END)',
+ 'services_critical_unhandled_on_ok_hosts' => 'SUM(CASE WHEN object_type = \'service\' AND host_state != 1 AND host_state != 2 AND state = 2 AND handled = 0 THEN 1 ELSE 0 END)',
+ 'services_critical_passive_on_ok_hosts' => 'SUM(CASE WHEN object_type = \'service\' AND host_state != 1 AND host_state != 2 AND state = 2 AND is_passive_checked = 1 THEN 1 ELSE 0 END)',
+ 'services_critical_not_checked_on_ok_hosts' => 'SUM(CASE WHEN object_type = \'service\' AND host_state != 1 AND host_state != 2 AND state = 2 AND is_active_checked = 0 AND is_passive_checked = 0 THEN 1 ELSE 0 END)',
+ 'services_unknown_handled_on_ok_hosts' => 'SUM(CASE WHEN object_type = \'service\' AND host_state != 1 AND host_state != 2 AND state = 3 AND handled > 0 THEN 1 ELSE 0 END)',
+ 'services_unknown_unhandled_on_ok_hosts' => 'SUM(CASE WHEN object_type = \'service\' AND host_state != 1 AND host_state != 2 AND state = 3 AND handled = 0 THEN 1 ELSE 0 END)',
+ 'services_unknown_passive_on_ok_hosts' => 'SUM(CASE WHEN object_type = \'service\' AND host_state != 1 AND host_state != 2 AND state = 3 AND is_passive_checked = 1 THEN 1 ELSE 0 END)',
+ 'services_unknown_not_checked_on_ok_hosts' => 'SUM(CASE WHEN object_type = \'service\' AND host_state != 1 AND host_state != 2 AND state = 3 AND is_active_checked = 0 AND is_passive_checked = 0 THEN 1 ELSE 0 END)',
+ 'services_ok_on_problem_hosts' => 'SUM(CASE WHEN object_type = \'service\' AND host_state != 0 AND host_state != 99 AND state = 0 THEN 1 ELSE 0 END)',
+ 'services_ok_not_checked_on_problem_hosts' => 'SUM(CASE WHEN object_type = \'service\' AND host_state != 0 AND host_state != 99 AND state = 0 AND is_active_checked = 0 AND is_passive_checked = 0 THEN 1 ELSE 0 END)',
+ 'services_pending_on_problem_hosts' => 'SUM(CASE WHEN object_type = \'service\' AND host_state != 0 AND host_state != 99 AND state = 99 THEN 1 ELSE 0 END)',
+ 'services_pending_not_checked_on_problem_hosts' => 'SUM(CASE WHEN object_type = \'service\' AND host_state != 0 AND host_state != 99 AND state = 99 AND is_active_checked = 0 AND is_passive_checked = 0 THEN 1 ELSE 0 END)',
+ 'services_warning_handled_on_problem_hosts' => 'SUM(CASE WHEN object_type = \'service\' AND host_state != 0 AND host_state != 99 AND state = 1 AND handled > 0 THEN 1 ELSE 0 END)',
+ 'services_warning_unhandled_on_problem_hosts' => 'SUM(CASE WHEN object_type = \'service\' AND host_state != 0 AND host_state != 99 AND state = 1 AND handled = 0 THEN 1 ELSE 0 END)',
+ 'services_warning_passive_on_problem_hosts' => 'SUM(CASE WHEN object_type = \'service\' AND host_state != 0 AND host_state != 99 AND state = 1 AND is_passive_checked = 1 THEN 1 ELSE 0 END)',
+ 'services_warning_not_checked_on_problem_hosts' => 'SUM(CASE WHEN object_type = \'service\' AND host_state != 0 AND host_state != 99 AND state = 1 AND is_active_checked = 0 AND is_passive_checked = 0 THEN 1 ELSE 0 END)',
+ 'services_critical_handled_on_problem_hosts' => 'SUM(CASE WHEN object_type = \'service\' AND host_state != 0 AND host_state != 99 AND state = 2 AND handled > 0 THEN 1 ELSE 0 END)',
+ 'services_critical_unhandled_on_problem_hosts' => 'SUM(CASE WHEN object_type = \'service\' AND host_state != 0 AND host_state != 99 AND state = 2 AND handled = 0 THEN 1 ELSE 0 END)',
+ 'services_critical_passive_on_problem_hosts' => 'SUM(CASE WHEN object_type = \'service\' AND host_state != 0 AND host_state != 99 AND state = 2 AND is_passive_checked = 1 THEN 1 ELSE 0 END)',
+ 'services_critical_not_checked_on_problem_hosts' => 'SUM(CASE WHEN object_type = \'service\' AND host_state != 0 AND host_state != 99 AND state = 2 AND is_active_checked = 0 AND is_passive_checked = 0 THEN 1 ELSE 0 END)',
+ 'services_unknown_handled_on_problem_hosts' => 'SUM(CASE WHEN object_type = \'service\' AND host_state != 0 AND host_state != 99 AND state = 3 AND handled > 0 THEN 1 ELSE 0 END)',
+ 'services_unknown_unhandled_on_problem_hosts' => 'SUM(CASE WHEN object_type = \'service\' AND host_state != 0 AND host_state != 99 AND state = 3 AND handled = 0 THEN 1 ELSE 0 END)',
+ 'services_unknown_passive_on_problem_hosts' => 'SUM(CASE WHEN object_type = \'service\' AND host_state != 0 AND host_state != 99 AND state = 3 AND is_passive_checked = 1 THEN 1 ELSE 0 END)',
+ 'services_unknown_not_checked_on_problem_hosts' => 'SUM(CASE WHEN object_type = \'service\' AND host_state != 0 AND host_state != 99 AND state = 3 AND is_active_checked = 0 AND is_passive_checked = 0 THEN 1 ELSE 0 END)'
+ )
+ );
+
+ /**
+ * The union
+ *
+ * @var Zend_Db_Select
+ */
+ protected $summaryQuery;
+
+ /**
+ * Subqueries used for the summary query
+ *
+ * @var IdoQuery[]
+ */
+ protected $subQueries = array();
+
+ /**
+ * {@inheritdoc}
+ */
+ public function allowsCustomVars()
+ {
+ foreach ($this->subQueries as $query) {
+ if (! $query->allowsCustomVars()) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function addFilter(Filter $filter)
+ {
+ foreach ($this->subQueries as $sub) {
+ $sub->applyFilter(clone $filter);
+ }
+ return $this;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function joinBaseTables()
+ {
+ // TODO(el): Allow to switch between hard and soft states
+ $hosts = $this->createSubQuery(
+ 'Hoststatus',
+ array(
+ 'handled' => 'host_handled',
+ 'host_problem',
+ 'host_state' => new Zend_Db_Expr('NULL'),
+ 'is_active_checked' => 'host_active_checks_enabled',
+ 'is_allowed_to_flap' => 'host_flap_detection_enabled',
+ 'is_flapping' => 'host_is_flapping',
+ 'is_passive_checked' => 'host_is_passive_checked',
+ 'is_processing_events' => 'host_event_handler_enabled',
+ 'is_triggering_notifications' => 'host_notifications_enabled',
+ 'object_type',
+ 'severity' => 'host_severity',
+ 'state_change' => 'host_last_state_change',
+ 'state' => 'host_state'
+ )
+ );
+ $this->subQueries[] = $hosts;
+ $services = $this->createSubQuery(
+ 'Servicestatus',
+ array(
+ 'handled' => 'service_handled',
+ 'host_problem',
+ 'host_state' => 'host_hard_state',
+ 'is_active_checked' => 'service_active_checks_enabled',
+ 'is_allowed_to_flap' => 'service_flap_detection_enabled',
+ 'is_flapping' => 'service_is_flapping',
+ 'is_passive_checked' => 'service_is_passive_checked',
+ 'is_processing_events' => 'service_event_handler_enabled',
+ 'is_triggering_notifications' => 'service_notifications_enabled',
+ 'object_type',
+ 'severity' => 'service_severity',
+ 'state_change' => 'service_last_state_change',
+ 'state' => 'service_state'
+ )
+ );
+ $this->subQueries[] = $services;
+ $this->summaryQuery = $this->db->select()->union(array($hosts, $services), Zend_Db_Select::SQL_UNION_ALL);
+ $this->select->from(array('statussummary' => $this->summaryQuery), array());
+ $this->joinedVirtualTables['hoststatussummary'] = true;
+ $this->joinedVirtualTables['servicestatussummary'] = true;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function order($columnOrAlias, $dir = null)
+ {
+ if (! $this->hasAliasName($columnOrAlias)) {
+ foreach ($this->subQueries as $sub) {
+ $sub->requireColumn($columnOrAlias);
+ }
+ }
+ return parent::order($columnOrAlias, $dir);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function where($condition, $value = null)
+ {
+ $this->requireColumn($condition);
+ foreach ($this->subQueries as $sub) {
+ $sub->where($condition, $value);
+ }
+ return $this;
+ }
+
+ public function whereEx(FilterExpression $ex)
+ {
+ $this->requireColumn($ex->getColumn());
+ foreach ($this->subQueries as $sub) {
+ $sub->whereEx($ex);
+ }
+
+ return $this;
+ }
+}
diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/UnhandledhostproblemsQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/UnhandledhostproblemsQuery.php
new file mode 100644
index 0000000..f4c4e07
--- /dev/null
+++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/UnhandledhostproblemsQuery.php
@@ -0,0 +1,48 @@
+<?php
+/* Icinga Web 2 | (c) 2017 Icinga Development Team | GPLv2+ */
+
+namespace Icinga\Module\Monitoring\Backend\Ido\Query;
+
+use Icinga\Data\Filter\Filter;
+
+/**
+ * Query for unhandled host problems
+ */
+class UnhandledhostproblemsQuery extends IdoQuery
+{
+ protected $allowCustomVars = true;
+
+ protected $columnMap = array(
+ 'problems' => array(
+ 'hosts_down_unhandled' => 'COUNT(*)',
+ )
+ );
+
+ /**
+ * The service status sub select
+ *
+ * @var HoststatusQuery
+ */
+ protected $subSelect;
+
+ public function addFilter(Filter $filter)
+ {
+ $this->subSelect->applyFilter(clone $filter);
+ return $this;
+ }
+
+ protected function joinBaseTables()
+ {
+ $this->subSelect = $this->createSubQuery(
+ 'Hoststatus',
+ array('host_name')
+ );
+ $this->subSelect->where('host_handled', 0);
+ $this->subSelect->where('host_state', 1);
+ $this->select->from(
+ array('problems' => $this->subSelect->setIsSubQuery(true)),
+ array()
+ );
+ $this->joinedVirtualTables['problems'] = true;
+ }
+}
diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/UnhandledserviceproblemsQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/UnhandledserviceproblemsQuery.php
new file mode 100644
index 0000000..a218caf
--- /dev/null
+++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/UnhandledserviceproblemsQuery.php
@@ -0,0 +1,48 @@
+<?php
+/* Icinga Web 2 | (c) 2017 Icinga Development Team | GPLv2+ */
+
+namespace Icinga\Module\Monitoring\Backend\Ido\Query;
+
+use Icinga\Data\Filter\Filter;
+
+/**
+ * Query for unhandled service problems
+ */
+class UnhandledserviceproblemsQuery extends IdoQuery
+{
+ protected $allowCustomVars = true;
+
+ protected $columnMap = array(
+ 'problems' => array(
+ 'services_critical_unhandled' => 'COUNT(*)',
+ )
+ );
+
+ /**
+ * The service status sub select
+ *
+ * @var ServicestatusQuery
+ */
+ protected $subSelect;
+
+ public function addFilter(Filter $filter)
+ {
+ $this->subSelect->applyFilter(clone $filter);
+ return $this;
+ }
+
+ protected function joinBaseTables()
+ {
+ $this->subSelect = $this->createSubQuery(
+ 'Servicestatus',
+ array('service_description')
+ );
+ $this->subSelect->where('service_handled', 0);
+ $this->subSelect->where('service_state', 2);
+ $this->select->from(
+ array('problems' => $this->subSelect->setIsSubQuery(true)),
+ array()
+ );
+ $this->joinedVirtualTables['problems'] = true;
+ }
+}