From 0e938f64b576e8c91d9d5292b215bce064262480 Mon Sep 17 00:00:00 2001 From: Johannes Rauh Date: Mon, 24 Nov 2025 10:13:29 +0100 Subject: [PATCH 01/26] Use typed class properties --- .../controllers/ChannelsController.php | 4 +-- .../controllers/ContactGroupsController.php | 4 +-- .../controllers/ContactsController.php | 6 ++-- .../controllers/IncidentsController.php | 4 +-- .../controllers/SchedulesController.php | 4 +-- application/forms/ChannelForm.php | 6 ++-- .../NotificationConfigProvider.php | 4 +++ application/forms/MoveRotationForm.php | 8 ++--- application/forms/RotationConfigForm.php | 32 +++++++++---------- application/forms/ScheduleForm.php | 2 +- application/forms/SourceForm.php | 4 +-- library/Notifications/Common/Database.php | 4 +-- library/Notifications/Common/LoadMore.php | 12 +++---- .../Notifications/Common/NoSubjectLink.php | 2 +- library/Notifications/Common/PsrLogger.php | 2 ++ library/Notifications/Daemon/Daemon.php | 23 ++++++------- library/Notifications/Daemon/Sender.php | 13 ++++---- library/Notifications/Daemon/Server.php | 21 ++++++------ .../Hook/ObjectsRendererHook.php | 6 ++-- .../Model/Behavior/IdTagAggregator.php | 4 +-- .../Model/Behavior/ObjectTags.php | 4 +-- .../Notifications/Model/Daemon/Connection.php | 16 +++++----- library/Notifications/Model/Daemon/Event.php | 12 +++---- library/Notifications/Model/Daemon/User.php | 10 ++---- .../ProvidedHook/SessionStorage.php | 4 +-- .../Control/SearchBar/ObjectSuggestions.php | 4 +-- .../Notifications/Web/Form/ContactForm.php | 4 +-- .../Web/Form/EventRuleDecorator.php | 3 +- library/Notifications/Widget/Calendar.php | 20 ++++++------ .../Widget/Calendar/Attendee.php | 7 ++-- .../Notifications/Widget/Calendar/DayGrid.php | 2 +- .../Notifications/Widget/Calendar/Entry.php | 11 +++++-- .../Widget/Calendar/WeekGrid.php | 2 +- .../Widget/Detail/IncidentDetail.php | 2 +- .../Widget/Detail/IncidentQuickActions.php | 8 ++--- .../Widget/Detail/ObjectHeader.php | 2 +- .../Widget/Detail/ScheduleDetail.php | 4 +-- .../Notifications/Widget/EventSourceBadge.php | 2 +- .../Widget/ItemList/PageSeparatorItem.php | 2 +- .../Widget/MemberSuggestions.php | 10 +++--- .../Widget/RuleEscalationRecipientBadge.php | 6 ++-- library/Notifications/Widget/ShowMore.php | 6 ++-- .../Widget/TimeGrid/BaseGrid.php | 14 ++++---- .../Widget/TimeGrid/DaysHeader.php | 4 +-- .../Widget/TimeGrid/DynamicGrid.php | 4 +-- .../Notifications/Widget/TimeGrid/Entry.php | 14 ++++---- .../Widget/TimeGrid/ExtraEntryCount.php | 8 ++--- .../Widget/TimeGrid/GridStep.php | 6 ++-- .../Widget/TimeGrid/Timescale.php | 4 +-- .../Notifications/Widget/TimeGrid/Util.php | 2 +- library/Notifications/Widget/Timeline.php | 14 ++++---- .../Notifications/Widget/Timeline/Entry.php | 6 ++-- .../Widget/Timeline/FutureEntry.php | 2 +- .../Notifications/Widget/Timeline/Member.php | 4 +-- .../Widget/Timeline/Rotation.php | 5 +-- 55 files changed, 200 insertions(+), 193 deletions(-) diff --git a/application/controllers/ChannelsController.php b/application/controllers/ChannelsController.php index 925f18900..3e4994824 100644 --- a/application/controllers/ChannelsController.php +++ b/application/controllers/ChannelsController.php @@ -30,8 +30,8 @@ class ChannelsController extends CompatController { use SearchControls; - /** @var Filter\Rule Filter from query string parameters */ - private $filter; + /** @var ?Filter\Rule Filter from query string parameters */ + private ?Filter\Rule $filter = null; public function init(): void { diff --git a/application/controllers/ContactGroupsController.php b/application/controllers/ContactGroupsController.php index 378f87539..cd92f468a 100644 --- a/application/controllers/ContactGroupsController.php +++ b/application/controllers/ContactGroupsController.php @@ -36,8 +36,8 @@ class ContactGroupsController extends CompatController use ConfigurationTabs; use SearchControls; - /** @var Filter\Rule Filter from query string parameters */ - private $filter; + /** @var ?Filter\Rule Filter from query string parameters */ + private ?Filter\Rule $filter = null; public function init(): void { diff --git a/application/controllers/ContactsController.php b/application/controllers/ContactsController.php index 6d84496dd..f3753b2c7 100644 --- a/application/controllers/ContactsController.php +++ b/application/controllers/ContactsController.php @@ -35,10 +35,10 @@ class ContactsController extends CompatController use SearchControls; /** @var Connection */ - private $db; + private Connection $db; - /** @var Filter\Rule Filter from query string parameters */ - private $filter; + /** @var ?Filter\Rule Filter from query string parameters */ + private ?Filter\Rule $filter = null; public function init() { diff --git a/application/controllers/IncidentsController.php b/application/controllers/IncidentsController.php index 7a050bbe7..89b1576c7 100644 --- a/application/controllers/IncidentsController.php +++ b/application/controllers/IncidentsController.php @@ -27,8 +27,8 @@ class IncidentsController extends CompatController use Auth; use SearchControls; - /** @var Filter\Rule Filter from query string parameters */ - private $filter; + /** @var ?Filter\Rule Filter from query string parameters */ + private ?Filter\Rule $filter = null; public function indexAction(): void { diff --git a/application/controllers/SchedulesController.php b/application/controllers/SchedulesController.php index 007a718b9..5b2291a12 100644 --- a/application/controllers/SchedulesController.php +++ b/application/controllers/SchedulesController.php @@ -25,8 +25,8 @@ class SchedulesController extends CompatController use ConfigurationTabs; use SearchControls; - /** @var Filter\Rule Filter from query string parameters */ - private $filter; + /** @var ?Filter\Rule Filter from query string parameters */ + private ?Filter\Rule $filter = null; public function init(): void { diff --git a/application/forms/ChannelForm.php b/application/forms/ChannelForm.php index 01994706c..b111905be 100644 --- a/application/forms/ChannelForm.php +++ b/application/forms/ChannelForm.php @@ -46,13 +46,13 @@ class ChannelForm extends CompatForm use CsrfCounterMeasure; /** @var Connection */ - private $db; + private Connection $db; /** @var ?int Channel ID */ - private $channelId; + private ?int $channelId = null; /** @var array */ - private $defaultChannelOptions = []; + private array $defaultChannelOptions = []; public function __construct(Connection $db) { diff --git a/application/forms/EventRuleConfigElements/NotificationConfigProvider.php b/application/forms/EventRuleConfigElements/NotificationConfigProvider.php index ff8aba6e2..9bee7d6e4 100644 --- a/application/forms/EventRuleConfigElements/NotificationConfigProvider.php +++ b/application/forms/EventRuleConfigElements/NotificationConfigProvider.php @@ -14,12 +14,16 @@ class NotificationConfigProvider implements ConfigProviderInterface { + /** @var ?ResultSet */ private ?ResultSet $contacts = null; + /** @var ?ResultSet */ private ?ResultSet $contactGroups = null; + /** @var ?ResultSet */ private ?ResultSet $schedules = null; + /** @var ?ResultSet */ private ?ResultSet $channels = null; public function fetchContacts(): iterable diff --git a/application/forms/MoveRotationForm.php b/application/forms/MoveRotationForm.php index 193e17486..8cfaab2cc 100644 --- a/application/forms/MoveRotationForm.php +++ b/application/forms/MoveRotationForm.php @@ -25,11 +25,11 @@ class MoveRotationForm extends Form protected $method = 'POST'; - /** @var Connection */ - protected $db; + /** @var ?Connection */ + protected ?Connection $db = null; - /** @var int */ - protected $scheduleId; + /** @var ?int */ + protected ?int $scheduleId = null; /** * Create a new MoveRotationForm diff --git a/application/forms/RotationConfigForm.php b/application/forms/RotationConfigForm.php index d798cbbaa..aab583cd8 100644 --- a/application/forms/RotationConfigForm.php +++ b/application/forms/RotationConfigForm.php @@ -52,41 +52,41 @@ class RotationConfigForm extends CompatForm */ public const EXPERIMENTAL_OVERRIDES = false; - /** @var ?int The ID of the affected schedule */ - protected $scheduleId; + /** @var int The ID of the affected schedule */ + protected int $scheduleId; /** @var Connection The database connection */ - protected $db; + protected Connection $db; - /** @var string The label shown on the submit button */ - protected $submitLabel; + /** @var ?string The label shown on the submit button */ + protected ?string $submitLabel = null; /** @var bool Whether to render the remove button */ - protected $showRemoveButton = false; + protected bool $showRemoveButton = false; - /** @var Url The URL to fetch member suggestions from */ - protected $suggestionUrl; + /** @var ?Url The URL to fetch member suggestions from */ + protected ?Url $suggestionUrl = null; /** @var bool Whether the mode selection is disabled */ - protected $disableModeSelection = false; + protected bool $disableModeSelection = false; /** @var ?DateTime The previous first handoff of this rotation's version */ - protected $previousHandoff; + protected ?DateTime $previousHandoff = null; /** @var ?DateTime The end of the last shift of this rotation's previous version */ - protected $previousShift; + protected ?DateTime $previousShift = null; /** @var ?DateTime The first handoff of a newer version for this rotation */ - protected $nextHandoff; + protected ?DateTime $nextHandoff = null; - /** @var int The rotation id */ - protected $rotationId; + /** @var ?int The rotation id */ + protected ?int $rotationId = null; /** @var string The timezone to display the timeline in */ - protected $displayTimezone; + protected string $displayTimezone; /** @var string The timezone the schedule is created in */ - protected $scheduleTimezone; + protected string $scheduleTimezone; /** * Set the label for the submit button diff --git a/application/forms/ScheduleForm.php b/application/forms/ScheduleForm.php index e2af36497..e87ae5863 100644 --- a/application/forms/ScheduleForm.php +++ b/application/forms/ScheduleForm.php @@ -30,7 +30,7 @@ class ScheduleForm extends CompatForm use CsrfCounterMeasure; /** @var ?string */ - protected ?string $submitLabel; + protected ?string $submitLabel = null; /** @var bool */ protected bool $showRemoveButton = false; diff --git a/application/forms/SourceForm.php b/application/forms/SourceForm.php index 15fa3ab8c..28255ee43 100644 --- a/application/forms/SourceForm.php +++ b/application/forms/SourceForm.php @@ -37,10 +37,10 @@ class SourceForm extends CompatForm public const TYPE_GENERIC = 'generic'; /** @var Connection */ - private $db; + private Connection $db; /** @var ?int */ - private $sourceId; + private ?int $sourceId = null; public function __construct(Connection $db) { diff --git a/library/Notifications/Common/Database.php b/library/Notifications/Common/Database.php index 4ca8fc6c0..119a40dc0 100644 --- a/library/Notifications/Common/Database.php +++ b/library/Notifications/Common/Database.php @@ -45,8 +45,8 @@ final class Database 'timeperiod_entry', ]; - /** @var Connection Database connection */ - private static $instance; + /** @var ?Connection Database connection */ + private static ?Connection $instance = null; /** Singleton class */ private function __construct() diff --git a/library/Notifications/Common/LoadMore.php b/library/Notifications/Common/LoadMore.php index 40140ea38..497283b0a 100644 --- a/library/Notifications/Common/LoadMore.php +++ b/library/Notifications/Common/LoadMore.php @@ -13,14 +13,14 @@ trait LoadMore { - /** @var int */ - protected $pageSize; + /** @var ?int */ + protected ?int $pageSize = null; - /** @var int */ - protected $pageNumber; + /** @var ?int */ + protected ?int $pageNumber = null; - /** @var Url */ - protected $loadMoreUrl; + /** @var ?Url */ + protected ?Url $loadMoreUrl = null; /** * Set the page size diff --git a/library/Notifications/Common/NoSubjectLink.php b/library/Notifications/Common/NoSubjectLink.php index dea92ac0b..77156efb9 100644 --- a/library/Notifications/Common/NoSubjectLink.php +++ b/library/Notifications/Common/NoSubjectLink.php @@ -8,7 +8,7 @@ trait NoSubjectLink { /** @var bool */ - protected $noSubjectLink = false; + protected bool $noSubjectLink = false; /** * Set whether a list item's subject should be a link diff --git a/library/Notifications/Common/PsrLogger.php b/library/Notifications/Common/PsrLogger.php index 55eb40074..984653585 100644 --- a/library/Notifications/Common/PsrLogger.php +++ b/library/Notifications/Common/PsrLogger.php @@ -25,6 +25,8 @@ class PsrLogger implements LoggerInterface * Map PSR-3 levels to Icinga's 4 levels. * emergency/alert/critical -> ERROR * notice -> INFO + * + * @var array */ private const MAP = [ LogLevel::EMERGENCY => 'error', diff --git a/library/Notifications/Daemon/Daemon.php b/library/Notifications/Daemon/Daemon.php index 187eff88d..ecfcc0809 100644 --- a/library/Notifications/Daemon/Daemon.php +++ b/library/Notifications/Daemon/Daemon.php @@ -27,34 +27,35 @@ class Daemon extends EventEmitter { + /** @var string */ protected const PREFIX = '[daemon] - '; /** @var Logger Instance of the logger class */ - protected static $logger; + protected static Logger $logger; - /** @var Daemon Instance of this class */ - private static $instance; + /** @var ?Daemon Instance of this class */ + private static ?Daemon $instance = null; /** @var LoopInterface Main loop */ - protected $loop; + protected LoopInterface $loop; /** @var Server Server object */ - protected $server; + protected Server $server; /** @var Sender Sender object */ - protected $sender; + protected Sender $sender; /** @var SQLConnection Database object */ - protected $database; + protected SQLConnection $database; /** @var bool Token which can be triggered to exit the main routine */ - protected $cancellationToken; + protected bool $cancellationToken; /** @var int Timestamp holding the creation's time of this {@see self::$instance instance} */ - protected $initializedAt; + protected int $initializedAt; - /** @var int Last checked incident identifier */ - protected $lastIncidentId; + /** @var ?int Last checked incident identifier */ + protected ?int $lastIncidentId = null; /** * Construct the singleton instance of the Daemon class diff --git a/library/Notifications/Daemon/Sender.php b/library/Notifications/Daemon/Sender.php index a0a53b1e9..d3c5b0701 100644 --- a/library/Notifications/Daemon/Sender.php +++ b/library/Notifications/Daemon/Sender.php @@ -12,22 +12,23 @@ class Sender { + /** @var string */ protected const PREFIX = '[daemon.sender] - '; - /** @var Sender Instance of this class */ - private static $instance; + /** @var ?Sender Instance of this class */ + private static ?Sender $instance = null; /** @var Logger Instance of the logger class */ - protected static $logger; + protected static Logger $logger; /** @var Daemon Daemon object reference */ - protected static $daemon; + protected static Daemon $daemon; /** @var Server Server object reference */ - protected static $server; + protected static Server $server; /** @var Closure {@see processNotification()} wrapper */ - protected $callback; + protected Closure $callback; /** * Construct the singleton instance of the Sender class diff --git a/library/Notifications/Daemon/Server.php b/library/Notifications/Daemon/Server.php index 1832a08d5..e56d3e5b0 100644 --- a/library/Notifications/Daemon/Server.php +++ b/library/Notifications/Daemon/Server.php @@ -24,31 +24,32 @@ class Server { + /** @var string */ protected const PREFIX = '[daemon.server] - '; - /** @var Server Instance of this class */ - private static $instance; + /** @var ?Server Instance of this class */ + private static ?Server $instance = null; - /** @var LoopInterface Reference to ReactPHP's main loop */ - protected $mainLoop; + /** @var ?LoopInterface Reference to ReactPHP's main loop */ + protected ?LoopInterface $mainLoop = null; /** @var Logger Instance of the logger class */ - protected static $logger; + protected static Logger $logger; /** @var SocketServer SocketServer object */ - protected $socket; + protected SocketServer $socket; /** @var HttpServer HttpServer object */ - protected $http; + protected HttpServer $http; /** @var array Socket connections */ - protected $connections; + protected array $connections; /** @var SQLConnection Database object */ - protected $dbLink; + protected SQLConnection $dbLink; /** @var Config Config object */ - protected $config; + protected Config $config; /** * Construct the singleton instance of the Server class diff --git a/library/Notifications/Hook/ObjectsRendererHook.php b/library/Notifications/Hook/ObjectsRendererHook.php index a15191a89..ee79cb3de 100644 --- a/library/Notifications/Hook/ObjectsRendererHook.php +++ b/library/Notifications/Hook/ObjectsRendererHook.php @@ -30,7 +30,7 @@ abstract class ObjectsRendererHook * * @var array>> */ - private static $objectIdTags = []; + private static array $objectIdTags = []; /** * Array of HTMLs for objects with their corresponding object IDs as keys @@ -39,7 +39,7 @@ abstract class ObjectsRendererHook * * @var array */ - private static $objectNameHtmls = []; + private static array $objectNameHtmls = []; /** * Array of object names with their corresponding object IDs as keys @@ -48,7 +48,7 @@ abstract class ObjectsRendererHook * * @var array */ - private static $objectNames = []; + private static array $objectNames = []; /** * Get the object names for the objects using the object ID tags diff --git a/library/Notifications/Model/Behavior/IdTagAggregator.php b/library/Notifications/Model/Behavior/IdTagAggregator.php index 2e1a6a710..db8b79b6a 100644 --- a/library/Notifications/Model/Behavior/IdTagAggregator.php +++ b/library/Notifications/Model/Behavior/IdTagAggregator.php @@ -20,8 +20,8 @@ class IdTagAggregator extends PropertyBehavior implements RewriteColumnBehavior, QueryAwareBehavior { - /** @var Query */ - protected $query; + /** @var ?Query */ + protected ?Query $query = null; final public function __construct() { diff --git a/library/Notifications/Model/Behavior/ObjectTags.php b/library/Notifications/Model/Behavior/ObjectTags.php index 86053be0e..b09df41c2 100644 --- a/library/Notifications/Model/Behavior/ObjectTags.php +++ b/library/Notifications/Model/Behavior/ObjectTags.php @@ -18,8 +18,8 @@ class ObjectTags implements RewriteColumnBehavior, QueryAwareBehavior { use Auth; - /** @var Query */ - protected $query; + /** @var ?Query */ + protected ?Query $query = null; public function setQuery(Query $query): self { diff --git a/library/Notifications/Model/Daemon/Connection.php b/library/Notifications/Model/Daemon/Connection.php index b44289e13..3c568c9b0 100644 --- a/library/Notifications/Model/Daemon/Connection.php +++ b/library/Notifications/Model/Daemon/Connection.php @@ -11,25 +11,25 @@ class Connection { /** @var ConnectionInterface Associated Connection from ReactPHP */ - protected $connection; + protected ConnectionInterface $connection; /** @var string Hostname */ - protected $host; + protected string $host; /** @var int Port */ - protected $port; + protected int $port; /** @var string Session identifier */ - protected $session; + protected string $session; /** @var User User information */ - protected $user; + protected User $user; /** @var ThroughStream Data stream between connection and server */ - protected $stream; + protected ThroughStream $stream; - /** @var string User agent */ - protected $userAgent; + /** @var ?string User agent */ + protected ?string $userAgent = null; /** * Construct an instance of the Connection class diff --git a/library/Notifications/Model/Daemon/Event.php b/library/Notifications/Model/Daemon/Event.php index b4239b032..d3a283de3 100644 --- a/library/Notifications/Model/Daemon/Event.php +++ b/library/Notifications/Model/Daemon/Event.php @@ -14,22 +14,22 @@ class Event { /** @var string Event identifier */ - protected $identifier; + protected string $identifier; /** @var stdClass Event data */ - protected $data; + protected stdClass $data; /** @var DateTime Creation date of event */ - protected $createdAt; + protected DateTime $createdAt; /** @var int Reconnect interval in milliseconds */ - protected $reconnectInterval; + protected int $reconnectInterval; /** @var int Last event identifier */ - protected $lastEventId; + protected int $lastEventId; /** @var int Contact identifier associated with this event */ - protected $contact; + protected int $contact; public function __construct(string $identifier, int $contact, stdClass $data, int $lastEventId = 0) { diff --git a/library/Notifications/Model/Daemon/User.php b/library/Notifications/Model/Daemon/User.php index 6926e4544..e84e7177d 100644 --- a/library/Notifications/Model/Daemon/User.php +++ b/library/Notifications/Model/Daemon/User.php @@ -8,16 +8,10 @@ class User { /** @var ?string Username */ - protected $username; + protected ?string $username = null; /** @var ?int Contact identifier */ - protected $contactId; - - public function __construct() - { - $this->username = null; - $this->contactId = null; - } + protected ?int $contactId = null; public function getUsername(): ?string { diff --git a/library/Notifications/ProvidedHook/SessionStorage.php b/library/Notifications/ProvidedHook/SessionStorage.php index f468890c6..3fcf3db82 100644 --- a/library/Notifications/ProvidedHook/SessionStorage.php +++ b/library/Notifications/ProvidedHook/SessionStorage.php @@ -20,10 +20,10 @@ class SessionStorage extends AuthenticationHook { /** @var Session\Session Session object */ - protected $session; + protected Session\Session $session; /** @var Connection Database object */ - protected $database; + protected Connection $database; public function __construct() { diff --git a/library/Notifications/Web/Control/SearchBar/ObjectSuggestions.php b/library/Notifications/Web/Control/SearchBar/ObjectSuggestions.php index ce839cff9..99102c1a4 100644 --- a/library/Notifications/Web/Control/SearchBar/ObjectSuggestions.php +++ b/library/Notifications/Web/Control/SearchBar/ObjectSuggestions.php @@ -32,8 +32,8 @@ class ObjectSuggestions extends Suggestions use Auth; use Translation; - /** @var Model */ - protected $model; + /** @var ?Model */ + protected ?Model $model = null; /** * Set the model to show suggestions for diff --git a/library/Notifications/Web/Form/ContactForm.php b/library/Notifications/Web/Form/ContactForm.php index 32a7daf47..fc194dffa 100644 --- a/library/Notifications/Web/Form/ContactForm.php +++ b/library/Notifications/Web/Form/ContactForm.php @@ -38,10 +38,10 @@ class ContactForm extends CompatForm public const ON_REMOVE = 'on_remove'; /** @var Connection */ - private $db; + private Connection $db; /** @var ?string Contact ID*/ - private $contactId; + private ?string $contactId = null; public function __construct(Connection $db) { diff --git a/library/Notifications/Web/Form/EventRuleDecorator.php b/library/Notifications/Web/Form/EventRuleDecorator.php index e1326a596..b4706ac57 100644 --- a/library/Notifications/Web/Form/EventRuleDecorator.php +++ b/library/Notifications/Web/Form/EventRuleDecorator.php @@ -14,7 +14,8 @@ class EventRuleDecorator extends HtmlDocument implements FormElementDecorator { - private $element; + /** @var FormElement */ + private FormElement $element; public function decorate(FormElement $formElement) { diff --git a/library/Notifications/Widget/Calendar.php b/library/Notifications/Widget/Calendar.php index 73af6fbb4..424ed1c7e 100644 --- a/library/Notifications/Widget/Calendar.php +++ b/library/Notifications/Widget/Calendar.php @@ -41,23 +41,23 @@ class Calendar extends BaseHtmlElement implements EntryProvider protected $defaultAttributes = ['class' => 'calendar']; - /** @var Controls */ - protected $controls; + /** @var ?Controls */ + protected ?Controls $controls = null; - /** @var Style */ - protected $style; + /** @var ?Style */ + protected ?Style $style = null; - /** @var BaseGrid The grid implementation */ - protected $grid; + /** @var ?BaseGrid The grid implementation */ + protected ?BaseGrid $grid = null; /** @var Entry[] */ - protected $entries = []; + protected array $entries = []; - /** @var Url */ - protected $addEntryUrl; + /** @var ?Url */ + protected ?Url $addEntryUrl = null; /** @var ?Url */ - protected $url; + protected ?Url $url = null; public function setControls(Controls $controls): self { diff --git a/library/Notifications/Widget/Calendar/Attendee.php b/library/Notifications/Widget/Calendar/Attendee.php index 14ee0c6d9..ec4762c97 100644 --- a/library/Notifications/Widget/Calendar/Attendee.php +++ b/library/Notifications/Widget/Calendar/Attendee.php @@ -15,13 +15,10 @@ class Attendee { /** @var string */ - protected $name; + protected string $name; /** @var string|ValidHtml */ - protected $icon = 'user'; - - /** @var string */ - protected $color = ''; + protected string|ValidHtml $icon = 'user'; public function __construct(string $name) { diff --git a/library/Notifications/Widget/Calendar/DayGrid.php b/library/Notifications/Widget/Calendar/DayGrid.php index 921d7ac77..8a464568d 100644 --- a/library/Notifications/Widget/Calendar/DayGrid.php +++ b/library/Notifications/Widget/Calendar/DayGrid.php @@ -18,7 +18,7 @@ class DayGrid extends BaseGrid { - protected $flowOfTime = BaseGrid::VERTICAL_FLOW_OF_TIME; + protected string $flowOfTime = BaseGrid::VERTICAL_FLOW_OF_TIME; public function setGridStart(DateTime $start): BaseGrid { diff --git a/library/Notifications/Widget/Calendar/Entry.php b/library/Notifications/Widget/Calendar/Entry.php index aaee41729..7fe85326f 100644 --- a/library/Notifications/Widget/Calendar/Entry.php +++ b/library/Notifications/Widget/Calendar/Entry.php @@ -11,6 +11,7 @@ use ipl\Html\HtmlElement; use ipl\Html\Text; use Icinga\Module\Notifications\Widget\TimeGrid; +use LogicException; /** * An entry on a calendar @@ -18,10 +19,10 @@ class Entry extends TimeGrid\Entry { /** @var ?string The description */ - protected $description; + protected ?string $description = null; - /** @var Attendee */ - protected $attendee; + /** @var ?Attendee */ + protected ?Attendee $attendee = null; /** * Set the description @@ -68,6 +69,10 @@ public function setAttendee(Attendee $attendee): self */ public function getAttendee(): Attendee { + if ($this->attendee === null) { + throw new LogicException('You are accessing an unset property. Please make sure to set it beforehand.'); + } + return $this->attendee; } diff --git a/library/Notifications/Widget/Calendar/WeekGrid.php b/library/Notifications/Widget/Calendar/WeekGrid.php index 7677b0818..8697f2692 100644 --- a/library/Notifications/Widget/Calendar/WeekGrid.php +++ b/library/Notifications/Widget/Calendar/WeekGrid.php @@ -18,7 +18,7 @@ class WeekGrid extends BaseGrid { - protected $flowOfTime = BaseGrid::VERTICAL_FLOW_OF_TIME; + protected string $flowOfTime = BaseGrid::VERTICAL_FLOW_OF_TIME; public function setGridStart(DateTime $start): BaseGrid { diff --git a/library/Notifications/Widget/Detail/IncidentDetail.php b/library/Notifications/Widget/Detail/IncidentDetail.php index cd89f3c6d..bfb36673a 100644 --- a/library/Notifications/Widget/Detail/IncidentDetail.php +++ b/library/Notifications/Widget/Detail/IncidentDetail.php @@ -32,7 +32,7 @@ class IncidentDetail extends BaseHtmlElement use Translation; /** @var Incident */ - protected $incident; + protected Incident $incident; protected $defaultAttributes = [ 'class' => 'incident-detail', diff --git a/library/Notifications/Widget/Detail/IncidentQuickActions.php b/library/Notifications/Widget/Detail/IncidentQuickActions.php index e99a58645..f2859753b 100644 --- a/library/Notifications/Widget/Detail/IncidentQuickActions.php +++ b/library/Notifications/Widget/Detail/IncidentQuickActions.php @@ -29,13 +29,13 @@ class IncidentQuickActions extends Form ]; /** @var Incident */ - protected $incident; + protected Incident $incident; /** @var int Current logged-in user's id */ - protected $currentUserId; + protected int $currentUserId; - /** @var IncidentContact */ - protected $incidentContact; + /** @var ?IncidentContact */ + protected ?IncidentContact $incidentContact = null; public function __construct(Incident $incident, int $currentUserId) { diff --git a/library/Notifications/Widget/Detail/ObjectHeader.php b/library/Notifications/Widget/Detail/ObjectHeader.php index bfcd5e4dc..29f2b2545 100644 --- a/library/Notifications/Widget/Detail/ObjectHeader.php +++ b/library/Notifications/Widget/Detail/ObjectHeader.php @@ -24,7 +24,7 @@ class ObjectHeader extends BaseHtmlElement { /** @var Item */ - protected $object; + protected Model $object; protected $tag = 'div'; diff --git a/library/Notifications/Widget/Detail/ScheduleDetail.php b/library/Notifications/Widget/Detail/ScheduleDetail.php index 18cc69d7c..700096945 100644 --- a/library/Notifications/Widget/Detail/ScheduleDetail.php +++ b/library/Notifications/Widget/Detail/ScheduleDetail.php @@ -30,10 +30,10 @@ class ScheduleDetail extends BaseHtmlElement protected $defaultAttributes = ['id' => 'notifications-schedule', 'class' => 'schedule-detail']; /** @var Schedule */ - protected $schedule; + protected Schedule $schedule; /** @var Controls */ - protected $controls; + protected Controls $controls; /** @var DateTime The day the timeline should start on */ protected DateTime $start; diff --git a/library/Notifications/Widget/EventSourceBadge.php b/library/Notifications/Widget/EventSourceBadge.php index 19f73d2d4..03774b4a1 100644 --- a/library/Notifications/Widget/EventSourceBadge.php +++ b/library/Notifications/Widget/EventSourceBadge.php @@ -13,7 +13,7 @@ class EventSourceBadge extends BaseHtmlElement { /** @var Source */ - protected $source; + protected Source $source; protected $tag = 'span'; diff --git a/library/Notifications/Widget/ItemList/PageSeparatorItem.php b/library/Notifications/Widget/ItemList/PageSeparatorItem.php index fd174777f..93f6925df 100644 --- a/library/Notifications/Widget/ItemList/PageSeparatorItem.php +++ b/library/Notifications/Widget/ItemList/PageSeparatorItem.php @@ -13,7 +13,7 @@ class PageSeparatorItem extends BaseHtmlElement protected $defaultAttributes = ['class' => 'list-item page-separator']; /** @var int */ - protected $pageNumber; + protected int $pageNumber; /** @var string */ protected $tag = 'li'; diff --git a/library/Notifications/Widget/MemberSuggestions.php b/library/Notifications/Widget/MemberSuggestions.php index 419e39e93..3d35fc7d7 100644 --- a/library/Notifications/Widget/MemberSuggestions.php +++ b/library/Notifications/Widget/MemberSuggestions.php @@ -18,14 +18,14 @@ class MemberSuggestions extends BaseHtmlElement { protected $tag = 'ul'; - /** @var string */ - protected $searchTerm; + /** @var ?string */ + protected ?string $searchTerm = null; - /** @var string */ - protected $originalValue; + /** @var ?string */ + protected ?string $originalValue = null; /** @var string[] */ - protected $excludeTerms = []; + protected array $excludeTerms = []; public function setSearchTerm(string $term): self { diff --git a/library/Notifications/Widget/RuleEscalationRecipientBadge.php b/library/Notifications/Widget/RuleEscalationRecipientBadge.php index d527d7b04..7c047bc88 100644 --- a/library/Notifications/Widget/RuleEscalationRecipientBadge.php +++ b/library/Notifications/Widget/RuleEscalationRecipientBadge.php @@ -14,10 +14,10 @@ class RuleEscalationRecipientBadge extends BaseHtmlElement { /** @var RuleEscalationRecipient */ - protected $recipient; + protected RuleEscalationRecipient $recipient; - /** @var int */ - protected $moreCount; + /** @var ?int */ + protected ?int $moreCount = null; protected $tag = 'span'; diff --git a/library/Notifications/Widget/ShowMore.php b/library/Notifications/Widget/ShowMore.php index 079d68a83..52b06d3ce 100644 --- a/library/Notifications/Widget/ShowMore.php +++ b/library/Notifications/Widget/ShowMore.php @@ -19,11 +19,11 @@ class ShowMore extends BaseHtmlElement protected $tag = 'div'; - protected $resultSet; + protected ResultSet $resultSet; - protected $url; + protected Url $url; - protected $label; + protected ?string $label = null; public function __construct(ResultSet $resultSet, Url $url, ?string $label = null) { diff --git a/library/Notifications/Widget/TimeGrid/BaseGrid.php b/library/Notifications/Widget/TimeGrid/BaseGrid.php index ba617365c..596adc42c 100644 --- a/library/Notifications/Widget/TimeGrid/BaseGrid.php +++ b/library/Notifications/Widget/TimeGrid/BaseGrid.php @@ -42,22 +42,22 @@ abstract class BaseGrid extends BaseHtmlElement protected $defaultAttributes = ['class' => ['time-grid']]; /** @var string The orientation of this grid's chronological order of entries */ - protected $flowOfTime = self::HORIZONTAL_FLOW_OF_TIME; + protected string $flowOfTime = self::HORIZONTAL_FLOW_OF_TIME; /** @var EntryProvider */ - protected $provider; + protected EntryProvider $provider; /** @var Style */ - protected $style; + protected Style $style; /** @var DateTime */ - protected $start; + protected DateTime $start; - /** @var DateTime */ - protected $end; + /** @var ?DateTime */ + protected ?DateTime $end = null; /** @var array Extra counts stored as [date1 => count1, date2 => count2]*/ - protected $extraEntriesCount = []; + protected array $extraEntriesCount = []; /** * Create a new time grid diff --git a/library/Notifications/Widget/TimeGrid/DaysHeader.php b/library/Notifications/Widget/TimeGrid/DaysHeader.php index 119b27687..879a4a47e 100644 --- a/library/Notifications/Widget/TimeGrid/DaysHeader.php +++ b/library/Notifications/Widget/TimeGrid/DaysHeader.php @@ -20,14 +20,14 @@ class DaysHeader extends BaseHtmlElement use Translation; /** @var int The number of days to show */ - protected $days; + protected int $days; protected $tag = 'div'; protected $defaultAttributes = ['class' => ['days-header', 'time-grid-header']]; /** @var DateTime Starting day */ - protected $startDay; + protected DateTime $startDay; /** * Create a new DaysHeader diff --git a/library/Notifications/Widget/TimeGrid/DynamicGrid.php b/library/Notifications/Widget/TimeGrid/DynamicGrid.php index cc6619613..941d5db2d 100644 --- a/library/Notifications/Widget/TimeGrid/DynamicGrid.php +++ b/library/Notifications/Widget/TimeGrid/DynamicGrid.php @@ -17,10 +17,10 @@ class DynamicGrid extends BaseGrid { /** @var int The number of days to show */ - protected $days = 7; + protected int $days = 7; /** @var ?BaseHtmlElement This grid's sidebar */ - protected $sideBar; + protected ?BaseHtmlElement $sideBar = null; public function setGridStart(DateTime $start): BaseGrid { diff --git a/library/Notifications/Widget/TimeGrid/Entry.php b/library/Notifications/Widget/TimeGrid/Entry.php index df3fde6d1..eac153e1f 100644 --- a/library/Notifications/Widget/TimeGrid/Entry.php +++ b/library/Notifications/Widget/TimeGrid/Entry.php @@ -45,22 +45,22 @@ abstract class Entry extends BaseHtmlElement protected $defaultAttributes = ['class' => 'entry']; /** @var int The entry id */ - protected $id; + protected int $id; /** @var ?DateTime When the entry starts */ - protected $start; + protected ?DateTime $start = null; /** @var ?DateTime When the entry ends */ - protected $end; + protected ?DateTime $end = null; /** @var ?int The 0-based position of the row where to place this entry on the grid */ - protected $position; + protected ?int $position = null; /** @var ?ContinuationType The continuation type */ - protected $continuationType; + protected ?string $continuationType = null; - /** @var Url The URL to show this entry */ - protected $url; + /** @var ?Url The URL to show this entry */ + protected ?Url $url = null; /** * Create a new entry diff --git a/library/Notifications/Widget/TimeGrid/ExtraEntryCount.php b/library/Notifications/Widget/TimeGrid/ExtraEntryCount.php index 48e6740e9..c4c90f4c7 100644 --- a/library/Notifications/Widget/TimeGrid/ExtraEntryCount.php +++ b/library/Notifications/Widget/TimeGrid/ExtraEntryCount.php @@ -13,11 +13,11 @@ class ExtraEntryCount extends ButtonLink { use Translation; - /** @var BaseGrid Grid this extra count is tied to*/ - protected $grid; + /** @var ?BaseGrid Grid this extra count is tied to*/ + protected ?BaseGrid $grid = null; - /** @var DateTime Grid step for which the extra count is being registered */ - protected $gridStep; + /** @var ?DateTime Grid step for which the extra count is being registered */ + protected ?DateTime $gridStep = null; /** * Set the grid this extra count is tied to diff --git a/library/Notifications/Widget/TimeGrid/GridStep.php b/library/Notifications/Widget/TimeGrid/GridStep.php index ab4be2e06..2b4024803 100644 --- a/library/Notifications/Widget/TimeGrid/GridStep.php +++ b/library/Notifications/Widget/TimeGrid/GridStep.php @@ -16,13 +16,13 @@ class GridStep extends BaseHtmlElement { /** @var DateTime Start time of the grid step */ - protected $start; + protected DateTime $start; /** @var DateTime End time of the grid step */ - protected $end; + protected DateTime $end; /** @var array{int, int} The x and y position of the step on the grid */ - protected $coordinates; + protected array $coordinates; protected $tag = 'div'; diff --git a/library/Notifications/Widget/TimeGrid/Timescale.php b/library/Notifications/Widget/TimeGrid/Timescale.php index 14ffa7147..8c4ef9530 100644 --- a/library/Notifications/Widget/TimeGrid/Timescale.php +++ b/library/Notifications/Widget/TimeGrid/Timescale.php @@ -27,10 +27,10 @@ class Timescale extends BaseHtmlElement protected $defaultAttributes = ['class' => 'timescale']; /** @var int The number of days shown */ - protected $days; + protected int $days; /** @var Style */ - protected $style; + protected Style $style; /** * Create a new Timescale diff --git a/library/Notifications/Widget/TimeGrid/Util.php b/library/Notifications/Widget/TimeGrid/Util.php index 127dd875f..38de2864a 100644 --- a/library/Notifications/Widget/TimeGrid/Util.php +++ b/library/Notifications/Widget/TimeGrid/Util.php @@ -11,7 +11,7 @@ final class Util { /** @var array */ - private static $entryColors = []; + private static array $entryColors = []; public static function diffHours(DateTime $from, DateTime $to) { diff --git a/library/Notifications/Widget/Timeline.php b/library/Notifications/Widget/Timeline.php index 5588042c7..03967f66c 100644 --- a/library/Notifications/Widget/Timeline.php +++ b/library/Notifications/Widget/Timeline.php @@ -43,25 +43,25 @@ class Timeline extends BaseHtmlElement implements EntryProvider protected $defaultAttributes = ['class' => ['timeline']]; /** @var array */ - protected $rotations = []; + protected array $rotations = []; /** @var int */ protected int $scheduleId; /** @var DateTime */ - protected $start; + protected DateTime $start; /** @var int */ - protected $days; + protected int $days; - /** @var Style */ - protected $style; + /** @var ?Style */ + protected ?Style $style = null; /** @var ?DynamicGrid|MinimalGrid */ - protected $grid; + protected DynamicGrid|MinimalGrid|null $grid = null; /** @var bool Whether to create the Timeline only with the Result using MinimalGrid */ - protected $minimalLayout = false; + protected bool $minimalLayout = false; /** @var int */ protected int $noOfRotations = 0; diff --git a/library/Notifications/Widget/Timeline/Entry.php b/library/Notifications/Widget/Timeline/Entry.php index c34986e8d..993eeb86f 100644 --- a/library/Notifications/Widget/Timeline/Entry.php +++ b/library/Notifications/Widget/Timeline/Entry.php @@ -16,14 +16,14 @@ class Entry extends TimeGrid\Entry { - /** @var Member */ - protected $member; + /** @var ?Member */ + protected ?Member $member = null; /** @var ?EntryFlyout Content of the flyoutmenu that is shown when the entry is hovered */ protected ?EntryFlyout $flyoutContent = null; /** @var ?DateTimeZone The timezone the schedule is created in */ - protected ?DateTimeZone $scheduleTimezone; + protected ?DateTimeZone $scheduleTimezone = null; /** * @var string A CSS class that changes the placement of the flyout diff --git a/library/Notifications/Widget/Timeline/FutureEntry.php b/library/Notifications/Widget/Timeline/FutureEntry.php index 11ee2451c..c59078d7d 100644 --- a/library/Notifications/Widget/Timeline/FutureEntry.php +++ b/library/Notifications/Widget/Timeline/FutureEntry.php @@ -20,7 +20,7 @@ class FutureEntry extends Entry { protected $defaultAttributes = ['class' => 'future-entry']; - protected $continuationType = Entry::TO_NEXT_GRID; + protected ?string $continuationType = Entry::TO_NEXT_GRID; public function __construct() { diff --git a/library/Notifications/Widget/Timeline/Member.php b/library/Notifications/Widget/Timeline/Member.php index 3ea982dcb..6cb8bd0ea 100644 --- a/library/Notifications/Widget/Timeline/Member.php +++ b/library/Notifications/Widget/Timeline/Member.php @@ -11,10 +11,10 @@ class Member { /** @var string */ - protected $name; + protected string $name; /** @var string */ - protected $icon = 'user'; + protected string $icon = 'user'; /** * Create a new Member diff --git a/library/Notifications/Widget/Timeline/Rotation.php b/library/Notifications/Widget/Timeline/Rotation.php index d1c10baf6..0fa354c0f 100644 --- a/library/Notifications/Widget/Timeline/Rotation.php +++ b/library/Notifications/Widget/Timeline/Rotation.php @@ -11,6 +11,7 @@ use Generator; use Icinga\Module\Notifications\Common\Links; use Icinga\Module\Notifications\Forms\RotationConfigForm; +use Icinga\Module\Notifications\Model\Rotation as RotationModel; use ipl\I18n\Translation; use ipl\Scheduler\RRule; use ipl\Stdlib\Filter; @@ -21,8 +22,8 @@ class Rotation { use Translation; - /** @var \Icinga\Module\Notifications\Model\Rotation */ - protected $model; + /** @var RotationModel */ + protected RotationModel $model; /** * Create a new Rotation From 93d464d2c72144bf83fb4857fc58055706d7d024 Mon Sep 17 00:00:00 2001 From: Johannes Rauh Date: Thu, 13 Nov 2025 09:16:38 +0100 Subject: [PATCH 02/26] Use typed method return values --- application/controllers/ConfigController.php | 4 ++-- .../controllers/ContactsController.php | 4 ++-- .../controllers/EventRulesController.php | 2 +- application/controllers/SourcesController.php | 2 +- application/forms/DatabaseConfigForm.php | 2 +- application/forms/MoveRotationForm.php | 8 ++++---- application/forms/RotationConfigForm.php | 6 +++--- library/Notifications/Common/Database.php | 3 ++- library/Notifications/Common/LoadMore.php | 6 +++--- library/Notifications/Common/PsrLogger.php | 4 +++- library/Notifications/Daemon/Daemon.php | 4 ++-- .../Model/Behavior/IcingaCustomVars.php | 4 ++-- .../Model/Behavior/IdTagAggregator.php | 15 +++++++++++--- .../Notifications/Model/Daemon/Connection.php | 4 ++-- .../Model/RuleEscalationRecipient.php | 2 +- .../Control/SearchBar/ExtraTagSuggestions.php | 10 +++++----- .../Control/SearchBar/ObjectSuggestions.php | 20 ++++++++++++------- .../Notifications/Web/Form/ContactForm.php | 4 ++-- .../Web/Form/EventRuleDecorator.php | 4 ++-- library/Notifications/Widget/Calendar.php | 2 +- .../Widget/Calendar/Controls.php | 2 +- .../Notifications/Widget/Calendar/DayGrid.php | 2 +- .../Widget/Calendar/MonthGrid.php | 2 +- .../Widget/Calendar/WeekGrid.php | 2 +- .../Widget/Detail/IncidentDetail.php | 16 ++++++++++----- .../Widget/Detail/IncidentQuickActions.php | 4 ++-- .../Widget/Detail/ScheduleDetail.php | 2 +- .../Notifications/Widget/EventSourceBadge.php | 4 ++-- .../Widget/ItemList/PageSeparatorItem.php | 2 +- .../Widget/RuleEscalationRecipientBadge.php | 2 +- library/Notifications/Widget/ShowMore.php | 2 +- .../Widget/TimeGrid/DynamicGrid.php | 2 +- .../Notifications/Widget/TimeGrid/Entry.php | 2 +- .../Widget/TimeGrid/ExtraEntryCount.php | 4 ++-- .../Widget/TimeGrid/GridStep.php | 2 +- .../Notifications/Widget/TimeGrid/Util.php | 10 +++++++++- library/Notifications/Widget/Timeline.php | 4 ++-- .../Widget/Timeline/Rotation.php | 4 ++-- 38 files changed, 105 insertions(+), 73 deletions(-) diff --git a/application/controllers/ConfigController.php b/application/controllers/ConfigController.php index dd50e4916..c6ddd2939 100644 --- a/application/controllers/ConfigController.php +++ b/application/controllers/ConfigController.php @@ -14,14 +14,14 @@ class ConfigController extends CompatController { - public function init() + public function init(): void { $this->assertPermission('config/modules'); parent::init(); } - public function databaseAction() + public function databaseAction(): void { $moduleConfig = Config::module('notifications'); $form = (new DatabaseConfigForm()) diff --git a/application/controllers/ContactsController.php b/application/controllers/ContactsController.php index f3753b2c7..b414415eb 100644 --- a/application/controllers/ContactsController.php +++ b/application/controllers/ContactsController.php @@ -40,14 +40,14 @@ class ContactsController extends CompatController /** @var ?Filter\Rule Filter from query string parameters */ private ?Filter\Rule $filter = null; - public function init() + public function init(): void { $this->assertPermission('notifications/config/contacts'); $this->db = Database::get(); } - public function indexAction() + public function indexAction(): void { $this->setTitle($this->translate('Contacts')); $this->getTabs()->activate('contacts'); diff --git a/application/controllers/EventRulesController.php b/application/controllers/EventRulesController.php index 7d6f26e87..05021a243 100644 --- a/application/controllers/EventRulesController.php +++ b/application/controllers/EventRulesController.php @@ -33,7 +33,7 @@ class EventRulesController extends CompatController use ConfigurationTabs; use SearchControls; - public function init() + public function init(): void { $this->assertPermission('notifications/config/event-rules'); } diff --git a/application/controllers/SourcesController.php b/application/controllers/SourcesController.php index 7a6eb0416..fe793266c 100644 --- a/application/controllers/SourcesController.php +++ b/application/controllers/SourcesController.php @@ -28,7 +28,7 @@ class SourcesController extends CompatController { use SearchControls; - public function init() + public function init(): void { $this->assertPermission('config/modules'); } diff --git a/application/forms/DatabaseConfigForm.php b/application/forms/DatabaseConfigForm.php index 5b4510591..3dce3353d 100644 --- a/application/forms/DatabaseConfigForm.php +++ b/application/forms/DatabaseConfigForm.php @@ -10,7 +10,7 @@ class DatabaseConfigForm extends CompatForm { - protected function assemble() + protected function assemble(): void { $dbResources = ResourceFactory::getResourceConfigs('db')->keys(); diff --git a/application/forms/MoveRotationForm.php b/application/forms/MoveRotationForm.php index 8cfaab2cc..77ff3e6fb 100644 --- a/application/forms/MoveRotationForm.php +++ b/application/forms/MoveRotationForm.php @@ -55,7 +55,7 @@ public function getScheduleId(): int return $this->scheduleId; } - public function getMessages() + public function getMessages(): array { $messages = parent::getMessages(); foreach ($this->getElements() as $element) { @@ -67,21 +67,21 @@ public function getMessages() return $messages; } - protected function assemble() + protected function assemble(): void { $this->addElement('hidden', 'rotation', ['required' => true]); $this->addElement('hidden', 'priority', ['required' => true]); $this->addElement($this->createCsrfCounterMeasure(Session::getSession()->getId())); } - protected function onError() + protected function onError(): void { $this->removeAttribute('hidden'); parent::onError(); } - protected function onSuccess() + protected function onSuccess(): void { $rotationId = $this->getValue('rotation'); $newPriority = $this->getValue('priority'); diff --git a/application/forms/RotationConfigForm.php b/application/forms/RotationConfigForm.php index aab583cd8..f04c5c229 100644 --- a/application/forms/RotationConfigForm.php +++ b/application/forms/RotationConfigForm.php @@ -131,7 +131,7 @@ public function setShowRemoveButton(bool $state = true): self * * @param Url $url * - * @return void + * @return $this */ public function setSuggestionUrl(Url $url): self { @@ -143,7 +143,7 @@ public function setSuggestionUrl(Url $url): self /** * Disable the mode selection * - * @return void + * @return $this */ public function disableModeSelection(): self { @@ -1067,7 +1067,7 @@ protected function assembleMultiDayOptions(FieldsetElement $options): DateTime return $firstHandoff; } - protected function assemble() + protected function assemble(): void { $this->getAttributes()->add('class', 'rotation-config'); diff --git a/library/Notifications/Common/Database.php b/library/Notifications/Common/Database.php index 119a40dc0..27502d516 100644 --- a/library/Notifications/Common/Database.php +++ b/library/Notifications/Common/Database.php @@ -210,7 +210,7 @@ private static function getConnection(): Connection * * @return int The given timestamp or 1 + the maximum changed_at value in the table, whichever is greater */ - private static function getNextChangedAt(Connection $db, string $table, $nowUnixMilli) + private static function getNextChangedAt(Connection $db, string $table, $nowUnixMilli): int { return $db->select( (new Select()) @@ -266,6 +266,7 @@ public static function registerGroupBy(Query $query, Select $select): void /** * Check if the given condition is part of the where clause with value 'y' * + * @param string $baseTable * @param string $conditionToFind * @param array $where * diff --git a/library/Notifications/Common/LoadMore.php b/library/Notifications/Common/LoadMore.php index 497283b0a..6852a12fb 100644 --- a/library/Notifications/Common/LoadMore.php +++ b/library/Notifications/Common/LoadMore.php @@ -29,7 +29,7 @@ trait LoadMore * * @return $this */ - public function setPageSize(int $size): self + public function setPageSize(int $size): static { $this->pageSize = $size; @@ -43,7 +43,7 @@ public function setPageSize(int $size): self * * @return $this */ - public function setPageNumber(int $number): self + public function setPageNumber(int $number): static { $this->pageNumber = $number; @@ -57,7 +57,7 @@ public function setPageNumber(int $number): self * * @return $this */ - public function setLoadMoreUrl(Url $url): self + public function setLoadMoreUrl(Url $url): static { $this->loadMoreUrl = $url; diff --git a/library/Notifications/Common/PsrLogger.php b/library/Notifications/Common/PsrLogger.php index 984653585..f01fb893a 100644 --- a/library/Notifications/Common/PsrLogger.php +++ b/library/Notifications/Common/PsrLogger.php @@ -45,8 +45,10 @@ class PsrLogger implements LoggerInterface * @param string $level The log level * @param string|Stringable $message The log message * @param array $context Additional context variables to interpolate in the message + * + * @return void */ - public function log($level, string|\Stringable $message, array $context = []): void + public function log($level, string|Stringable $message, array $context = []): void { $level = strtolower((string) $level); $icingaMethod = self::MAP[$level] ?? 'debug'; diff --git a/library/Notifications/Daemon/Daemon.php b/library/Notifications/Daemon/Daemon.php index ecfcc0809..2ffec3c02 100644 --- a/library/Notifications/Daemon/Daemon.php +++ b/library/Notifications/Daemon/Daemon.php @@ -152,9 +152,9 @@ protected function reload(): void * * @param bool $isManualShutdown manual trigger for the shutdown * - * @return never-return + * @return never */ - protected function shutdown(bool $isManualShutdown = false) + protected function shutdown(bool $isManualShutdown = false): never { self::$logger::info(self::PREFIX . "shutting down" . ($isManualShutdown ? " (manually triggered)" : "")); diff --git a/library/Notifications/Model/Behavior/IcingaCustomVars.php b/library/Notifications/Model/Behavior/IcingaCustomVars.php index eeed276ca..88fc49ffc 100644 --- a/library/Notifications/Model/Behavior/IcingaCustomVars.php +++ b/library/Notifications/Model/Behavior/IcingaCustomVars.php @@ -27,7 +27,7 @@ public function isSelectableColumn(string $name): bool || str_starts_with($name, self::SERVICE_PREFIX); } - public function rewriteColumn($column, ?string $relation = null) + public function rewriteColumn($column, ?string $relation = null): null { return null; } @@ -54,7 +54,7 @@ public function rewriteColumnDefinition(ColumnDefinition $def, string $relation) )); } - public function rewriteCondition(Filter\Condition $condition, $relation = null) + public function rewriteCondition(Filter\Condition $condition, $relation = null): Filter\Condition|Filter\Rule|null { if (! $this->isSelectableColumn($condition->metaData()->get('columnName', ''))) { return null; diff --git a/library/Notifications/Model/Behavior/IdTagAggregator.php b/library/Notifications/Model/Behavior/IdTagAggregator.php index db8b79b6a..69c7c5c41 100644 --- a/library/Notifications/Model/Behavior/IdTagAggregator.php +++ b/library/Notifications/Model/Behavior/IdTagAggregator.php @@ -29,9 +29,12 @@ final public function __construct() parent::__construct(['id_tags']); } - public function setQuery(Query $query) + /** @return $this */ + public function setQuery(Query $query): static { $this->query = $query; + + return $this; } public function rewriteColumn($column, ?string $relation = null) @@ -69,7 +72,8 @@ public function isSelectableColumn(string $name): bool return $name === 'id_tags'; } - public function fromDb($value, $key, $context) + /** @return array */ + public function fromDb($value, $key, $context): array { if (! is_string($value)) { return []; @@ -83,7 +87,12 @@ public function fromDb($value, $key, $context) return $tags; } - public function toDb($value, $key, $context) + /** + * @return never + * + * @throws InvalidColumnException + */ + public function toDb($value, $key, $context): never { throw new InvalidColumnException($key, new Objects()); } diff --git a/library/Notifications/Model/Daemon/Connection.php b/library/Notifications/Model/Daemon/Connection.php index 3c568c9b0..fae3bd839 100644 --- a/library/Notifications/Model/Daemon/Connection.php +++ b/library/Notifications/Model/Daemon/Connection.php @@ -71,7 +71,7 @@ public function getAddress(): string return $this->host . ':' . $this->port; } - public function getSession(): ?string + public function getSession(): string { return $this->session; } @@ -112,7 +112,7 @@ public function setUserAgent(string $userAgent): void * @return object{host: string, port: string, addr: string} | false Host, port and full address or false if the * parsing failed */ - public static function parseHostAndPort(?string $address) + public static function parseHostAndPort(?string $address): object|false { if ($address === null) { return false; diff --git a/library/Notifications/Model/RuleEscalationRecipient.php b/library/Notifications/Model/RuleEscalationRecipient.php index c3498da0b..ec54a2e10 100644 --- a/library/Notifications/Model/RuleEscalationRecipient.php +++ b/library/Notifications/Model/RuleEscalationRecipient.php @@ -91,7 +91,7 @@ public function createRelations(Relations $relations): void * * @return Contact|Contactgroup|Schedule|null */ - public function getRecipient(): ?Model + public function getRecipient(): Contact|Contactgroup|Schedule|null { $recipientModel = null; if ($this->contact_id) { diff --git a/library/Notifications/Web/Control/SearchBar/ExtraTagSuggestions.php b/library/Notifications/Web/Control/SearchBar/ExtraTagSuggestions.php index 08c39fab7..d7bc0c15e 100644 --- a/library/Notifications/Web/Control/SearchBar/ExtraTagSuggestions.php +++ b/library/Notifications/Web/Control/SearchBar/ExtraTagSuggestions.php @@ -5,26 +5,26 @@ namespace Icinga\Module\Notifications\Web\Control\SearchBar; +use Generator; use Icinga\Module\Notifications\Common\Database; use Icinga\Module\Notifications\Model\ObjectExtraTag; use Icinga\Module\Notifications\Util\ObjectSuggestionsCursor; -use ipl\Web\Control\SearchBar\Suggestions; use ipl\Stdlib\Filter; -use Traversable; +use ipl\Web\Control\SearchBar\Suggestions; class ExtraTagSuggestions extends Suggestions { - protected function fetchValueSuggestions($column, $searchTerm, Filter\Chain $searchFilter) + protected function fetchValueSuggestions($column, $searchTerm, Filter\Chain $searchFilter): Generator { yield; } - protected function createQuickSearchFilter($searchTerm) + protected function createQuickSearchFilter($searchTerm): Filter\Any { return Filter::any(); } - protected function fetchColumnSuggestions($searchTerm) + protected function fetchColumnSuggestions($searchTerm): Generator { $searchColumns = (new ObjectSuggestionsCursor( Database::get(), diff --git a/library/Notifications/Web/Control/SearchBar/ObjectSuggestions.php b/library/Notifications/Web/Control/SearchBar/ObjectSuggestions.php index 99102c1a4..a7e8fc5a0 100644 --- a/library/Notifications/Web/Control/SearchBar/ObjectSuggestions.php +++ b/library/Notifications/Web/Control/SearchBar/ObjectSuggestions.php @@ -5,6 +5,7 @@ namespace Icinga\Module\Notifications\Web\Control\SearchBar; +use Generator; use Icinga\Module\Notifications\Common\Auth; use Icinga\Module\Notifications\Common\Database; use Icinga\Module\Notifications\Model\Behavior\IcingaCustomVars; @@ -42,7 +43,7 @@ class ObjectSuggestions extends Suggestions * * @return $this */ - public function setModel($model): self + public function setModel(string|Model $model): self { if (is_string($model)) { $model = new $model(); @@ -90,7 +91,7 @@ protected function shouldShowRelationFor(string $column): bool return $columnPath[0] !== $tableName; } - protected function createQuickSearchFilter($searchTerm) + protected function createQuickSearchFilter($searchTerm): Filter\Any|Filter\Chain { $model = $this->getModel(); $resolver = $model::on(Database::get())->getResolver(); @@ -105,8 +106,11 @@ protected function createQuickSearchFilter($searchTerm) return $quickFilter; } - protected function fetchValueSuggestions($column, $searchTerm, Filter\Chain $searchFilter) - { + protected function fetchValueSuggestions( + $column, + $searchTerm, + Filter\Chain $searchFilter + ): ObjectSuggestionsCursor { $model = $this->getModel(); $query = $model::on(Database::get()); $query->limit(static::DEFAULT_LIMIT); @@ -192,7 +196,7 @@ protected function fetchValueSuggestions($column, $searchTerm, Filter\Chain $sea } } - protected function fetchColumnSuggestions($searchTerm) + protected function fetchColumnSuggestions($searchTerm): Generator { $model = $this->getModel(); $query = $model::on(Database::get()); @@ -275,7 +279,7 @@ protected function queryTags(Model $model, string $searchTerm): Query return $tags; } - protected function matchSuggestion($path, $label, $searchTerm) + protected function matchSuggestion($path, $label, $searchTerm): bool { if (preg_match('/[_.](id)$/', $path)) { // Only suggest exotic columns if the user knows the full column path @@ -315,8 +319,10 @@ public static function collectFilterColumns(Model $model, Resolver $resolver): T * @param Model $subject * @param array $models * @param array $path + * + * @return void */ - protected static function collectRelations(Resolver $resolver, Model $subject, array &$models, array $path) + protected static function collectRelations(Resolver $resolver, Model $subject, array &$models, array $path): void { foreach ($resolver->getRelations($subject) as $name => $relation) { /** @var Relation $relation */ diff --git a/library/Notifications/Web/Form/ContactForm.php b/library/Notifications/Web/Form/ContactForm.php index fc194dffa..255ef511c 100644 --- a/library/Notifications/Web/Form/ContactForm.php +++ b/library/Notifications/Web/Form/ContactForm.php @@ -68,7 +68,7 @@ private function hasBeenRemoved(): bool return $csrf !== null && $csrf->isValid() && $btn !== null && $btn->getName() === 'delete'; } - public function isValidEvent($event) + public function isValidEvent($event): bool { if ($event === self::ON_REMOVE) { return true; @@ -77,7 +77,7 @@ public function isValidEvent($event) return parent::isValidEvent($event); } - protected function assemble() + protected function assemble(): void { $this->addAttributes(['class' => 'contact-form']); $this->addCsrfCounterMeasure(Session::getSession()->getId()); diff --git a/library/Notifications/Web/Form/EventRuleDecorator.php b/library/Notifications/Web/Form/EventRuleDecorator.php index b4706ac57..893534ee5 100644 --- a/library/Notifications/Web/Form/EventRuleDecorator.php +++ b/library/Notifications/Web/Form/EventRuleDecorator.php @@ -17,7 +17,7 @@ class EventRuleDecorator extends HtmlDocument implements FormElementDecorator /** @var FormElement */ private FormElement $element; - public function decorate(FormElement $formElement) + public function decorate(FormElement $formElement): void { $me = clone $this; @@ -25,7 +25,7 @@ public function decorate(FormElement $formElement) $formElement->prependWrapper($me); } - protected function assemble() + protected function assemble(): void { $this->addHtml($this->element); diff --git a/library/Notifications/Widget/Calendar.php b/library/Notifications/Widget/Calendar.php index 424ed1c7e..790df5f68 100644 --- a/library/Notifications/Widget/Calendar.php +++ b/library/Notifications/Widget/Calendar.php @@ -172,7 +172,7 @@ public function getEntries(): Traversable yield from $this->entries; } - protected function assemble() + protected function assemble(): void { $modeStart = $this->getModeStart(); diff --git a/library/Notifications/Widget/Calendar/Controls.php b/library/Notifications/Widget/Calendar/Controls.php index d58b88a4c..311df9d22 100644 --- a/library/Notifications/Widget/Calendar/Controls.php +++ b/library/Notifications/Widget/Calendar/Controls.php @@ -41,7 +41,7 @@ public function getViewMode(): string return $this->getPopulatedValue('mode', Calendar::MODE_WEEK); } - protected function assemble() + protected function assemble(): void { switch ($this->getPopulatedValue('mode', Calendar::MODE_WEEK)) { case Calendar::MODE_MONTH: diff --git a/library/Notifications/Widget/Calendar/DayGrid.php b/library/Notifications/Widget/Calendar/DayGrid.php index 8a464568d..769cb0b7e 100644 --- a/library/Notifications/Widget/Calendar/DayGrid.php +++ b/library/Notifications/Widget/Calendar/DayGrid.php @@ -117,7 +117,7 @@ protected function createSidebar(): BaseHtmlElement return $sidebar; } - protected function assemble() + protected function assemble(): void { $this->addHtml( $this->createHeader(), diff --git a/library/Notifications/Widget/Calendar/MonthGrid.php b/library/Notifications/Widget/Calendar/MonthGrid.php index f47a8becd..042c3e3bc 100644 --- a/library/Notifications/Widget/Calendar/MonthGrid.php +++ b/library/Notifications/Widget/Calendar/MonthGrid.php @@ -120,7 +120,7 @@ protected function createSidebar(): BaseHtmlElement return $sidebar; } - protected function assemble() + protected function assemble(): void { $this->addHtml( $this->createHeader(), diff --git a/library/Notifications/Widget/Calendar/WeekGrid.php b/library/Notifications/Widget/Calendar/WeekGrid.php index 8697f2692..8d8c6c1a0 100644 --- a/library/Notifications/Widget/Calendar/WeekGrid.php +++ b/library/Notifications/Widget/Calendar/WeekGrid.php @@ -126,7 +126,7 @@ protected function createSidebar(): BaseHtmlElement return $sidebar; } - protected function assemble() + protected function assemble(): void { $this->addHtml( $this->createHeader(), diff --git a/library/Notifications/Widget/Detail/IncidentDetail.php b/library/Notifications/Widget/Detail/IncidentDetail.php index bfb36673a..7abaa351b 100644 --- a/library/Notifications/Widget/Detail/IncidentDetail.php +++ b/library/Notifications/Widget/Detail/IncidentDetail.php @@ -22,6 +22,7 @@ use ipl\Html\HtmlElement; use ipl\Html\Table; use ipl\Html\Text; +use ipl\Html\ValidHtml; use ipl\I18n\Translation; use ipl\Stdlib\Filter; use ipl\Web\Layout\MinimalItemLayout; @@ -46,7 +47,8 @@ public function __construct(Incident $incident) $this->incident = $incident; } - protected function createContacts() + /** @return ValidHtml[] */ + protected function createContacts(): array { $contacts = []; $query = $this->incident->incident_contact @@ -72,7 +74,8 @@ protected function createContacts() ]; } - protected function createRelatedObject() + /** @return ValidHtml[] */ + protected function createRelatedObject(): array { $objectUrl = ObjectsRendererHook::renderObjectLink($this->incident->object); @@ -86,7 +89,8 @@ protected function createRelatedObject() ]; } - protected function createHistory() + /** @return ValidHtml[] */ + protected function createHistory(): array { $query = $this->incident->incident_history ->with([ @@ -106,7 +110,8 @@ protected function createHistory() ]; } - protected function createSource() + /** @return ValidHtml[] */ + protected function createSource(): array { $list = new HtmlElement('ul', Attributes::create(['class' => 'source-list'])); $list->addHtml(new HtmlElement('li', null, new EventSourceBadge($this->incident->object->source))); @@ -117,6 +122,7 @@ protected function createSource() ]; } + /** @return ValidHtml[] */ protected function createObjectTag(): array { $tags = []; @@ -177,7 +183,7 @@ protected function createObjectTag(): array return $result; } - protected function assemble() + protected function assemble(): void { $this->add([ $this->createContacts(), diff --git a/library/Notifications/Widget/Detail/IncidentQuickActions.php b/library/Notifications/Widget/Detail/IncidentQuickActions.php index f2859753b..b07d1a11c 100644 --- a/library/Notifications/Widget/Detail/IncidentQuickActions.php +++ b/library/Notifications/Widget/Detail/IncidentQuickActions.php @@ -100,7 +100,7 @@ protected function assembleUnsubscribeButton(): void ); } - protected function assemble() + protected function assemble(): void { $this->addElement($this->createCsrfCounterMeasure(Session::getSession()->getId())); @@ -121,7 +121,7 @@ protected function assemble() } } - protected function onSuccess() + protected function onSuccess(): void { $incidentContact = $this->fetchIncidentContact(); $pressedButton = $this->getPressedSubmitElement()->getName(); diff --git a/library/Notifications/Widget/Detail/ScheduleDetail.php b/library/Notifications/Widget/Detail/ScheduleDetail.php index 700096945..52062245f 100644 --- a/library/Notifications/Widget/Detail/ScheduleDetail.php +++ b/library/Notifications/Widget/Detail/ScheduleDetail.php @@ -87,7 +87,7 @@ protected function createTimeline(): Timeline return $timeline; } - protected function assemble() + protected function assemble(): void { $timeline = $this->createTimeline(); if (! $this->hasRotation) { diff --git a/library/Notifications/Widget/EventSourceBadge.php b/library/Notifications/Widget/EventSourceBadge.php index 03774b4a1..00f4ebb4d 100644 --- a/library/Notifications/Widget/EventSourceBadge.php +++ b/library/Notifications/Widget/EventSourceBadge.php @@ -22,14 +22,14 @@ class EventSourceBadge extends BaseHtmlElement /** * Create an event source badge with source icon * - * @param Source $source + * @param Source $source */ public function __construct(Source $source) { $this->source = $source; } - protected function assemble() + protected function assemble(): void { if ($this->source->name === null) { $title = $this->source->type; diff --git a/library/Notifications/Widget/ItemList/PageSeparatorItem.php b/library/Notifications/Widget/ItemList/PageSeparatorItem.php index 93f6925df..d52d38653 100644 --- a/library/Notifications/Widget/ItemList/PageSeparatorItem.php +++ b/library/Notifications/Widget/ItemList/PageSeparatorItem.php @@ -23,7 +23,7 @@ public function __construct(int $pageNumber) $this->pageNumber = $pageNumber; } - protected function assemble() + protected function assemble(): void { $this->add(Html::tag( 'a', diff --git a/library/Notifications/Widget/RuleEscalationRecipientBadge.php b/library/Notifications/Widget/RuleEscalationRecipientBadge.php index 7c047bc88..1119c2377 100644 --- a/library/Notifications/Widget/RuleEscalationRecipientBadge.php +++ b/library/Notifications/Widget/RuleEscalationRecipientBadge.php @@ -53,7 +53,7 @@ public function createBadge() return Html::tag('span', ['class' => 'badge'], [new Icon($icon), $recipientModel->$nameColumn]); } - protected function assemble() + protected function assemble(): void { $this->add($this->createBadge()); diff --git a/library/Notifications/Widget/ShowMore.php b/library/Notifications/Widget/ShowMore.php index 52b06d3ce..2a47e1f47 100644 --- a/library/Notifications/Widget/ShowMore.php +++ b/library/Notifications/Widget/ShowMore.php @@ -53,7 +53,7 @@ public function renderUnwrapped(): string return ''; } - protected function assemble() + protected function assemble(): void { if ($this->resultSet->hasMore()) { $this->add(new ActionLink($this->getLabel(), $this->url)); diff --git a/library/Notifications/Widget/TimeGrid/DynamicGrid.php b/library/Notifications/Widget/TimeGrid/DynamicGrid.php index 941d5db2d..d58b723b0 100644 --- a/library/Notifications/Widget/TimeGrid/DynamicGrid.php +++ b/library/Notifications/Widget/TimeGrid/DynamicGrid.php @@ -121,7 +121,7 @@ protected function createGridSteps(): Traversable } } - protected function assemble() + protected function assemble(): void { $this->style->addFor($this, [ '--primaryColumns' => $this->days, diff --git a/library/Notifications/Widget/TimeGrid/Entry.php b/library/Notifications/Widget/TimeGrid/Entry.php index eac153e1f..fbdb3c3e2 100644 --- a/library/Notifications/Widget/TimeGrid/Entry.php +++ b/library/Notifications/Widget/TimeGrid/Entry.php @@ -213,7 +213,7 @@ abstract public function getColor(int $transparency): string; abstract protected function assembleContainer(BaseHtmlElement $container): void; - protected function assemble() + protected function assemble(): void { $this->getAttributes() ->add('data-entry-id', $this->getId()) diff --git a/library/Notifications/Widget/TimeGrid/ExtraEntryCount.php b/library/Notifications/Widget/TimeGrid/ExtraEntryCount.php index c4c90f4c7..a7e0f2cf3 100644 --- a/library/Notifications/Widget/TimeGrid/ExtraEntryCount.php +++ b/library/Notifications/Widget/TimeGrid/ExtraEntryCount.php @@ -47,7 +47,7 @@ public function setGridStep(DateTime $gridStep): self return $this; } - protected function assemble() + protected function assemble(): void { $count = $this->grid->getExtraEntryCount($this->gridStep); $this->addAttributes(['class' => 'extra-count']) @@ -64,7 +64,7 @@ protected function assemble() ); } - public function renderUnwrapped() + public function renderUnwrapped(): string { if ($this->grid->getExtraEntryCount($this->gridStep) > 0) { return parent::renderUnwrapped(); diff --git a/library/Notifications/Widget/TimeGrid/GridStep.php b/library/Notifications/Widget/TimeGrid/GridStep.php index 2b4024803..72ae3733c 100644 --- a/library/Notifications/Widget/TimeGrid/GridStep.php +++ b/library/Notifications/Widget/TimeGrid/GridStep.php @@ -73,7 +73,7 @@ public function getCoordinates(): array return $this->coordinates; } - protected function registerAttributeCallbacks(Attributes $attributes) + protected function registerAttributeCallbacks(Attributes $attributes): void { $this->getAttributes() ->registerAttributeCallback('data-start', function () { diff --git a/library/Notifications/Widget/TimeGrid/Util.php b/library/Notifications/Widget/TimeGrid/Util.php index 38de2864a..fcd7a5b13 100644 --- a/library/Notifications/Widget/TimeGrid/Util.php +++ b/library/Notifications/Widget/TimeGrid/Util.php @@ -13,7 +13,15 @@ final class Util /** @var array */ private static array $entryColors = []; - public static function diffHours(DateTime $from, DateTime $to) + /** + * @param DateTime $from + * @param DateTime $to + * + * @return float|int + * + * @throws InvalidArgumentException + */ + public static function diffHours(DateTime $from, DateTime $to): float|int { $diff = $from->diff($to); if ($diff->invert) { diff --git a/library/Notifications/Widget/Timeline.php b/library/Notifications/Widget/Timeline.php index 03967f66c..ddf1b489f 100644 --- a/library/Notifications/Widget/Timeline.php +++ b/library/Notifications/Widget/Timeline.php @@ -283,7 +283,7 @@ public function getEntries(): Traversable * * @return DynamicGrid|MinimalGrid */ - protected function getGrid() + protected function getGrid(): DynamicGrid|MinimalGrid { if ($this->grid === null) { if ($this->minimalLayout) { @@ -341,7 +341,7 @@ protected function assembleSidebarEntry(Rotation $rotation): BaseHtmlElement return $entry; } - protected function assemble() + protected function assemble(): void { if ($this->minimalLayout && empty($this->rotations)) { $this->addHtml(new HtmlElement( diff --git a/library/Notifications/Widget/Timeline/Rotation.php b/library/Notifications/Widget/Timeline/Rotation.php index 0fa354c0f..4b71967ae 100644 --- a/library/Notifications/Widget/Timeline/Rotation.php +++ b/library/Notifications/Widget/Timeline/Rotation.php @@ -28,9 +28,9 @@ class Rotation /** * Create a new Rotation * - * @param \Icinga\Module\Notifications\Model\Rotation $model + * @param RotationModel $model */ - public function __construct(\Icinga\Module\Notifications\Model\Rotation $model) + public function __construct(RotationModel $model) { $this->model = $model; } From 1c5ca0b2fc12f0b25752e0f42ca5e492b2303b1e Mon Sep 17 00:00:00 2001 From: Johannes Rauh Date: Thu, 13 Nov 2025 09:17:04 +0100 Subject: [PATCH 03/26] Sort imports --- application/controllers/ApiController.php | 3 --- application/controllers/ContactsController.php | 4 ++-- application/controllers/IncidentsController.php | 2 +- .../Api/OpenApiDescriptionElement/OadV1Delete.php | 3 --- .../Api/OpenApiDescriptionElement/OadV1Get.php | 1 - .../Api/OpenApiDescriptionElement/OadV1GetPlural.php | 1 - .../Api/OpenApiDescriptionElement/OadV1Post.php | 3 +-- .../Api/OpenApiDescriptionElement/OadV1Put.php | 2 +- .../Parameter/PathParameter.php | 2 +- .../Parameter/QueryParameter.php | 2 +- .../Response/Error404Response.php | 3 --- .../Response/ErrorResponse.php | 2 +- .../Response/SuccessDataResponse.php | 2 +- .../Response/SuccessResponse.php | 2 +- library/Notifications/Api/V1/ApiV1.php | 4 ++-- library/Notifications/Api/V1/Channels.php | 2 +- library/Notifications/Api/V1/Contacts.php | 10 +++++----- library/Notifications/Common/Database.php | 1 - library/Notifications/Common/HttpMethod.php | 1 - library/Notifications/Daemon/Daemon.php | 3 --- library/Notifications/Test/BaseApiV1TestCase.php | 3 +-- .../Web/Control/SearchBar/ObjectSuggestions.php | 2 +- .../application/controllers/ApiV1ContactGroupsTest.php | 1 - test/php/application/controllers/ApiV1ContactsTest.php | 3 --- 24 files changed, 20 insertions(+), 42 deletions(-) diff --git a/application/controllers/ApiController.php b/application/controllers/ApiController.php index 62e910d76..175c437a9 100644 --- a/application/controllers/ApiController.php +++ b/application/controllers/ApiController.php @@ -5,8 +5,6 @@ namespace Icinga\Module\Notifications\Controllers; -use Exception; -use Icinga\Exception\Http\HttpBadRequestException; use Icinga\Module\Notifications\Api\Middleware\DispatchMiddleware; use Icinga\Module\Notifications\Api\Middleware\EndpointExecutionMiddleware; use Icinga\Module\Notifications\Api\Middleware\ErrorHandlingMiddleware; @@ -15,7 +13,6 @@ use Icinga\Module\Notifications\Api\Middleware\RoutingMiddleware; use Icinga\Module\Notifications\Api\Middleware\ValidationMiddleware; use Icinga\Security\SecurityException; -use Icinga\Web\Request; use ipl\Web\Compat\CompatController; use Psr\Http\Message\ResponseInterface; diff --git a/application/controllers/ContactsController.php b/application/controllers/ContactsController.php index b414415eb..3a85acd89 100644 --- a/application/controllers/ContactsController.php +++ b/application/controllers/ContactsController.php @@ -6,12 +6,12 @@ namespace Icinga\Module\Notifications\Controllers; use Icinga\Module\Notifications\Common\ConfigurationTabs; +use Icinga\Module\Notifications\Common\Database; use Icinga\Module\Notifications\Common\Links; use Icinga\Module\Notifications\Model\Channel; +use Icinga\Module\Notifications\Model\Contact; use Icinga\Module\Notifications\View\ContactRenderer; use Icinga\Module\Notifications\Web\Control\SearchBar\ObjectSuggestions; -use Icinga\Module\Notifications\Common\Database; -use Icinga\Module\Notifications\Model\Contact; use Icinga\Module\Notifications\Web\Form\ContactForm; use Icinga\Module\Notifications\Widget\ItemList\ObjectList; use Icinga\Web\Notification; diff --git a/application/controllers/IncidentsController.php b/application/controllers/IncidentsController.php index 89b1576c7..2267623a1 100644 --- a/application/controllers/IncidentsController.php +++ b/application/controllers/IncidentsController.php @@ -8,9 +8,9 @@ use Icinga\Module\Notifications\Common\Auth; use Icinga\Module\Notifications\Common\Database; use Icinga\Module\Notifications\Hook\ObjectsRendererHook; +use Icinga\Module\Notifications\Model\Incident; use Icinga\Module\Notifications\View\IncidentRenderer; use Icinga\Module\Notifications\Web\Control\SearchBar\ObjectSuggestions; -use Icinga\Module\Notifications\Model\Incident; use Icinga\Module\Notifications\Widget\ItemList\ObjectList; use ipl\Stdlib\Filter; use ipl\Web\Compat\CompatController; diff --git a/library/Notifications/Api/OpenApiDescriptionElement/OadV1Delete.php b/library/Notifications/Api/OpenApiDescriptionElement/OadV1Delete.php index f5dfacc03..9c384e8b2 100644 --- a/library/Notifications/Api/OpenApiDescriptionElement/OadV1Delete.php +++ b/library/Notifications/Api/OpenApiDescriptionElement/OadV1Delete.php @@ -12,9 +12,6 @@ use Icinga\Module\Notifications\Api\OpenApiDescriptionElement\Response\Example\ResponseExample; use Icinga\Module\Notifications\Api\OpenApiDescriptionElement\Response\SuccessResponse; use OpenApi\Attributes\Delete; -use OpenApi\Attributes\ExternalDocumentation; -use OpenApi\Attributes\RequestBody; -use OpenApi\Attributes as OA; #[Attribute(Attribute::TARGET_CLASS | Attribute::TARGET_METHOD)] class OadV1Delete extends Delete diff --git a/library/Notifications/Api/OpenApiDescriptionElement/OadV1Get.php b/library/Notifications/Api/OpenApiDescriptionElement/OadV1Get.php index 490142ff5..7f8965eb0 100644 --- a/library/Notifications/Api/OpenApiDescriptionElement/OadV1Get.php +++ b/library/Notifications/Api/OpenApiDescriptionElement/OadV1Get.php @@ -11,7 +11,6 @@ use Icinga\Module\Notifications\Api\OpenApiDescriptionElement\Response\Example\ResponseExample; use Icinga\Module\Notifications\Api\OpenApiDescriptionElement\Response\SuccessDataResponse; use OpenApi\Attributes\Get; -use OpenApi\Attributes as OA; #[Attribute(Attribute::TARGET_CLASS | Attribute::TARGET_METHOD | Attribute::IS_REPEATABLE)] class OadV1Get extends Get diff --git a/library/Notifications/Api/OpenApiDescriptionElement/OadV1GetPlural.php b/library/Notifications/Api/OpenApiDescriptionElement/OadV1GetPlural.php index ff5874955..fc54d0e7b 100644 --- a/library/Notifications/Api/OpenApiDescriptionElement/OadV1GetPlural.php +++ b/library/Notifications/Api/OpenApiDescriptionElement/OadV1GetPlural.php @@ -10,7 +10,6 @@ use Icinga\Module\Notifications\Api\OpenApiDescriptionElement\Response\Example\ResponseExample; use Icinga\Module\Notifications\Api\OpenApiDescriptionElement\Response\SuccessDataResponse; use OpenApi\Attributes\Get; -use OpenApi\Attributes as OA; #[Attribute(Attribute::TARGET_CLASS | Attribute::TARGET_METHOD | Attribute::IS_REPEATABLE)] class OadV1GetPlural extends Get diff --git a/library/Notifications/Api/OpenApiDescriptionElement/OadV1Post.php b/library/Notifications/Api/OpenApiDescriptionElement/OadV1Post.php index e8a9bb127..afc174e8d 100644 --- a/library/Notifications/Api/OpenApiDescriptionElement/OadV1Post.php +++ b/library/Notifications/Api/OpenApiDescriptionElement/OadV1Post.php @@ -10,9 +10,8 @@ use Icinga\Module\Notifications\Api\OpenApiDescriptionElement\Response\ErrorResponse; use Icinga\Module\Notifications\Api\OpenApiDescriptionElement\Response\Example\ResponseExample; use Icinga\Module\Notifications\Api\OpenApiDescriptionElement\Response\SuccessResponse; -use OpenApi\Attributes\Post; -use OpenApi\Attributes\RequestBody; use OpenApi\Attributes as OA; +use OpenApi\Attributes\Post; #[Attribute(Attribute::TARGET_CLASS | Attribute::TARGET_METHOD | Attribute::IS_REPEATABLE)] class OadV1Post extends Post diff --git a/library/Notifications/Api/OpenApiDescriptionElement/OadV1Put.php b/library/Notifications/Api/OpenApiDescriptionElement/OadV1Put.php index 5f4aa2e82..7109d8fcd 100644 --- a/library/Notifications/Api/OpenApiDescriptionElement/OadV1Put.php +++ b/library/Notifications/Api/OpenApiDescriptionElement/OadV1Put.php @@ -10,9 +10,9 @@ use Icinga\Module\Notifications\Api\OpenApiDescriptionElement\Response\ErrorResponse; use Icinga\Module\Notifications\Api\OpenApiDescriptionElement\Response\Example\ResponseExample; use Icinga\Module\Notifications\Api\OpenApiDescriptionElement\Response\SuccessResponse; +use OpenApi\Attributes as OA; use OpenApi\Attributes\Put; use OpenApi\Attributes\RequestBody; -use OpenApi\Attributes as OA; #[Attribute(Attribute::TARGET_CLASS | Attribute::TARGET_METHOD | Attribute::IS_REPEATABLE)] class OadV1Put extends Put diff --git a/library/Notifications/Api/OpenApiDescriptionElement/Parameter/PathParameter.php b/library/Notifications/Api/OpenApiDescriptionElement/Parameter/PathParameter.php index 7b9f65039..a7e7434b0 100644 --- a/library/Notifications/Api/OpenApiDescriptionElement/Parameter/PathParameter.php +++ b/library/Notifications/Api/OpenApiDescriptionElement/Parameter/PathParameter.php @@ -5,10 +5,10 @@ namespace Icinga\Module\Notifications\Api\OpenApiDescriptionElement\Parameter; +use OpenApi\Attributes as OA; use OpenApi\Attributes\Parameter; use OpenApi\Attributes\Schema; use OpenApi\Generator; -use OpenApi\Attributes as OA; class PathParameter extends Parameter { diff --git a/library/Notifications/Api/OpenApiDescriptionElement/Parameter/QueryParameter.php b/library/Notifications/Api/OpenApiDescriptionElement/Parameter/QueryParameter.php index 3dfd93f3c..0ef4e9042 100644 --- a/library/Notifications/Api/OpenApiDescriptionElement/Parameter/QueryParameter.php +++ b/library/Notifications/Api/OpenApiDescriptionElement/Parameter/QueryParameter.php @@ -5,8 +5,8 @@ namespace Icinga\Module\Notifications\Api\OpenApiDescriptionElement\Parameter; -use OpenApi\Attributes\Parameter; use OpenApi\Attributes as OA; +use OpenApi\Attributes\Parameter; use OpenApi\Attributes\Schema; class QueryParameter extends Parameter diff --git a/library/Notifications/Api/OpenApiDescriptionElement/Response/Error404Response.php b/library/Notifications/Api/OpenApiDescriptionElement/Response/Error404Response.php index cd31c2616..9cd11c42c 100644 --- a/library/Notifications/Api/OpenApiDescriptionElement/Response/Error404Response.php +++ b/library/Notifications/Api/OpenApiDescriptionElement/Response/Error404Response.php @@ -5,12 +5,9 @@ namespace Icinga\Module\Notifications\Api\OpenApiDescriptionElement\Response; -use OpenApi\Attributes\Attachable; use OpenApi\Attributes\Examples; use OpenApi\Attributes\JsonContent; -use OpenApi\Attributes\MediaType; use OpenApi\Attributes\Response; -use OpenApi\Attributes\XmlContent; class Error404Response extends Response { diff --git a/library/Notifications/Api/OpenApiDescriptionElement/Response/ErrorResponse.php b/library/Notifications/Api/OpenApiDescriptionElement/Response/ErrorResponse.php index f8c42167d..e2cf505aa 100644 --- a/library/Notifications/Api/OpenApiDescriptionElement/Response/ErrorResponse.php +++ b/library/Notifications/Api/OpenApiDescriptionElement/Response/ErrorResponse.php @@ -5,8 +5,8 @@ namespace Icinga\Module\Notifications\Api\OpenApiDescriptionElement\Response; -use OpenApi\Attributes\Response; use OpenApi\Attributes as OA; +use OpenApi\Attributes\Response; #[OA\Schema( schema: 'ErrorResponse', diff --git a/library/Notifications/Api/OpenApiDescriptionElement/Response/SuccessDataResponse.php b/library/Notifications/Api/OpenApiDescriptionElement/Response/SuccessDataResponse.php index a8df0fb0b..28b7261be 100644 --- a/library/Notifications/Api/OpenApiDescriptionElement/Response/SuccessDataResponse.php +++ b/library/Notifications/Api/OpenApiDescriptionElement/Response/SuccessDataResponse.php @@ -5,8 +5,8 @@ namespace Icinga\Module\Notifications\Api\OpenApiDescriptionElement\Response; -use OpenApi\Attributes\Response; use OpenApi\Attributes as OA; +use OpenApi\Attributes\Response; class SuccessDataResponse extends Response { diff --git a/library/Notifications/Api/OpenApiDescriptionElement/Response/SuccessResponse.php b/library/Notifications/Api/OpenApiDescriptionElement/Response/SuccessResponse.php index 84a6b0228..bf7bd09be 100644 --- a/library/Notifications/Api/OpenApiDescriptionElement/Response/SuccessResponse.php +++ b/library/Notifications/Api/OpenApiDescriptionElement/Response/SuccessResponse.php @@ -5,8 +5,8 @@ namespace Icinga\Module\Notifications\Api\OpenApiDescriptionElement\Response; -use OpenApi\Attributes\Response; use OpenApi\Attributes as OA; +use OpenApi\Attributes\Response; #[OA\Schema( schema: 'SuccessResponse', diff --git a/library/Notifications/Api/V1/ApiV1.php b/library/Notifications/Api/V1/ApiV1.php index 80e528560..bcbe87339 100644 --- a/library/Notifications/Api/V1/ApiV1.php +++ b/library/Notifications/Api/V1/ApiV1.php @@ -12,16 +12,16 @@ use Icinga\Exception\Json\JsonEncodeException; use Icinga\Module\Notifications\Api\ApiCore; use Icinga\Module\Notifications\Api\Exception\InvalidFilterParameterException; -use Icinga\Module\Notifications\Common\HttpMethod; use Icinga\Module\Notifications\Common\Database; +use Icinga\Module\Notifications\Common\HttpMethod; use Icinga\Util\Json; use ipl\Sql\Compat\FilterProcessor; use ipl\Sql\Select; use ipl\Stdlib\Filter\Condition; use ipl\Web\Filter\QueryString; +use OpenApi\Attributes as OA; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; -use OpenApi\Attributes as OA; use Ramsey\Uuid\Uuid; use stdClass; diff --git a/library/Notifications/Api/V1/Channels.php b/library/Notifications/Api/V1/Channels.php index b7cbd1d81..c068d221e 100644 --- a/library/Notifications/Api/V1/Channels.php +++ b/library/Notifications/Api/V1/Channels.php @@ -9,10 +9,10 @@ use Icinga\Exception\Http\HttpNotFoundException; use Icinga\Exception\Json\JsonEncodeException; use Icinga\Module\Notifications\Api\EndpointInterface; +use Icinga\Module\Notifications\Api\OpenApiDescriptionElement\OadV1Get; use Icinga\Module\Notifications\Api\OpenApiDescriptionElement\OadV1GetPlural; use Icinga\Module\Notifications\Api\OpenApiDescriptionElement\Parameter\PathParameter; use Icinga\Module\Notifications\Api\OpenApiDescriptionElement\Parameter\QueryParameter; -use Icinga\Module\Notifications\Api\OpenApiDescriptionElement\OadV1Get; use Icinga\Module\Notifications\Api\OpenApiDescriptionElement\Schema\SchemaUUID; use Icinga\Module\Notifications\Common\Database; use Icinga\Util\Json; diff --git a/library/Notifications/Api/V1/Contacts.php b/library/Notifications/Api/V1/Contacts.php index 177e6c34f..b69e6fc1e 100644 --- a/library/Notifications/Api/V1/Contacts.php +++ b/library/Notifications/Api/V1/Contacts.php @@ -11,9 +11,6 @@ use Icinga\Exception\Http\HttpNotFoundException; use Icinga\Exception\Json\JsonEncodeException; use Icinga\Module\Notifications\Api\EndpointInterface; -use Icinga\Module\Notifications\Model\Contact; -use Psr\Http\Message\ResponseInterface; -use Psr\Http\Server\RequestHandlerInterface; use Icinga\Module\Notifications\Api\OpenApiDescriptionElement\OadV1Delete; use Icinga\Module\Notifications\Api\OpenApiDescriptionElement\OadV1Get; use Icinga\Module\Notifications\Api\OpenApiDescriptionElement\OadV1GetPlural; @@ -23,16 +20,19 @@ use Icinga\Module\Notifications\Api\OpenApiDescriptionElement\Parameter\QueryParameter; use Icinga\Module\Notifications\Api\OpenApiDescriptionElement\Response\Example\ResponseExample; use Icinga\Module\Notifications\Api\OpenApiDescriptionElement\Schema\SchemaUUID; -use Ramsey\Uuid\Uuid; use Icinga\Module\Notifications\Common\Database; +use Icinga\Module\Notifications\Model\Contact; use Icinga\Module\Notifications\Model\Rotation; use Icinga\Module\Notifications\Model\RotationMember; use Icinga\Module\Notifications\Model\RuleEscalationRecipient; use Icinga\Util\Json; use ipl\Sql\Select; use ipl\Stdlib\Filter; -use stdClass; use OpenApi\Attributes as OA; +use Psr\Http\Message\ResponseInterface; +use Psr\Http\Server\RequestHandlerInterface; +use Ramsey\Uuid\Uuid; +use stdClass; /** * @phpstan-type requestBody array{ diff --git a/library/Notifications/Common/Database.php b/library/Notifications/Common/Database.php index 27502d516..fa2bdcfad 100644 --- a/library/Notifications/Common/Database.php +++ b/library/Notifications/Common/Database.php @@ -5,7 +5,6 @@ namespace Icinga\Module\Notifications\Common; -use DateTime; use Icinga\Application\Config as AppConfig; use Icinga\Data\ResourceFactory; use Icinga\Exception\ConfigurationError; diff --git a/library/Notifications/Common/HttpMethod.php b/library/Notifications/Common/HttpMethod.php index 855b0dae7..b26338495 100644 --- a/library/Notifications/Common/HttpMethod.php +++ b/library/Notifications/Common/HttpMethod.php @@ -6,7 +6,6 @@ namespace Icinga\Module\Notifications\Common; use Psr\Http\Message\ServerRequestInterface; -use StringBackedEnum; enum HttpMethod: string { diff --git a/library/Notifications/Daemon/Daemon.php b/library/Notifications/Daemon/Daemon.php index 2ffec3c02..267173df2 100644 --- a/library/Notifications/Daemon/Daemon.php +++ b/library/Notifications/Daemon/Daemon.php @@ -5,8 +5,6 @@ namespace Icinga\Module\Notifications\Daemon; -use DateTimeInterface; -use DateTimeZone; use Evenement\EventEmitter; use Icinga\Application\Logger; use Icinga\Module\Notifications\Common\Database; @@ -17,7 +15,6 @@ use Icinga\Module\Notifications\Model\Daemon\EventIdentifier; use Icinga\Module\Notifications\Model\Incident; use Icinga\Module\Notifications\Model\IncidentHistory; -use Icinga\Module\Notifications\Model\ObjectIdTag; use ipl\Sql\Connection as SQLConnection; use ipl\Stdlib\Filter; use React\EventLoop\Loop; diff --git a/library/Notifications/Test/BaseApiV1TestCase.php b/library/Notifications/Test/BaseApiV1TestCase.php index 774b9c9d0..d8b5070e9 100644 --- a/library/Notifications/Test/BaseApiV1TestCase.php +++ b/library/Notifications/Test/BaseApiV1TestCase.php @@ -7,13 +7,12 @@ use DateTime; use GuzzleHttp\Client; -use Icinga\Module\Notifications\Api\V1\Channels; use Icinga\Util\Json; use Icinga\Web\Url; use ipl\Sql\Connection; use ipl\Sql\Select; -use Psr\Http\Message\ResponseInterface; use PHPUnit\Framework\TestCase; +use Psr\Http\Message\ResponseInterface; class BaseApiV1TestCase extends TestCase { diff --git a/library/Notifications/Web/Control/SearchBar/ObjectSuggestions.php b/library/Notifications/Web/Control/SearchBar/ObjectSuggestions.php index a7e8fc5a0..c833c721b 100644 --- a/library/Notifications/Web/Control/SearchBar/ObjectSuggestions.php +++ b/library/Notifications/Web/Control/SearchBar/ObjectSuggestions.php @@ -21,10 +21,10 @@ use ipl\Orm\Relation; use ipl\Orm\Relation\HasOne; use ipl\Orm\Resolver; +use ipl\Stdlib\Filter; use ipl\Stdlib\Seq; use ipl\Web\Control\SearchBar\SearchException; use ipl\Web\Control\SearchBar\Suggestions; -use ipl\Stdlib\Filter; use PDO; use Traversable; diff --git a/test/php/application/controllers/ApiV1ContactGroupsTest.php b/test/php/application/controllers/ApiV1ContactGroupsTest.php index 86eb28038..2fa92ad7f 100644 --- a/test/php/application/controllers/ApiV1ContactGroupsTest.php +++ b/test/php/application/controllers/ApiV1ContactGroupsTest.php @@ -5,7 +5,6 @@ namespace Tests\Icinga\Module\Notifications\Controllers; -use GuzzleHttp\Client; use Icinga\Module\Notifications\Test\BaseApiV1TestCase; use Icinga\Web\Url; use ipl\Sql\Connection; diff --git a/test/php/application/controllers/ApiV1ContactsTest.php b/test/php/application/controllers/ApiV1ContactsTest.php index 8c465f3e5..ffb352f67 100644 --- a/test/php/application/controllers/ApiV1ContactsTest.php +++ b/test/php/application/controllers/ApiV1ContactsTest.php @@ -5,12 +5,9 @@ namespace Tests\Icinga\Module\Notifications\Controllers; -use GuzzleHttp\Client; -use Icinga\Exception\IcingaException; use Icinga\Module\Notifications\Test\BaseApiV1TestCase; use Icinga\Web\Url; use ipl\Sql\Connection; -use stdClass; use WebSocket\Base; use PHPUnit\Framework\Attributes\DataProvider; From 1a148d22597364217381988874bf763ad01a3d6b Mon Sep 17 00:00:00 2001 From: Johannes Rauh Date: Thu, 13 Nov 2025 09:21:54 +0100 Subject: [PATCH 04/26] Document thrown exceptions --- application/forms/RotationConfigForm.php | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/application/forms/RotationConfigForm.php b/application/forms/RotationConfigForm.php index f04c5c229..75836dbf0 100644 --- a/application/forms/RotationConfigForm.php +++ b/application/forms/RotationConfigForm.php @@ -214,6 +214,9 @@ public function __construct(int $scheduleId, Connection $db, string $displayTime * @param int $rotationId * * @return $this + * + * @throws LogicException If an invalid rotation mode is set + * @throws ConfigurationError If the schedule's timezone is invalid' * @throws HttpNotFoundException If the rotation with the given ID does not exist */ public function loadRotation(int $rotationId): self @@ -433,6 +436,8 @@ public function addRotation(): void * @param int $rotationId * * @return void + * + * @throws LogicException If the priority is not set */ public function editRotation(int $rotationId): void { @@ -556,6 +561,8 @@ public function editRotation(int $rotationId): void * @param int $id * * @return void + * + * @throws LogicException If the priority is not set */ public function removeRotation(int $id): void { @@ -588,6 +595,8 @@ public function removeRotation(int $id): void * @param ?int $priority * * @return void + * + * @throws LogicException If the priority is not set */ public function wipeRotation(?int $priority = null): void { @@ -1598,6 +1607,8 @@ private function yieldRecurrenceRules(int $count): Generator * @param DateTime $before * * @return array{0: ?DateTime, 1?: array{0: DateTime, 1: DateTime}} + * + * @throws LogicException If the frequency is not supported */ private function calculateRemainingHandoffs(Rule $rrule, DateInterval $shiftDuration, DateTime $before): array { From 5c8ac14a2340c86b943a9947efa5872fd2d7d49d Mon Sep 17 00:00:00 2001 From: Johannes Rauh Date: Thu, 13 Nov 2025 10:06:21 +0100 Subject: [PATCH 05/26] Use match expressions --- application/forms/ChannelForm.php | 33 +++--------- application/forms/RotationConfigForm.php | 21 ++------ library/Notifications/Model/Channel.php | 17 ++---- .../Notifications/Model/IncidentHistory.php | 19 +++---- .../Model/RuleEscalationRecipient.php | 20 +++---- .../View/IncidentHistoryRenderer.php | 53 +++++++------------ .../Notifications/View/IncidentRenderer.php | 19 +++---- library/Notifications/Web/FilterRenderer.php | 32 ++++------- .../Widget/Detail/ObjectHeader.php | 19 ++----- 9 files changed, 70 insertions(+), 163 deletions(-) diff --git a/application/forms/ChannelForm.php b/application/forms/ChannelForm.php index b111905be..13343c936 100644 --- a/application/forms/ChannelForm.php +++ b/application/forms/ChannelForm.php @@ -332,31 +332,14 @@ protected function createConfigElements(string $type, string $config): void */ protected function getElementType(string $configType): string { - switch ($configType) { - case 'string': - $elementType = 'text'; - break; - case 'number': - $elementType = 'number'; - break; - case 'text': - $elementType = 'textarea'; - break; - case 'bool': - $elementType = 'checkbox'; - break; - case 'option': - case 'options': - $elementType = 'select'; - break; - case 'secret': - $elementType = 'password'; - break; - default: - $elementType = 'text'; - } - - return $elementType; + return match ($configType) { + 'number' => 'number', + 'text' => 'textarea', + 'bool' => 'checkbox', + 'option', 'options' => 'select', + 'secret' => 'password', + default => 'text' + }; } /** diff --git a/application/forms/RotationConfigForm.php b/application/forms/RotationConfigForm.php index 75836dbf0..116200250 100644 --- a/application/forms/RotationConfigForm.php +++ b/application/forms/RotationConfigForm.php @@ -225,22 +225,11 @@ public function loadRotation(int $rotationId): self if (self::EXPERIMENTAL_OVERRIDES) { $getHandoff = function (Rotation $rotation): DateTime { - switch ($rotation->mode) { - case '24-7': - $time = $rotation->options['at']; - - break; - case 'partial': - $time = $rotation->options['from']; - - break; - case 'multi': - $time = $rotation->options['from_at']; - - break; - default: - throw new LogicException('Invalid mode'); - } + $time = match ($rotation->mode) { + '24-7' => $rotation->options['at'], + 'partial' => $rotation->options['from'], + 'multi' => $rotation->options['from_at'] + }; $handoff = DateTime::createFromFormat( 'Y-m-d H:i', diff --git a/library/Notifications/Model/Channel.php b/library/Notifications/Model/Channel.php index 53e7f5925..4c3253bae 100644 --- a/library/Notifications/Model/Channel.php +++ b/library/Notifications/Model/Channel.php @@ -96,17 +96,10 @@ public function createRelations(Relations $relations): void */ public function getIcon(): Icon { - switch ($this->type) { - case 'rocketchat': - $icon = new Icon('comment-dots'); - break; - case 'email': - $icon = new Icon('at'); - break; - default: - $icon = new Icon('envelope'); - } - - return $icon; + return match ($this->type) { + 'rocketchat' => new Icon('comment-dots'), + 'email' => new Icon('at'), + default => new Icon('envelope') + }; } } diff --git a/library/Notifications/Model/IncidentHistory.php b/library/Notifications/Model/IncidentHistory.php index 19ca741a9..7d7481fd5 100644 --- a/library/Notifications/Model/IncidentHistory.php +++ b/library/Notifications/Model/IncidentHistory.php @@ -141,17 +141,12 @@ public function createRelations(Relations $relations): void */ public static function translateNotificationState(string $state): string { - switch ($state) { - case 'sent': - return t('sent', 'notifications.transmission.state'); - case 'failed': - return t('failed', 'notifications.transmission.state'); - case 'pending': - return t('pending', 'notifications.transmission.state'); - case 'suppressed': - return t('suppressed', 'notifications.transmission.state'); - default: - return t('unknown', 'notifications.transmission.state'); - } + return match ($state) { + 'sent' => t('sent', 'notifications.transmission.state'), + 'failed' => t('failed', 'notifications.transmission.state'), + 'pending' => t('pending', 'notifications.transmission.state'), + 'suppressed' => t('suppressed', 'notifications.transmission.state'), + default => t('unknown', 'notifications.transmission.state') + }; } } diff --git a/library/Notifications/Model/RuleEscalationRecipient.php b/library/Notifications/Model/RuleEscalationRecipient.php index ec54a2e10..51b1fead0 100644 --- a/library/Notifications/Model/RuleEscalationRecipient.php +++ b/library/Notifications/Model/RuleEscalationRecipient.php @@ -93,19 +93,11 @@ public function createRelations(Relations $relations): void */ public function getRecipient(): Contact|Contactgroup|Schedule|null { - $recipientModel = null; - if ($this->contact_id) { - $recipientModel = $this->contact->first(); - } - - if ($this->contactgroup_id) { - $recipientModel = $this->contactgroup->first(); - } - - if ($this->schedule_id) { - $recipientModel = $this->schedule->first(); - } - - return $recipientModel; + return match (true) { + (bool) $this->contact_id => $this->contact->first(), + (bool) $this->contactgroup_id => $this->contactgroup->first(), + (bool) $this->schedule_id => $this->schedule->first(), + default => null + }; } } diff --git a/library/Notifications/View/IncidentHistoryRenderer.php b/library/Notifications/View/IncidentHistoryRenderer.php index 0b66cf205..14add551c 100644 --- a/library/Notifications/View/IncidentHistoryRenderer.php +++ b/library/Notifications/View/IncidentHistoryRenderer.php @@ -83,28 +83,18 @@ public function assemble($item, string $name, HtmlDocument $element, string $lay */ protected function getIncidentEventIcon(IncidentHistory $item): string { - switch ($item->type) { - case 'opened': - return Icons::OPENED; - case 'muted': - return Icons::MUTE; - case 'unmuted': - return Icons::UNMUTE; - case 'incident_severity_changed': - return $this->getSeverityIcon($item); - case 'recipient_role_changed': - return $this->getRoleIcon($item); - case 'closed': - return Icons::CLOSED; - case 'rule_matched': - return Icons::RULE_MATCHED; - case 'escalation_triggered': - return Icons::TRIGGERED; - case 'notified': - return Icons::NOTIFIED; - default: - return Icons::UNDEFINED; - } + return match ($item->type) { + 'opened' => Icons::OPENED, + 'muted' => Icons::MUTE, + 'unmuted' => Icons::UNMUTE, + 'incident_severity_changed' => $this->getSeverityIcon($item), + 'recipient_role_changed' => $this->getRoleIcon($item), + 'closed' => Icons::CLOSED, + 'rule_matched' => Icons::RULE_MATCHED, + 'escalation_triggered' => Icons::TRIGGERED, + 'notified' => Icons::NOTIFIED, + default => Icons::UNDEFINED + }; } /** @@ -116,18 +106,13 @@ protected function getIncidentEventIcon(IncidentHistory $item): string */ protected function getSeverityIcon(IncidentHistory $item): string { - switch ($item->new_severity) { - case 'ok': - return Icons::OK; - case 'warning': - return Icons::WARNING; - case 'err': - return Icons::ERROR; - case 'crit': - return Icons::CRITICAL; - default: - return Icons::UNDEFINED; - } + return match ($item->new_severity) { + 'ok' => Icons::OK, + 'warning' => Icons::WARNING, + 'err' => Icons::ERROR, + 'crit' => Icons::CRITICAL, + default => Icons::UNDEFINED + }; } /** diff --git a/library/Notifications/View/IncidentRenderer.php b/library/Notifications/View/IncidentRenderer.php index 6b5e4730c..18593dd27 100644 --- a/library/Notifications/View/IncidentRenderer.php +++ b/library/Notifications/View/IncidentRenderer.php @@ -35,19 +35,12 @@ public function assembleAttributes($item, Attributes $attributes, string $layout public function assembleVisual($item, HtmlDocument $visual, string $layout): void { - switch ($item->severity) { - case 'ok': - $icon = Icons::OK; - break; - case 'err': - $icon = Icons::ERROR; - break; - case 'crit': - $icon = Icons::CRITICAL; - break; - default: - $icon = Icons::WARNING; - } + $icon = match ($item->severity) { + 'ok' => Icons::OK, + 'err' => Icons::ERROR, + 'crit' => Icons::CRITICAL, + default => Icons::WARNING + }; $content = new Icon($icon, ['class' => ['severity-' . $item->severity]]); diff --git a/library/Notifications/Web/FilterRenderer.php b/library/Notifications/Web/FilterRenderer.php index 6bfe0ca6b..8b32e55e3 100644 --- a/library/Notifications/Web/FilterRenderer.php +++ b/library/Notifications/Web/FilterRenderer.php @@ -23,28 +23,16 @@ protected function renderCondition(Filter\Condition $condition): void return; } - switch (true) { - case $condition instanceof Filter\Unequal: - case $condition instanceof Filter\Unlike: - $this->string .= '!='; - break; - case $condition instanceof Filter\Equal: - case $condition instanceof Filter\Like: - $this->string .= '='; - break; - case $condition instanceof Filter\GreaterThan: - $this->string .= '>'; - break; - case $condition instanceof Filter\LessThan: - $this->string .= '<'; - break; - case $condition instanceof Filter\GreaterThanOrEqual: - $this->string .= '>='; - break; - case $condition instanceof Filter\LessThanOrEqual: - $this->string .= '<='; - break; - } + $this->string .= match (true) { + $condition instanceof Filter\Unequal, + $condition instanceof Filter\Unlike => '!=', + $condition instanceof Filter\Equal, + $condition instanceof Filter\Like => '=', + $condition instanceof Filter\GreaterThan => '>', + $condition instanceof Filter\LessThan => '<', + $condition instanceof Filter\GreaterThanOrEqual => '>=', + $condition instanceof Filter\LessThanOrEqual => '<=' + }; if (is_array($value)) { $this->string .= '(' . join('|', $value) . ')'; diff --git a/library/Notifications/Widget/Detail/ObjectHeader.php b/library/Notifications/Widget/Detail/ObjectHeader.php index 29f2b2545..f4cc05e83 100644 --- a/library/Notifications/Widget/Detail/ObjectHeader.php +++ b/library/Notifications/Widget/Detail/ObjectHeader.php @@ -38,23 +38,12 @@ public function __construct(Model $object) $this->object = $object; } - /** - * @throws NotImplementedError When the object type is not supported - */ protected function assemble(): void { - switch (true) { - case $this->object instanceof Incident: - $renderer = new IncidentRenderer(); - - break; - case $this->object instanceof Contactgroup: - $renderer = new ContactgroupRenderer(); - - break; - default: - throw new NotImplementedError('Not implemented'); - } + $renderer = match (true) { + $this->object instanceof Incident => new IncidentRenderer(), + $this->object instanceof Contactgroup => new ContactgroupRenderer() + }; $layout = new HeaderItemLayout($this->object, $renderer); From d335b1b27e3dd6dff48f213376ee0928bc59e2e0 Mon Sep 17 00:00:00 2001 From: Johannes Rauh Date: Thu, 13 Nov 2025 10:16:24 +0100 Subject: [PATCH 06/26] Use modern string functions --- application/controllers/DaemonController.php | 2 +- application/forms/RotationConfigForm.php | 2 +- library/Notifications/Common/Database.php | 2 +- library/Notifications/Model/Behavior/ObjectTags.php | 2 +- library/Notifications/Model/Daemon/Connection.php | 4 ++-- .../Web/Control/SearchBar/ObjectSuggestions.php | 8 ++++---- 6 files changed, 10 insertions(+), 10 deletions(-) diff --git a/application/controllers/DaemonController.php b/application/controllers/DaemonController.php index fbf91c3d0..777e88f22 100644 --- a/application/controllers/DaemonController.php +++ b/application/controllers/DaemonController.php @@ -61,7 +61,7 @@ public function scriptAction(): void ->getBaseDir() . '/public/js'; $filePath = realpath($root . DIRECTORY_SEPARATOR . 'notifications-' . $fileName . $extension); - if ($filePath === false || substr($filePath, 0, strlen($root)) !== $root) { + if ($filePath === false || ! str_starts_with($filePath, $root)) { if ($fileName === 'undefined') { $this->httpNotFound(t("No file name submitted")); } diff --git a/application/forms/RotationConfigForm.php b/application/forms/RotationConfigForm.php index 116200250..625f4f0b4 100644 --- a/application/forms/RotationConfigForm.php +++ b/application/forms/RotationConfigForm.php @@ -1100,7 +1100,7 @@ protected function assemble(): void $groupTerms = []; foreach ($terms as $term) { /** @var TermInput\Term $term */ - if (strpos($term->getSearchValue(), ':') === false) { + if (! str_contains($term->getSearchValue(), ':')) { // TODO: Auto-correct this to a valid type:id pair, if possible $term->setMessage($this->translate('Is not a contact nor a group of contacts')); continue; diff --git a/library/Notifications/Common/Database.php b/library/Notifications/Common/Database.php index fa2bdcfad..67ba65d86 100644 --- a/library/Notifications/Common/Database.php +++ b/library/Notifications/Common/Database.php @@ -167,7 +167,7 @@ private static function getConnection(): Connection // getNextChangedAt() wants MAX(changed_at) of all rows, deleted or not foreach ($select->getColumns() as $column) { - if ($column instanceof Expression && strpos($column->getStatement(), 'MAX(changed_at)') !== false) { + if ($column instanceof Expression && str_contains($column->getStatement(), 'MAX(changed_at)')) { return; } } diff --git a/library/Notifications/Model/Behavior/ObjectTags.php b/library/Notifications/Model/Behavior/ObjectTags.php index b09df41c2..dc942f032 100644 --- a/library/Notifications/Model/Behavior/ObjectTags.php +++ b/library/Notifications/Model/Behavior/ObjectTags.php @@ -35,7 +35,7 @@ public function rewriteCondition(Filter\Condition $condition, $relation = null): /** @var ?string $column */ $column = $condition->metaData()->get('columnName'); if ($column !== null) { - if (substr($relation, -10) === 'extra_tag.') { + if (str_ends_with($relation, 'extra_tag.')) { $relation = substr($relation, 0, -10) . 'object_extra_tag.'; } else { // tag. $relation = substr($relation, 0, -4) . 'object_id_tag.'; diff --git a/library/Notifications/Model/Daemon/Connection.php b/library/Notifications/Model/Daemon/Connection.php index fae3bd839..a90b9f53a 100644 --- a/library/Notifications/Model/Daemon/Connection.php +++ b/library/Notifications/Model/Daemon/Connection.php @@ -133,9 +133,9 @@ public static function parseHostAndPort(?string $address): object|false return false; } - if (strpos($host, '[') !== false) { + if (str_contains($host, '[')) { // IPv6 format - if (strpos($host, '.')) { + if (str_contains($host, '.')) { // IPv4 represented in IPv6 $offset = strrpos($host, ':'); $parsed->host = substr($host, $offset === false ? 0 : $offset + 1, -1); diff --git a/library/Notifications/Web/Control/SearchBar/ObjectSuggestions.php b/library/Notifications/Web/Control/SearchBar/ObjectSuggestions.php index c833c721b..a35c00061 100644 --- a/library/Notifications/Web/Control/SearchBar/ObjectSuggestions.php +++ b/library/Notifications/Web/Control/SearchBar/ObjectSuggestions.php @@ -115,7 +115,7 @@ protected function fetchValueSuggestions( $query = $model::on(Database::get()); $query->limit(static::DEFAULT_LIMIT); - if (strpos($column, ' ') !== false) { + if (str_contains($column, ' ')) { // $column may be a label /** @var string $path */ [$path, $_] = Seq::find( @@ -135,10 +135,10 @@ protected function fetchValueSuggestions( [$targetPath, $columnName] = $splitted; $isTag = false; - if (substr($targetPath, -4) === '.tag') { + if (str_ends_with($targetPath, '.tag')) { $isTag = true; $targetPath = substr($targetPath, 0, -3) . 'object_id_tag'; - } elseif (substr($targetPath, -10) === '.extra_tag') { + } elseif (str_ends_with($targetPath, '.extra_tag')) { $isTag = true; $targetPath = substr($targetPath, 0, -9) . 'object_extra_tag'; } elseif ( @@ -153,7 +153,7 @@ protected function fetchValueSuggestions( ); } - if (strpos($targetPath, '.') !== false) { + if (str_contains($targetPath, '.')) { try { $query->with($targetPath); // TODO: Remove this, once ipl/orm does it as early } catch (InvalidRelationException $e) { From 9a5e011b8aa547a896fe3cd8c2fb014c5719a1ac Mon Sep 17 00:00:00 2001 From: Johannes Rauh Date: Fri, 14 Nov 2025 09:16:42 +0100 Subject: [PATCH 07/26] Replace deprecated code --- application/controllers/ChannelController.php | 3 ++- application/controllers/ChannelsController.php | 3 ++- application/controllers/ConfigController.php | 3 ++- application/controllers/ContactController.php | 3 ++- application/controllers/ContactGroupController.php | 4 ++-- application/controllers/ContactGroupsController.php | 2 +- application/controllers/IncidentController.php | 3 ++- application/forms/ChannelForm.php | 2 +- application/forms/MoveRotationForm.php | 2 +- 9 files changed, 15 insertions(+), 10 deletions(-) diff --git a/application/controllers/ChannelController.php b/application/controllers/ChannelController.php index a1764998a..f6a823881 100644 --- a/application/controllers/ChannelController.php +++ b/application/controllers/ChannelController.php @@ -8,6 +8,7 @@ use Icinga\Module\Notifications\Common\Database; use Icinga\Module\Notifications\Forms\ChannelForm; use Icinga\Web\Notification; +use ipl\Html\Contract\Form; use ipl\Web\Compat\CompatController; class ChannelController extends CompatController @@ -22,7 +23,7 @@ public function indexAction(): void $channelId = $this->params->getRequired('id'); $form = (new ChannelForm(Database::get())) ->loadChannel($channelId) - ->on(ChannelForm::ON_SUCCESS, function (ChannelForm $form) { + ->on(Form::ON_SUBMIT, function (ChannelForm $form) { if ($form->getPressedSubmitElement()->getName() === 'delete') { $form->removeChannel(); Notification::success(sprintf( diff --git a/application/controllers/ChannelsController.php b/application/controllers/ChannelsController.php index 3e4994824..4d70d0fa4 100644 --- a/application/controllers/ChannelsController.php +++ b/application/controllers/ChannelsController.php @@ -16,6 +16,7 @@ use Icinga\Web\Notification; use Icinga\Web\Widget\Tab; use Icinga\Web\Widget\Tabs; +use ipl\Html\Contract\Form; use ipl\Sql\Expression; use ipl\Stdlib\Filter; use ipl\Web\Compat\CompatController; @@ -111,7 +112,7 @@ public function addAction(): void { $this->addTitleTab(t('Add Channel')); $form = (new ChannelForm(Database::get())) - ->on(ChannelForm::ON_SUCCESS, function (ChannelForm $form) { + ->on(Form::ON_SUBMIT, function (ChannelForm $form) { $form->addChannel(); Notification::success( sprintf( diff --git a/application/controllers/ConfigController.php b/application/controllers/ConfigController.php index c6ddd2939..0aad1c667 100644 --- a/application/controllers/ConfigController.php +++ b/application/controllers/ConfigController.php @@ -10,6 +10,7 @@ use Icinga\Web\Notification; use Icinga\Web\Widget\Tab; use Icinga\Web\Widget\Tabs; +use ipl\Html\Contract\Form; use ipl\Web\Compat\CompatController; class ConfigController extends CompatController @@ -26,7 +27,7 @@ public function databaseAction(): void $moduleConfig = Config::module('notifications'); $form = (new DatabaseConfigForm()) ->populate($moduleConfig->getSection('database')) - ->on(DatabaseConfigForm::ON_SUCCESS, function ($form) use ($moduleConfig) { + ->on(Form::ON_SUBMIT, function ($form) use ($moduleConfig) { $moduleConfig->setSection('database', $form->getValues()); $moduleConfig->saveIni(); diff --git a/application/controllers/ContactController.php b/application/controllers/ContactController.php index 205fcd582..fb3304fde 100644 --- a/application/controllers/ContactController.php +++ b/application/controllers/ContactController.php @@ -14,6 +14,7 @@ use Icinga\Module\Notifications\Web\Form\ContactForm; use Icinga\Repository\Repository; use Icinga\Web\Notification; +use ipl\Html\Contract\Form; use ipl\Web\Compat\CompatController; use ipl\Web\FormElement\SearchSuggestions; @@ -30,7 +31,7 @@ public function indexAction(): void $form = (new ContactForm(Database::get())) ->loadContact($contactId) - ->on(ContactForm::ON_SUCCESS, function (ContactForm $form) { + ->on(Form::ON_SUBMIT, function (ContactForm $form) { $form->editContact(); Notification::success(sprintf( t('Contact "%s" has successfully been saved'), diff --git a/application/controllers/ContactGroupController.php b/application/controllers/ContactGroupController.php index 036e95f16..a395aacf4 100644 --- a/application/controllers/ContactGroupController.php +++ b/application/controllers/ContactGroupController.php @@ -14,7 +14,7 @@ use Icinga\Module\Notifications\Widget\Detail\ObjectHeader; use Icinga\Module\Notifications\Widget\ItemList\ObjectList; use Icinga\Web\Notification; -use ipl\Html\Form; +use ipl\Html\Contract\Form; use ipl\Html\Text; use ipl\Stdlib\Filter; use ipl\Web\Compat\CompatController; @@ -98,7 +98,7 @@ public function editAction(): void } } }) - ->on(Form::ON_SUCCESS, function (ContactGroupForm $form) use ($groupId) { + ->on(Form::ON_SUBMIT, function (ContactGroupForm $form) use ($groupId) { $form->editGroup(); Notification::success(sprintf( t('Successfully updated contact group %s'), diff --git a/application/controllers/ContactGroupsController.php b/application/controllers/ContactGroupsController.php index cd92f468a..fb2f63e2a 100644 --- a/application/controllers/ContactGroupsController.php +++ b/application/controllers/ContactGroupsController.php @@ -161,7 +161,7 @@ public function addAction(): void } } }) - ->on(Form::ON_SUCCESS, function (ContactGroupForm $form) { + ->on(Form::ON_SUBMIT, function (ContactGroupForm $form) { $groupIdentifier = $form->addGroup(); Notification::success($this->translate('New contact group has been successfully added')); diff --git a/application/controllers/IncidentController.php b/application/controllers/IncidentController.php index 479297b53..7be7d3e22 100644 --- a/application/controllers/IncidentController.php +++ b/application/controllers/IncidentController.php @@ -13,6 +13,7 @@ use Icinga\Module\Notifications\Widget\Detail\IncidentDetail; use Icinga\Module\Notifications\Widget\Detail\IncidentQuickActions; use Icinga\Module\Notifications\Widget\Detail\ObjectHeader; +use ipl\Html\Contract\Form; use ipl\Stdlib\Filter; use ipl\Web\Compat\CompatController; @@ -51,7 +52,7 @@ public function indexAction(): void if ($contact !== null) { $this->addControl( (new IncidentQuickActions($incident, $contact->id)) - ->on(IncidentQuickActions::ON_SUCCESS, function () use ($incident) { + ->on(Form::ON_SUBMIT, function () use ($incident) { $this->redirectNow(Links::incident($incident->id)); }) ->handleRequest($this->getServerRequest()) diff --git a/application/forms/ChannelForm.php b/application/forms/ChannelForm.php index 13343c936..053b74a0e 100644 --- a/application/forms/ChannelForm.php +++ b/application/forms/ChannelForm.php @@ -73,7 +73,7 @@ protected function assemble(): void } $this->addAttributes(['class' => 'channel-form']); - $this->addElement($this->createCsrfCounterMeasure(Session::getSession()->getId())); + $this->addCsrfCounterMeasure(Session::getSession()->getId()); $this->addElement( 'text', diff --git a/application/forms/MoveRotationForm.php b/application/forms/MoveRotationForm.php index 77ff3e6fb..8097a0f0a 100644 --- a/application/forms/MoveRotationForm.php +++ b/application/forms/MoveRotationForm.php @@ -71,7 +71,7 @@ protected function assemble(): void { $this->addElement('hidden', 'rotation', ['required' => true]); $this->addElement('hidden', 'priority', ['required' => true]); - $this->addElement($this->createCsrfCounterMeasure(Session::getSession()->getId())); + $this->addCsrfCounterMeasure(Session::getSession()->getId()); } protected function onError(): void From fef89ba2e3dfe25b8d932d3fef2f93ded4671c13 Mon Sep 17 00:00:00 2001 From: Johannes Rauh Date: Fri, 14 Nov 2025 09:23:39 +0100 Subject: [PATCH 08/26] Explicitly create Attributes --- application/controllers/ContactGroupController.php | 3 ++- application/controllers/EventRuleController.php | 5 +++-- application/controllers/IncidentController.php | 3 ++- application/controllers/ScheduleController.php | 3 ++- .../forms/EventRuleConfigElements/DynamicElements.php | 5 +++-- library/Notifications/Common/LoadMore.php | 3 ++- library/Notifications/View/IncidentRenderer.php | 2 +- library/Notifications/Web/Form/ContactForm.php | 2 +- library/Notifications/Widget/EventSourceBadge.php | 3 ++- library/Notifications/Widget/TimeGrid/DynamicGrid.php | 2 +- library/Notifications/Widget/TimeGrid/ExtraEntryCount.php | 3 ++- 11 files changed, 21 insertions(+), 13 deletions(-) diff --git a/application/controllers/ContactGroupController.php b/application/controllers/ContactGroupController.php index a395aacf4..efb3df6d5 100644 --- a/application/controllers/ContactGroupController.php +++ b/application/controllers/ContactGroupController.php @@ -14,6 +14,7 @@ use Icinga\Module\Notifications\Widget\Detail\ObjectHeader; use Icinga\Module\Notifications\Widget\ItemList\ObjectList; use Icinga\Web\Notification; +use ipl\Html\Attributes; use ipl\Html\Contract\Form; use ipl\Html\Text; use ipl\Stdlib\Filter; @@ -41,7 +42,7 @@ public function indexAction(): void $this->httpNotFound(t('Contact group not found')); } - $this->controls->addAttributes(['class' => 'contactgroup-detail']); + $this->controls->addAttributes(Attributes::create(['class' => 'contactgroup-detail'])); $this->addControl(new ObjectHeader($group)); diff --git a/application/controllers/EventRuleController.php b/application/controllers/EventRuleController.php index 69b255925..a69166f93 100644 --- a/application/controllers/EventRuleController.php +++ b/application/controllers/EventRuleController.php @@ -20,6 +20,7 @@ use Icinga\Module\Notifications\Web\Control\SearchBar\ExtraTagSuggestions; use Icinga\Web\Notification; use Icinga\Web\Session; +use ipl\Html\Attributes; use ipl\Html\Contract\Form; use ipl\Html\Html; use ipl\Stdlib\Filter; @@ -46,8 +47,8 @@ public function init(): void public function indexAction(): void { - $this->controls->addAttributes(['class' => 'event-rule-detail']); - $this->content->addAttributes(['class' => 'event-rule-detail']); + $this->controls->addAttributes(Attributes::create(['class' => 'event-rule-detail'])); + $this->content->addAttributes(Attributes::create(['class' => 'event-rule-detail'])); $this->getTabs()->disableLegacyExtensions(); $ruleId = (int) $this->params->getRequired('id'); diff --git a/application/controllers/IncidentController.php b/application/controllers/IncidentController.php index 7be7d3e22..2fa6f9c53 100644 --- a/application/controllers/IncidentController.php +++ b/application/controllers/IncidentController.php @@ -13,6 +13,7 @@ use Icinga\Module\Notifications\Widget\Detail\IncidentDetail; use Icinga\Module\Notifications\Widget\Detail\IncidentQuickActions; use Icinga\Module\Notifications\Widget\Detail\ObjectHeader; +use ipl\Html\Attributes; use ipl\Html\Contract\Form; use ipl\Stdlib\Filter; use ipl\Web\Compat\CompatController; @@ -42,7 +43,7 @@ public function indexAction(): void $this->addControl(new ObjectHeader($incident)); - $this->controls->addAttributes(['class' => 'incident-detail']); + $this->controls->addAttributes(Attributes::create(['class' => 'incident-detail'])); $contact = Contact::on(Database::get()) ->columns('id') diff --git a/application/controllers/ScheduleController.php b/application/controllers/ScheduleController.php index 4a4c20883..ddbc19211 100644 --- a/application/controllers/ScheduleController.php +++ b/application/controllers/ScheduleController.php @@ -16,6 +16,7 @@ use Icinga\Module\Notifications\Widget\Detail\ScheduleDetail; use Icinga\Module\Notifications\Widget\TimezoneWarning; use Icinga\Web\Session; +use ipl\Html\Attributes; use ipl\Html\Contract\Form; use ipl\Html\Html; use ipl\Stdlib\Filter; @@ -61,7 +62,7 @@ public function indexAction(): void ))->openInModal() ); - $this->controls->addAttributes(['class' => 'schedule-detail-controls']); + $this->controls->addAttributes(Attributes::create(['class' => 'schedule-detail-controls'])); $scheduleControls = (new ScheduleDetail\Controls()) ->setAction(Url::fromRequest()->getAbsoluteUrl()) diff --git a/application/forms/EventRuleConfigElements/DynamicElements.php b/application/forms/EventRuleConfigElements/DynamicElements.php index 766aae71c..b8985414b 100644 --- a/application/forms/EventRuleConfigElements/DynamicElements.php +++ b/application/forms/EventRuleConfigElements/DynamicElements.php @@ -5,6 +5,7 @@ namespace Icinga\Module\Notifications\Forms\EventRuleConfigElements; +use ipl\Html\Attributes; use ipl\Html\Contract\FormElement; use ipl\Html\FormElement\SubmitButtonElement; @@ -87,7 +88,7 @@ protected function assemble(): void $count++; } - $add = $this->createAddButton()->addAttributes(['formnovalidate' => true]); + $add = $this->createAddButton()->addAttributes(Attributes::create(['formnovalidate' => true])); $this->registerElement($add); if ($add->hasBeenPressed()) { $this->createRemoveButton($newCount); @@ -115,6 +116,6 @@ protected function assemble(): void $this->clearPopulatedValue('count'); $this->addElement('hidden', 'count', ['ignore' => true, 'value' => $newCount]); - $this->addAttributes(['class' => ['dynamic-list', $newCount === 0 ? 'empty' : '']]); + $this->addAttributes(Attributes::create(['class' => ['dynamic-list', $newCount === 0 ? 'empty' : '']])); } } diff --git a/library/Notifications/Common/LoadMore.php b/library/Notifications/Common/LoadMore.php index 6852a12fb..355bd1b53 100644 --- a/library/Notifications/Common/LoadMore.php +++ b/library/Notifications/Common/LoadMore.php @@ -8,6 +8,7 @@ use Generator; use Icinga\Module\Notifications\Widget\ItemList\PageSeparatorItem; use Icinga\Module\Notifications\Widget\ShowMore; +use ipl\Html\Attributes; use ipl\Orm\ResultSet; use ipl\Web\Url; @@ -102,7 +103,7 @@ protected function getIterator(ResultSet $result): Generator ->setLabel(t('Load More')) ->setAttribute('data-no-icinga-ajax', true); - $this->add($showMore->setTag('li')->addAttributes(['class' => 'list-item'])); + $this->add($showMore->setTag('li')->addAttributes(Attributes::create(['class' => 'list-item']))); } } } diff --git a/library/Notifications/View/IncidentRenderer.php b/library/Notifications/View/IncidentRenderer.php index 18593dd27..22a74885d 100644 --- a/library/Notifications/View/IncidentRenderer.php +++ b/library/Notifications/View/IncidentRenderer.php @@ -85,7 +85,7 @@ public function assembleExtendedInfo($item, HtmlDocument $info, string $layout): $source = $item->object->source; $info->addHtml( (new Ball(Ball::SIZE_BIG)) - ->addAttributes(['class' => 'source-icon']) + ->addAttributes(Attributes::create(['class' => 'source-icon'])) ->addHtml($source->getIcon()) ); diff --git a/library/Notifications/Web/Form/ContactForm.php b/library/Notifications/Web/Form/ContactForm.php index 255ef511c..7b67a3431 100644 --- a/library/Notifications/Web/Form/ContactForm.php +++ b/library/Notifications/Web/Form/ContactForm.php @@ -79,7 +79,7 @@ public function isValidEvent($event): bool protected function assemble(): void { - $this->addAttributes(['class' => 'contact-form']); + $this->addAttributes(Attributes::create(['class' => 'contact-form'])); $this->addCsrfCounterMeasure(Session::getSession()->getId()); // Fieldset for contact full name and username diff --git a/library/Notifications/Widget/EventSourceBadge.php b/library/Notifications/Widget/EventSourceBadge.php index 00f4ebb4d..ca0edab3a 100644 --- a/library/Notifications/Widget/EventSourceBadge.php +++ b/library/Notifications/Widget/EventSourceBadge.php @@ -6,6 +6,7 @@ namespace Icinga\Module\Notifications\Widget; use Icinga\Module\Notifications\Model\Source; +use ipl\Html\Attributes; use ipl\Html\BaseHtmlElement; use ipl\Html\Html; use ipl\Web\Widget\Ball; @@ -42,7 +43,7 @@ protected function assemble(): void ->add('title', $title); $this->addHtml((new Ball(Ball::SIZE_LARGE)) - ->addAttributes(['class' => 'source-icon']) + ->addAttributes(Attributes::create(['class' => 'source-icon'])) ->addHtml($this->source->getIcon())); $this->add(Html::tag('span', ['class' => 'name'], $this->source->name ?? $this->source->type)); } diff --git a/library/Notifications/Widget/TimeGrid/DynamicGrid.php b/library/Notifications/Widget/TimeGrid/DynamicGrid.php index d58b723b0..e595006c8 100644 --- a/library/Notifications/Widget/TimeGrid/DynamicGrid.php +++ b/library/Notifications/Widget/TimeGrid/DynamicGrid.php @@ -54,7 +54,7 @@ public function setDays(int $days): self */ public function addToSideBar(BaseHtmlElement $row): self { - $row->addAttributes(['class' => 'row-title']); + $row->addAttributes(Attributes::create(['class' => 'row-title'])); $this->sideBar()->addHtml($row); return $this; diff --git a/library/Notifications/Widget/TimeGrid/ExtraEntryCount.php b/library/Notifications/Widget/TimeGrid/ExtraEntryCount.php index a7e0f2cf3..a91417392 100644 --- a/library/Notifications/Widget/TimeGrid/ExtraEntryCount.php +++ b/library/Notifications/Widget/TimeGrid/ExtraEntryCount.php @@ -6,6 +6,7 @@ namespace Icinga\Module\Notifications\Widget\TimeGrid; use DateTime; +use ipl\Html\Attributes; use ipl\I18n\Translation; use ipl\Web\Widget\ButtonLink; @@ -50,7 +51,7 @@ public function setGridStep(DateTime $gridStep): self protected function assemble(): void { $count = $this->grid->getExtraEntryCount($this->gridStep); - $this->addAttributes(['class' => 'extra-count']) + $this->addAttributes(Attributes::create(['class' => 'extra-count'])) ->setBaseTarget('_self') ->setContent( sprintf( From ee15c03fcd5245b49c9bc0aff6eab257b11ed31a Mon Sep 17 00:00:00 2001 From: Johannes Rauh Date: Fri, 14 Nov 2025 09:25:04 +0100 Subject: [PATCH 09/26] Add inline type docs --- application/controllers/ChannelsController.php | 2 -- application/controllers/ConfigController.php | 2 -- application/controllers/ContactGroupController.php | 1 + application/controllers/EventRuleController.php | 1 + application/controllers/IncidentController.php | 1 + application/forms/ContactGroupForm.php | 1 + application/forms/RotationConfigForm.php | 2 ++ library/Notifications/Api/V1/ContactGroups.php | 1 + library/Notifications/Api/V1/Contacts.php | 1 + library/Notifications/View/EventRuleRenderer.php | 2 ++ 10 files changed, 10 insertions(+), 4 deletions(-) diff --git a/application/controllers/ChannelsController.php b/application/controllers/ChannelsController.php index 4d70d0fa4..f3ddc933c 100644 --- a/application/controllers/ChannelsController.php +++ b/application/controllers/ChannelsController.php @@ -14,7 +14,6 @@ use Icinga\Module\Notifications\Web\Control\SearchBar\ObjectSuggestions; use Icinga\Module\Notifications\Widget\ItemList\ObjectList; use Icinga\Web\Notification; -use Icinga\Web\Widget\Tab; use Icinga\Web\Widget\Tabs; use ipl\Html\Contract\Form; use ipl\Sql\Expression; @@ -172,7 +171,6 @@ protected function getFilter(): Filter\Rule */ protected function mergeTabs(Tabs $tabs): void { - /** @var Tab $tab */ foreach ($tabs->getTabs() as $tab) { $this->tabs->add($tab->getName(), $tab); } diff --git a/application/controllers/ConfigController.php b/application/controllers/ConfigController.php index 0aad1c667..d013dc0e1 100644 --- a/application/controllers/ConfigController.php +++ b/application/controllers/ConfigController.php @@ -8,7 +8,6 @@ use Icinga\Application\Config; use Icinga\Module\Notifications\Forms\DatabaseConfigForm; use Icinga\Web\Notification; -use Icinga\Web\Widget\Tab; use Icinga\Web\Widget\Tabs; use ipl\Html\Contract\Form; use ipl\Web\Compat\CompatController; @@ -48,7 +47,6 @@ public function databaseAction(): void */ protected function mergeTabs(Tabs $tabs): void { - /** @var Tab $tab */ foreach ($tabs->getTabs() as $tab) { $this->tabs->add($tab->getName(), $tab); } diff --git a/application/controllers/ContactGroupController.php b/application/controllers/ContactGroupController.php index efb3df6d5..484ab1e51 100644 --- a/application/controllers/ContactGroupController.php +++ b/application/controllers/ContactGroupController.php @@ -37,6 +37,7 @@ public function indexAction(): void ->columns(['id', 'name']) ->filter(Filter::equal('id', $groupId)); + /** @var ?Contactgroup $group */ $group = $query->first(); if ($group === null) { $this->httpNotFound(t('Contact group not found')); diff --git a/application/controllers/EventRuleController.php b/application/controllers/EventRuleController.php index a69166f93..836711b6b 100644 --- a/application/controllers/EventRuleController.php +++ b/application/controllers/EventRuleController.php @@ -207,6 +207,7 @@ public function searchEditorAction(): void )) ->first(); } elseif (isset($this->session->source)) { + /** @var ?Source $source */ $source = Source::on(Database::get()) ->columns(['id', 'type']) ->filter(Filter::equal('id', $this->session->source)) diff --git a/application/controllers/IncidentController.php b/application/controllers/IncidentController.php index 2fa6f9c53..7dcf4a918 100644 --- a/application/controllers/IncidentController.php +++ b/application/controllers/IncidentController.php @@ -45,6 +45,7 @@ public function indexAction(): void $this->controls->addAttributes(Attributes::create(['class' => 'incident-detail'])); + /** @var ?Contact $contact */ $contact = Contact::on(Database::get()) ->columns('id') ->filter(Filter::equal('username', $this->Auth()->getUser()->getUsername())) diff --git a/application/forms/ContactGroupForm.php b/application/forms/ContactGroupForm.php index 794e9689c..43796ab7d 100644 --- a/application/forms/ContactGroupForm.php +++ b/application/forms/ContactGroupForm.php @@ -416,6 +416,7 @@ private function fetchDbValues(): array ->columns(['id', 'name']) ->filter(Filter::equal('id', $this->contactgroupId)); + /** @var ?Contactgroup $group */ $group = $query->first(); if ($group === null) { throw new HttpNotFoundException($this->translate('Contact group not found')); diff --git a/application/forms/RotationConfigForm.php b/application/forms/RotationConfigForm.php index 625f4f0b4..0fd54282d 100644 --- a/application/forms/RotationConfigForm.php +++ b/application/forms/RotationConfigForm.php @@ -22,6 +22,7 @@ use ipl\Html\DeferredText; use ipl\Html\FormDecoration\DescriptionDecorator; use ipl\Html\FormElement\FieldsetElement; +use ipl\Html\FormElement\SelectElement; use ipl\Html\HtmlDocument; use ipl\Html\HtmlElement; use ipl\Html\Text; @@ -989,6 +990,7 @@ protected function assembleMultiDayOptions(FieldsetElement $options): DateTime ); } + /** @var SelectElement $toAt */ $toAt = $options->createElement('select', 'to_at', [ 'class' => 'autosubmit', 'required' => true, diff --git a/library/Notifications/Api/V1/ContactGroups.php b/library/Notifications/Api/V1/ContactGroups.php index f3b5cfe33..f91fb9f34 100644 --- a/library/Notifications/Api/V1/ContactGroups.php +++ b/library/Notifications/Api/V1/ContactGroups.php @@ -796,6 +796,7 @@ private function fetchDbValues(int $contactgroupId): array ->columns(['id', 'name']) ->filter(Filter::equal('id', $contactgroupId)); + /** @var ?Contactgroup $group */ $group = $query->first(); if ($group === null) { throw new HttpNotFoundException('Contact group not found'); diff --git a/library/Notifications/Api/V1/Contacts.php b/library/Notifications/Api/V1/Contacts.php index b69e6fc1e..ec8f0f8e2 100644 --- a/library/Notifications/Api/V1/Contacts.php +++ b/library/Notifications/Api/V1/Contacts.php @@ -1010,6 +1010,7 @@ private function fetchDbValues(int $contactId): array ->columns(['id', 'full_name', 'default_channel_id']) ->filter(Filter::equal('id', $contactId)); + /** @var ?Contact $contact */ $contact = $query->first(); if ($contact === null) { throw new HttpNotFoundException('Contact contact not found'); diff --git a/library/Notifications/View/EventRuleRenderer.php b/library/Notifications/View/EventRuleRenderer.php index d0d0d2cb0..9d8301ab6 100644 --- a/library/Notifications/View/EventRuleRenderer.php +++ b/library/Notifications/View/EventRuleRenderer.php @@ -7,6 +7,7 @@ use Icinga\Module\Notifications\Common\Links; use Icinga\Module\Notifications\Model\Rule; +use Icinga\Module\Notifications\Model\RuleEscalation; use Icinga\Module\Notifications\Widget\RuleEscalationRecipientBadge; use ipl\Html\Attributes; use ipl\Html\HtmlDocument; @@ -38,6 +39,7 @@ public function assembleCaption($item, HtmlDocument $caption, string $layout): v public function assembleExtendedInfo($item, HtmlDocument $info, string $layout): void { + /** @var ?RuleEscalation $rs */ $rs = $item->rule_escalation->first(); if ($rs) { $recipientCount = $rs->rule_escalation_recipient->count(); From ef9f6794cf64b091292339d291f747a1b555bc33 Mon Sep 17 00:00:00 2001 From: Johannes Rauh Date: Fri, 14 Nov 2025 10:00:29 +0100 Subject: [PATCH 10/26] Use imports --- .../controllers/EventRuleController.php | 3 ++- application/forms/RotationConfigForm.php | 26 ++++++++++--------- .../LegacyRequestConversionMiddleware.php | 3 ++- .../Response/ErrorResponse.php | 3 ++- .../Response/SuccessResponse.php | 3 ++- library/Notifications/Model/ExtraTag.php | 3 ++- library/Notifications/Model/Tag.php | 3 ++- .../Control/SearchBar/ObjectSuggestions.php | 3 ++- .../Notifications/Widget/Calendar/Entry.php | 2 +- .../Widget/Timeline/EntryFlyout.php | 10 ++++--- .../Notifications/Widget/CalendarTest.php | 5 ++-- 11 files changed, 38 insertions(+), 26 deletions(-) diff --git a/application/controllers/EventRuleController.php b/application/controllers/EventRuleController.php index 836711b6b..6a8312d13 100644 --- a/application/controllers/EventRuleController.php +++ b/application/controllers/EventRuleController.php @@ -8,6 +8,7 @@ use Icinga\Application\Hook; use Icinga\Application\Logger; use Icinga\Exception\Http\HttpNotFoundException; +use Icinga\Exception\MissingParameterException; use Icinga\Module\Notifications\Common\Auth; use Icinga\Module\Notifications\Common\Database; use Icinga\Module\Notifications\Common\Links; @@ -190,7 +191,7 @@ public function completeAction(): void * * @return void * - * @throws \Icinga\Exception\MissingParameterException + * @throws MissingParameterException */ public function searchEditorAction(): void { diff --git a/application/forms/RotationConfigForm.php b/application/forms/RotationConfigForm.php index 0fd54282d..000c95444 100644 --- a/application/forms/RotationConfigForm.php +++ b/application/forms/RotationConfigForm.php @@ -18,6 +18,7 @@ use Icinga\Module\Notifications\Model\TimeperiodEntry; use Icinga\Util\Json; use Icinga\Web\Session; +use IntlDateFormatter; use ipl\Html\Attributes; use ipl\Html\DeferredText; use ipl\Html\FormDecoration\DescriptionDecorator; @@ -37,6 +38,7 @@ use ipl\Web\FormDecorator\IcingaFormDecorator; use ipl\Web\FormElement\TermInput; use ipl\Web\Url; +use Locale; use LogicException; use Recurr\Frequency; use Recurr\Rule; @@ -1249,10 +1251,10 @@ function ($value, $validator) use ($earliestHandoff, $firstHandoff, $latestHando } else { return sprintf( $this->translate('The rotation will start on %s'), - (new \IntlDateFormatter( - \Locale::getDefault(), - \IntlDateFormatter::MEDIUM, - \IntlDateFormatter::SHORT, + (new IntlDateFormatter( + Locale::getDefault(), + IntlDateFormatter::MEDIUM, + IntlDateFormatter::SHORT, $this->scheduleTimezone ))->format($actualFirstHandoff) ); @@ -1272,10 +1274,10 @@ function ($value, $validator) use ($earliestHandoff, $firstHandoff, $latestHando return sprintf( $this->translate('In your chosen display timezone (%s) this is the %s'), $this->displayTimezone, - (new \IntlDateFormatter( - \Locale::getDefault(), - \IntlDateFormatter::MEDIUM, - \IntlDateFormatter::SHORT, + (new IntlDateFormatter( + Locale::getDefault(), + IntlDateFormatter::MEDIUM, + IntlDateFormatter::SHORT, $this->displayTimezone ))->format($actualFirstHandoff) ); @@ -1364,10 +1366,10 @@ private function parseDateAndTime(?string $date = null, ?string $time = null): D */ private function getTimeOptions(): array { - $formatter = new \IntlDateFormatter( - \Locale::getDefault(), - \IntlDateFormatter::NONE, - \IntlDateFormatter::SHORT, + $formatter = new IntlDateFormatter( + Locale::getDefault(), + IntlDateFormatter::NONE, + IntlDateFormatter::SHORT, $this->scheduleTimezone ); diff --git a/library/Notifications/Api/Middleware/LegacyRequestConversionMiddleware.php b/library/Notifications/Api/Middleware/LegacyRequestConversionMiddleware.php index 0e62e1c5b..3a125bbbd 100644 --- a/library/Notifications/Api/Middleware/LegacyRequestConversionMiddleware.php +++ b/library/Notifications/Api/Middleware/LegacyRequestConversionMiddleware.php @@ -14,6 +14,7 @@ use Psr\Http\Message\ServerRequestInterface; use Psr\Http\Server\MiddlewareInterface; use Psr\Http\Server\RequestHandlerInterface; +use Zend_Controller_Request_Exception; /** * LegacyRequestConversionMiddleware is a middleware that converts a legacy request @@ -56,7 +57,7 @@ public function process(ServerRequestInterface $request, RequestHandlerInterface $requestBody = $this->legacyRequest->getPost(); } catch (JsonDecodeException) { throw new HttpBadRequestException('Invalid request body: given content is not a valid JSON'); - } catch (\Zend_Controller_Request_Exception) { + } catch (Zend_Controller_Request_Exception) { throw new HttpBadRequestException('Invalid request header: Content-Type must be application/json'); } diff --git a/library/Notifications/Api/OpenApiDescriptionElement/Response/ErrorResponse.php b/library/Notifications/Api/OpenApiDescriptionElement/Response/ErrorResponse.php index e2cf505aa..848106214 100644 --- a/library/Notifications/Api/OpenApiDescriptionElement/Response/ErrorResponse.php +++ b/library/Notifications/Api/OpenApiDescriptionElement/Response/ErrorResponse.php @@ -5,6 +5,7 @@ namespace Icinga\Module\Notifications\Api\OpenApiDescriptionElement\Response; +use InvalidArgumentException; use OpenApi\Attributes as OA; use OpenApi\Attributes\Response; @@ -44,7 +45,7 @@ public function __construct( if (isset(self::ERROR_RESPONSES[$response])) { $description = self::ERROR_RESPONSES[$response]; } else { - throw new \InvalidArgumentException('Unexpected response type'); + throw new InvalidArgumentException('Unexpected response type'); } parent::__construct( diff --git a/library/Notifications/Api/OpenApiDescriptionElement/Response/SuccessResponse.php b/library/Notifications/Api/OpenApiDescriptionElement/Response/SuccessResponse.php index bf7bd09be..8cd58f06d 100644 --- a/library/Notifications/Api/OpenApiDescriptionElement/Response/SuccessResponse.php +++ b/library/Notifications/Api/OpenApiDescriptionElement/Response/SuccessResponse.php @@ -5,6 +5,7 @@ namespace Icinga\Module\Notifications\Api\OpenApiDescriptionElement\Response; +use InvalidArgumentException; use OpenApi\Attributes as OA; use OpenApi\Attributes\Response; @@ -36,7 +37,7 @@ public function __construct( ?array $links = null, ) { if (! isset(self::SUCCESS_RESPONSES[$response])) { - throw new \InvalidArgumentException('Unexpected response type'); + throw new InvalidArgumentException('Unexpected response type'); } $content = $response !== 204 diff --git a/library/Notifications/Model/ExtraTag.php b/library/Notifications/Model/ExtraTag.php index 5375a8d5c..2ff0628a9 100644 --- a/library/Notifications/Model/ExtraTag.php +++ b/library/Notifications/Model/ExtraTag.php @@ -8,6 +8,7 @@ use Icinga\Module\Notifications\Model\Behavior\ObjectTags; use ipl\Orm\Behaviors; use ipl\Sql\Connection; +use LogicException; class ExtraTag extends ObjectExtraTag { @@ -17,7 +18,7 @@ class ExtraTag extends ObjectExtraTag */ public static function on(Connection $_) { - throw new \LogicException('Documentation says: DO NOT USE. Can\'t you read?'); + throw new LogicException('Documentation says: DO NOT USE. Can\'t you read?'); } public function createBehaviors(Behaviors $behaviors): void diff --git a/library/Notifications/Model/Tag.php b/library/Notifications/Model/Tag.php index 08d45dfa0..2c3e78a40 100644 --- a/library/Notifications/Model/Tag.php +++ b/library/Notifications/Model/Tag.php @@ -8,6 +8,7 @@ use Icinga\Module\Notifications\Model\Behavior\ObjectTags; use ipl\Orm\Behaviors; use ipl\Sql\Connection; +use LogicException; class Tag extends ObjectIdTag { @@ -17,7 +18,7 @@ class Tag extends ObjectIdTag */ public static function on(Connection $_) { - throw new \LogicException('Documentation says: DO NOT USE. Can\'t you read?'); + throw new LogicException('Documentation says: DO NOT USE. Can\'t you read?'); } public function createBehaviors(Behaviors $behaviors): void diff --git a/library/Notifications/Web/Control/SearchBar/ObjectSuggestions.php b/library/Notifications/Web/Control/SearchBar/ObjectSuggestions.php index a35c00061..dd9d82bba 100644 --- a/library/Notifications/Web/Control/SearchBar/ObjectSuggestions.php +++ b/library/Notifications/Web/Control/SearchBar/ObjectSuggestions.php @@ -25,6 +25,7 @@ use ipl\Stdlib\Seq; use ipl\Web\Control\SearchBar\SearchException; use ipl\Web\Control\SearchBar\Suggestions; +use LogicException; use PDO; use Traversable; @@ -62,7 +63,7 @@ public function setModel(string|Model $model): self public function getModel(): Model { if ($this->model === null) { - throw new \LogicException( + throw new LogicException( 'You are accessing an unset property. Please make sure to set it beforehand.' ); } diff --git a/library/Notifications/Widget/Calendar/Entry.php b/library/Notifications/Widget/Calendar/Entry.php index 7fe85326f..b5cb4fd56 100644 --- a/library/Notifications/Widget/Calendar/Entry.php +++ b/library/Notifications/Widget/Calendar/Entry.php @@ -6,11 +6,11 @@ namespace Icinga\Module\Notifications\Widget\Calendar; use DateTimeInterface; +use Icinga\Module\Notifications\Widget\TimeGrid; use ipl\Html\Attributes; use ipl\Html\BaseHtmlElement; use ipl\Html\HtmlElement; use ipl\Html\Text; -use Icinga\Module\Notifications\Widget\TimeGrid; use LogicException; /** diff --git a/library/Notifications/Widget/Timeline/EntryFlyout.php b/library/Notifications/Widget/Timeline/EntryFlyout.php index 36122c71b..deb0571e5 100644 --- a/library/Notifications/Widget/Timeline/EntryFlyout.php +++ b/library/Notifications/Widget/Timeline/EntryFlyout.php @@ -7,6 +7,7 @@ use DateTime; use DateTimeZone; +use IntlDateFormatter; use ipl\Html\Attributes; use ipl\Html\BaseHtmlElement; use ipl\Html\FormattedString; @@ -16,6 +17,7 @@ use ipl\Html\ValidHtml; use ipl\I18n\Translation; use ipl\Web\Widget\Icon; +use Locale; class EntryFlyout extends BaseHtmlElement { @@ -343,15 +345,15 @@ protected function generateAndSetRotationInfo(DateTimeZone $scheduleTimezone): s 7 => $this->translate("Sun") ]; - $noneType = \IntlDateFormatter::NONE; - $shortType = \IntlDateFormatter::SHORT; + $noneType = IntlDateFormatter::NONE; + $shortType = IntlDateFormatter::SHORT; $startTime = match ($this->mode) { '24-7' => $this->rotationOptions['at'], 'partial' => $this->rotationOptions['from'], 'multi' => $this->rotationOptions['from_at'] }; - $timeFormatter = new \IntlDateFormatter(\Locale::getDefault(), $noneType, $shortType, $this->displayTimezone); - $dateFormatter = new \IntlDateFormatter(\Locale::getDefault(), $shortType, $noneType, $this->displayTimezone); + $timeFormatter = new IntlDateFormatter(Locale::getDefault(), $noneType, $shortType, $this->displayTimezone); + $dateFormatter = new IntlDateFormatter(Locale::getDefault(), $shortType, $noneType, $this->displayTimezone); $firstHandoffDt = DateTime::createFromFormat( 'Y-m-d H:i', diff --git a/test/php/library/Notifications/Widget/CalendarTest.php b/test/php/library/Notifications/Widget/CalendarTest.php index 7cb987a34..cbc7bbc13 100644 --- a/test/php/library/Notifications/Widget/CalendarTest.php +++ b/test/php/library/Notifications/Widget/CalendarTest.php @@ -5,6 +5,7 @@ namespace Tests\Icinga\Module\Notifications\Widget; +use DateTime; use Icinga\Module\Notifications\Widget\Calendar; use ipl\I18n\NoopTranslator; use ipl\I18n\StaticTranslator; @@ -33,7 +34,7 @@ public function testMonthGridStartsAtTheFirstDayOfItsFirstDaysWeek() $calendar->setControls($controls); $this->assertEquals( - new \DateTime('2023-01-30T00:00:00+0100'), + new DateTime('2023-01-30T00:00:00+0100'), $calendar->getGrid()->getGridStart() ); } finally { @@ -60,7 +61,7 @@ public function testMonthGridVisualizesSixWeeks() $calendar->setControls($controls); $this->assertEquals( - new \DateTime('2023-03-13T00:00:00+0100'), + new DateTime('2023-03-13T00:00:00+0100'), $calendar->getGrid()->getGridEnd() ); } finally { From b88f838ee258cdf049031ab2b97d4b729ac99bfc Mon Sep 17 00:00:00 2001 From: Johannes Rauh Date: Fri, 14 Nov 2025 10:07:15 +0100 Subject: [PATCH 11/26] Fix typos --- doc/api/api-v1-public.json | 154 +++++++++--------- .../OpenApiDescriptionElement/OadV1Put.php | 2 +- .../Response/SuccessDataResponse.php | 2 +- 3 files changed, 79 insertions(+), 79 deletions(-) diff --git a/doc/api/api-v1-public.json b/doc/api/api-v1-public.json index 778ea066e..0361b86a6 100644 --- a/doc/api/api-v1-public.json +++ b/doc/api/api-v1-public.json @@ -144,7 +144,7 @@ "properties": { "data": { "$ref": "#/components/schemas/Channel", - "description": "Successfull response with the Channel object" + "description": "Successful response with the Channel object" } }, "type": "object" @@ -482,7 +482,7 @@ "properties": { "data": { "$ref": "#/components/schemas/Contactgroup", - "description": "Successfull response with the Contactgroup object" + "description": "Successful response with the Contactgroup object" } }, "type": "object" @@ -595,7 +595,7 @@ } }, "links": { - "GetContactgroupByIdentifiere": { + "GetContactgroupByIdentifier": { "operationId": "getContactgroup", "parameters": { "identifier": "$response.header.X-Resource-Identifier" @@ -1290,7 +1290,7 @@ "properties": { "data": { "$ref": "#/components/schemas/Contact", - "description": "Successfull response with the Contact object" + "description": "Successful response with the Contact object" } }, "type": "object" @@ -1403,7 +1403,7 @@ } }, "links": { - "GetContactByIdentifiere": { + "GetContactByIdentifier": { "operationId": "getContact", "parameters": { "identifier": "$response.header.X-Resource-Identifier" @@ -2001,78 +2001,6 @@ } }, "examples": { - "IdentifierMismatch": { - "summary": "Identifier mismatch", - "value": { - "message": "Identifier mismatch" - } - }, - "IdentifierNotFound": { - "summary": "Identifier not found", - "value": { - "message": "Identifier not found" - } - }, - "IdentifierPayloadIdMissmatch": { - "summary": "Identifier and payload Id missmatch", - "value": { - "message": "Identifier mismatch: the Payload id must be different from the URL identifier" - } - }, - "InvalidContentType": { - "summary": "Invalid content type", - "value": { - "message": "Invalid request header: Content-Type must be application/json" - } - }, - "InvalidFilterParameter": { - "summary": "Invalid filter parameter", - "value": { - "message": "Invalid request parameter: Filter column x is not allowed" - } - }, - "InvalidIdentifier": { - "summary": "Identifier is not valid", - "value": { - "message": "The given identifier is not a valid UUID" - } - }, - "InvalidRequestBodyFieldFormat": { - "summary": "Invalid request body field format", - "value": { - "message": "Invalid request body: expects x to be of type y" - } - }, - "InvalidRequestBodyFormat": { - "summary": "Invalid request body format", - "value": { - "message": "Invalid request body: given content is not a valid JSON" - } - }, - "InvalidRequestBodyId": { - "summary": "Invalid request body id", - "value": { - "message": "Invalid request body: given id is not a valid UUID" - } - }, - "MissingRequiredRequestBodyField": { - "summary": "Missing required request body field", - "value": { - "message": "Invalid request body: the field x must be present" - } - }, - "NoIdentifierWithFilter": { - "summary": "No identifier with filter", - "value": { - "message": "Invalid request: GET with identifier and query parameters, it's not allowed to use both together." - } - }, - "UnexpectedQueryParameter": { - "summary": "Unexpected query parameter", - "value": { - "message": "Unexpected query parameter: Filter is only allowed for GET requests" - } - }, "InvalidUserFormat": { "summary": "Invalid user format", "value": { @@ -2150,6 +2078,78 @@ "value": { "message": "Username x already exists" } + }, + "IdentifierMismatch": { + "summary": "Identifier mismatch", + "value": { + "message": "Identifier mismatch" + } + }, + "IdentifierNotFound": { + "summary": "Identifier not found", + "value": { + "message": "Identifier not found" + } + }, + "IdentifierPayloadIdMissmatch": { + "summary": "Identifier and payload Id missmatch", + "value": { + "message": "Identifier mismatch: the Payload id must be different from the URL identifier" + } + }, + "InvalidContentType": { + "summary": "Invalid content type", + "value": { + "message": "Invalid request header: Content-Type must be application/json" + } + }, + "InvalidFilterParameter": { + "summary": "Invalid filter parameter", + "value": { + "message": "Invalid request parameter: Filter column x is not allowed" + } + }, + "InvalidIdentifier": { + "summary": "Identifier is not valid", + "value": { + "message": "The given identifier is not a valid UUID" + } + }, + "InvalidRequestBodyFieldFormat": { + "summary": "Invalid request body field format", + "value": { + "message": "Invalid request body: expects x to be of type y" + } + }, + "InvalidRequestBodyFormat": { + "summary": "Invalid request body format", + "value": { + "message": "Invalid request body: given content is not a valid JSON" + } + }, + "InvalidRequestBodyId": { + "summary": "Invalid request body id", + "value": { + "message": "Invalid request body: given id is not a valid UUID" + } + }, + "MissingRequiredRequestBodyField": { + "summary": "Missing required request body field", + "value": { + "message": "Invalid request body: the field x must be present" + } + }, + "NoIdentifierWithFilter": { + "summary": "No identifier with filter", + "value": { + "message": "Invalid request: GET with identifier and query parameters, it's not allowed to use both together." + } + }, + "UnexpectedQueryParameter": { + "summary": "Unexpected query parameter", + "value": { + "message": "Unexpected query parameter: Filter is only allowed for GET requests" + } } }, "securitySchemes": { diff --git a/library/Notifications/Api/OpenApiDescriptionElement/OadV1Put.php b/library/Notifications/Api/OpenApiDescriptionElement/OadV1Put.php index 7109d8fcd..4afefbc92 100644 --- a/library/Notifications/Api/OpenApiDescriptionElement/OadV1Put.php +++ b/library/Notifications/Api/OpenApiDescriptionElement/OadV1Put.php @@ -72,7 +72,7 @@ public function __construct( ], links: [ new OA\Link( - link: 'Get' . $entityName . 'ByIdentifiere', + link: 'Get' . $entityName . 'ByIdentifier', operationId: 'get' . $entityName, parameters: [ 'identifier' => '$response.header.X-Resource-Identifier' diff --git a/library/Notifications/Api/OpenApiDescriptionElement/Response/SuccessDataResponse.php b/library/Notifications/Api/OpenApiDescriptionElement/Response/SuccessDataResponse.php index 28b7261be..7aa8b8e47 100644 --- a/library/Notifications/Api/OpenApiDescriptionElement/Response/SuccessDataResponse.php +++ b/library/Notifications/Api/OpenApiDescriptionElement/Response/SuccessDataResponse.php @@ -34,7 +34,7 @@ public function __construct( new OA\Property( property: 'data', ref: '#/components/schemas/' . $entityName, - description: sprintf('Successfull response with the %s object', $entityName), + description: sprintf('Successful response with the %s object', $entityName), type: 'object', ), ] From 7952d2fe7c688e4389c0f70750a5c8b36ea92fbb Mon Sep 17 00:00:00 2001 From: Johannes Rauh Date: Fri, 14 Nov 2025 10:12:03 +0100 Subject: [PATCH 12/26] Adjust method docs --- application/controllers/ApiController.php | 1 + application/controllers/EventRuleController.php | 1 + application/forms/RotationConfigForm.php | 2 +- library/Notifications/Api/V1/Channels.php | 2 ++ library/Notifications/Api/V1/ContactGroups.php | 1 + library/Notifications/Hook/ObjectsRendererHook.php | 2 -- library/Notifications/Model/Behavior/IdTagAggregator.php | 4 ++++ library/Notifications/Model/Daemon/Event.php | 1 + library/Notifications/Widget/Timeline/Rotation.php | 2 ++ 9 files changed, 13 insertions(+), 3 deletions(-) diff --git a/application/controllers/ApiController.php b/application/controllers/ApiController.php index 175c437a9..05b7bb311 100644 --- a/application/controllers/ApiController.php +++ b/application/controllers/ApiController.php @@ -24,6 +24,7 @@ class ApiController extends CompatController * Processes API requests for the Notifications module, serving as the main entry point for all API interactions. * * @return never + * * @throws SecurityException */ public function indexAction(): never diff --git a/application/controllers/EventRuleController.php b/application/controllers/EventRuleController.php index 6a8312d13..a2e90f5b3 100644 --- a/application/controllers/EventRuleController.php +++ b/application/controllers/EventRuleController.php @@ -326,6 +326,7 @@ public function editAction(): void * @param int $ruleId * * @return Rule + * * @throws HttpNotFoundException */ private function fetchRule(int $ruleId): Rule diff --git a/application/forms/RotationConfigForm.php b/application/forms/RotationConfigForm.php index 000c95444..692e19ffd 100644 --- a/application/forms/RotationConfigForm.php +++ b/application/forms/RotationConfigForm.php @@ -584,7 +584,7 @@ public function removeRotation(int $id): void /** * Remove all versions of the rotation from the database * - * @param ?int $priority + * @param ?int $priority The priority of the rotations to remove * * @return void * diff --git a/library/Notifications/Api/V1/Channels.php b/library/Notifications/Api/V1/Channels.php index c068d221e..3bf4a9dae 100644 --- a/library/Notifications/Api/V1/Channels.php +++ b/library/Notifications/Api/V1/Channels.php @@ -75,7 +75,9 @@ public function getEndpoint(): string * * @param string|null $identifier * @param string $queryFilter + * * @return ResponseInterface + * * @throws HttpBadRequestException * @throws HttpNotFoundException * @throws JsonEncodeException diff --git a/library/Notifications/Api/V1/ContactGroups.php b/library/Notifications/Api/V1/ContactGroups.php index f91fb9f34..3bbed133e 100644 --- a/library/Notifications/Api/V1/ContactGroups.php +++ b/library/Notifications/Api/V1/ContactGroups.php @@ -621,6 +621,7 @@ private function assertValidRequestBody(array $requestBody): void * @param requestBody $requestBody * * @return void + * * @throws HttpException */ private function addContactgroup(array $requestBody): void diff --git a/library/Notifications/Hook/ObjectsRendererHook.php b/library/Notifications/Hook/ObjectsRendererHook.php index ee79cb3de..0b343900d 100644 --- a/library/Notifications/Hook/ObjectsRendererHook.php +++ b/library/Notifications/Hook/ObjectsRendererHook.php @@ -227,8 +227,6 @@ final public static function getObjectName(Objects $obj): BaseHtmlElement * If the object name is not loaded, it is prepared using object ID tags and the same is returned. * * @param Objects $obj - * @param bool $prepare If true prepares the object name string from the hook implementation if it is not - * already present in the cache * * @return string */ diff --git a/library/Notifications/Model/Behavior/IdTagAggregator.php b/library/Notifications/Model/Behavior/IdTagAggregator.php index 69c7c5c41..c3033dabf 100644 --- a/library/Notifications/Model/Behavior/IdTagAggregator.php +++ b/library/Notifications/Model/Behavior/IdTagAggregator.php @@ -88,6 +88,10 @@ public function fromDb($value, $key, $context): array } /** + * @param mixed $value + * @param mixed $key + * @param mixed $context + * * @return never * * @throws InvalidColumnException diff --git a/library/Notifications/Model/Daemon/Event.php b/library/Notifications/Model/Daemon/Event.php index d3a283de3..4535a28eb 100644 --- a/library/Notifications/Model/Daemon/Event.php +++ b/library/Notifications/Model/Daemon/Event.php @@ -82,6 +82,7 @@ public function setReconnectInterval(int $reconnectInterval): void * {@link https://html.spec.whatwg.org/multipage/server-sent-events.html#parsing-an-event-stream SSE Spec} * * @return string + * * @throws JsonEncodeException */ protected function compileMessage(): string diff --git a/library/Notifications/Widget/Timeline/Rotation.php b/library/Notifications/Widget/Timeline/Rotation.php index 4b71967ae..3cea0677e 100644 --- a/library/Notifications/Widget/Timeline/Rotation.php +++ b/library/Notifications/Widget/Timeline/Rotation.php @@ -78,6 +78,8 @@ public function getPriority(): int /** * Create the base version of the flyout for this rotation * + * @param DateTimeZone $displayTimezone + * * @return EntryFlyout */ public function generateEntryInfo(DateTimeZone $displayTimezone): EntryFlyout From 8993180d821efff99152bad10ef6bd7b0096a4ec Mon Sep 17 00:00:00 2001 From: Johannes Rauh Date: Fri, 14 Nov 2025 10:12:38 +0100 Subject: [PATCH 13/26] Add method param types --- library/Notifications/Widget/Timeline/Entry.php | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/library/Notifications/Widget/Timeline/Entry.php b/library/Notifications/Widget/Timeline/Entry.php index 993eeb86f..12303187c 100644 --- a/library/Notifications/Widget/Timeline/Entry.php +++ b/library/Notifications/Widget/Timeline/Entry.php @@ -132,8 +132,11 @@ public function getWidthClass(): string * * @return $this */ - public function calculateAndSetWidthClass(BaseGrid $grid, $mediumThreshold = 0.2, $narrowThreshold = 0.1): static - { + public function calculateAndSetWidthClass( + BaseGrid $grid, + float $mediumThreshold = 0.2, + float $narrowThreshold = 0.1 + ): static { $totalGridDuration = $grid->getGridEnd()->getTimestamp() - $grid->getGridStart()->getTimestamp(); $start = max($this->getStart()->getTimestamp(), $grid->getGridStart()->getTimestamp()); $end = min($this->getEnd()->getTimestamp(), $grid->getGridEnd()->getTimestamp()); From 1f788bd21c96baac5b5a69e28dca7bdf28ac205f Mon Sep 17 00:00:00 2001 From: Johannes Rauh Date: Fri, 14 Nov 2025 10:13:31 +0100 Subject: [PATCH 14/26] Use nullsafe operator --- application/forms/RotationConfigForm.php | 2 +- library/Notifications/Widget/Calendar.php | 6 +----- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/application/forms/RotationConfigForm.php b/application/forms/RotationConfigForm.php index 692e19ffd..6c60e5c0a 100644 --- a/application/forms/RotationConfigForm.php +++ b/application/forms/RotationConfigForm.php @@ -1201,7 +1201,7 @@ protected function assemble(): void 'type' => 'date', 'required' => true, 'aria-describedby' => 'first-handoff-description', - 'min' => $earliestHandoff !== null ? $earliestHandoff->format('Y-m-d') : null, + 'min' => $earliestHandoff?->format('Y-m-d'), 'max' => $latestHandoff->format('Y-m-d'), 'label' => $this->translate('Rotation Start'), 'value' => $firstHandoffDefault, diff --git a/library/Notifications/Widget/Calendar.php b/library/Notifications/Widget/Calendar.php index 790df5f68..a47681358 100644 --- a/library/Notifications/Widget/Calendar.php +++ b/library/Notifications/Widget/Calendar.php @@ -100,11 +100,7 @@ public function setAddEntryUrl(?Url $url): self public function getStepUrl(GridStep $step): ?Url { - if ($this->addEntryUrl === null) { - return null; - } - - return $this->addEntryUrl->with('start', $step->getStart()->format('Y-m-d\TH:i:s')); + return $this->addEntryUrl?->with('start', $step->getStart()->format('Y-m-d\TH:i:s')); } public function setUrl(?Url $url): self From ccc6227972cc9bac0177bb01a0183db09397829e Mon Sep 17 00:00:00 2001 From: Johannes Rauh Date: Mon, 24 Nov 2025 09:51:19 +0100 Subject: [PATCH 15/26] Fix indentations and spaces --- application/controllers/SourcesController.php | 2 +- application/forms/ContactGroupForm.php | 14 +- .../Notifications/Api/EndpointInterface.php | 1 + .../Middleware/ErrorHandlingMiddleware.php | 4 +- .../Parameter/PathParameter.php | 14 +- .../Parameter/QueryParameter.php | 4 +- .../Response/ErrorResponse.php | 1 - library/Notifications/Api/V1/ApiV1.php | 1 + .../Notifications/Api/V1/ContactGroups.php | 1 + library/Notifications/Api/V1/Contacts.php | 9 +- library/Notifications/Common/Database.php | 5 +- library/Notifications/Model/Rotation.php | 2 +- .../Notifications/Test/BaseApiV1TestCase.php | 28 ++-- .../Notifications/Web/Form/ContactForm.php | 2 +- .../Widget/TimeGrid/BaseGrid.php | 2 +- .../Widget/TimeGrid/ExtraEntryCount.php | 2 +- .../Widget/Timeline/EntryFlyout.php | 2 +- .../controllers/ApiV1ContactGroupsTest.php | 30 ++-- .../controllers/ApiV1ContactsTest.php | 136 +++++++++--------- 19 files changed, 131 insertions(+), 129 deletions(-) diff --git a/application/controllers/SourcesController.php b/application/controllers/SourcesController.php index fe793266c..970a6b6ce 100644 --- a/application/controllers/SourcesController.php +++ b/application/controllers/SourcesController.php @@ -39,7 +39,7 @@ public function indexAction(): void $this->getTabs()->activate('sources'); $sources = Source::on(Database::get()) - ->columns(['id', 'type', 'name']); + ->columns(['id', 'type', 'name']); $limitControl = $this->createLimitControl(); $paginationControl = $this->createPaginationControl($sources); diff --git a/application/forms/ContactGroupForm.php b/application/forms/ContactGroupForm.php index 43796ab7d..919b0849a 100644 --- a/application/forms/ContactGroupForm.php +++ b/application/forms/ContactGroupForm.php @@ -66,10 +66,10 @@ protected function assemble(): void ->on(TermInput::ON_SAVE, $callValidation) ->on(TermInput::ON_PASTE, $callValidation); - // TODO: TermInput is not compatible with the new decorators yet: https://github.com/Icinga/ipl-web/pull/317 - $legacyDecorator = new IcingaFormDecorator(); - $termInput->setDefaultElementDecorator($legacyDecorator); - $legacyDecorator->decorate($termInput); + // TODO: TermInput is not compatible with the new decorators yet: https://github.com/Icinga/ipl-web/pull/317 + $legacyDecorator = new IcingaFormDecorator(); + $termInput->setDefaultElementDecorator($legacyDecorator); + $legacyDecorator->decorate($termInput); $this->addElement( 'text', @@ -364,9 +364,9 @@ public function removeContactgroup(): void $escalationIds = $this->db->fetchCol( RuleEscalationRecipient::on($this->db) - ->columns('rule_escalation_id') - ->filter(Filter::equal('contactgroup_id', $this->contactgroupId)) - ->assembleSelect() + ->columns('rule_escalation_id') + ->filter(Filter::equal('contactgroup_id', $this->contactgroupId)) + ->assembleSelect() ); $this->db->update('rule_escalation_recipient', $markAsDeleted, $updateCondition); diff --git a/library/Notifications/Api/EndpointInterface.php b/library/Notifications/Api/EndpointInterface.php index 6f7a57d97..a558a5c82 100644 --- a/library/Notifications/Api/EndpointInterface.php +++ b/library/Notifications/Api/EndpointInterface.php @@ -8,5 +8,6 @@ interface EndpointInterface { public function getEndpoint(): string; + public function getAllowedMethods(): array; } diff --git a/library/Notifications/Api/Middleware/ErrorHandlingMiddleware.php b/library/Notifications/Api/Middleware/ErrorHandlingMiddleware.php index a53d91edf..49d6e38d2 100644 --- a/library/Notifications/Api/Middleware/ErrorHandlingMiddleware.php +++ b/library/Notifications/Api/Middleware/ErrorHandlingMiddleware.php @@ -37,9 +37,7 @@ public function process(ServerRequestInterface $request, RequestHandlerInterface return new Response( 400, ['Content-Type' => 'application/json'], - Json::sanitize([ - 'message' => $e->getMessage() - ]) + Json::sanitize(['message' => $e->getMessage()]) ); } catch (Throwable $e) { Logger::error($e); diff --git a/library/Notifications/Api/OpenApiDescriptionElement/Parameter/PathParameter.php b/library/Notifications/Api/OpenApiDescriptionElement/Parameter/PathParameter.php index a7e7434b0..b6d8d872d 100644 --- a/library/Notifications/Api/OpenApiDescriptionElement/Parameter/PathParameter.php +++ b/library/Notifications/Api/OpenApiDescriptionElement/Parameter/PathParameter.php @@ -22,16 +22,16 @@ public function __construct( ?string $example = null, ) { $schema = $identifierSchema !== null - ? new OA\Schema(ref: '#/components/schemas/' . $identifierSchema) - : ($schema !== null ? $schema : new OA\Schema(type: 'string')); + ? new OA\Schema(ref: '#/components/schemas/' . $identifierSchema) + : ($schema !== null ? $schema : new OA\Schema(type: 'string')); $params = [ 'parameter' => $parameter ?? Generator::UNDEFINED, - 'name' => $name ?? Generator::UNDEFINED, - 'description' => $description ?? Generator::UNDEFINED, - 'in' => 'path', - 'required' => $required ?? true, - 'schema' => $schema, + 'name' => $name ?? Generator::UNDEFINED, + 'description' => $description ?? Generator::UNDEFINED, + 'in' => 'path', + 'required' => $required ?? true, + 'schema' => $schema, ]; $params = $example !== null ? array_merge($params, ['example' => $example]) : $params; diff --git a/library/Notifications/Api/OpenApiDescriptionElement/Parameter/QueryParameter.php b/library/Notifications/Api/OpenApiDescriptionElement/Parameter/QueryParameter.php index 0ef4e9042..01c895b9b 100644 --- a/library/Notifications/Api/OpenApiDescriptionElement/Parameter/QueryParameter.php +++ b/library/Notifications/Api/OpenApiDescriptionElement/Parameter/QueryParameter.php @@ -33,8 +33,8 @@ public function __construct( 'schema' => $schema, ]; - $params = $example !== null ? array_merge($params, ['example' => $example]) : $params; + $params = $example !== null ? array_merge($params, ['example' => $example]) : $params; - parent::__construct(...$params); + parent::__construct(...$params); } } diff --git a/library/Notifications/Api/OpenApiDescriptionElement/Response/ErrorResponse.php b/library/Notifications/Api/OpenApiDescriptionElement/Response/ErrorResponse.php index 848106214..d7a1b33ea 100644 --- a/library/Notifications/Api/OpenApiDescriptionElement/Response/ErrorResponse.php +++ b/library/Notifications/Api/OpenApiDescriptionElement/Response/ErrorResponse.php @@ -21,7 +21,6 @@ ], type: 'object', )] - class ErrorResponse extends Response { public const ERROR_RESPONSES = [ diff --git a/library/Notifications/Api/V1/ApiV1.php b/library/Notifications/Api/V1/ApiV1.php index bcbe87339..8730546b3 100644 --- a/library/Notifications/Api/V1/ApiV1.php +++ b/library/Notifications/Api/V1/ApiV1.php @@ -93,6 +93,7 @@ public function handleRequest(ServerRequestInterface $request): ResponseInterfac * Override this method to modify the row before it is returned in the response. * * @param stdClass $row + * * @return void */ public function prepareRow(stdClass $row): void diff --git a/library/Notifications/Api/V1/ContactGroups.php b/library/Notifications/Api/V1/ContactGroups.php index 3bbed133e..23c339ee6 100644 --- a/library/Notifications/Api/V1/ContactGroups.php +++ b/library/Notifications/Api/V1/ContactGroups.php @@ -787,6 +787,7 @@ private function assertUniqueName(string $name, ?int $contactgroupId = null): vo * Fetch the values from the database * * @param int $contactgroupId + * * @return array * * @throws HttpNotFoundException diff --git a/library/Notifications/Api/V1/Contacts.php b/library/Notifications/Api/V1/Contacts.php index ec8f0f8e2..775bfbe45 100644 --- a/library/Notifications/Api/V1/Contacts.php +++ b/library/Notifications/Api/V1/Contacts.php @@ -510,10 +510,10 @@ public function delete(string $identifier): ResponseInterface public function prepareRow(stdClass $row): void { - $row->groups = ContactGroups::fetchGroupIdentifiers($row->contact_id); - $row->addresses = self::fetchContactAddresses($row->contact_id) ?: new stdClass(); + $row->groups = ContactGroups::fetchGroupIdentifiers($row->contact_id); + $row->addresses = self::fetchContactAddresses($row->contact_id) ?: new stdClass(); - unset($row->contact_id); + unset($row->contact_id); } /** @@ -577,6 +577,7 @@ public static function getContactId(string $identifier): ?int * @param string[] $groups * * @return void + * * @throws HttpException */ private function addGroups(int $contactId, array $groups): void @@ -625,6 +626,7 @@ private function addAddresses(int $contactId, array $addresses): void * @param requestBody $requestBody * * @return void + * * @throws HttpException */ private function addContact(array $requestBody): void @@ -1000,6 +1002,7 @@ public static function fetchUserIdentifiers(int $contactgroupId): array * Fetch the values from the database * * @param int $contactId + * * @return array * * @throws HttpNotFoundException diff --git a/library/Notifications/Common/Database.php b/library/Notifications/Common/Database.php index 67ba65d86..e1ea1ed62 100644 --- a/library/Notifications/Common/Database.php +++ b/library/Notifications/Common/Database.php @@ -277,9 +277,8 @@ private static function hasCondition(string $baseTable, string $conditionToFind, if (is_array($value)) { $found = self::hasCondition($baseTable, $conditionToFind, $value); } else { - $found = ( - $condition === $conditionToFind || $condition === $baseTable . '.' . $conditionToFind - ) && $value === 'y'; + $found = ($condition === $conditionToFind || $condition === $baseTable . '.' . $conditionToFind) + && $value === 'y'; } if ($found) { diff --git a/library/Notifications/Model/Rotation.php b/library/Notifications/Model/Rotation.php index 319c955be..f0e95fa27 100644 --- a/library/Notifications/Model/Rotation.php +++ b/library/Notifications/Model/Rotation.php @@ -128,7 +128,7 @@ public function delete(): void $changedAt = (int) (new DateTime())->format("Uv"); $markAsDeleted = ['changed_at' => $changedAt, 'deleted' => 'y']; - $db->update('timeperiod_entry', $markAsDeleted, ['timeperiod_id = ?' => $timeperiodId, 'deleted = ?' => 'n']); + $db->update('timeperiod_entry', $markAsDeleted, ['timeperiod_id = ?' => $timeperiodId, 'deleted = ?' => 'n']); $db->update('timeperiod', $markAsDeleted, ['id = ?' => $timeperiodId]); $db->update( diff --git a/library/Notifications/Test/BaseApiV1TestCase.php b/library/Notifications/Test/BaseApiV1TestCase.php index d8b5070e9..f56f0c8e0 100644 --- a/library/Notifications/Test/BaseApiV1TestCase.php +++ b/library/Notifications/Test/BaseApiV1TestCase.php @@ -37,18 +37,18 @@ class BaseApiV1TestCase extends TestCase protected static function initializeNotificationsDb(Connection $db, string $driver): void { $db->insert('available_channel_type', [ - 'type' => 'email', - 'name' => 'Email', - 'version' => 1, - 'author' => 'Test', - 'config_attrs' => '' - ]); + 'type' => 'email', + 'name' => 'Email', + 'version' => 1, + 'author' => 'Test', + 'config_attrs' => '' + ]); $db->insert('available_channel_type', [ - 'type' => 'webhook', - 'name' => 'Webhook', - 'version' => 1, - 'author' => 'Test', - 'config_attrs' => '' + 'type' => 'webhook', + 'name' => 'Webhook', + 'version' => 1, + 'author' => 'Test', + 'config_attrs' => '' ]); $db->insert('available_channel_type', [ 'type' => 'rocketchat', @@ -120,9 +120,9 @@ protected static function createContacts(Connection $db): void $contactIds = $db->select( (new Select()) - ->from('contact') - ->columns('id') - ->where(['external_uuid IN (?)' => [self::CONTACT_UUID, self::CONTACT_UUID_2]]) + ->from('contact') + ->columns('id') + ->where(['external_uuid IN (?)' => [self::CONTACT_UUID, self::CONTACT_UUID_2]]) )->fetchAll(\PDO::FETCH_COLUMN); foreach ($contactIds as $contactId) { diff --git a/library/Notifications/Web/Form/ContactForm.php b/library/Notifications/Web/Form/ContactForm.php index 7b67a3431..5dd73078d 100644 --- a/library/Notifications/Web/Form/ContactForm.php +++ b/library/Notifications/Web/Form/ContactForm.php @@ -40,7 +40,7 @@ class ContactForm extends CompatForm /** @var Connection */ private Connection $db; - /** @var ?string Contact ID*/ + /** @var ?string Contact ID */ private ?string $contactId = null; public function __construct(Connection $db) diff --git a/library/Notifications/Widget/TimeGrid/BaseGrid.php b/library/Notifications/Widget/TimeGrid/BaseGrid.php index 596adc42c..28c62ca36 100644 --- a/library/Notifications/Widget/TimeGrid/BaseGrid.php +++ b/library/Notifications/Widget/TimeGrid/BaseGrid.php @@ -56,7 +56,7 @@ abstract class BaseGrid extends BaseHtmlElement /** @var ?DateTime */ protected ?DateTime $end = null; - /** @var array Extra counts stored as [date1 => count1, date2 => count2]*/ + /** @var array Extra counts stored as [date1 => count1, date2 => count2] */ protected array $extraEntriesCount = []; /** diff --git a/library/Notifications/Widget/TimeGrid/ExtraEntryCount.php b/library/Notifications/Widget/TimeGrid/ExtraEntryCount.php index a91417392..29532815e 100644 --- a/library/Notifications/Widget/TimeGrid/ExtraEntryCount.php +++ b/library/Notifications/Widget/TimeGrid/ExtraEntryCount.php @@ -14,7 +14,7 @@ class ExtraEntryCount extends ButtonLink { use Translation; - /** @var ?BaseGrid Grid this extra count is tied to*/ + /** @var ?BaseGrid Grid this extra count is tied to */ protected ?BaseGrid $grid = null; /** @var ?DateTime Grid step for which the extra count is being registered */ diff --git a/library/Notifications/Widget/Timeline/EntryFlyout.php b/library/Notifications/Widget/Timeline/EntryFlyout.php index deb0571e5..879dde2d7 100644 --- a/library/Notifications/Widget/Timeline/EntryFlyout.php +++ b/library/Notifications/Widget/Timeline/EntryFlyout.php @@ -26,7 +26,7 @@ class EntryFlyout extends BaseHtmlElement /** @var ?Member Member who is on duty during the entry's timespan */ protected ?Member $activeMember = null; - /** @var ?string Mode of the entry's rotation can be "partial", "multi" or "24-7"*/ + /** @var ?string Mode of the entry's rotation can be "partial", "multi" or "24-7" */ protected ?string $mode = null; /** @var ?array All members of the entry's rotation */ diff --git a/test/php/application/controllers/ApiV1ContactGroupsTest.php b/test/php/application/controllers/ApiV1ContactGroupsTest.php index 2fa92ad7f..b2bed7c09 100644 --- a/test/php/application/controllers/ApiV1ContactGroupsTest.php +++ b/test/php/application/controllers/ApiV1ContactGroupsTest.php @@ -366,7 +366,7 @@ public function testPostToReplaceWithMissingRequiredFields( 'POST', $endpoint, 'v1/contact-groups/' . BaseApiV1TestCase::GROUP_UUID, - json: [ + json: [ 'id' => BaseApiV1TestCase::GROUP_UUID_3, 'users' => [] ] @@ -409,7 +409,7 @@ public function testPostToReplaceWithInvalidFieldsFormat( 'POST', $endpoint, 'v1/contact-groups/' . BaseApiV1TestCase::GROUP_UUID, - json: [ + json: [ 'id' => BaseApiV1TestCase::GROUP_UUID_3, 'name' => ['Test'], 'users' => [] @@ -492,7 +492,7 @@ public function testPostToCreateWithMissingRequiredFields(Connection $db, Url $e 'POST', $endpoint, 'v1/contact-groups', - json:[ + json: [ 'id' => BaseApiV1TestCase::GROUP_UUID_3, 'users' => [] ] @@ -553,7 +553,7 @@ public function testPostToCreateWithInvalidFieldsFormat( 'POST', $endpoint, 'v1/contact-groups/', - json: [ + json: [ 'id' => BaseApiV1TestCase::GROUP_UUID_3, 'name' => ['Test'], 'users' => [] @@ -690,7 +690,7 @@ public function testPutToUpdateWithFilter(Connection $db, Url $endpoint): void 'PUT', $endpoint, 'v1/contact-groups?id=' . BaseApiV1TestCase::GROUP_UUID, - json: [ + json: [ 'id' => BaseApiV1TestCase::GROUP_UUID, 'name' => 'Test', 'users' => [] @@ -755,7 +755,7 @@ public function testPutToUpdateWithMissingRequiredFields( 'PUT', $endpoint, 'v1/contact-groups/' . BaseApiV1TestCase::GROUP_UUID, - json: [ + json: [ 'id' => BaseApiV1TestCase::GROUP_UUID, 'users' => [] ] @@ -798,7 +798,7 @@ public function testPutToUpdateWithInvalidFieldsFormat( 'PUT', $endpoint, 'v1/contact-groups/' . BaseApiV1TestCase::GROUP_UUID, - json: [ + json: [ 'id' => BaseApiV1TestCase::GROUP_UUID, 'name' => ['Test'], 'users' => [] @@ -842,7 +842,7 @@ public function testPutToUpdateWithDifferentPayloadId( 'PUT', $endpoint, 'v1/contact-groups/' . BaseApiV1TestCase::GROUP_UUID, - json: [ + json: [ 'id' => BaseApiV1TestCase::GROUP_UUID_2, 'name' => 'Test', 'users' => [] @@ -861,7 +861,7 @@ public function testPutToCreateWithValidData(Connection $db, Url $endpoint): voi 'PUT', $endpoint, 'v1/contact-groups/' . BaseApiV1TestCase::GROUP_UUID_3, - json: [ + json: [ 'id' => BaseApiV1TestCase::GROUP_UUID_3, 'name' => 'Test' ] @@ -901,7 +901,7 @@ public function testPutToUpdateWithValidData(Connection $db, Url $endpoint): voi 'PUT', $endpoint, 'v1/contact-groups/' . BaseApiV1TestCase::GROUP_UUID, - json: [ + json: [ 'id' => BaseApiV1TestCase::GROUP_UUID, 'name' => 'Test (replaced)', 'users' => [] @@ -936,7 +936,7 @@ public function testPutToUpdateWithInvalidData(Connection $db, Url $endpoint): v 'PUT', $endpoint, 'v1/contact-groups/' . BaseApiV1TestCase::GROUP_UUID, - json: [ + json: [ 'id' => BaseApiV1TestCase::GROUP_UUID, 'name' => 'Test', 'users' => [BaseApiV1TestCase::CONTACT_UUID_3] @@ -958,7 +958,7 @@ public function testPutToCreateWithValidOptionalData(Connection $db, Url $endpoi 'PUT', $endpoint, 'v1/contact-groups/' . BaseApiV1TestCase::GROUP_UUID_3, - json: [ + json: [ 'id' => BaseApiV1TestCase::GROUP_UUID_3, 'name' => 'Test', 'users' => [BaseApiV1TestCase::CONTACT_UUID] @@ -1000,7 +1000,7 @@ public function testPutToCreateWithMissingRequiredFields(Connection $db, Url $en 'PUT', $endpoint, 'v1/contact-groups/' . BaseApiV1TestCase::GROUP_UUID_3, - json: [ + json: [ 'id' => BaseApiV1TestCase::GROUP_UUID_3, 'users' => [] ] @@ -1018,7 +1018,7 @@ public function testPutToCreateWithMissingRequiredFields(Connection $db, Url $en 'PUT', $endpoint, 'v1/contact-groups/' . BaseApiV1TestCase::GROUP_UUID_3, - json: [ + json: [ 'name' => 'Test', 'users' => [] ] @@ -1061,7 +1061,7 @@ public function testPutToCreateWithInvalidFieldsFormat( 'PUT', $endpoint, 'v1/contact-groups/' . BaseApiV1TestCase::GROUP_UUID_3, - json: [ + json: [ 'id' => BaseApiV1TestCase::GROUP_UUID_3, 'name' => ['Test'], 'users' => [] diff --git a/test/php/application/controllers/ApiV1ContactsTest.php b/test/php/application/controllers/ApiV1ContactsTest.php index ffb352f67..a21ef177b 100644 --- a/test/php/application/controllers/ApiV1ContactsTest.php +++ b/test/php/application/controllers/ApiV1ContactsTest.php @@ -240,7 +240,7 @@ public function testPostToReplaceWithUnknownIdentifier(Connection $db, Url $endp 'POST', $endpoint, 'v1/contacts/' . BaseApiV1TestCase::CONTACT_UUID_3, - json: [ + json: [ 'id' => BaseApiV1TestCase::CONTACT_UUID_4, 'full_name' => 'Test', 'default_channel' => BaseApiV1TestCase::CHANNEL_UUID, @@ -262,7 +262,7 @@ public function testPostToReplaceWithIndifferentPayloadId( 'POST', $endpoint, 'v1/contacts/' . BaseApiV1TestCase::CONTACT_UUID, - json: [ + json: [ 'id' => BaseApiV1TestCase::CONTACT_UUID, 'full_name' => 'Test', 'default_channel' => BaseApiV1TestCase::CHANNEL_UUID, @@ -287,7 +287,7 @@ public function testPostToReplaceWithAlreadyExistingPayloadId( 'POST', $endpoint, 'v1/contacts/' . BaseApiV1TestCase::CONTACT_UUID, - json: [ + json: [ 'id' => BaseApiV1TestCase::CONTACT_UUID_2, 'full_name' => 'Test', 'default_channel' => BaseApiV1TestCase::CHANNEL_UUID, @@ -307,7 +307,7 @@ public function testPostToReplaceWithValidData(Connection $db, Url $endpoint): v 'POST', $endpoint, 'v1/contacts/' . BaseApiV1TestCase::CONTACT_UUID, - json: [ + json: [ 'id' => BaseApiV1TestCase::CONTACT_UUID_3, 'full_name' => 'Test (replaced)', 'default_channel' => BaseApiV1TestCase::CHANNEL_UUID, @@ -352,7 +352,7 @@ public function testPostToCreateWithExistingPayloadId(Connection $db, Url $endpo 'POST', $endpoint, 'v1/contacts', - json: [ + json: [ 'id' => BaseApiV1TestCase::CONTACT_UUID, 'full_name' => 'Test', 'default_channel' => BaseApiV1TestCase::CHANNEL_UUID, @@ -372,7 +372,7 @@ public function testPostToCreateWithValidData(Connection $db, Url $endpoint): vo 'POST', $endpoint, 'v1/contacts', - json: [ + json: [ 'id' => BaseApiV1TestCase::CONTACT_UUID_3, 'full_name' => 'Test', 'default_channel' => BaseApiV1TestCase::CHANNEL_UUID, @@ -420,7 +420,7 @@ public function testPostToReplaceWithMissingRequiredFields( 'POST', $endpoint, 'v1/contacts/' . BaseApiV1TestCase::CONTACT_UUID, - json: [ + json: [ 'full_name' => 'Test', 'default_channel' => BaseApiV1TestCase::CHANNEL_UUID, 'addresses' => ['email' => 'test@example.com'] @@ -439,7 +439,7 @@ public function testPostToReplaceWithMissingRequiredFields( 'POST', $endpoint, 'v1/contacts/' . BaseApiV1TestCase::CONTACT_UUID, - json: [ + json: [ 'id' => BaseApiV1TestCase::CONTACT_UUID_3, 'default_channel' => BaseApiV1TestCase::CHANNEL_UUID, 'addresses' => ['email' => 'test@example.com'] @@ -458,7 +458,7 @@ public function testPostToReplaceWithMissingRequiredFields( 'POST', $endpoint, 'v1/contacts/' . BaseApiV1TestCase::CONTACT_UUID, - json: [ + json: [ 'id' => BaseApiV1TestCase::CONTACT_UUID_3, 'full_name' => 'Test', 'addresses' => ['email' => 'test@example.com'] @@ -477,7 +477,7 @@ public function testPostToReplaceWithMissingRequiredFields( 'POST', $endpoint, 'v1/contacts/' . BaseApiV1TestCase::CONTACT_UUID, - json: [ + json: [ 'id' => BaseApiV1TestCase::CONTACT_UUID_3, 'full_name' => 'Test', 'default_channel' => BaseApiV1TestCase::CHANNEL_UUID, @@ -504,7 +504,7 @@ public function testPostToReplaceWithInvalidFieldFormat( 'POST', $endpoint, 'v1/contacts/' . BaseApiV1TestCase::CONTACT_UUID, - json: [ + json: [ 'id' => [BaseApiV1TestCase::CONTACT_UUID_3], 'full_name' => 'Test', 'default_channel' => BaseApiV1TestCase::CHANNEL_UUID, @@ -524,7 +524,7 @@ public function testPostToReplaceWithInvalidFieldFormat( 'POST', $endpoint, 'v1/contacts/' . BaseApiV1TestCase::CONTACT_UUID, - json: [ + json: [ 'id' => BaseApiV1TestCase::CONTACT_UUID_3, 'full_name' => ['Test'], 'default_channel' => BaseApiV1TestCase::CHANNEL_UUID, @@ -544,7 +544,7 @@ public function testPostToReplaceWithInvalidFieldFormat( 'POST', $endpoint, 'v1/contacts/' . BaseApiV1TestCase::CONTACT_UUID, - json: [ + json: [ 'id' => BaseApiV1TestCase::CONTACT_UUID_3, 'full_name' => 'Test', 'default_channel' => [BaseApiV1TestCase::CHANNEL_UUID], @@ -564,7 +564,7 @@ public function testPostToReplaceWithInvalidFieldFormat( 'POST', $endpoint, 'v1/contacts/' . BaseApiV1TestCase::CONTACT_UUID, - json: [ + json: [ 'id' => BaseApiV1TestCase::CONTACT_UUID_3, 'full_name' => 'Test', 'default_channel' => BaseApiV1TestCase::CHANNEL_UUID, @@ -586,7 +586,7 @@ public function testPostToReplaceWithInvalidFieldFormat( 'POST', $endpoint, 'v1/contacts/' . BaseApiV1TestCase::CONTACT_UUID, - json: [ + json: [ 'id' => BaseApiV1TestCase::CONTACT_UUID_3, 'full_name' => 'Test', 'default_channel' => BaseApiV1TestCase::CHANNEL_UUID, @@ -607,7 +607,7 @@ public function testPostToReplaceWithInvalidFieldFormat( 'POST', $endpoint, 'v1/contacts/' . BaseApiV1TestCase::CONTACT_UUID, - json: [ + json: [ 'id' => BaseApiV1TestCase::CONTACT_UUID_3, 'full_name' => 'Test', 'default_channel' => BaseApiV1TestCase::CHANNEL_UUID, @@ -631,7 +631,7 @@ public function testPostToCreateWithValidOptionalData(Connection $db, Url $endpo 'POST', $endpoint, 'v1/contacts', - json: [ + json: [ 'id' => BaseApiV1TestCase::CONTACT_UUID_3, 'full_name' => 'Test3', 'username' => 'test3', @@ -686,7 +686,7 @@ public function testPostToCreateWithWebhookAsDefaultChannel(Connection $db, Url 'POST', $endpoint, 'v1/contacts', - json: [ + json: [ 'id' => BaseApiV1TestCase::CONTACT_UUID_3, 'full_name' => 'Test3', 'default_channel' => BaseApiV1TestCase::CHANNEL_UUID_2 @@ -713,7 +713,7 @@ public function testPostToCreateWithInvalidDefaultChannel(Connection $db, Url $e 'POST', $endpoint, 'v1/contacts', - json: [ + json: [ 'id' => BaseApiV1TestCase::CONTACT_UUID_3, 'full_name' => 'Test', 'default_channel' => 'invalid_uuid', @@ -737,7 +737,7 @@ public function testPostToCreateWithMissingRequiredFields(Connection $db, Url $e 'POST', $endpoint, 'v1/contacts', - json: [ + json: [ 'full_name' => 'Test', 'default_channel' => BaseApiV1TestCase::CHANNEL_UUID, 'addresses' => ['email' => 'test@example.com'] @@ -756,7 +756,7 @@ public function testPostToCreateWithMissingRequiredFields(Connection $db, Url $e 'POST', $endpoint, 'v1/contacts', - json: [ + json: [ 'id' => BaseApiV1TestCase::CONTACT_UUID_3, 'default_channel' => BaseApiV1TestCase::CHANNEL_UUID, 'addresses' => ['email' => 'test@example.com'] @@ -775,7 +775,7 @@ public function testPostToCreateWithMissingRequiredFields(Connection $db, Url $e 'POST', $endpoint, 'v1/contacts', - json: [ + json: [ 'id' => BaseApiV1TestCase::CONTACT_UUID_3, 'full_name' => 'Test', 'addresses' => ['email' => 'test@example.com'] @@ -794,7 +794,7 @@ public function testPostToCreateWithMissingRequiredFields(Connection $db, Url $e 'POST', $endpoint, 'v1/contacts', - json: [ + json: [ 'id' => BaseApiV1TestCase::CONTACT_UUID_3, 'full_name' => 'Test', 'default_channel' => BaseApiV1TestCase::CHANNEL_UUID, @@ -820,7 +820,7 @@ public function testPostToCreateWithInvalidFieldFormat( 'POST', $endpoint, 'v1/contacts/', - json: [ + json: [ 'id' => [BaseApiV1TestCase::CONTACT_UUID_3], 'full_name' => 'Test', 'default_channel' => BaseApiV1TestCase::CHANNEL_UUID, @@ -840,7 +840,7 @@ public function testPostToCreateWithInvalidFieldFormat( 'POST', $endpoint, 'v1/contacts/', - json: [ + json: [ 'id' => BaseApiV1TestCase::CONTACT_UUID_3, 'full_name' => ['Test'], 'default_channel' => BaseApiV1TestCase::CHANNEL_UUID, @@ -860,7 +860,7 @@ public function testPostToCreateWithInvalidFieldFormat( 'POST', $endpoint, 'v1/contacts/', - json: [ + json: [ 'id' => BaseApiV1TestCase::CONTACT_UUID_3, 'full_name' => 'Test', 'default_channel' => [BaseApiV1TestCase::CHANNEL_UUID], @@ -880,7 +880,7 @@ public function testPostToCreateWithInvalidFieldFormat( 'POST', $endpoint, 'v1/contacts/', - json: [ + json: [ 'id' => BaseApiV1TestCase::CONTACT_UUID_3, 'full_name' => 'Test', 'default_channel' => BaseApiV1TestCase::CHANNEL_UUID, @@ -902,7 +902,7 @@ public function testPostToCreateWithInvalidFieldFormat( 'POST', $endpoint, 'v1/contacts/', - json: [ + json: [ 'id' => BaseApiV1TestCase::CONTACT_UUID_3, 'full_name' => 'Test', 'default_channel' => BaseApiV1TestCase::CHANNEL_UUID, @@ -923,7 +923,7 @@ public function testPostToCreateWithInvalidFieldFormat( 'POST', $endpoint, 'v1/contacts/', - json: [ + json: [ 'id' => BaseApiV1TestCase::CONTACT_UUID_3, 'full_name' => 'Test', 'default_channel' => BaseApiV1TestCase::CHANNEL_UUID, @@ -948,7 +948,7 @@ public function testPostToCreateWithInvalidAddresses(Connection $db, Url $endpoi 'POST', $endpoint, 'v1/contacts', - json: [ + json: [ 'id' => BaseApiV1TestCase::CONTACT_UUID_3, 'full_name' => 'Test', 'default_channel' => BaseApiV1TestCase::CHANNEL_UUID, @@ -971,7 +971,7 @@ public function testPostToCreateWithInvalidAddresses(Connection $db, Url $endpoi 'POST', $endpoint, 'v1/contacts', - json: [ + json: [ 'id' => BaseApiV1TestCase::CONTACT_UUID_3, 'full_name' => 'Test', 'default_channel' => BaseApiV1TestCase::CHANNEL_UUID, @@ -993,7 +993,7 @@ public function testPostToCreateWithInvalidAddresses(Connection $db, Url $endpoi 'POST', $endpoint, 'v1/contacts', - json: [ + json: [ 'id' => BaseApiV1TestCase::CONTACT_UUID_3, 'full_name' => 'Test', 'default_channel' => BaseApiV1TestCase::CHANNEL_UUID, @@ -1020,7 +1020,7 @@ public function testPostToCreateWithInvalidOptionalData(Connection $db, Url $end 'POST', $endpoint, 'v1/contacts', - json: [ + json: [ 'id' => BaseApiV1TestCase::CONTACT_UUID_3, 'full_name' => 'Test', 'username' => 'test', @@ -1038,7 +1038,7 @@ public function testPostToCreateWithInvalidOptionalData(Connection $db, Url $end 'POST', $endpoint, 'v1/contacts', - json: [ + json: [ 'id' => BaseApiV1TestCase::CONTACT_UUID_3, 'full_name' => 'Test', 'default_channel' => BaseApiV1TestCase::CHANNEL_UUID, @@ -1061,7 +1061,7 @@ public function testPostToCreateWithInvalidOptionalData(Connection $db, Url $end 'POST', $endpoint, 'v1/contacts', - json: [ + json: [ 'id' => BaseApiV1TestCase::CONTACT_UUID_3, 'full_name' => 'Test', 'default_channel' => BaseApiV1TestCase::CHANNEL_UUID, @@ -1161,7 +1161,7 @@ public function testPutToUpdateWithoutIdentifier(Connection $db, Url $endpoint): 'PUT', $endpoint, 'v1/contacts', - json: [ + json: [ 'id' => BaseApiV1TestCase::CONTACT_UUID_3, 'full_name' => 'Test', 'default_channel' => BaseApiV1TestCase::CHANNEL_UUID, @@ -1187,7 +1187,7 @@ public function testPutToUpdateWithMissingRequiredFields( 'PUT', $endpoint, 'v1/contacts/' . BaseApiV1TestCase::CONTACT_UUID, - json: [ + json: [ 'full_name' => 'Test', 'default_channel' => BaseApiV1TestCase::CHANNEL_UUID, ] @@ -1205,7 +1205,7 @@ public function testPutToUpdateWithMissingRequiredFields( 'PUT', $endpoint, 'v1/contacts/' . BaseApiV1TestCase::CONTACT_UUID, - json: [ + json: [ 'id' => BaseApiV1TestCase::CONTACT_UUID, 'default_channel' => BaseApiV1TestCase::CHANNEL_UUID, ] @@ -1223,7 +1223,7 @@ public function testPutToUpdateWithMissingRequiredFields( 'PUT', $endpoint, 'v1/contacts/' . BaseApiV1TestCase::CONTACT_UUID, - json: [ + json: [ 'id' => BaseApiV1TestCase::CONTACT_UUID, 'full_name' => 'Test', ] @@ -1241,7 +1241,7 @@ public function testPutToUpdateWithMissingRequiredFields( 'PUT', $endpoint, 'v1/contacts/' . BaseApiV1TestCase::CONTACT_UUID, - json: [ + json: [ 'id' => BaseApiV1TestCase::CONTACT_UUID, 'full_name' => 'Test', 'default_channel' => BaseApiV1TestCase::CHANNEL_UUID, @@ -1268,7 +1268,7 @@ public function testPutToUpdateWithInvalidFieldFormat( 'PUT', $endpoint, 'v1/contacts/' . BaseApiV1TestCase::CONTACT_UUID, - json: [ + json: [ 'id' => [BaseApiV1TestCase::CONTACT_UUID], 'full_name' => 'Test', 'default_channel' => BaseApiV1TestCase::CHANNEL_UUID, @@ -1288,7 +1288,7 @@ public function testPutToUpdateWithInvalidFieldFormat( 'PUT', $endpoint, 'v1/contacts/' . BaseApiV1TestCase::CONTACT_UUID, - json: [ + json: [ 'id' => BaseApiV1TestCase::CONTACT_UUID, 'full_name' => ['Test'], 'default_channel' => BaseApiV1TestCase::CHANNEL_UUID, @@ -1308,7 +1308,7 @@ public function testPutToUpdateWithInvalidFieldFormat( 'PUT', $endpoint, 'v1/contacts/' . BaseApiV1TestCase::CONTACT_UUID, - json: [ + json: [ 'id' => BaseApiV1TestCase::CONTACT_UUID, 'full_name' => 'Test', 'default_channel' => [BaseApiV1TestCase::CHANNEL_UUID], @@ -1328,7 +1328,7 @@ public function testPutToUpdateWithInvalidFieldFormat( 'PUT', $endpoint, 'v1/contacts/' . BaseApiV1TestCase::CONTACT_UUID, - json: [ + json: [ 'id' => BaseApiV1TestCase::CONTACT_UUID, 'full_name' => 'Test', 'default_channel' => BaseApiV1TestCase::CHANNEL_UUID, @@ -1350,7 +1350,7 @@ public function testPutToUpdateWithInvalidFieldFormat( 'PUT', $endpoint, 'v1/contacts/' . BaseApiV1TestCase::CONTACT_UUID, - json: [ + json: [ 'id' => BaseApiV1TestCase::CONTACT_UUID, 'full_name' => 'Test', 'default_channel' => BaseApiV1TestCase::CHANNEL_UUID, @@ -1371,7 +1371,7 @@ public function testPutToUpdateWithInvalidFieldFormat( 'PUT', $endpoint, 'v1/contacts/' . BaseApiV1TestCase::CONTACT_UUID, - json: [ + json: [ 'id' => BaseApiV1TestCase::CONTACT_UUID, 'full_name' => 'Test', 'default_channel' => BaseApiV1TestCase::CHANNEL_UUID, @@ -1397,7 +1397,7 @@ public function testPutToUpdateWithDifferentPayloadId( 'PUT', $endpoint, 'v1/contacts/' . BaseApiV1TestCase::CONTACT_UUID, - json: [ + json: [ 'id' => BaseApiV1TestCase::CONTACT_UUID_3, 'full_name' => 'Test', 'default_channel' => BaseApiV1TestCase::CHANNEL_UUID, @@ -1417,7 +1417,7 @@ public function testPutToCreateWithValidData(Connection $db, Url $endpoint): voi 'PUT', $endpoint, 'v1/contacts/' . BaseApiV1TestCase::CONTACT_UUID_3, - json: [ + json: [ 'id' => BaseApiV1TestCase::CONTACT_UUID_3, 'full_name' => 'Test', 'default_channel' => BaseApiV1TestCase::CHANNEL_UUID, @@ -1469,7 +1469,7 @@ public function testPutToUpdateWithValidData(Connection $db, Url $endpoint): voi 'PUT', $endpoint, 'v1/contacts/' . BaseApiV1TestCase::CONTACT_UUID, - json: [ + json: [ 'id' => BaseApiV1TestCase::CONTACT_UUID, 'full_name' => 'Test', 'default_channel' => BaseApiV1TestCase::CHANNEL_UUID, @@ -1507,7 +1507,7 @@ public function testPutToUpdateWithInvalidData(Connection $db, Url $endpoint): v 'PUT', $endpoint, 'v1/contacts/' . BaseApiV1TestCase::CONTACT_UUID, - json: [ + json: [ 'id' => BaseApiV1TestCase::CONTACT_UUID, 'full_name' => 'Test', 'default_channel' => BaseApiV1TestCase::CHANNEL_UUID_3, @@ -1529,7 +1529,7 @@ public function testPutToUpdateWithInvalidData(Connection $db, Url $endpoint): v 'PUT', $endpoint, 'v1/contacts/' . BaseApiV1TestCase::CONTACT_UUID, - json: [ + json: [ 'id' => BaseApiV1TestCase::CONTACT_UUID, 'full_name' => 'Test', 'default_channel' => BaseApiV1TestCase::CHANNEL_UUID, @@ -1552,7 +1552,7 @@ public function testPutToUpdateWithInvalidData(Connection $db, Url $endpoint): v 'PUT', $endpoint, 'v1/contacts/' . BaseApiV1TestCase::CONTACT_UUID, - json: [ + json: [ 'id' => BaseApiV1TestCase::CONTACT_UUID, 'full_name' => 'Test', 'default_channel' => BaseApiV1TestCase::CHANNEL_UUID, @@ -1579,7 +1579,7 @@ public function testPutToCreateWithMissingRequiredFields(Connection $db, Url $en 'PUT', $endpoint, 'v1/contacts/' . BaseApiV1TestCase::CONTACT_UUID_3, - json: [ + json: [ 'id' => BaseApiV1TestCase::CONTACT_UUID_3, 'default_channel' => BaseApiV1TestCase::CHANNEL_UUID, ] @@ -1597,7 +1597,7 @@ public function testPutToCreateWithMissingRequiredFields(Connection $db, Url $en 'PUT', $endpoint, 'v1/contacts/' . BaseApiV1TestCase::CONTACT_UUID_3, - json: [ + json: [ 'full_name' => 'Test', 'default_channel' => BaseApiV1TestCase::CHANNEL_UUID, ] @@ -1615,7 +1615,7 @@ public function testPutToCreateWithMissingRequiredFields(Connection $db, Url $en 'PUT', $endpoint, 'v1/contacts/' . BaseApiV1TestCase::CONTACT_UUID_3, - json: [ + json: [ 'id' => BaseApiV1TestCase::CONTACT_UUID_3, 'full_name' => 'Test', ] @@ -1632,7 +1632,7 @@ public function testPutToCreateWithMissingRequiredFields(Connection $db, Url $en 'PUT', $endpoint, 'v1/contacts/' . BaseApiV1TestCase::CONTACT_UUID_3, - json: [ + json: [ 'id' => BaseApiV1TestCase::CONTACT_UUID_3, 'full_name' => 'Test', 'default_channel' => BaseApiV1TestCase::CHANNEL_UUID, @@ -1658,7 +1658,7 @@ public function testPutToCreateWithInvalidFieldFormat( 'PUT', $endpoint, 'v1/contacts/' . BaseApiV1TestCase::CONTACT_UUID_3, - json: [ + json: [ 'id' => [BaseApiV1TestCase::CONTACT_UUID_3], 'full_name' => 'Test', 'default_channel' => BaseApiV1TestCase::CHANNEL_UUID, @@ -1678,7 +1678,7 @@ public function testPutToCreateWithInvalidFieldFormat( 'PUT', $endpoint, 'v1/contacts/' . BaseApiV1TestCase::CONTACT_UUID_3, - json: [ + json: [ 'id' => BaseApiV1TestCase::CONTACT_UUID_3, 'full_name' => ['Test'], 'default_channel' => BaseApiV1TestCase::CHANNEL_UUID, @@ -1698,7 +1698,7 @@ public function testPutToCreateWithInvalidFieldFormat( 'PUT', $endpoint, 'v1/contacts/' . BaseApiV1TestCase::CONTACT_UUID_3, - json: [ + json: [ 'id' => BaseApiV1TestCase::CONTACT_UUID_3, 'full_name' => 'Test', 'default_channel' => [BaseApiV1TestCase::CHANNEL_UUID], @@ -1718,7 +1718,7 @@ public function testPutToCreateWithInvalidFieldFormat( 'PUT', $endpoint, 'v1/contacts/' . BaseApiV1TestCase::CONTACT_UUID_3, - json: [ + json: [ 'id' => BaseApiV1TestCase::CONTACT_UUID_3, 'full_name' => 'Test', 'default_channel' => BaseApiV1TestCase::CHANNEL_UUID, @@ -1740,7 +1740,7 @@ public function testPutToCreateWithInvalidFieldFormat( 'PUT', $endpoint, 'v1/contacts/' . BaseApiV1TestCase::CONTACT_UUID_3, - json: [ + json: [ 'id' => BaseApiV1TestCase::CONTACT_UUID_3, 'full_name' => 'Test', 'default_channel' => BaseApiV1TestCase::CHANNEL_UUID, @@ -1761,7 +1761,7 @@ public function testPutToCreateWithInvalidFieldFormat( 'PUT', $endpoint, 'v1/contacts/' . BaseApiV1TestCase::CONTACT_UUID_3, - json: [ + json: [ 'id' => BaseApiV1TestCase::CONTACT_UUID_3, 'full_name' => 'Test', 'default_channel' => BaseApiV1TestCase::CHANNEL_UUID, @@ -1786,7 +1786,7 @@ public function testPutToChangeGroupMemberships(Connection $db, Url $endpoint): 'PUT', $endpoint, 'v1/contacts/' . BaseApiV1TestCase::CONTACT_UUID, - json: [ + json: [ 'id' => BaseApiV1TestCase::CONTACT_UUID, 'full_name' => 'Test', 'default_channel' => BaseApiV1TestCase::CHANNEL_UUID, @@ -1820,7 +1820,7 @@ public function testPutToChangeGroupMemberships(Connection $db, Url $endpoint): 'PUT', $endpoint, 'v1/contacts/' . BaseApiV1TestCase::CONTACT_UUID, - json: [ + json: [ 'id' => BaseApiV1TestCase::CONTACT_UUID, 'full_name' => 'Test', 'default_channel' => BaseApiV1TestCase::CHANNEL_UUID, @@ -1854,7 +1854,7 @@ public function testPutToChangeGroupMemberships(Connection $db, Url $endpoint): 'PUT', $endpoint, 'v1/contacts/' . BaseApiV1TestCase::CONTACT_UUID, - json: [ + json: [ 'id' => BaseApiV1TestCase::CONTACT_UUID, 'full_name' => 'Test', 'default_channel' => BaseApiV1TestCase::CHANNEL_UUID, @@ -1892,7 +1892,7 @@ public function testPutToChangeAddresses(Connection $db, Url $endpoint): void 'PUT', $endpoint, 'v1/contacts/' . BaseApiV1TestCase::CONTACT_UUID, - json: [ + json: [ 'id' => BaseApiV1TestCase::CONTACT_UUID, 'full_name' => 'Test', 'default_channel' => BaseApiV1TestCase::CHANNEL_UUID, @@ -1933,7 +1933,7 @@ public function testPutToChangeAddresses(Connection $db, Url $endpoint): void 'PUT', $endpoint, 'v1/contacts/' . BaseApiV1TestCase::CONTACT_UUID, - json: [ + json: [ 'id' => BaseApiV1TestCase::CONTACT_UUID, 'full_name' => 'Test', 'default_channel' => BaseApiV1TestCase::CHANNEL_UUID, @@ -1972,7 +1972,7 @@ public function testPutToChangeAddresses(Connection $db, Url $endpoint): void 'PUT', $endpoint, 'v1/contacts/' . BaseApiV1TestCase::CONTACT_UUID, - json: [ + json: [ 'id' => BaseApiV1TestCase::CONTACT_UUID, 'full_name' => 'Test', 'default_channel' => BaseApiV1TestCase::CHANNEL_UUID, From c91fd2a5d26977e6765e74e0cc86aed6d3bbf907 Mon Sep 17 00:00:00 2001 From: Johannes Rauh Date: Mon, 24 Nov 2025 10:28:14 +0100 Subject: [PATCH 16/26] Fix invalid key for select input --- application/forms/DatabaseConfigForm.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/application/forms/DatabaseConfigForm.php b/application/forms/DatabaseConfigForm.php index 3dce3353d..b8af96a81 100644 --- a/application/forms/DatabaseConfigForm.php +++ b/application/forms/DatabaseConfigForm.php @@ -18,14 +18,14 @@ protected function assemble(): void 'select', 'resource', [ - 'label' => $this->translate('Database'), - 'options' => array_merge( + 'label' => $this->translate('Database'), + 'options' => array_merge( ['' => sprintf(' - %s - ', $this->translate('Please choose'))], array_combine($dbResources, $dbResources) ), - 'disable' => [''], - 'required' => true, - 'value' => '' + 'disabledOptions' => [''], + 'required' => true, + 'value' => '' ] ); From 5e815b7c7da0beb1c709f8c4688e2cf4ea239c09 Mon Sep 17 00:00:00 2001 From: Johannes Rauh Date: Wed, 26 Nov 2025 10:24:08 +0100 Subject: [PATCH 17/26] Remove superfluous `$filter` property --- .../controllers/ChannelsController.php | 20 +------------------ .../controllers/ContactGroupsController.php | 20 +------------------ .../controllers/ContactsController.php | 20 +------------------ .../controllers/IncidentsController.php | 20 +------------------ .../controllers/SchedulesController.php | 20 +------------------ 5 files changed, 5 insertions(+), 95 deletions(-) diff --git a/application/controllers/ChannelsController.php b/application/controllers/ChannelsController.php index f3ddc933c..12d6998a1 100644 --- a/application/controllers/ChannelsController.php +++ b/application/controllers/ChannelsController.php @@ -17,7 +17,6 @@ use Icinga\Web\Widget\Tabs; use ipl\Html\Contract\Form; use ipl\Sql\Expression; -use ipl\Stdlib\Filter; use ipl\Web\Compat\CompatController; use ipl\Web\Compat\SearchControls; use ipl\Web\Control\LimitControl; @@ -30,9 +29,6 @@ class ChannelsController extends CompatController { use SearchControls; - /** @var ?Filter\Rule Filter from query string parameters */ - private ?Filter\Rule $filter = null; - public function init(): void { $this->assertPermission('config/modules'); @@ -65,7 +61,7 @@ public function indexAction(): void if ($searchBar->hasBeenSent() && ! $searchBar->isValid()) { if ($searchBar->hasBeenSubmitted()) { - $filter = $this->getFilter(); + $filter = QueryString::parse((string) $this->params); } else { $this->addControl($searchBar); $this->sendMultipartUpdate(); @@ -148,20 +144,6 @@ public function searchEditorAction(): void $this->setTitle($this->translate('Adjust Filter')); } - /** - * Get the filter created from query string parameters - * - * @return Filter\Rule - */ - protected function getFilter(): Filter\Rule - { - if ($this->filter === null) { - $this->filter = QueryString::parse((string) $this->params); - } - - return $this->filter; - } - /** * Merge tabs with other tabs contained in this tab panel * diff --git a/application/controllers/ContactGroupsController.php b/application/controllers/ContactGroupsController.php index fb2f63e2a..eb913cf83 100644 --- a/application/controllers/ContactGroupsController.php +++ b/application/controllers/ContactGroupsController.php @@ -21,7 +21,6 @@ use ipl\Html\HtmlString; use ipl\Html\TemplateString; use ipl\Sql\Expression; -use ipl\Stdlib\Filter; use ipl\Web\Compat\CompatController; use ipl\Web\Compat\SearchControls; use ipl\Web\Control\LimitControl; @@ -36,9 +35,6 @@ class ContactGroupsController extends CompatController use ConfigurationTabs; use SearchControls; - /** @var ?Filter\Rule Filter from query string parameters */ - private ?Filter\Rule $filter = null; - public function init(): void { $this->assertPermission('notifications/config/contacts'); @@ -71,7 +67,7 @@ public function indexAction(): void if ($searchBar->hasBeenSent() && ! $searchBar->isValid()) { if ($searchBar->hasBeenSubmitted()) { - $filter = $this->getFilter(); + $filter = QueryString::parse((string) $this->params); } else { $this->addControl($searchBar); $this->sendMultipartUpdate(); @@ -204,18 +200,4 @@ public function suggestMemberAction(): void $this->getDocument()->addHtml($members); } - - /** - * Get the filter created from query string parameters - * - * @return Filter\Rule - */ - private function getFilter(): Filter\Rule - { - if ($this->filter === null) { - $this->filter = QueryString::parse((string) $this->params); - } - - return $this->filter; - } } diff --git a/application/controllers/ContactsController.php b/application/controllers/ContactsController.php index 3a85acd89..def757d1e 100644 --- a/application/controllers/ContactsController.php +++ b/application/controllers/ContactsController.php @@ -19,7 +19,6 @@ use ipl\Html\TemplateString; use ipl\Sql\Connection; use ipl\Sql\Expression; -use ipl\Stdlib\Filter; use ipl\Web\Compat\CompatController; use ipl\Web\Compat\SearchControls; use ipl\Web\Control\LimitControl; @@ -37,9 +36,6 @@ class ContactsController extends CompatController /** @var Connection */ private Connection $db; - /** @var ?Filter\Rule Filter from query string parameters */ - private ?Filter\Rule $filter = null; - public function init(): void { $this->assertPermission('notifications/config/contacts'); @@ -74,7 +70,7 @@ public function indexAction(): void if ($searchBar->hasBeenSent() && ! $searchBar->isValid()) { if ($searchBar->hasBeenSubmitted()) { - $filter = $this->getFilter(); + $filter = QueryString::parse((string) $this->params); } else { $this->addControl($searchBar); $this->sendMultipartUpdate(); @@ -165,18 +161,4 @@ public function searchEditorAction(): void $this->getDocument()->add($editor); $this->setTitle($this->translate('Adjust Filter')); } - - /** - * Get the filter created from query string parameters - * - * @return Filter\Rule - */ - protected function getFilter(): Filter\Rule - { - if ($this->filter === null) { - $this->filter = QueryString::parse((string) $this->params); - } - - return $this->filter; - } } diff --git a/application/controllers/IncidentsController.php b/application/controllers/IncidentsController.php index 2267623a1..af0d338e6 100644 --- a/application/controllers/IncidentsController.php +++ b/application/controllers/IncidentsController.php @@ -12,7 +12,6 @@ use Icinga\Module\Notifications\View\IncidentRenderer; use Icinga\Module\Notifications\Web\Control\SearchBar\ObjectSuggestions; use Icinga\Module\Notifications\Widget\ItemList\ObjectList; -use ipl\Stdlib\Filter; use ipl\Web\Compat\CompatController; use ipl\Web\Compat\SearchControls; use ipl\Web\Control\LimitControl; @@ -27,9 +26,6 @@ class IncidentsController extends CompatController use Auth; use SearchControls; - /** @var ?Filter\Rule Filter from query string parameters */ - private ?Filter\Rule $filter = null; - public function indexAction(): void { $this->addTitleTab(t('Incidents')); @@ -56,7 +52,7 @@ public function indexAction(): void if ($searchBar->hasBeenSent() && ! $searchBar->isValid()) { if ($searchBar->hasBeenSubmitted()) { - $filter = $this->getFilter(); + $filter = QueryString::parse((string) $this->params); } else { $this->addControl($searchBar); $this->sendMultipartUpdate(); @@ -115,18 +111,4 @@ protected function getPageSize($default) { return parent::getPageSize($default ?? 50); } - - /** - * Get the filter created from query string parameters - * - * @return Filter\Rule - */ - public function getFilter(): Filter\Rule - { - if ($this->filter === null) { - $this->filter = QueryString::parse((string) $this->params); - } - - return $this->filter; - } } diff --git a/application/controllers/SchedulesController.php b/application/controllers/SchedulesController.php index 5b2291a12..3703b480c 100644 --- a/application/controllers/SchedulesController.php +++ b/application/controllers/SchedulesController.php @@ -12,7 +12,6 @@ use Icinga\Module\Notifications\View\ScheduleRenderer; use Icinga\Module\Notifications\Web\Control\SearchBar\ObjectSuggestions; use Icinga\Module\Notifications\Widget\ItemList\ObjectList; -use ipl\Stdlib\Filter; use ipl\Web\Compat\CompatController; use ipl\Web\Compat\SearchControls; use ipl\Web\Control\LimitControl; @@ -25,9 +24,6 @@ class SchedulesController extends CompatController use ConfigurationTabs; use SearchControls; - /** @var ?Filter\Rule Filter from query string parameters */ - private ?Filter\Rule $filter = null; - public function init(): void { $this->assertPermission('notifications/config/schedules'); @@ -57,7 +53,7 @@ public function indexAction(): void if ($searchBar->hasBeenSent() && ! $searchBar->isValid()) { if ($searchBar->hasBeenSubmitted()) { - $filter = $this->getFilter(); + $filter = QueryString::parse((string) $this->params); } else { $this->addControl($searchBar); $this->sendMultipartUpdate(); @@ -109,18 +105,4 @@ public function searchEditorAction(): void $this->getDocument()->add($editor); $this->setTitle(t('Adjust Filter')); } - - /** - * Get the filter created from query string parameters - * - * @return Filter\Rule - */ - private function getFilter(): Filter\Rule - { - if ($this->filter === null) { - $this->filter = QueryString::parse((string) $this->params); - } - - return $this->filter; - } } From 6bbf7fb2fe9380e5debe31db9bc35e5269e61fc7 Mon Sep 17 00:00:00 2001 From: Johannes Rauh Date: Wed, 26 Nov 2025 10:26:51 +0100 Subject: [PATCH 18/26] Remove properties that use parent value as default --- application/forms/MoveRotationForm.php | 2 -- library/Notifications/Widget/Detail/ScheduleDetail/Controls.php | 2 -- 2 files changed, 4 deletions(-) diff --git a/application/forms/MoveRotationForm.php b/application/forms/MoveRotationForm.php index 8097a0f0a..1791e5616 100644 --- a/application/forms/MoveRotationForm.php +++ b/application/forms/MoveRotationForm.php @@ -23,8 +23,6 @@ class MoveRotationForm extends Form protected $defaultAttributes = ['hidden' => true]; - protected $method = 'POST'; - /** @var ?Connection */ protected ?Connection $db = null; diff --git a/library/Notifications/Widget/Detail/ScheduleDetail/Controls.php b/library/Notifications/Widget/Detail/ScheduleDetail/Controls.php index 8f81a6280..6c712257b 100644 --- a/library/Notifications/Widget/Detail/ScheduleDetail/Controls.php +++ b/library/Notifications/Widget/Detail/ScheduleDetail/Controls.php @@ -27,8 +27,6 @@ class Controls extends Form /** @var string The default mode */ public const DEFAULT_MODE = 'week'; - protected $method = 'POST'; - protected $defaultAttributes = ['class' => 'schedule-controls', 'name' => 'schedule-detail-controls-form']; /** @var ?string */ From bbebbca175f54d3fd79d8570bc6860108ea3fbc8 Mon Sep 17 00:00:00 2001 From: Johannes Rauh Date: Tue, 24 Mar 2026 15:01:01 +0100 Subject: [PATCH 19/26] Fix typo in PHPDoc --- application/forms/RotationConfigForm.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/application/forms/RotationConfigForm.php b/application/forms/RotationConfigForm.php index 6c60e5c0a..e06dc89ee 100644 --- a/application/forms/RotationConfigForm.php +++ b/application/forms/RotationConfigForm.php @@ -219,7 +219,7 @@ public function __construct(int $scheduleId, Connection $db, string $displayTime * @return $this * * @throws LogicException If an invalid rotation mode is set - * @throws ConfigurationError If the schedule's timezone is invalid' + * @throws ConfigurationError If the schedule's timezone is invalid * @throws HttpNotFoundException If the rotation with the given ID does not exist */ public function loadRotation(int $rotationId): self From 0c6a689b6fb35f6d27bf37adee1dbc4776507512 Mon Sep 17 00:00:00 2001 From: Johannes Rauh Date: Tue, 24 Mar 2026 15:31:36 +0100 Subject: [PATCH 20/26] Remove redundant `@var` annotations from typed properties --- application/controllers/ContactsController.php | 1 - application/controllers/EventRuleController.php | 1 - application/controllers/ScheduleController.php | 1 - application/forms/ChannelForm.php | 1 - application/forms/ContactGroupForm.php | 1 - .../EventRuleConfigElements/NotificationConfigProvider.php | 4 ---- application/forms/EventRuleConfigForm.php | 1 - application/forms/MoveRotationForm.php | 2 -- application/forms/ScheduleForm.php | 5 ----- library/Notifications/Common/LoadMore.php | 3 --- library/Notifications/Common/NoSubjectLink.php | 1 - library/Notifications/Model/Behavior/IdTagAggregator.php | 1 - library/Notifications/Model/Behavior/ObjectTags.php | 1 - .../Web/Control/SearchBar/ObjectSuggestions.php | 1 - library/Notifications/Web/Form/ContactForm.php | 1 - library/Notifications/Web/Form/EventRuleDecorator.php | 1 - library/Notifications/Widget/Calendar.php | 4 ---- library/Notifications/Widget/Calendar/Attendee.php | 2 -- library/Notifications/Widget/Calendar/Entry.php | 1 - library/Notifications/Widget/Detail/IncidentDetail.php | 1 - .../Notifications/Widget/Detail/IncidentQuickActions.php | 2 -- library/Notifications/Widget/Detail/ScheduleDetail.php | 3 --- .../Notifications/Widget/Detail/ScheduleDetail/Controls.php | 1 - library/Notifications/Widget/EventSourceBadge.php | 1 - library/Notifications/Widget/ItemList/PageSeparatorItem.php | 1 - library/Notifications/Widget/MemberSuggestions.php | 2 -- .../Notifications/Widget/RuleEscalationRecipientBadge.php | 2 -- library/Notifications/Widget/TimeGrid/BaseGrid.php | 4 ---- library/Notifications/Widget/TimeGrid/Timescale.php | 1 - library/Notifications/Widget/Timeline.php | 6 ------ library/Notifications/Widget/Timeline/Entry.php | 1 - library/Notifications/Widget/Timeline/Member.php | 2 -- library/Notifications/Widget/Timeline/Rotation.php | 1 - 33 files changed, 61 deletions(-) diff --git a/application/controllers/ContactsController.php b/application/controllers/ContactsController.php index def757d1e..e424de373 100644 --- a/application/controllers/ContactsController.php +++ b/application/controllers/ContactsController.php @@ -33,7 +33,6 @@ class ContactsController extends CompatController use ConfigurationTabs; use SearchControls; - /** @var Connection */ private Connection $db; public function init(): void diff --git a/application/controllers/EventRuleController.php b/application/controllers/EventRuleController.php index a2e90f5b3..0986147f2 100644 --- a/application/controllers/EventRuleController.php +++ b/application/controllers/EventRuleController.php @@ -37,7 +37,6 @@ class EventRuleController extends CompatController { use Auth; - /** @var Session\SessionNamespace */ private Session\SessionNamespace $session; public function init(): void diff --git a/application/controllers/ScheduleController.php b/application/controllers/ScheduleController.php index ddbc19211..aafcf0773 100644 --- a/application/controllers/ScheduleController.php +++ b/application/controllers/ScheduleController.php @@ -26,7 +26,6 @@ class ScheduleController extends CompatController { - /** @var ?Session\SessionNamespace */ private ?Session\SessionNamespace $session = null; public function init(): void diff --git a/application/forms/ChannelForm.php b/application/forms/ChannelForm.php index 053b74a0e..5fd22e89d 100644 --- a/application/forms/ChannelForm.php +++ b/application/forms/ChannelForm.php @@ -45,7 +45,6 @@ class ChannelForm extends CompatForm { use CsrfCounterMeasure; - /** @var Connection */ private Connection $db; /** @var ?int Channel ID */ diff --git a/application/forms/ContactGroupForm.php b/application/forms/ContactGroupForm.php index 919b0849a..95ea44da7 100644 --- a/application/forms/ContactGroupForm.php +++ b/application/forms/ContactGroupForm.php @@ -30,7 +30,6 @@ class ContactGroupForm extends CompatForm { use CsrfCounterMeasure; - /** @var Connection */ private Connection $db; /** @var ?int Contact group id */ diff --git a/application/forms/EventRuleConfigElements/NotificationConfigProvider.php b/application/forms/EventRuleConfigElements/NotificationConfigProvider.php index 9bee7d6e4..ff8aba6e2 100644 --- a/application/forms/EventRuleConfigElements/NotificationConfigProvider.php +++ b/application/forms/EventRuleConfigElements/NotificationConfigProvider.php @@ -14,16 +14,12 @@ class NotificationConfigProvider implements ConfigProviderInterface { - /** @var ?ResultSet */ private ?ResultSet $contacts = null; - /** @var ?ResultSet */ private ?ResultSet $contactGroups = null; - /** @var ?ResultSet */ private ?ResultSet $schedules = null; - /** @var ?ResultSet */ private ?ResultSet $channels = null; public function fetchContacts(): iterable diff --git a/application/forms/EventRuleConfigForm.php b/application/forms/EventRuleConfigForm.php index dd1882883..fd5b1adf7 100755 --- a/application/forms/EventRuleConfigForm.php +++ b/application/forms/EventRuleConfigForm.php @@ -34,7 +34,6 @@ class EventRuleConfigForm extends CompatForm 'id' => 'event-rule-config-form' ]; - /** @var ConfigProviderInterface */ protected ConfigProviderInterface $configProvider; /** @var Url Search editor URL for the config filter fieldset */ diff --git a/application/forms/MoveRotationForm.php b/application/forms/MoveRotationForm.php index 1791e5616..a33f7e21e 100644 --- a/application/forms/MoveRotationForm.php +++ b/application/forms/MoveRotationForm.php @@ -23,10 +23,8 @@ class MoveRotationForm extends Form protected $defaultAttributes = ['hidden' => true]; - /** @var ?Connection */ protected ?Connection $db = null; - /** @var ?int */ protected ?int $scheduleId = null; /** diff --git a/application/forms/ScheduleForm.php b/application/forms/ScheduleForm.php index e87ae5863..8a3ec5160 100644 --- a/application/forms/ScheduleForm.php +++ b/application/forms/ScheduleForm.php @@ -29,19 +29,14 @@ class ScheduleForm extends CompatForm { use CsrfCounterMeasure; - /** @var ?string */ protected ?string $submitLabel = null; - /** @var bool */ protected bool $showRemoveButton = false; - /** @var bool */ protected bool $showTimezoneSuggestionInput = false; - /** @var Connection */ private Connection $db; - /** @var ?int */ private ?int $scheduleId = null; public function __construct(Connection $db) diff --git a/library/Notifications/Common/LoadMore.php b/library/Notifications/Common/LoadMore.php index 355bd1b53..8c6c0ddc1 100644 --- a/library/Notifications/Common/LoadMore.php +++ b/library/Notifications/Common/LoadMore.php @@ -14,13 +14,10 @@ trait LoadMore { - /** @var ?int */ protected ?int $pageSize = null; - /** @var ?int */ protected ?int $pageNumber = null; - /** @var ?Url */ protected ?Url $loadMoreUrl = null; /** diff --git a/library/Notifications/Common/NoSubjectLink.php b/library/Notifications/Common/NoSubjectLink.php index 77156efb9..168499e2f 100644 --- a/library/Notifications/Common/NoSubjectLink.php +++ b/library/Notifications/Common/NoSubjectLink.php @@ -7,7 +7,6 @@ trait NoSubjectLink { - /** @var bool */ protected bool $noSubjectLink = false; /** diff --git a/library/Notifications/Model/Behavior/IdTagAggregator.php b/library/Notifications/Model/Behavior/IdTagAggregator.php index c3033dabf..0b4697f37 100644 --- a/library/Notifications/Model/Behavior/IdTagAggregator.php +++ b/library/Notifications/Model/Behavior/IdTagAggregator.php @@ -20,7 +20,6 @@ class IdTagAggregator extends PropertyBehavior implements RewriteColumnBehavior, QueryAwareBehavior { - /** @var ?Query */ protected ?Query $query = null; final public function __construct() diff --git a/library/Notifications/Model/Behavior/ObjectTags.php b/library/Notifications/Model/Behavior/ObjectTags.php index dc942f032..0e44ca6fd 100644 --- a/library/Notifications/Model/Behavior/ObjectTags.php +++ b/library/Notifications/Model/Behavior/ObjectTags.php @@ -18,7 +18,6 @@ class ObjectTags implements RewriteColumnBehavior, QueryAwareBehavior { use Auth; - /** @var ?Query */ protected ?Query $query = null; public function setQuery(Query $query): self diff --git a/library/Notifications/Web/Control/SearchBar/ObjectSuggestions.php b/library/Notifications/Web/Control/SearchBar/ObjectSuggestions.php index dd9d82bba..f930b1a5f 100644 --- a/library/Notifications/Web/Control/SearchBar/ObjectSuggestions.php +++ b/library/Notifications/Web/Control/SearchBar/ObjectSuggestions.php @@ -34,7 +34,6 @@ class ObjectSuggestions extends Suggestions use Auth; use Translation; - /** @var ?Model */ protected ?Model $model = null; /** diff --git a/library/Notifications/Web/Form/ContactForm.php b/library/Notifications/Web/Form/ContactForm.php index 5dd73078d..d0d5f8f2c 100644 --- a/library/Notifications/Web/Form/ContactForm.php +++ b/library/Notifications/Web/Form/ContactForm.php @@ -37,7 +37,6 @@ class ContactForm extends CompatForm /** @var string Emitted in case the contact should be deleted */ public const ON_REMOVE = 'on_remove'; - /** @var Connection */ private Connection $db; /** @var ?string Contact ID */ diff --git a/library/Notifications/Web/Form/EventRuleDecorator.php b/library/Notifications/Web/Form/EventRuleDecorator.php index 893534ee5..cf7e73191 100644 --- a/library/Notifications/Web/Form/EventRuleDecorator.php +++ b/library/Notifications/Web/Form/EventRuleDecorator.php @@ -14,7 +14,6 @@ class EventRuleDecorator extends HtmlDocument implements FormElementDecorator { - /** @var FormElement */ private FormElement $element; public function decorate(FormElement $formElement): void diff --git a/library/Notifications/Widget/Calendar.php b/library/Notifications/Widget/Calendar.php index a47681358..c1ee8cb6a 100644 --- a/library/Notifications/Widget/Calendar.php +++ b/library/Notifications/Widget/Calendar.php @@ -41,10 +41,8 @@ class Calendar extends BaseHtmlElement implements EntryProvider protected $defaultAttributes = ['class' => 'calendar']; - /** @var ?Controls */ protected ?Controls $controls = null; - /** @var ?Style */ protected ?Style $style = null; /** @var ?BaseGrid The grid implementation */ @@ -53,10 +51,8 @@ class Calendar extends BaseHtmlElement implements EntryProvider /** @var Entry[] */ protected array $entries = []; - /** @var ?Url */ protected ?Url $addEntryUrl = null; - /** @var ?Url */ protected ?Url $url = null; public function setControls(Controls $controls): self diff --git a/library/Notifications/Widget/Calendar/Attendee.php b/library/Notifications/Widget/Calendar/Attendee.php index ec4762c97..ab57c28b5 100644 --- a/library/Notifications/Widget/Calendar/Attendee.php +++ b/library/Notifications/Widget/Calendar/Attendee.php @@ -14,10 +14,8 @@ */ class Attendee { - /** @var string */ protected string $name; - /** @var string|ValidHtml */ protected string|ValidHtml $icon = 'user'; public function __construct(string $name) diff --git a/library/Notifications/Widget/Calendar/Entry.php b/library/Notifications/Widget/Calendar/Entry.php index b5cb4fd56..3ef3c13ef 100644 --- a/library/Notifications/Widget/Calendar/Entry.php +++ b/library/Notifications/Widget/Calendar/Entry.php @@ -21,7 +21,6 @@ class Entry extends TimeGrid\Entry /** @var ?string The description */ protected ?string $description = null; - /** @var ?Attendee */ protected ?Attendee $attendee = null; /** diff --git a/library/Notifications/Widget/Detail/IncidentDetail.php b/library/Notifications/Widget/Detail/IncidentDetail.php index 7abaa351b..b94d163ba 100644 --- a/library/Notifications/Widget/Detail/IncidentDetail.php +++ b/library/Notifications/Widget/Detail/IncidentDetail.php @@ -32,7 +32,6 @@ class IncidentDetail extends BaseHtmlElement use Auth; use Translation; - /** @var Incident */ protected Incident $incident; protected $defaultAttributes = [ diff --git a/library/Notifications/Widget/Detail/IncidentQuickActions.php b/library/Notifications/Widget/Detail/IncidentQuickActions.php index b07d1a11c..9b6929e54 100644 --- a/library/Notifications/Widget/Detail/IncidentQuickActions.php +++ b/library/Notifications/Widget/Detail/IncidentQuickActions.php @@ -28,13 +28,11 @@ class IncidentQuickActions extends Form 'name' => 'incident-quick-actions' ]; - /** @var Incident */ protected Incident $incident; /** @var int Current logged-in user's id */ protected int $currentUserId; - /** @var ?IncidentContact */ protected ?IncidentContact $incidentContact = null; public function __construct(Incident $incident, int $currentUserId) diff --git a/library/Notifications/Widget/Detail/ScheduleDetail.php b/library/Notifications/Widget/Detail/ScheduleDetail.php index 52062245f..46652edce 100644 --- a/library/Notifications/Widget/Detail/ScheduleDetail.php +++ b/library/Notifications/Widget/Detail/ScheduleDetail.php @@ -29,16 +29,13 @@ class ScheduleDetail extends BaseHtmlElement protected $defaultAttributes = ['id' => 'notifications-schedule', 'class' => 'schedule-detail']; - /** @var Schedule */ protected Schedule $schedule; - /** @var Controls */ protected Controls $controls; /** @var DateTime The day the timeline should start on */ protected DateTime $start; - /** @var bool */ private bool $hasRotation = false; /** diff --git a/library/Notifications/Widget/Detail/ScheduleDetail/Controls.php b/library/Notifications/Widget/Detail/ScheduleDetail/Controls.php index 6c712257b..b9da5ea7e 100644 --- a/library/Notifications/Widget/Detail/ScheduleDetail/Controls.php +++ b/library/Notifications/Widget/Detail/ScheduleDetail/Controls.php @@ -29,7 +29,6 @@ class Controls extends Form protected $defaultAttributes = ['class' => 'schedule-controls', 'name' => 'schedule-detail-controls-form']; - /** @var ?string */ protected ?string $defaultTimezone = null; /** diff --git a/library/Notifications/Widget/EventSourceBadge.php b/library/Notifications/Widget/EventSourceBadge.php index ca0edab3a..00b2268d4 100644 --- a/library/Notifications/Widget/EventSourceBadge.php +++ b/library/Notifications/Widget/EventSourceBadge.php @@ -13,7 +13,6 @@ class EventSourceBadge extends BaseHtmlElement { - /** @var Source */ protected Source $source; protected $tag = 'span'; diff --git a/library/Notifications/Widget/ItemList/PageSeparatorItem.php b/library/Notifications/Widget/ItemList/PageSeparatorItem.php index d52d38653..ee5e7349f 100644 --- a/library/Notifications/Widget/ItemList/PageSeparatorItem.php +++ b/library/Notifications/Widget/ItemList/PageSeparatorItem.php @@ -12,7 +12,6 @@ class PageSeparatorItem extends BaseHtmlElement { protected $defaultAttributes = ['class' => 'list-item page-separator']; - /** @var int */ protected int $pageNumber; /** @var string */ diff --git a/library/Notifications/Widget/MemberSuggestions.php b/library/Notifications/Widget/MemberSuggestions.php index 3d35fc7d7..5a71a1b62 100644 --- a/library/Notifications/Widget/MemberSuggestions.php +++ b/library/Notifications/Widget/MemberSuggestions.php @@ -18,10 +18,8 @@ class MemberSuggestions extends BaseHtmlElement { protected $tag = 'ul'; - /** @var ?string */ protected ?string $searchTerm = null; - /** @var ?string */ protected ?string $originalValue = null; /** @var string[] */ diff --git a/library/Notifications/Widget/RuleEscalationRecipientBadge.php b/library/Notifications/Widget/RuleEscalationRecipientBadge.php index 1119c2377..1c8f5b13c 100644 --- a/library/Notifications/Widget/RuleEscalationRecipientBadge.php +++ b/library/Notifications/Widget/RuleEscalationRecipientBadge.php @@ -13,10 +13,8 @@ class RuleEscalationRecipientBadge extends BaseHtmlElement { - /** @var RuleEscalationRecipient */ protected RuleEscalationRecipient $recipient; - /** @var ?int */ protected ?int $moreCount = null; protected $tag = 'span'; diff --git a/library/Notifications/Widget/TimeGrid/BaseGrid.php b/library/Notifications/Widget/TimeGrid/BaseGrid.php index 28c62ca36..eca89e767 100644 --- a/library/Notifications/Widget/TimeGrid/BaseGrid.php +++ b/library/Notifications/Widget/TimeGrid/BaseGrid.php @@ -44,16 +44,12 @@ abstract class BaseGrid extends BaseHtmlElement /** @var string The orientation of this grid's chronological order of entries */ protected string $flowOfTime = self::HORIZONTAL_FLOW_OF_TIME; - /** @var EntryProvider */ protected EntryProvider $provider; - /** @var Style */ protected Style $style; - /** @var DateTime */ protected DateTime $start; - /** @var ?DateTime */ protected ?DateTime $end = null; /** @var array Extra counts stored as [date1 => count1, date2 => count2] */ diff --git a/library/Notifications/Widget/TimeGrid/Timescale.php b/library/Notifications/Widget/TimeGrid/Timescale.php index 8c4ef9530..e1afa1315 100644 --- a/library/Notifications/Widget/TimeGrid/Timescale.php +++ b/library/Notifications/Widget/TimeGrid/Timescale.php @@ -29,7 +29,6 @@ class Timescale extends BaseHtmlElement /** @var int The number of days shown */ protected int $days; - /** @var Style */ protected Style $style; /** diff --git a/library/Notifications/Widget/Timeline.php b/library/Notifications/Widget/Timeline.php index ddf1b489f..1d54ceffa 100644 --- a/library/Notifications/Widget/Timeline.php +++ b/library/Notifications/Widget/Timeline.php @@ -45,25 +45,19 @@ class Timeline extends BaseHtmlElement implements EntryProvider /** @var array */ protected array $rotations = []; - /** @var int */ protected int $scheduleId; - /** @var DateTime */ protected DateTime $start; - /** @var int */ protected int $days; - /** @var ?Style */ protected ?Style $style = null; - /** @var ?DynamicGrid|MinimalGrid */ protected DynamicGrid|MinimalGrid|null $grid = null; /** @var bool Whether to create the Timeline only with the Result using MinimalGrid */ protected bool $minimalLayout = false; - /** @var int */ protected int $noOfRotations = 0; /** diff --git a/library/Notifications/Widget/Timeline/Entry.php b/library/Notifications/Widget/Timeline/Entry.php index 12303187c..685777e3d 100644 --- a/library/Notifications/Widget/Timeline/Entry.php +++ b/library/Notifications/Widget/Timeline/Entry.php @@ -16,7 +16,6 @@ class Entry extends TimeGrid\Entry { - /** @var ?Member */ protected ?Member $member = null; /** @var ?EntryFlyout Content of the flyoutmenu that is shown when the entry is hovered */ diff --git a/library/Notifications/Widget/Timeline/Member.php b/library/Notifications/Widget/Timeline/Member.php index 6cb8bd0ea..ba5f051cd 100644 --- a/library/Notifications/Widget/Timeline/Member.php +++ b/library/Notifications/Widget/Timeline/Member.php @@ -10,10 +10,8 @@ */ class Member { - /** @var string */ protected string $name; - /** @var string */ protected string $icon = 'user'; /** diff --git a/library/Notifications/Widget/Timeline/Rotation.php b/library/Notifications/Widget/Timeline/Rotation.php index 3cea0677e..0a67017ed 100644 --- a/library/Notifications/Widget/Timeline/Rotation.php +++ b/library/Notifications/Widget/Timeline/Rotation.php @@ -22,7 +22,6 @@ class Rotation { use Translation; - /** @var RotationModel */ protected RotationModel $model; /** From f199d3667add66528327a34270fee52b3f9dfc91 Mon Sep 17 00:00:00 2001 From: Johannes Rauh Date: Wed, 25 Mar 2026 09:20:30 +0100 Subject: [PATCH 21/26] Use `static` return value where appropriate --- application/forms/ChannelForm.php | 4 ++-- application/forms/ContactGroupForm.php | 2 +- application/forms/EventRuleForm.php | 2 +- application/forms/RotationConfigForm.php | 10 +++++----- application/forms/ScheduleForm.php | 6 +++--- application/forms/SourceForm.php | 2 +- .../Api/Middleware/MiddlewarePipeline.php | 2 +- library/Notifications/Common/NoSubjectLink.php | 2 +- .../Notifications/Model/Behavior/IdTagAggregator.php | 2 +- .../Web/Control/SearchBar/ObjectSuggestions.php | 2 +- library/Notifications/Web/Form/ContactForm.php | 2 +- library/Notifications/Widget/Calendar.php | 10 +++++----- library/Notifications/Widget/Calendar/Attendee.php | 2 +- library/Notifications/Widget/Calendar/DayGrid.php | 2 +- library/Notifications/Widget/Calendar/Entry.php | 4 ++-- library/Notifications/Widget/Calendar/MonthGrid.php | 2 +- library/Notifications/Widget/Calendar/WeekGrid.php | 2 +- library/Notifications/Widget/MemberSuggestions.php | 8 ++++---- library/Notifications/Widget/ShowMore.php | 2 +- library/Notifications/Widget/TimeGrid/BaseGrid.php | 2 +- library/Notifications/Widget/TimeGrid/DynamicGrid.php | 6 +++--- library/Notifications/Widget/TimeGrid/Entry.php | 10 +++++----- .../Notifications/Widget/TimeGrid/ExtraEntryCount.php | 4 ++-- library/Notifications/Widget/Timeline.php | 4 ++-- library/Notifications/Widget/Timeline/Entry.php | 2 +- library/Notifications/Widget/Timeline/Member.php | 2 +- library/Notifications/Widget/Timeline/MinimalGrid.php | 2 +- 27 files changed, 50 insertions(+), 50 deletions(-) diff --git a/application/forms/ChannelForm.php b/application/forms/ChannelForm.php index 5fd22e89d..20b15a049 100644 --- a/application/forms/ChannelForm.php +++ b/application/forms/ChannelForm.php @@ -199,7 +199,7 @@ public function hasBeenSubmitted(): bool * * @throws HttpNotFoundException */ - public function loadChannel(int $id): self + public function loadChannel(int $id): static { $this->channelId = $id; $this->populate($this->fetchDbValues()); @@ -471,7 +471,7 @@ private function fetchDbValues(): array * * @return $this */ - public function validate(): self + public function validate(): static { parent::validate(); diff --git a/application/forms/ContactGroupForm.php b/application/forms/ContactGroupForm.php index 95ea44da7..8bcec8e05 100644 --- a/application/forms/ContactGroupForm.php +++ b/application/forms/ContactGroupForm.php @@ -167,7 +167,7 @@ protected function validateTerms(array $terms): void * * @return $this */ - public function loadContactgroup(int $groupId): self + public function loadContactgroup(int $groupId): static { $this->contactgroupId = $groupId; diff --git a/application/forms/EventRuleForm.php b/application/forms/EventRuleForm.php index 82ba38f10..6c08c269e 100644 --- a/application/forms/EventRuleForm.php +++ b/application/forms/EventRuleForm.php @@ -28,7 +28,7 @@ class EventRuleForm extends CompatForm * * @return $this */ - public function setAvailableSources(array $sources): self + public function setAvailableSources(array $sources): static { $this->sources = $sources; diff --git a/application/forms/RotationConfigForm.php b/application/forms/RotationConfigForm.php index e06dc89ee..5014429d7 100644 --- a/application/forms/RotationConfigForm.php +++ b/application/forms/RotationConfigForm.php @@ -98,7 +98,7 @@ class RotationConfigForm extends CompatForm * * @return $this */ - public function setSubmitLabel(string $label): self + public function setSubmitLabel(string $label): static { $this->submitLabel = $label; @@ -122,7 +122,7 @@ public function getSubmitLabel(): string * * @return $this */ - public function setShowRemoveButton(bool $state = true): self + public function setShowRemoveButton(bool $state = true): static { $this->showRemoveButton = $state; @@ -136,7 +136,7 @@ public function setShowRemoveButton(bool $state = true): self * * @return $this */ - public function setSuggestionUrl(Url $url): self + public function setSuggestionUrl(Url $url): static { $this->suggestionUrl = $url; @@ -148,7 +148,7 @@ public function setSuggestionUrl(Url $url): self * * @return $this */ - public function disableModeSelection(): self + public function disableModeSelection(): static { $this->disableModeSelection = true; @@ -222,7 +222,7 @@ public function __construct(int $scheduleId, Connection $db, string $displayTime * @throws ConfigurationError If the schedule's timezone is invalid * @throws HttpNotFoundException If the rotation with the given ID does not exist */ - public function loadRotation(int $rotationId): self + public function loadRotation(int $rotationId): static { $this->rotationId = $rotationId; diff --git a/application/forms/ScheduleForm.php b/application/forms/ScheduleForm.php index 8a3ec5160..ab5f4b32c 100644 --- a/application/forms/ScheduleForm.php +++ b/application/forms/ScheduleForm.php @@ -45,7 +45,7 @@ public function __construct(Connection $db) $this->applyDefaultElementDecorators(); } - public function setSubmitLabel(string $label): self + public function setSubmitLabel(string $label): static { $this->submitLabel = $label; @@ -57,7 +57,7 @@ public function getSubmitLabel(): string return $this->submitLabel ?? $this->translate('Create Schedule'); } - public function setShowRemoveButton(bool $state = true): self + public function setShowRemoveButton(bool $state = true): static { $this->showRemoveButton = $state; @@ -71,7 +71,7 @@ public function setShowRemoveButton(bool $state = true): self * * @return $this */ - public function setShowTimezoneSuggestionInput(bool $state = true): self + public function setShowTimezoneSuggestionInput(bool $state = true): static { $this->showTimezoneSuggestionInput = $state; diff --git a/application/forms/SourceForm.php b/application/forms/SourceForm.php index 28255ee43..acb3520bc 100644 --- a/application/forms/SourceForm.php +++ b/application/forms/SourceForm.php @@ -234,7 +234,7 @@ function ($value, CallbackValidator $validator) { * * @return $this */ - public function loadSource(int $id): self + public function loadSource(int $id): static { $this->sourceId = $id; diff --git a/library/Notifications/Api/Middleware/MiddlewarePipeline.php b/library/Notifications/Api/Middleware/MiddlewarePipeline.php index 94e5e17c5..9f5195f86 100644 --- a/library/Notifications/Api/Middleware/MiddlewarePipeline.php +++ b/library/Notifications/Api/Middleware/MiddlewarePipeline.php @@ -46,7 +46,7 @@ public function __construct( * * @return $this */ - public function pipe(MiddlewareInterface $middleware): self + public function pipe(MiddlewareInterface $middleware): static { $this->pipeline->enqueue($middleware); diff --git a/library/Notifications/Common/NoSubjectLink.php b/library/Notifications/Common/NoSubjectLink.php index 168499e2f..eb0a3848a 100644 --- a/library/Notifications/Common/NoSubjectLink.php +++ b/library/Notifications/Common/NoSubjectLink.php @@ -16,7 +16,7 @@ trait NoSubjectLink * * @return $this */ - public function setNoSubjectLink(bool $state = true): self + public function setNoSubjectLink(bool $state = true): static { $this->noSubjectLink = $state; diff --git a/library/Notifications/Model/Behavior/IdTagAggregator.php b/library/Notifications/Model/Behavior/IdTagAggregator.php index 0b4697f37..dcc2eef59 100644 --- a/library/Notifications/Model/Behavior/IdTagAggregator.php +++ b/library/Notifications/Model/Behavior/IdTagAggregator.php @@ -29,7 +29,7 @@ final public function __construct() } /** @return $this */ - public function setQuery(Query $query): static + public function setQuery(Query $query) { $this->query = $query; diff --git a/library/Notifications/Web/Control/SearchBar/ObjectSuggestions.php b/library/Notifications/Web/Control/SearchBar/ObjectSuggestions.php index f930b1a5f..74b8801cb 100644 --- a/library/Notifications/Web/Control/SearchBar/ObjectSuggestions.php +++ b/library/Notifications/Web/Control/SearchBar/ObjectSuggestions.php @@ -43,7 +43,7 @@ class ObjectSuggestions extends Suggestions * * @return $this */ - public function setModel(string|Model $model): self + public function setModel(string|Model $model): static { if (is_string($model)) { $model = new $model(); diff --git a/library/Notifications/Web/Form/ContactForm.php b/library/Notifications/Web/Form/ContactForm.php index d0d5f8f2c..21b7c902f 100644 --- a/library/Notifications/Web/Form/ContactForm.php +++ b/library/Notifications/Web/Form/ContactForm.php @@ -217,7 +217,7 @@ protected function assemble(): void * * @throws HttpNotFoundException */ - public function loadContact(int $id): self + public function loadContact(int $id): static { $this->contactId = $id; diff --git a/library/Notifications/Widget/Calendar.php b/library/Notifications/Widget/Calendar.php index c1ee8cb6a..7ed9cdeab 100644 --- a/library/Notifications/Widget/Calendar.php +++ b/library/Notifications/Widget/Calendar.php @@ -55,7 +55,7 @@ class Calendar extends BaseHtmlElement implements EntryProvider protected ?Url $url = null; - public function setControls(Controls $controls): self + public function setControls(Controls $controls): static { $this->controls = $controls; @@ -71,7 +71,7 @@ public function getControls(): Controls return $this->controls; } - public function setStyle(Style $style): self + public function setStyle(Style $style): static { $this->style = $style; @@ -87,7 +87,7 @@ public function getStyle(): Style return $this->style; } - public function setAddEntryUrl(?Url $url): self + public function setAddEntryUrl(?Url $url): static { $this->addEntryUrl = $url; @@ -99,7 +99,7 @@ public function getStepUrl(GridStep $step): ?Url return $this->addEntryUrl?->with('start', $step->getStart()->format('Y-m-d\TH:i:s')); } - public function setUrl(?Url $url): self + public function setUrl(?Url $url): static { $this->url = $url; @@ -152,7 +152,7 @@ public function getGrid(): BaseGrid return $this->grid; } - public function addEntry(Entry $entry): self + public function addEntry(Entry $entry): static { $this->entries[] = $entry; diff --git a/library/Notifications/Widget/Calendar/Attendee.php b/library/Notifications/Widget/Calendar/Attendee.php index ab57c28b5..ba3e373a8 100644 --- a/library/Notifications/Widget/Calendar/Attendee.php +++ b/library/Notifications/Widget/Calendar/Attendee.php @@ -28,7 +28,7 @@ public function getName(): string return $this->name; } - public function setIcon($icon): self + public function setIcon($icon): static { if ($icon === null) { throw new InvalidArgumentException('Cannot unset icon'); diff --git a/library/Notifications/Widget/Calendar/DayGrid.php b/library/Notifications/Widget/Calendar/DayGrid.php index 769cb0b7e..df1ccd4eb 100644 --- a/library/Notifications/Widget/Calendar/DayGrid.php +++ b/library/Notifications/Widget/Calendar/DayGrid.php @@ -20,7 +20,7 @@ class DayGrid extends BaseGrid { protected string $flowOfTime = BaseGrid::VERTICAL_FLOW_OF_TIME; - public function setGridStart(DateTime $start): BaseGrid + public function setGridStart(DateTime $start): static { if ($start->format('H:i:s') !== '00:00:00') { throw new InvalidArgumentException('Start is not midnight'); diff --git a/library/Notifications/Widget/Calendar/Entry.php b/library/Notifications/Widget/Calendar/Entry.php index 3ef3c13ef..e9e03674d 100644 --- a/library/Notifications/Widget/Calendar/Entry.php +++ b/library/Notifications/Widget/Calendar/Entry.php @@ -30,7 +30,7 @@ class Entry extends TimeGrid\Entry * * @return $this */ - public function setDescription(?string $description): self + public function setDescription(?string $description): static { $this->description = $description; @@ -54,7 +54,7 @@ public function getDescription(): ?string * * @return $this */ - public function setAttendee(Attendee $attendee): self + public function setAttendee(Attendee $attendee): static { $this->attendee = $attendee; diff --git a/library/Notifications/Widget/Calendar/MonthGrid.php b/library/Notifications/Widget/Calendar/MonthGrid.php index 042c3e3bc..932a78925 100644 --- a/library/Notifications/Widget/Calendar/MonthGrid.php +++ b/library/Notifications/Widget/Calendar/MonthGrid.php @@ -18,7 +18,7 @@ class MonthGrid extends BaseGrid { - public function setGridStart(DateTime $start): BaseGrid + public function setGridStart(DateTime $start): static { if ($start->format('j:H:i:s') !== '1:00:00:00') { throw new InvalidArgumentException('Start is not the first of the month or not midnight'); diff --git a/library/Notifications/Widget/Calendar/WeekGrid.php b/library/Notifications/Widget/Calendar/WeekGrid.php index 8d8c6c1a0..731afb839 100644 --- a/library/Notifications/Widget/Calendar/WeekGrid.php +++ b/library/Notifications/Widget/Calendar/WeekGrid.php @@ -20,7 +20,7 @@ class WeekGrid extends BaseGrid { protected string $flowOfTime = BaseGrid::VERTICAL_FLOW_OF_TIME; - public function setGridStart(DateTime $start): BaseGrid + public function setGridStart(DateTime $start): static { if ($start->format('w:H:i:s') !== '1:00:00:00') { throw new InvalidArgumentException('Start is not a monday or not midnight'); diff --git a/library/Notifications/Widget/MemberSuggestions.php b/library/Notifications/Widget/MemberSuggestions.php index 5a71a1b62..16ed84c78 100644 --- a/library/Notifications/Widget/MemberSuggestions.php +++ b/library/Notifications/Widget/MemberSuggestions.php @@ -25,21 +25,21 @@ class MemberSuggestions extends BaseHtmlElement /** @var string[] */ protected array $excludeTerms = []; - public function setSearchTerm(string $term): self + public function setSearchTerm(string $term): static { $this->searchTerm = $term; return $this; } - public function setOriginalValue(string $term): self + public function setOriginalValue(string $term): static { $this->originalValue = $term; return $this; } - public function excludeTerms(array $terms): self + public function excludeTerms(array $terms): static { $this->excludeTerms = $terms; @@ -53,7 +53,7 @@ public function excludeTerms(array $terms): self * * @return $this */ - public function forRequest(ServerRequestInterface $request): self + public function forRequest(ServerRequestInterface $request): static { if ($request->getMethod() !== 'POST') { return $this; diff --git a/library/Notifications/Widget/ShowMore.php b/library/Notifications/Widget/ShowMore.php index 2a47e1f47..ecaa7a0e0 100644 --- a/library/Notifications/Widget/ShowMore.php +++ b/library/Notifications/Widget/ShowMore.php @@ -32,7 +32,7 @@ public function __construct(ResultSet $resultSet, Url $url, ?string $label = nul $this->url = $url; } - public function setLabel(string $label): self + public function setLabel(string $label): static { $this->label = $label; diff --git a/library/Notifications/Widget/TimeGrid/BaseGrid.php b/library/Notifications/Widget/TimeGrid/BaseGrid.php index eca89e767..66874f154 100644 --- a/library/Notifications/Widget/TimeGrid/BaseGrid.php +++ b/library/Notifications/Widget/TimeGrid/BaseGrid.php @@ -77,7 +77,7 @@ public function getGridStart(): DateTime return $this->start; } - public function setGridStart(DateTime $start): self + public function setGridStart(DateTime $start): static { $this->start = $start; diff --git a/library/Notifications/Widget/TimeGrid/DynamicGrid.php b/library/Notifications/Widget/TimeGrid/DynamicGrid.php index e595006c8..e51709a2b 100644 --- a/library/Notifications/Widget/TimeGrid/DynamicGrid.php +++ b/library/Notifications/Widget/TimeGrid/DynamicGrid.php @@ -22,7 +22,7 @@ class DynamicGrid extends BaseGrid /** @var ?BaseHtmlElement This grid's sidebar */ protected ?BaseHtmlElement $sideBar = null; - public function setGridStart(DateTime $start): BaseGrid + public function setGridStart(DateTime $start): static { if ($start->format('H:i:s') !== '00:00:00') { throw new InvalidArgumentException('Start is not midnight'); @@ -38,7 +38,7 @@ public function setGridStart(DateTime $start): BaseGrid * * @return $this */ - public function setDays(int $days): self + public function setDays(int $days): static { $this->days = $days; @@ -52,7 +52,7 @@ public function setDays(int $days): self * * @return $this */ - public function addToSideBar(BaseHtmlElement $row): self + public function addToSideBar(BaseHtmlElement $row): static { $row->addAttributes(Attributes::create(['class' => 'row-title'])); $this->sideBar()->addHtml($row); diff --git a/library/Notifications/Widget/TimeGrid/Entry.php b/library/Notifications/Widget/TimeGrid/Entry.php index fbdb3c3e2..7eb4c8369 100644 --- a/library/Notifications/Widget/TimeGrid/Entry.php +++ b/library/Notifications/Widget/TimeGrid/Entry.php @@ -89,7 +89,7 @@ public function getId(): int * * @return $this */ - public function setStart(DateTime $start): self + public function setStart(DateTime $start): static { $this->start = $start; @@ -113,7 +113,7 @@ public function getStart(): ?DateTime * * @return $this */ - public function setEnd(DateTime $end): self + public function setEnd(DateTime $end): static { $this->end = $end; @@ -137,7 +137,7 @@ public function getEnd(): ?DateTime * * @return $this */ - public function setPosition(?int $position): self + public function setPosition(?int $position): static { $this->position = $position; @@ -161,7 +161,7 @@ public function getPosition(): ?int * * @return $this */ - public function setContinuationType(?string $continuationType): self + public function setContinuationType(?string $continuationType): static { $this->continuationType = $continuationType; @@ -185,7 +185,7 @@ public function getContinuationType(): ?string * * @return $this */ - public function setUrl(?Url $url): self + public function setUrl(?Url $url): static { $this->url = $url; diff --git a/library/Notifications/Widget/TimeGrid/ExtraEntryCount.php b/library/Notifications/Widget/TimeGrid/ExtraEntryCount.php index 29532815e..b9a613062 100644 --- a/library/Notifications/Widget/TimeGrid/ExtraEntryCount.php +++ b/library/Notifications/Widget/TimeGrid/ExtraEntryCount.php @@ -27,7 +27,7 @@ class ExtraEntryCount extends ButtonLink * * @return $this */ - public function setGrid(BaseGrid $grid): self + public function setGrid(BaseGrid $grid): static { $this->grid = $grid; @@ -41,7 +41,7 @@ public function setGrid(BaseGrid $grid): self * * @return $this */ - public function setGridStep(DateTime $gridStep): self + public function setGridStep(DateTime $gridStep): static { $this->gridStep = clone $gridStep; diff --git a/library/Notifications/Widget/Timeline.php b/library/Notifications/Widget/Timeline.php index 1d54ceffa..d94a9bff3 100644 --- a/library/Notifications/Widget/Timeline.php +++ b/library/Notifications/Widget/Timeline.php @@ -67,7 +67,7 @@ class Timeline extends BaseHtmlElement implements EntryProvider * * @return $this */ - public function setStyle(Style $style): self + public function setStyle(Style $style): static { $this->style = $style; @@ -107,7 +107,7 @@ public function __construct(int $scheduleId, DateTime $start, int $days) * * @return $this */ - public function minimalLayout(): self + public function minimalLayout(): static { $this->minimalLayout = true; diff --git a/library/Notifications/Widget/Timeline/Entry.php b/library/Notifications/Widget/Timeline/Entry.php index 685777e3d..02744257d 100644 --- a/library/Notifications/Widget/Timeline/Entry.php +++ b/library/Notifications/Widget/Timeline/Entry.php @@ -33,7 +33,7 @@ class Entry extends TimeGrid\Entry */ protected string $widthClass = "wide-entry"; - public function setMember(Member $member): self + public function setMember(Member $member): static { $this->member = $member; diff --git a/library/Notifications/Widget/Timeline/Member.php b/library/Notifications/Widget/Timeline/Member.php index ba5f051cd..db82d96ab 100644 --- a/library/Notifications/Widget/Timeline/Member.php +++ b/library/Notifications/Widget/Timeline/Member.php @@ -41,7 +41,7 @@ public function getName(): string * * @return $this */ - public function setIcon(string $icon): self + public function setIcon(string $icon): static { $this->icon = $icon; diff --git a/library/Notifications/Widget/Timeline/MinimalGrid.php b/library/Notifications/Widget/Timeline/MinimalGrid.php index 2986c6a03..9dd801ba1 100644 --- a/library/Notifications/Widget/Timeline/MinimalGrid.php +++ b/library/Notifications/Widget/Timeline/MinimalGrid.php @@ -20,7 +20,7 @@ class MinimalGrid extends BaseGrid /** @var int Number of days to show in the grid */ private const DAYS = 7; - public function setGridStart(DateTime $start): BaseGrid + public function setGridStart(DateTime $start): static { if ($start->format('H:i:s') !== '00:00:00') { throw new InvalidArgumentException('Start is not midnight'); From a181f9f01a2c2222ce39165cc667785449816cbe Mon Sep 17 00:00:00 2001 From: Johannes Rauh Date: Wed, 25 Mar 2026 09:28:15 +0100 Subject: [PATCH 22/26] Narrow types where possible --- library/Notifications/Daemon/Server.php | 6 +++--- library/Notifications/Model/Daemon/Connection.php | 6 +++--- library/Notifications/Widget/TimeGrid/BaseGrid.php | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/library/Notifications/Daemon/Server.php b/library/Notifications/Daemon/Server.php index e56d3e5b0..c20709904 100644 --- a/library/Notifications/Daemon/Server.php +++ b/library/Notifications/Daemon/Server.php @@ -30,8 +30,8 @@ class Server /** @var ?Server Instance of this class */ private static ?Server $instance = null; - /** @var ?LoopInterface Reference to ReactPHP's main loop */ - protected ?LoopInterface $mainLoop = null; + /** @var LoopInterface Reference to ReactPHP's main loop */ + protected LoopInterface $mainLoop; /** @var Logger Instance of the logger class */ protected static Logger $logger; @@ -79,7 +79,7 @@ public static function get(LoopInterface &$mainLoop): Server { if (self::$instance === null) { self::$instance = new Server($mainLoop); - } elseif ((self::$instance->mainLoop !== null) && (self::$instance->mainLoop !== $mainLoop)) { + } elseif (self::$instance->mainLoop !== $mainLoop) { // main loop changed, reloading daemon server self::$instance->mainLoop = $mainLoop; self::$instance->reload(); diff --git a/library/Notifications/Model/Daemon/Connection.php b/library/Notifications/Model/Daemon/Connection.php index a90b9f53a..818791682 100644 --- a/library/Notifications/Model/Daemon/Connection.php +++ b/library/Notifications/Model/Daemon/Connection.php @@ -28,8 +28,8 @@ class Connection /** @var ThroughStream Data stream between connection and server */ protected ThroughStream $stream; - /** @var ?string User agent */ - protected ?string $userAgent = null; + /** @var string User agent */ + protected string $userAgent; /** * Construct an instance of the Connection class @@ -91,7 +91,7 @@ public function getUser(): User return $this->user; } - public function getUserAgent(): ?string + public function getUserAgent(): string { return $this->userAgent; } diff --git a/library/Notifications/Widget/TimeGrid/BaseGrid.php b/library/Notifications/Widget/TimeGrid/BaseGrid.php index 66874f154..3b50cd18a 100644 --- a/library/Notifications/Widget/TimeGrid/BaseGrid.php +++ b/library/Notifications/Widget/TimeGrid/BaseGrid.php @@ -52,7 +52,7 @@ abstract class BaseGrid extends BaseHtmlElement protected ?DateTime $end = null; - /** @var array Extra counts stored as [date1 => count1, date2 => count2] */ + /** @var array Extra counts stored as [date1 => count1, date2 => count2] */ protected array $extraEntriesCount = []; /** From 84eb151999395afc46dfe6608b966fdd3c1470e6 Mon Sep 17 00:00:00 2001 From: Bastian Lederer Date: Wed, 29 Apr 2026 08:28:57 +0200 Subject: [PATCH 23/26] `IdTagAggregator`: Remove unnecessary param annotations --- library/Notifications/Model/Behavior/IdTagAggregator.php | 4 ---- 1 file changed, 4 deletions(-) diff --git a/library/Notifications/Model/Behavior/IdTagAggregator.php b/library/Notifications/Model/Behavior/IdTagAggregator.php index dcc2eef59..ac900557c 100644 --- a/library/Notifications/Model/Behavior/IdTagAggregator.php +++ b/library/Notifications/Model/Behavior/IdTagAggregator.php @@ -87,10 +87,6 @@ public function fromDb($value, $key, $context): array } /** - * @param mixed $value - * @param mixed $key - * @param mixed $context - * * @return never * * @throws InvalidColumnException From 5b83a9b44805b8e18cca59dfac6d05e7ca1486cd Mon Sep 17 00:00:00 2001 From: Bastian Lederer Date: Wed, 29 Apr 2026 08:31:50 +0200 Subject: [PATCH 24/26] Remove `NoSubjectLink` and `EventRuleDecorator` They are no longer used anywhere --- .../Notifications/Common/NoSubjectLink.php | 35 -------------- .../Web/Form/EventRuleDecorator.php | 46 ------------------- 2 files changed, 81 deletions(-) delete mode 100644 library/Notifications/Common/NoSubjectLink.php delete mode 100644 library/Notifications/Web/Form/EventRuleDecorator.php diff --git a/library/Notifications/Common/NoSubjectLink.php b/library/Notifications/Common/NoSubjectLink.php deleted file mode 100644 index eb0a3848a..000000000 --- a/library/Notifications/Common/NoSubjectLink.php +++ /dev/null @@ -1,35 +0,0 @@ - -// SPDX-License-Identifier: GPL-3.0-or-later - -namespace Icinga\Module\Notifications\Common; - -trait NoSubjectLink -{ - protected bool $noSubjectLink = false; - - /** - * Set whether a list item's subject should be a link - * - * @param bool $state - * - * @return $this - */ - public function setNoSubjectLink(bool $state = true): static - { - $this->noSubjectLink = $state; - - return $this; - } - - /** - * Get whether a list item's subject should be a link - * - * @return bool - */ - public function getNoSubjectLink(): bool - { - return $this->noSubjectLink; - } -} diff --git a/library/Notifications/Web/Form/EventRuleDecorator.php b/library/Notifications/Web/Form/EventRuleDecorator.php deleted file mode 100644 index cf7e73191..000000000 --- a/library/Notifications/Web/Form/EventRuleDecorator.php +++ /dev/null @@ -1,46 +0,0 @@ - -// SPDX-License-Identifier: GPL-3.0-or-later - -namespace Icinga\Module\Notifications\Web\Form; - -use ipl\Html\Attributes; -use ipl\Html\Contract\FormElement; -use ipl\Html\Contract\FormElementDecorator; -use ipl\Html\HtmlDocument; -use ipl\Html\HtmlElement; -use ipl\Web\Widget\Icon; - -class EventRuleDecorator extends HtmlDocument implements FormElementDecorator -{ - private FormElement $element; - - public function decorate(FormElement $formElement): void - { - $me = clone $this; - - $me->element = $formElement; - $formElement->prependWrapper($me); - } - - protected function assemble(): void - { - $this->addHtml($this->element); - - if ($this->element->hasBeenValidated() && ! $this->element->isValid()) { - $errors = new HtmlElement('ul', Attributes::create(['class' => 'errors'])); - foreach ($this->element->getMessages() as $message) { - $errors->addHtml(new HtmlElement( - 'li', - null, - new Icon('circle-exclamation', [ - 'title' => $message - ]) - )); - } - - $this->addHtml($errors); - } - } -} From c9a1d134bfbd8366677e951fcd1ed4825b0715b0 Mon Sep 17 00:00:00 2001 From: Bastian Lederer Date: Thu, 30 Apr 2026 08:17:59 +0200 Subject: [PATCH 25/26] Remove unused imports --- test/php/application/controllers/ApiV1ChannelsTest.php | 1 - test/php/application/controllers/ApiV1ContactGroupsTest.php | 1 - test/php/application/controllers/ApiV1ContactsTest.php | 1 - 3 files changed, 3 deletions(-) diff --git a/test/php/application/controllers/ApiV1ChannelsTest.php b/test/php/application/controllers/ApiV1ChannelsTest.php index 6209db19d..98cad271d 100644 --- a/test/php/application/controllers/ApiV1ChannelsTest.php +++ b/test/php/application/controllers/ApiV1ChannelsTest.php @@ -8,7 +8,6 @@ use Icinga\Module\Notifications\Test\BaseApiV1TestCase; use Icinga\Web\Url; use ipl\Sql\Connection; -use WebSocket\Base; use PHPUnit\Framework\Attributes\DataProvider; class ApiV1ChannelsTest extends BaseApiV1TestCase diff --git a/test/php/application/controllers/ApiV1ContactGroupsTest.php b/test/php/application/controllers/ApiV1ContactGroupsTest.php index b2bed7c09..9858fdc4d 100644 --- a/test/php/application/controllers/ApiV1ContactGroupsTest.php +++ b/test/php/application/controllers/ApiV1ContactGroupsTest.php @@ -8,7 +8,6 @@ use Icinga\Module\Notifications\Test\BaseApiV1TestCase; use Icinga\Web\Url; use ipl\Sql\Connection; -use WebSocket\Base; use PHPUnit\Framework\Attributes\DataProvider; class ApiV1ContactGroupsTest extends BaseApiV1TestCase diff --git a/test/php/application/controllers/ApiV1ContactsTest.php b/test/php/application/controllers/ApiV1ContactsTest.php index a21ef177b..2815afa33 100644 --- a/test/php/application/controllers/ApiV1ContactsTest.php +++ b/test/php/application/controllers/ApiV1ContactsTest.php @@ -8,7 +8,6 @@ use Icinga\Module\Notifications\Test\BaseApiV1TestCase; use Icinga\Web\Url; use ipl\Sql\Connection; -use WebSocket\Base; use PHPUnit\Framework\Attributes\DataProvider; class ApiV1ContactsTest extends BaseApiV1TestCase From 0f538b9d2298bd0041f326eaa5cd62344c4c3eb8 Mon Sep 17 00:00:00 2001 From: Bastian Lederer Date: Thu, 30 Apr 2026 08:42:24 +0200 Subject: [PATCH 26/26] Cleanup phpstan-baseline --- phpstan-baseline-standard.neon | 222 --------------------------------- 1 file changed, 222 deletions(-) diff --git a/phpstan-baseline-standard.neon b/phpstan-baseline-standard.neon index cefcfab60..2e5eb131d 100644 --- a/phpstan-baseline-standard.neon +++ b/phpstan-baseline-standard.neon @@ -18,30 +18,12 @@ parameters: count: 1 path: application/controllers/ChannelsController.php - - - message: '#^Method Icinga\\Module\\Notifications\\Controllers\\ConfigController\:\:databaseAction\(\) has no return type specified\.$#' - identifier: missingType.return - count: 1 - path: application/controllers/ConfigController.php - - - - message: '#^Method Icinga\\Module\\Notifications\\Controllers\\ContactsController\:\:indexAction\(\) has no return type specified\.$#' - identifier: missingType.return - count: 1 - path: application/controllers/ContactsController.php - - message: '#^Cannot call method getUsername\(\) on Icinga\\User\|null\.$#' identifier: method.nonObject count: 1 path: application/controllers/IncidentController.php - - - message: '#^Parameter \#2 \$currentUserId of class Icinga\\Module\\Notifications\\Widget\\Detail\\IncidentQuickActions constructor expects int, mixed given\.$#' - identifier: argument.type - count: 1 - path: application/controllers/IncidentController.php - - message: '#^Cannot cast mixed to int\.$#' identifier: cast.int @@ -60,12 +42,6 @@ parameters: count: 1 path: application/forms/ChannelForm.php - - - message: '#^Method Icinga\\Module\\Notifications\\Forms\\DatabaseConfigForm\:\:assemble\(\) has no return type specified\.$#' - identifier: missingType.return - count: 1 - path: application/forms/DatabaseConfigForm.php - - message: '#^Argument of an invalid type array\|null supplied for foreach, only iterables are supported\.$#' identifier: foreach.nonIterable @@ -216,30 +192,12 @@ parameters: count: 2 path: library/Notifications/Web/Control/SearchBar/ExtraTagSuggestions.php - - - message: '#^Method Icinga\\Module\\Notifications\\Web\\Control\\SearchBar\\ExtraTagSuggestions\:\:fetchColumnSuggestions\(\) return type has no value type specified in iterable type Traversable\.$#' - identifier: missingType.iterableValue - count: 1 - path: library/Notifications/Web/Control/SearchBar/ExtraTagSuggestions.php - - - - message: '#^Method Icinga\\Module\\Notifications\\Web\\Control\\SearchBar\\ExtraTagSuggestions\:\:fetchValueSuggestions\(\) return type has no value type specified in iterable type Traversable\.$#' - identifier: missingType.iterableValue - count: 1 - path: library/Notifications/Web/Control/SearchBar/ExtraTagSuggestions.php - - message: '#^Method Icinga\\Module\\Notifications\\Web\\Control\\SearchBar\\ObjectSuggestions\:\:collectFilterColumns\(\) return type has no value type specified in iterable type Traversable\.$#' identifier: missingType.iterableValue count: 1 path: library/Notifications/Web/Control/SearchBar/ObjectSuggestions.php - - - message: '#^Method Icinga\\Module\\Notifications\\Web\\Control\\SearchBar\\ObjectSuggestions\:\:collectRelations\(\) has no return type specified\.$#' - identifier: missingType.return - count: 1 - path: library/Notifications/Web/Control/SearchBar/ObjectSuggestions.php - - message: '#^Method Icinga\\Module\\Notifications\\Web\\Control\\SearchBar\\ObjectSuggestions\:\:collectRelations\(\) has parameter \$models with no value type specified in iterable type array\.$#' identifier: missingType.iterableValue @@ -252,24 +210,6 @@ parameters: count: 1 path: library/Notifications/Web/Control/SearchBar/ObjectSuggestions.php - - - message: '#^Method Icinga\\Module\\Notifications\\Web\\Control\\SearchBar\\ObjectSuggestions\:\:fetchColumnSuggestions\(\) return type has no value type specified in iterable type Traversable\.$#' - identifier: missingType.iterableValue - count: 1 - path: library/Notifications/Web/Control/SearchBar/ObjectSuggestions.php - - - - message: '#^Method Icinga\\Module\\Notifications\\Web\\Control\\SearchBar\\ObjectSuggestions\:\:fetchValueSuggestions\(\) return type has no value type specified in iterable type Traversable\.$#' - identifier: missingType.iterableValue - count: 1 - path: library/Notifications/Web/Control/SearchBar/ObjectSuggestions.php - - - - message: '#^Property Icinga\\Module\\Notifications\\Web\\Control\\SearchBar\\ObjectSuggestions\:\:\$model \(ipl\\Orm\\Model\) does not accept object\.$#' - identifier: assign.propertyType - count: 1 - path: library/Notifications/Web/Control/SearchBar/ObjectSuggestions.php - - message: '#^Cannot access property \$address on mixed\.$#' identifier: property.nonObject @@ -288,36 +228,6 @@ parameters: count: 2 path: library/Notifications/Web/Form/ContactForm.php - - - message: '#^Method Icinga\\Module\\Notifications\\Web\\Form\\ContactForm\:\:assemble\(\) has no return type specified\.$#' - identifier: missingType.return - count: 1 - path: library/Notifications/Web/Form/ContactForm.php - - - - message: '#^Method Icinga\\Module\\Notifications\\Web\\Form\\EventRuleDecorator\:\:assemble\(\) has no return type specified\.$#' - identifier: missingType.return - count: 1 - path: library/Notifications/Web/Form/EventRuleDecorator.php - - - - message: '#^Method Icinga\\Module\\Notifications\\Web\\Form\\EventRuleDecorator\:\:decorate\(\) has no return type specified\.$#' - identifier: missingType.return - count: 1 - path: library/Notifications/Web/Form/EventRuleDecorator.php - - - - message: '#^Property Icinga\\Module\\Notifications\\Web\\Form\\EventRuleDecorator\:\:\$element has no type specified\.$#' - identifier: missingType.property - count: 1 - path: library/Notifications/Web/Form/EventRuleDecorator.php - - - - message: '#^Method Icinga\\Module\\Notifications\\Widget\\Calendar\:\:assemble\(\) has no return type specified\.$#' - identifier: missingType.return - count: 1 - path: library/Notifications/Widget/Calendar.php - - message: '#^Method Icinga\\Module\\Notifications\\Widget\\Calendar\:\:getModeStart\(\) should return DateTime but returns DateTime\|false\.$#' identifier: return.type @@ -336,158 +246,26 @@ parameters: count: 1 path: library/Notifications/Widget/Calendar.php - - - message: '#^Property Icinga\\Module\\Notifications\\Widget\\Calendar\:\:\$addEntryUrl \(ipl\\Web\\Url\) does not accept ipl\\Web\\Url\|null\.$#' - identifier: assign.propertyType - count: 1 - path: library/Notifications/Widget/Calendar.php - - message: '#^Method Icinga\\Module\\Notifications\\Widget\\Calendar\\Attendee\:\:setIcon\(\) has parameter \$icon with no type specified\.$#' identifier: missingType.parameter count: 1 path: library/Notifications/Widget/Calendar/Attendee.php - - - message: '#^Method Icinga\\Module\\Notifications\\Widget\\Calendar\\Controls\:\:assemble\(\) has no return type specified\.$#' - identifier: missingType.return - count: 1 - path: library/Notifications/Widget/Calendar/Controls.php - - message: '#^Method Icinga\\Module\\Notifications\\Widget\\Calendar\\Controls\:\:getViewMode\(\) should return string but returns mixed\.$#' identifier: return.type count: 1 path: library/Notifications/Widget/Calendar/Controls.php - - - message: '#^Method Icinga\\Module\\Notifications\\Widget\\Calendar\\DayGrid\:\:assemble\(\) has no return type specified\.$#' - identifier: missingType.return - count: 1 - path: library/Notifications/Widget/Calendar/DayGrid.php - - - - message: '#^Method Icinga\\Module\\Notifications\\Widget\\Calendar\\MonthGrid\:\:assemble\(\) has no return type specified\.$#' - identifier: missingType.return - count: 1 - path: library/Notifications/Widget/Calendar/MonthGrid.php - - - - message: '#^Method Icinga\\Module\\Notifications\\Widget\\Calendar\\WeekGrid\:\:assemble\(\) has no return type specified\.$#' - identifier: missingType.return - count: 1 - path: library/Notifications/Widget/Calendar/WeekGrid.php - - - - message: '#^Method Icinga\\Module\\Notifications\\Widget\\Detail\\IncidentDetail\:\:assemble\(\) has no return type specified\.$#' - identifier: missingType.return - count: 1 - path: library/Notifications/Widget/Detail/IncidentDetail.php - - - - message: '#^Method Icinga\\Module\\Notifications\\Widget\\Detail\\IncidentDetail\:\:createContacts\(\) has no return type specified\.$#' - identifier: missingType.return - count: 1 - path: library/Notifications/Widget/Detail/IncidentDetail.php - - - - message: '#^Method Icinga\\Module\\Notifications\\Widget\\Detail\\IncidentDetail\:\:createHistory\(\) has no return type specified\.$#' - identifier: missingType.return - count: 1 - path: library/Notifications/Widget/Detail/IncidentDetail.php - - - - message: '#^Method Icinga\\Module\\Notifications\\Widget\\Detail\\IncidentDetail\:\:createRelatedObject\(\) has no return type specified\.$#' - identifier: missingType.return - count: 1 - path: library/Notifications/Widget/Detail/IncidentDetail.php - - - - message: '#^Method Icinga\\Module\\Notifications\\Widget\\Detail\\IncidentDetail\:\:createSource\(\) has no return type specified\.$#' - identifier: missingType.return - count: 1 - path: library/Notifications/Widget/Detail/IncidentDetail.php - - message: '#^Cannot call method getName\(\) on ipl\\Html\\Contract\\FormSubmitElement\|null\.$#' identifier: method.nonObject count: 1 path: library/Notifications/Widget/Detail/IncidentQuickActions.php - - - message: '#^Method Icinga\\Module\\Notifications\\Widget\\Detail\\IncidentQuickActions\:\:assemble\(\) has no return type specified\.$#' - identifier: missingType.return - count: 1 - path: library/Notifications/Widget/Detail/IncidentQuickActions.php - - - - message: '#^Method Icinga\\Module\\Notifications\\Widget\\Detail\\IncidentQuickActions\:\:fetchIncidentContact\(\) should return Icinga\\Module\\Notifications\\Model\\IncidentContact but returns ipl\\Orm\\Model\.$#' - identifier: return.type - count: 1 - path: library/Notifications/Widget/Detail/IncidentQuickActions.php - - - - message: '#^Method Icinga\\Module\\Notifications\\Widget\\Detail\\IncidentQuickActions\:\:onSuccess\(\) has no return type specified\.$#' - identifier: missingType.return - count: 1 - path: library/Notifications/Widget/Detail/IncidentQuickActions.php - - - - message: '#^Property Icinga\\Module\\Notifications\\Widget\\Detail\\IncidentQuickActions\:\:\$incidentContact \(Icinga\\Module\\Notifications\\Model\\IncidentContact\) does not accept ipl\\Orm\\Model\.$#' - identifier: assign.propertyType - count: 1 - path: library/Notifications/Widget/Detail/IncidentQuickActions.php - - - - message: '#^Method Icinga\\Module\\Notifications\\Widget\\EventSourceBadge\:\:assemble\(\) has no return type specified\.$#' - identifier: missingType.return - count: 1 - path: library/Notifications/Widget/EventSourceBadge.php - - - - message: '#^Method Icinga\\Module\\Notifications\\Widget\\ItemList\\PageSeparatorItem\:\:assemble\(\) has no return type specified\.$#' - identifier: missingType.return - count: 1 - path: library/Notifications/Widget/ItemList/PageSeparatorItem.php - - - - message: '#^Method Icinga\\Module\\Notifications\\Widget\\RuleEscalationRecipientBadge\:\:assemble\(\) has no return type specified\.$#' - identifier: missingType.return - count: 1 - path: library/Notifications/Widget/RuleEscalationRecipientBadge.php - - message: '#^Method Icinga\\Module\\Notifications\\Widget\\RuleEscalationRecipientBadge\:\:createBadge\(\) has no return type specified\.$#' identifier: missingType.return count: 1 path: library/Notifications/Widget/RuleEscalationRecipientBadge.php - - - - message: '#^Property Icinga\\Module\\Notifications\\Widget\\RuleEscalationRecipientBadge\:\:\$moreCount \(int\) does not accept int\|null\.$#' - identifier: assign.propertyType - count: 1 - path: library/Notifications/Widget/RuleEscalationRecipientBadge.php - - - - message: '#^Method Icinga\\Module\\Notifications\\Widget\\ShowMore\:\:assemble\(\) has no return type specified\.$#' - identifier: missingType.return - count: 1 - path: library/Notifications/Widget/ShowMore.php - - - - message: '#^Property Icinga\\Module\\Notifications\\Widget\\ShowMore\:\:\$label has no type specified\.$#' - identifier: missingType.property - count: 1 - path: library/Notifications/Widget/ShowMore.php - - - - message: '#^Property Icinga\\Module\\Notifications\\Widget\\ShowMore\:\:\$resultSet has no type specified\.$#' - identifier: missingType.property - count: 1 - path: library/Notifications/Widget/ShowMore.php - - - - message: '#^Property Icinga\\Module\\Notifications\\Widget\\ShowMore\:\:\$url has no type specified\.$#' - identifier: missingType.property - count: 1 - path: library/Notifications/Widget/ShowMore.php