From a0901c4b7f2db488cb4fb3be2dd921a0308f4659 Mon Sep 17 00:00:00 2001
From: Daniel Baumann <daniel.baumann@progress-linux.org>
Date: Sun, 28 Apr 2024 14:36:40 +0200
Subject: Adding upstream version 1.0.2.

Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
---
 .../Command/Object/AcknowledgeProblemCommand.php   | 140 +++++++++++++++
 .../Icingadb/Command/Object/AddCommentCommand.php  |  42 +++++
 library/Icingadb/Command/Object/CommandAuthor.php  |  45 +++++
 .../Command/Object/DeleteCommentCommand.php        |  52 ++++++
 .../Command/Object/DeleteDowntimeCommand.php       |  58 ++++++
 .../Icingadb/Command/Object/GetObjectCommand.php   |  71 ++++++++
 library/Icingadb/Command/Object/ObjectCommand.php  |  51 ++++++
 .../Command/Object/ProcessCheckResultCommand.php   | 140 +++++++++++++++
 .../Object/PropagateHostDowntimeCommand.php        |  42 +++++
 .../Object/RemoveAcknowledgementCommand.php        |  13 ++
 .../Command/Object/ScheduleCheckCommand.php        |  86 +++++++++
 .../Command/Object/ScheduleHostDowntimeCommand.php |  42 +++++
 .../Object/ScheduleServiceDowntimeCommand.php      | 196 +++++++++++++++++++++
 .../Object/SendCustomNotificationCommand.php       |  44 +++++
 .../Command/Object/ToggleObjectFeatureCommand.php  | 108 ++++++++++++
 .../Icingadb/Command/Object/WithCommentCommand.php |  50 ++++++
 16 files changed, 1180 insertions(+)
 create mode 100644 library/Icingadb/Command/Object/AcknowledgeProblemCommand.php
 create mode 100644 library/Icingadb/Command/Object/AddCommentCommand.php
 create mode 100644 library/Icingadb/Command/Object/CommandAuthor.php
 create mode 100644 library/Icingadb/Command/Object/DeleteCommentCommand.php
 create mode 100644 library/Icingadb/Command/Object/DeleteDowntimeCommand.php
 create mode 100644 library/Icingadb/Command/Object/GetObjectCommand.php
 create mode 100644 library/Icingadb/Command/Object/ObjectCommand.php
 create mode 100644 library/Icingadb/Command/Object/ProcessCheckResultCommand.php
 create mode 100644 library/Icingadb/Command/Object/PropagateHostDowntimeCommand.php
 create mode 100644 library/Icingadb/Command/Object/RemoveAcknowledgementCommand.php
 create mode 100644 library/Icingadb/Command/Object/ScheduleCheckCommand.php
 create mode 100644 library/Icingadb/Command/Object/ScheduleHostDowntimeCommand.php
 create mode 100644 library/Icingadb/Command/Object/ScheduleServiceDowntimeCommand.php
 create mode 100644 library/Icingadb/Command/Object/SendCustomNotificationCommand.php
 create mode 100644 library/Icingadb/Command/Object/ToggleObjectFeatureCommand.php
 create mode 100644 library/Icingadb/Command/Object/WithCommentCommand.php

(limited to 'library/Icingadb/Command/Object')

diff --git a/library/Icingadb/Command/Object/AcknowledgeProblemCommand.php b/library/Icingadb/Command/Object/AcknowledgeProblemCommand.php
new file mode 100644
index 0000000..baae24c
--- /dev/null
+++ b/library/Icingadb/Command/Object/AcknowledgeProblemCommand.php
@@ -0,0 +1,140 @@
+<?php
+
+/* Icinga DB Web | (c) 2021 Icinga GmbH | GPLv2 */
+
+namespace Icinga\Module\Icingadb\Command\Object;
+
+/**
+ * Acknowledge a host or service problem
+ */
+class AcknowledgeProblemCommand extends WithCommentCommand
+{
+    /**
+     * Whether the acknowledgement is sticky
+     *
+     * Sticky acknowledgements remain until the host or service recovers. Non-sticky acknowledgements will be
+     * automatically removed when the host or service state changes.
+     *
+     * @var bool
+     */
+    protected $sticky = false;
+
+    /**
+     * Whether to send a notification about the acknowledgement
+
+     * @var bool
+     */
+    protected $notify = false;
+
+    /**
+     * Whether the comment associated with the acknowledgement is persistent
+     *
+     * Persistent comments are not lost the next time the monitoring host restarts.
+     *
+     * @var bool
+     */
+    protected $persistent = false;
+
+    /**
+     * Optional time when the acknowledgement should expire
+     *
+     * @var int
+     */
+    protected $expireTime;
+
+    /**
+     * Set whether the acknowledgement is sticky
+     *
+     * @param   bool $sticky
+     *
+     * @return  $this
+     */
+    public function setSticky(bool $sticky = true): self
+    {
+        $this->sticky = $sticky;
+
+        return $this;
+    }
+
+    /**
+     * Is the acknowledgement sticky?
+     *
+     * @return bool
+     */
+    public function getSticky(): bool
+    {
+        return $this->sticky;
+    }
+
+    /**
+     * Set whether to send a notification about the acknowledgement
+     *
+     * @param   bool $notify
+     *
+     * @return  $this
+     */
+    public function setNotify(bool $notify = true): self
+    {
+        $this->notify = $notify;
+
+        return $this;
+    }
+
+    /**
+     * Get whether to send a notification about the acknowledgement
+     *
+     * @return bool
+     */
+    public function getNotify(): bool
+    {
+        return $this->notify;
+    }
+
+    /**
+     * Set whether the comment associated with the acknowledgement is persistent
+     *
+     * @param   bool $persistent
+     *
+     * @return  $this
+     */
+    public function setPersistent(bool $persistent = true): self
+    {
+        $this->persistent = $persistent;
+
+        return $this;
+    }
+
+    /**
+     * Is the comment associated with the acknowledgement is persistent?
+     *
+     * @return bool
+     */
+    public function getPersistent(): bool
+    {
+        return $this->persistent;
+    }
+
+    /**
+     * Set the time when the acknowledgement should expire
+     *
+     * @param   int $expireTime
+     *
+     * @return  $this
+     */
+    public function setExpireTime(int $expireTime): self
+    {
+        $this->expireTime = $expireTime;
+
+        return $this;
+    }
+
+    /**
+     * Get the time when the acknowledgement should expire
+     *
+     * @return ?int
+     */
+    public function getExpireTime()
+    {
+        return $this->expireTime;
+    }
+}
diff --git a/library/Icingadb/Command/Object/AddCommentCommand.php b/library/Icingadb/Command/Object/AddCommentCommand.php
new file mode 100644
index 0000000..c853b25
--- /dev/null
+++ b/library/Icingadb/Command/Object/AddCommentCommand.php
@@ -0,0 +1,42 @@
+<?php
+
+/* Icinga DB Web | (c) 2021 Icinga GmbH | GPLv2 */
+
+namespace Icinga\Module\Icingadb\Command\Object;
+
+/**
+ * Add a comment to a host or service
+ */
+class AddCommentCommand extends WithCommentCommand
+{
+    /**
+     * Optional time when the acknowledgement should expire
+     *
+     * @var int
+     */
+    protected $expireTime;
+
+    /**
+     * Set the time when the acknowledgement should expire
+     *
+     * @param   int $expireTime
+     *
+     * @return  $this
+     */
+    public function setExpireTime(int $expireTime): self
+    {
+        $this->expireTime = $expireTime;
+
+        return $this;
+    }
+
+    /**
+     * Get the time when the acknowledgement should expire
+     *
+     * @return ?int
+     */
+    public function getExpireTime()
+    {
+        return $this->expireTime;
+    }
+}
diff --git a/library/Icingadb/Command/Object/CommandAuthor.php b/library/Icingadb/Command/Object/CommandAuthor.php
new file mode 100644
index 0000000..f323b63
--- /dev/null
+++ b/library/Icingadb/Command/Object/CommandAuthor.php
@@ -0,0 +1,45 @@
+<?php
+
+/* Icinga DB Web | (c) 2021 Icinga GmbH | GPLv2 */
+
+namespace Icinga\Module\Icingadb\Command\Object;
+
+trait CommandAuthor
+{
+    /**
+     * Author of the command
+     *
+     * @var string
+     */
+    protected $author;
+
+    /**
+     * Set the author
+     *
+     * @param   string $author
+     *
+     * @return  $this
+     */
+    public function setAuthor(string $author): self
+    {
+        $this->author = $author;
+
+        return $this;
+    }
+
+    /**
+     * Get the author
+     *
+     * @return string
+     */
+    public function getAuthor(): string
+    {
+        if ($this->author === null) {
+            throw new \LogicException(
+                'You are accessing an unset property. Please make sure to set it beforehand.'
+            );
+        }
+
+        return $this->author;
+    }
+}
diff --git a/library/Icingadb/Command/Object/DeleteCommentCommand.php b/library/Icingadb/Command/Object/DeleteCommentCommand.php
new file mode 100644
index 0000000..8bfc2a3
--- /dev/null
+++ b/library/Icingadb/Command/Object/DeleteCommentCommand.php
@@ -0,0 +1,52 @@
+<?php
+
+/* Icinga DB Web | (c) 2021 Icinga GmbH | GPLv2 */
+
+namespace Icinga\Module\Icingadb\Command\Object;
+
+use Icinga\Module\Icingadb\Command\IcingaCommand;
+
+/**
+ * Delete a host or service comment
+ */
+class DeleteCommentCommand extends IcingaCommand
+{
+    use CommandAuthor;
+
+    /**
+     * Name of the comment
+     *
+     * @var string
+     */
+    protected $commentName;
+
+    /**
+     * Get the name of the comment
+     *
+     * @return string
+     */
+    public function getCommentName(): string
+    {
+        if ($this->commentName === null) {
+            throw new \LogicException(
+                'You are accessing an unset property. Please make sure to set it beforehand.'
+            );
+        }
+
+        return $this->commentName;
+    }
+
+    /**
+     * Set the name of the comment
+     *
+     * @param   string  $commentName
+     *
+     * @return  $this
+     */
+    public function setCommentName(string $commentName): self
+    {
+        $this->commentName = $commentName;
+
+        return $this;
+    }
+}
diff --git a/library/Icingadb/Command/Object/DeleteDowntimeCommand.php b/library/Icingadb/Command/Object/DeleteDowntimeCommand.php
new file mode 100644
index 0000000..a0867fa
--- /dev/null
+++ b/library/Icingadb/Command/Object/DeleteDowntimeCommand.php
@@ -0,0 +1,58 @@
+<?php
+
+/* Icinga DB Web | (c) 2021 Icinga GmbH | GPLv2 */
+
+namespace Icinga\Module\Icingadb\Command\Object;
+
+use Icinga\Module\Icingadb\Command\IcingaCommand;
+
+/**
+ * Delete a host or service downtime
+ */
+class DeleteDowntimeCommand extends IcingaCommand
+{
+    use CommandAuthor;
+
+    /**
+     * Name of the downtime (Icinga 2.4+)
+     *
+     * Required for removing the downtime via Icinga 2's API.
+     *
+     * @var string
+     */
+    protected $downtimeName;
+
+    /**
+     * Get the name of the downtime (Icinga 2.4+)
+     *
+     * Required for removing the downtime via Icinga 2's API.
+     *
+     * @return string
+     */
+    public function getDowntimeName(): string
+    {
+        if ($this->downtimeName === null) {
+            throw new \LogicException(
+                'You are accessing an unset property. Please make sure to set it beforehand.'
+            );
+        }
+
+        return $this->downtimeName;
+    }
+
+    /**
+     * Set the name of the downtime (Icinga 2.4+)
+     *
+     * Required for removing the downtime via Icinga 2's API.
+     *
+     * @param   string  $downtimeName
+     *
+     * @return  $this
+     */
+    public function setDowntimeName(string $downtimeName): self
+    {
+        $this->downtimeName = $downtimeName;
+
+        return $this;
+    }
+}
diff --git a/library/Icingadb/Command/Object/GetObjectCommand.php b/library/Icingadb/Command/Object/GetObjectCommand.php
new file mode 100644
index 0000000..372a555
--- /dev/null
+++ b/library/Icingadb/Command/Object/GetObjectCommand.php
@@ -0,0 +1,71 @@
+<?php
+
+/* Icinga DB Web | (c) 2021 Icinga GmbH | GPLv2 */
+
+namespace Icinga\Module\Icingadb\Command\Object;
+
+use Icinga\Module\Icingadb\Model\Host;
+use Icinga\Module\Icingadb\Model\Service;
+use LogicException;
+
+class GetObjectCommand extends ObjectCommand
+{
+    /** @var array */
+    protected $attributes;
+
+    /**
+     * Get the object name used in the Icinga 2 API
+     *
+     * @return string
+     */
+    public function getObjectName(): string
+    {
+        switch (true) {
+            case $this->object instanceof Service:
+                return $this->object->host->name . '!' . $this->object->name;
+            default:
+                return $this->object->name;
+        }
+    }
+
+    /**
+     * Get the sub-route of the endpoint for this object
+     *
+     * @return string
+     */
+    public function getObjectPluralType(): string
+    {
+        switch (true) {
+            case $this->object instanceof Host:
+                return 'hosts';
+            case $this->object instanceof Service:
+                return 'services';
+            default:
+                throw new LogicException(sprintf('Invalid object type %s provided', get_class($this->object)));
+        }
+    }
+
+    /**
+     * Get the attributes to query
+     *
+     * @return ?array
+     */
+    public function getAttributes()
+    {
+        return $this->attributes;
+    }
+
+    /**
+     * Set the attributes to query
+     *
+     * @param array $attributes
+     *
+     * @return $this
+     */
+    public function setAttributes(array $attributes): self
+    {
+        $this->attributes = $attributes;
+
+        return $this;
+    }
+}
diff --git a/library/Icingadb/Command/Object/ObjectCommand.php b/library/Icingadb/Command/Object/ObjectCommand.php
new file mode 100644
index 0000000..7dae799
--- /dev/null
+++ b/library/Icingadb/Command/Object/ObjectCommand.php
@@ -0,0 +1,51 @@
+<?php
+
+/* Icinga DB Web | (c) 2021 Icinga GmbH | GPLv2 */
+
+namespace Icinga\Module\Icingadb\Command\Object;
+
+use Icinga\Module\Icingadb\Command\IcingaCommand;
+use ipl\Orm\Model;
+
+/**
+ * Base class for commands that involve a monitored object, i.e. a host or service
+ */
+abstract class ObjectCommand extends IcingaCommand
+{
+    /**
+     * Involved object
+     *
+     * @var Model
+     */
+    protected $object;
+
+    /**
+     * Set the involved object
+     *
+     * @param   Model $object
+     *
+     * @return  $this
+     */
+    public function setObject(Model $object): self
+    {
+        $this->object = $object;
+
+        return $this;
+    }
+
+    /**
+     * Get the involved object
+     *
+     * @return Model
+     */
+    public function getObject(): Model
+    {
+        if ($this->object === null) {
+            throw new \LogicException(
+                'You are accessing an unset property. Please make sure to set it beforehand.'
+            );
+        }
+
+        return $this->object;
+    }
+}
diff --git a/library/Icingadb/Command/Object/ProcessCheckResultCommand.php b/library/Icingadb/Command/Object/ProcessCheckResultCommand.php
new file mode 100644
index 0000000..3d7e956
--- /dev/null
+++ b/library/Icingadb/Command/Object/ProcessCheckResultCommand.php
@@ -0,0 +1,140 @@
+<?php
+
+/* Icinga DB Web | (c) 2021 Icinga GmbH | GPLv2 */
+
+namespace Icinga\Module\Icingadb\Command\Object;
+
+/**
+ * Submit a passive check result for a host or service
+ */
+class ProcessCheckResultCommand extends ObjectCommand
+{
+    /**
+     * Host up
+     */
+    const HOST_UP = 0;
+
+    /**
+     * Host down
+     */
+    const HOST_DOWN = 1;
+
+    /**
+     * Service ok
+     */
+    const SERVICE_OK = 0;
+
+    /**
+     * Service warning
+     */
+    const SERVICE_WARNING = 1;
+
+    /**
+     * Service critical
+     */
+    const SERVICE_CRITICAL = 2;
+
+    /**
+     * Service unknown
+     */
+    const SERVICE_UNKNOWN = 3;
+
+    /**
+     * Status code of the host or service check result
+     *
+     * @var int
+     */
+    protected $status;
+
+    /**
+     * Text output of the host or service check result
+     *
+     * @var string
+     */
+    protected $output;
+
+    /**
+     * Optional performance data of the host or service check result
+     *
+     * @var string
+     */
+    protected $performanceData;
+
+    /**
+     * Set the status code of the host or service check result
+     *
+     * @param   int $status
+     *
+     * @return  $this
+     */
+    public function setStatus(int $status): self
+    {
+        $this->status = $status;
+
+        return $this;
+    }
+
+    /**
+     * Get the status code of the host or service check result
+     *
+     * @return int
+     */
+    public function getStatus(): int
+    {
+        if ($this->status === null) {
+            throw new \LogicException(
+                'You are accessing an unset property. Please make sure to set it beforehand.'
+            );
+        }
+
+        return $this->status;
+    }
+
+    /**
+     * Set the text output of the host or service check result
+     *
+     * @param   string $output
+     *
+     * @return  $this
+     */
+    public function setOutput(string $output): self
+    {
+        $this->output = $output;
+
+        return $this;
+    }
+
+    /**
+     * Get the text output of the host or service check result
+     *
+     * @return ?string
+     */
+    public function getOutput()
+    {
+        return $this->output;
+    }
+
+    /**
+     * Set the performance data of the host or service check result
+     *
+     * @param   string|null $performanceData
+     *
+     * @return  $this
+     */
+    public function setPerformanceData(string $performanceData = null): self
+    {
+        $this->performanceData = $performanceData;
+
+        return $this;
+    }
+
+    /**
+     * Get the performance data of the host or service check result
+     *
+     * @return ?string
+     */
+    public function getPerformanceData()
+    {
+        return $this->performanceData;
+    }
+}
diff --git a/library/Icingadb/Command/Object/PropagateHostDowntimeCommand.php b/library/Icingadb/Command/Object/PropagateHostDowntimeCommand.php
new file mode 100644
index 0000000..88964fb
--- /dev/null
+++ b/library/Icingadb/Command/Object/PropagateHostDowntimeCommand.php
@@ -0,0 +1,42 @@
+<?php
+
+/* Icinga DB Web | (c) 2021 Icinga GmbH | GPLv2 */
+
+namespace Icinga\Module\Icingadb\Command\Object;
+
+/**
+ * Schedule and propagate host downtime
+ */
+class PropagateHostDowntimeCommand extends ScheduleHostDowntimeCommand
+{
+    /**
+     * Whether the downtime for child hosts are all set to be triggered by this' host downtime
+     *
+     * @var bool
+     */
+    protected $triggered = false;
+
+    /**
+     * Set whether the downtime for child hosts are all set to be triggered by this' host downtime
+     *
+     * @param   bool $triggered
+     *
+     * @return  $this
+     */
+    public function setTriggered(bool $triggered = true): self
+    {
+        $this->triggered = $triggered;
+
+        return $this;
+    }
+
+    /**
+     * Get whether the downtime for child hosts are all set to be triggered by this' host downtime
+     *
+     * @return bool
+     */
+    public function getTriggered(): bool
+    {
+        return $this->triggered;
+    }
+}
diff --git a/library/Icingadb/Command/Object/RemoveAcknowledgementCommand.php b/library/Icingadb/Command/Object/RemoveAcknowledgementCommand.php
new file mode 100644
index 0000000..49a22a3
--- /dev/null
+++ b/library/Icingadb/Command/Object/RemoveAcknowledgementCommand.php
@@ -0,0 +1,13 @@
+<?php
+
+/* Icinga DB Web | (c) 2021 Icinga GmbH | GPLv2 */
+
+namespace Icinga\Module\Icingadb\Command\Object;
+
+/**
+ * Remove a problem acknowledgement from a host or service
+ */
+class RemoveAcknowledgementCommand extends ObjectCommand
+{
+    use CommandAuthor;
+}
diff --git a/library/Icingadb/Command/Object/ScheduleCheckCommand.php b/library/Icingadb/Command/Object/ScheduleCheckCommand.php
new file mode 100644
index 0000000..c3f2097
--- /dev/null
+++ b/library/Icingadb/Command/Object/ScheduleCheckCommand.php
@@ -0,0 +1,86 @@
+<?php
+
+/* Icinga DB Web | (c) 2021 Icinga GmbH | GPLv2 */
+
+namespace Icinga\Module\Icingadb\Command\Object;
+
+/**
+ * Schedule a check
+ */
+class ScheduleCheckCommand extends ObjectCommand
+{
+    /**
+     * Time when the next check of a host or service is to be scheduled
+     *
+     * If active checks are disabled on a host- or service-specific or program-wide basis or the host or service is
+     * already scheduled to be checked at an earlier time, etc. The check may not actually be scheduled at the time
+     * specified. This behaviour can be overridden by setting `ScheduledCheck::$forced' to true.
+     *
+     * @var int Unix timestamp
+     */
+    protected $checkTime;
+
+    /**
+     * Whether the check is forced
+     *
+     * Forced checks are performed regardless of what time it is (e.g. time period restrictions are ignored) and whether
+     * or not active checks are enabled on a host- or service-specific or program-wide basis.
+     *
+     * @var bool
+     */
+    protected $forced = false;
+
+    /**
+     * Set the time when the next check of a host or service is to be scheduled
+     *
+     * @param   int $checkTime Unix timestamp
+     *
+     * @return  $this
+     */
+    public function setCheckTime(int $checkTime): self
+    {
+        $this->checkTime = $checkTime;
+
+        return $this;
+    }
+
+    /**
+     * Get the time when the next check of a host or service is to be scheduled
+     *
+     * @return int Unix timestamp
+     */
+    public function getCheckTime(): int
+    {
+        if ($this->checkTime === null) {
+            throw new \LogicException(
+                'You are accessing an unset property. Please make sure to set it beforehand.'
+            );
+        }
+
+        return $this->checkTime;
+    }
+
+    /**
+     * Set whether the check is forced
+     *
+     * @param   bool $forced
+     *
+     * @return  $this
+     */
+    public function setForced(bool $forced = true): self
+    {
+        $this->forced = $forced;
+
+        return $this;
+    }
+
+    /**
+     * Get whether the check is forced
+     *
+     * @return bool
+     */
+    public function getForced(): bool
+    {
+        return $this->forced;
+    }
+}
diff --git a/library/Icingadb/Command/Object/ScheduleHostDowntimeCommand.php b/library/Icingadb/Command/Object/ScheduleHostDowntimeCommand.php
new file mode 100644
index 0000000..0e4d84f
--- /dev/null
+++ b/library/Icingadb/Command/Object/ScheduleHostDowntimeCommand.php
@@ -0,0 +1,42 @@
+<?php
+
+/* Icinga DB Web | (c) 2021 Icinga GmbH | GPLv2 */
+
+namespace Icinga\Module\Icingadb\Command\Object;
+
+/**
+ * Schedule a host downtime
+ */
+class ScheduleHostDowntimeCommand extends ScheduleServiceDowntimeCommand
+{
+    /**
+     * Whether to schedule a downtime for all services associated with a particular host
+     *
+     * @var bool
+     */
+    protected $forAllServices = false;
+
+    /**
+     * Set whether to schedule a downtime for all services associated with a particular host
+     *
+     * @param   bool $forAllServices
+     *
+     * @return  $this
+     */
+    public function setForAllServices(bool $forAllServices = true): self
+    {
+        $this->forAllServices = $forAllServices;
+
+        return $this;
+    }
+
+    /**
+     * Get whether to schedule a downtime for all services associated with a particular host
+     *
+     * @return bool
+     */
+    public function getForAllServices(): bool
+    {
+        return $this->forAllServices;
+    }
+}
diff --git a/library/Icingadb/Command/Object/ScheduleServiceDowntimeCommand.php b/library/Icingadb/Command/Object/ScheduleServiceDowntimeCommand.php
new file mode 100644
index 0000000..3bad28e
--- /dev/null
+++ b/library/Icingadb/Command/Object/ScheduleServiceDowntimeCommand.php
@@ -0,0 +1,196 @@
+<?php
+
+/* Icinga DB Web | (c) 2021 Icinga GmbH | GPLv2 */
+
+namespace Icinga\Module\Icingadb\Command\Object;
+
+/**
+ * Schedule a service downtime
+ */
+class ScheduleServiceDowntimeCommand extends AddCommentCommand
+{
+    /**
+     * Downtime starts at the exact time specified
+     *
+     * If `Downtime::$fixed' is set to false, the time between `Downtime::$start' and `Downtime::$end' at which a
+     * host or service transitions to a problem state determines the time at which the downtime actually starts.
+     * The downtime will then last for `Downtime::$duration' seconds.
+     *
+     * @var int Unix timestamp
+     */
+    protected $start;
+
+    /**
+     * Downtime ends at the exact time specified
+     *
+     * If `Downtime::$fixed' is set to false, the time between `Downtime::$start' and `Downtime::$end' at which a
+     * host or service transitions to a problem state determines the time at which the downtime actually starts.
+     * The downtime will then last for `Downtime::$duration' seconds.
+     *
+     * @var int Unix timestamp
+     */
+    protected $end;
+
+    /**
+     * Whether it's a fixed or flexible downtime
+     *
+     * @var bool
+     */
+    protected $fixed = true;
+
+    /**
+     * ID of the downtime which triggers this downtime
+     *
+     * The start of this downtime is triggered by the start of the other scheduled host or service downtime.
+     *
+     * @var int|null
+     */
+    protected $triggerId;
+
+    /**
+     * The duration in seconds the downtime must last if it's a flexible downtime
+     *
+     * If `Downtime::$fixed' is set to false, the downtime will last for the duration in seconds specified, even
+     * if the host or service recovers before the downtime expires.
+     *
+     * @var int|null
+     */
+    protected $duration;
+
+    /**
+     * Set the time when the downtime should start
+     *
+     * @param   int $start Unix timestamp
+     *
+     * @return  $this
+     */
+    public function setStart(int $start): self
+    {
+        $this->start = $start;
+
+        return $this;
+    }
+
+    /**
+     * Get the time when the downtime should start
+     *
+     * @return int Unix timestamp
+     */
+    public function getStart(): int
+    {
+        if ($this->start === null) {
+            throw new \LogicException(
+                'You are accessing an unset property. Please make sure to set it beforehand.'
+            );
+        }
+
+        return $this->start;
+    }
+
+    /**
+     * Set the time when the downtime should end
+     *
+     * @param   int $end Unix timestamp
+     *
+     * @return  $this
+     */
+    public function setEnd(int $end): self
+    {
+        $this->end = $end;
+
+        return $this;
+    }
+
+    /**
+     * Get the time when the downtime should end
+     *
+     * @return int Unix timestamp
+     */
+    public function getEnd(): int
+    {
+        if ($this->start === null) {
+            throw new \LogicException(
+                'You are accessing an unset property. Please make sure to set it beforehand.'
+            );
+        }
+
+        return $this->end;
+    }
+
+    /**
+     * Set whether it's a fixed or flexible downtime
+     *
+     * @param   boolean $fixed
+     *
+     * @return  $this
+     */
+    public function setFixed(bool $fixed = true): self
+    {
+        $this->fixed = $fixed;
+
+        return $this;
+    }
+
+    /**
+     * Is the downtime fixed?
+     *
+     * @return boolean
+     */
+    public function getFixed(): bool
+    {
+        return $this->fixed;
+    }
+
+    /**
+     * Set the ID of the downtime which triggers this downtime
+     *
+     * @param   int $triggerId
+     *
+     * @return  $this
+     */
+    public function setTriggerId(int $triggerId): self
+    {
+        $this->triggerId = $triggerId;
+
+        return $this;
+    }
+
+    /**
+     * Get the ID of the downtime which triggers this downtime
+     *
+     * @return int|null
+     */
+    public function getTriggerId()
+    {
+        return $this->triggerId;
+    }
+
+    /**
+     * Set the duration in seconds the downtime must last if it's a flexible downtime
+     *
+     * @param   int $duration
+     *
+     * @return  $this
+     */
+    public function setDuration(int $duration): self
+    {
+        $this->duration = $duration;
+
+        return $this;
+    }
+
+    /**
+     * Get the duration in seconds the downtime must last if it's a flexible downtime
+     *
+     * @return int|null
+     */
+    public function getDuration()
+    {
+        return $this->duration;
+    }
+
+    public function getName(): string
+    {
+        return 'ScheduleDowntime';
+    }
+}
diff --git a/library/Icingadb/Command/Object/SendCustomNotificationCommand.php b/library/Icingadb/Command/Object/SendCustomNotificationCommand.php
new file mode 100644
index 0000000..de90620
--- /dev/null
+++ b/library/Icingadb/Command/Object/SendCustomNotificationCommand.php
@@ -0,0 +1,44 @@
+<?php
+
+/* Icinga DB Web | (c) 2021 Icinga GmbH | GPLv2 */
+
+namespace Icinga\Module\Icingadb\Command\Object;
+
+/**
+ * Send custom notifications for a host or service
+ */
+class SendCustomNotificationCommand extends WithCommentCommand
+{
+    /**
+     * Whether the notification is forced
+     *
+     * Forced notifications are sent out regardless of time restrictions and whether or not notifications are enabled.
+     *
+     * @var bool
+     */
+    protected $forced;
+
+    /**
+     * Get whether to force the notification
+     *
+     * @return ?bool
+     */
+    public function getForced()
+    {
+        return $this->forced;
+    }
+
+    /**
+     * Set whether to force the notification
+     *
+     * @param   bool $forced
+     *
+     * @return  $this
+     */
+    public function setForced(bool $forced = true): self
+    {
+        $this->forced = $forced;
+
+        return $this;
+    }
+}
diff --git a/library/Icingadb/Command/Object/ToggleObjectFeatureCommand.php b/library/Icingadb/Command/Object/ToggleObjectFeatureCommand.php
new file mode 100644
index 0000000..699a113
--- /dev/null
+++ b/library/Icingadb/Command/Object/ToggleObjectFeatureCommand.php
@@ -0,0 +1,108 @@
+<?php
+
+/* Icinga DB Web | (c) 2021 Icinga GmbH | GPLv2 */
+
+namespace Icinga\Module\Icingadb\Command\Object;
+
+/**
+ * Enable or disable a feature of an Icinga object, i.e. host or service
+ */
+class ToggleObjectFeatureCommand extends ObjectCommand
+{
+    /**
+     * Feature for enabling or disabling active checks of a host or service
+     */
+    const FEATURE_ACTIVE_CHECKS = 'active_checks_enabled';
+
+    /**
+     * Feature for enabling or disabling passive checks of a host or service
+     */
+    const FEATURE_PASSIVE_CHECKS = 'passive_checks_enabled';
+
+    /**
+     * Feature for enabling or disabling notifications for a host or service
+     *
+     * Notifications will be sent out only if notifications are enabled on a program-wide basis as well.
+     */
+    const FEATURE_NOTIFICATIONS = 'notifications_enabled';
+
+    /**
+     * Feature for enabling or disabling event handler for a host or service
+     */
+    const FEATURE_EVENT_HANDLER = 'event_handler_enabled';
+
+    /**
+     * Feature for enabling or disabling flap detection for a host or service.
+     *
+     * In order to enable flap detection flap detection must be enabled on a program-wide basis as well.
+     */
+    const FEATURE_FLAP_DETECTION = 'flapping_enabled';
+
+    /**
+     * Feature that is to be enabled or disabled
+     *
+     * @var string
+     */
+    protected $feature;
+
+    /**
+     * Whether the feature should be enabled or disabled
+     *
+     * @var bool
+     */
+    protected $enabled;
+
+    /**
+     * Set the feature that is to be enabled or disabled
+     *
+     * @param   string $feature
+     *
+     * @return  $this
+     */
+    public function setFeature(string $feature): self
+    {
+        $this->feature = $feature;
+
+        return $this;
+    }
+
+    /**
+     * Get the feature that is to be enabled or disabled
+     *
+     * @return string
+     */
+    public function getFeature(): string
+    {
+        if ($this->feature === null) {
+            throw new \LogicException(
+                'You are accessing an unset property. Please make sure to set it beforehand.'
+            );
+        }
+
+        return $this->feature;
+    }
+
+    /**
+     * Set whether the feature should be enabled or disabled
+     *
+     * @param   bool $enabled
+     *
+     * @return  $this
+     */
+    public function setEnabled(bool $enabled = true): self
+    {
+        $this->enabled = $enabled;
+
+        return $this;
+    }
+
+    /**
+     * Get whether the feature should be enabled or disabled
+     *
+     * @return ?bool
+     */
+    public function getEnabled()
+    {
+        return $this->enabled;
+    }
+}
diff --git a/library/Icingadb/Command/Object/WithCommentCommand.php b/library/Icingadb/Command/Object/WithCommentCommand.php
new file mode 100644
index 0000000..299c998
--- /dev/null
+++ b/library/Icingadb/Command/Object/WithCommentCommand.php
@@ -0,0 +1,50 @@
+<?php
+
+/* Icinga DB Web | (c) 2021 Icinga GmbH | GPLv2 */
+
+namespace Icinga\Module\Icingadb\Command\Object;
+
+/**
+ * Base class for commands adding comments
+ */
+abstract class WithCommentCommand extends ObjectCommand
+{
+    use CommandAuthor;
+
+    /**
+     * Comment
+     *
+     * @var string
+     */
+    protected $comment;
+
+    /**
+     * Set the comment
+     *
+     * @param   string $comment
+     *
+     * @return  $this
+     */
+    public function setComment(string $comment): self
+    {
+        $this->comment = $comment;
+
+        return $this;
+    }
+
+    /**
+     * Get the comment
+     *
+     * @return string
+     */
+    public function getComment(): string
+    {
+        if ($this->comment === null) {
+            throw new \LogicException(
+                'You are accessing an unset property. Please make sure to set it beforehand.'
+            );
+        }
+
+        return $this->comment;
+    }
+}
-- 
cgit v1.2.3