From fbacf83a13587fa719a1267a265041fb99aa3560 Mon Sep 17 00:00:00 2001 From: Mattias Geniar Date: Sat, 14 Feb 2026 14:32:37 +0100 Subject: [PATCH 01/10] Add missing resources in our API --- src/Concerns/SupportsAiResponsesEndpoints.php | 33 +++++ ...pportsApplicationHealthChecksEndpoints.php | 17 +++ .../SupportsCronCheckDefinitionsEndpoints.php | 8 ++ ...portsDnsBlocklistHistoryItemsEndpoints.php | 25 ++++ src/Concerns/SupportsDomainEndpoints.php | 17 +++ src/Concerns/SupportsMonitorEndpoints.php | 36 ++++++ ...pportsNotificationDestinationEndpoints.php | 111 ++++++++++++++++ .../SupportsPortsHistoryItemsEndpoints.php | 25 ++++ ...rtsRecurringMaintenancePeriodEndpoints.php | 51 ++++++++ src/Concerns/SupportsStatusPageEndpoints.php | 42 ++++++ ...portsStatusPageUpdateTemplateEndpoints.php | 43 +++++++ src/Concerns/SupportsTagEndpoints.php | 25 ++++ src/Concerns/SupportsTagGroupEndpoints.php | 43 +++++++ src/Dto/AiResponse.php | 36 ++++++ src/Dto/DnsBlocklistHistoryItem.php | 30 +++++ src/Dto/DomainInfo.php | 29 +++++ src/Dto/PortsHistoryItem.php | 34 +++++ src/Dto/RecurringMaintenancePeriod.php | 40 ++++++ src/Dto/StatusPageUpdateTemplate.php | 36 ++++++ src/Dto/Tag.php | 32 +++++ src/Dto/TagGroup.php | 32 +++++ src/Enums/CheckType.php | 3 + src/OhDear.php | 18 +++ .../AiResponses/GetAiResponseRequest.php | 28 ++++ .../AiResponses/GetAiResponsesRequest.php | 27 ++++ .../GetLatestAiResponseRequest.php | 27 ++++ .../SnoozeApplicationHealthCheckRequest.php | 40 ++++++ .../UnsnoozeApplicationHealthCheckRequest.php | 28 ++++ .../SyncCronCheckDefinitionsRequest.php | 39 ++++++ .../GetDnsBlocklistHistoryItemRequest.php | 28 ++++ .../GetDnsBlocklistHistoryItemsRequest.php | 27 ++++ src/Requests/Domain/GetDomainRequest.php | 27 ++++ .../AddToBrokenLinksWhitelistRequest.php | 32 +++++ .../DeleteNotificationDestinationRequest.php | 21 +++ .../Monitors/GetMonitorByUrlRequest.php | 27 ++++ .../UpdateNotificationDestinationRequest.php | 38 ++++++ ...TagGroupNotificationDestinationRequest.php | 37 ++++++ ...reateTagNotificationDestinationRequest.php | 37 ++++++ ...eateTeamNotificationDestinationRequest.php | 37 ++++++ ...TagGroupNotificationDestinationRequest.php | 21 +++ ...eleteTagNotificationDestinationRequest.php | 21 +++ ...leteTeamNotificationDestinationRequest.php | 21 +++ ...agGroupNotificationDestinationsRequest.php | 27 ++++ .../GetTagNotificationDestinationsRequest.php | 23 ++++ ...GetTeamNotificationDestinationsRequest.php | 23 ++++ ...TagGroupNotificationDestinationRequest.php | 38 ++++++ ...pdateTagNotificationDestinationRequest.php | 38 ++++++ ...dateTeamNotificationDestinationRequest.php | 38 ++++++ .../GetPortsHistoryItemRequest.php | 28 ++++ .../GetPortsHistoryItemsRequest.php | 27 ++++ ...reateRecurringMaintenancePeriodRequest.php | 36 ++++++ ...eleteRecurringMaintenancePeriodRequest.php | 20 +++ .../GetRecurringMaintenancePeriodRequest.php | 27 ++++ .../GetRecurringMaintenancePeriodsRequest.php | 27 ++++ ...pdateRecurringMaintenancePeriodRequest.php | 37 ++++++ .../AddStatusPageMonitorsRequest.php | 37 ++++++ .../StatusPages/CreateStatusPageRequest.php | 36 ++++++ .../CreateStatusPageUpdateTemplateRequest.php | 36 ++++++ .../DeleteStatusPageMonitorRequest.php | 21 +++ .../DeleteStatusPageUpdateTemplateRequest.php | 20 +++ .../GetStatusPageUpdateTemplatesRequest.php | 23 ++++ .../GetStatusPageUpdatesRequest.php | 30 +++++ .../UpdateStatusPageUpdateRequest.php | 37 ++++++ .../UpdateStatusPageUpdateTemplateRequest.php | 37 ++++++ .../TagGroups/CreateTagGroupRequest.php | 36 ++++++ .../TagGroups/DeleteTagGroupRequest.php | 20 +++ .../TagGroups/GetTagGroupsRequest.php | 23 ++++ .../TagGroups/UpdateTagGroupRequest.php | 37 ++++++ src/Requests/Tags/CreateTagRequest.php | 36 ++++++ src/Requests/Tags/GetTagsRequest.php | 23 ++++ .../Saloon/add-status-page-monitors.json | 1 + .../Saloon/add-to-broken-links-whitelist.json | 1 + tests/Fixtures/Saloon/ai-response.json | 1 + tests/Fixtures/Saloon/ai-responses.json | 1 + .../create-recurring-maintenance-period.json | 1 + .../create-status-page-update-template.json | 1 + tests/Fixtures/Saloon/create-status-page.json | 1 + ...te-tag-group-notification-destination.json | 1 + tests/Fixtures/Saloon/create-tag-group.json | 1 + .../create-tag-notification-destination.json | 1 + tests/Fixtures/Saloon/create-tag.json | 1 + .../create-team-notification-destination.json | 1 + .../delete-notification-destination.json | 1 + .../delete-recurring-maintenance-period.json | 1 + .../Saloon/delete-status-page-monitor.json | 1 + .../delete-status-page-update-template.json | 1 + tests/Fixtures/Saloon/delete-tag-group.json | 1 + .../Saloon/dns-blocklist-history-item.json | 1 + .../Saloon/dns-blocklist-history-items.json | 1 + tests/Fixtures/Saloon/domain.json | 1 + tests/Fixtures/Saloon/latest-ai-response.json | 1 + tests/Fixtures/Saloon/monitor-by-url.json | 1 + tests/Fixtures/Saloon/ports-history-item.json | 1 + .../Fixtures/Saloon/ports-history-items.json | 1 + .../Saloon/recurring-maintenance-period.json | 1 + .../Saloon/recurring-maintenance-periods.json | 1 + .../snooze-application-health-check.json | 1 + .../Saloon/status-page-update-templates.json | 1 + .../Fixtures/Saloon/status-page-updates.json | 1 + .../Saloon/sync-cron-check-definitions.json | 1 + .../tag-group-notification-destinations.json | 1 + tests/Fixtures/Saloon/tag-groups.json | 1 + .../Saloon/tag-notification-destinations.json | 1 + tests/Fixtures/Saloon/tags.json | 1 + .../team-notification-destinations.json | 1 + .../unsnooze-application-health-check.json | 1 + .../update-notification-destination.json | 1 + .../update-recurring-maintenance-period.json | 1 + .../update-status-page-update-template.json | 1 + .../Saloon/update-status-page-update.json | 1 + tests/Fixtures/Saloon/update-tag-group.json | 1 + tests/OhDearTests/AiResponsesTest.php | 48 +++++++ .../ApplicationHealthChecksTest.php | 26 ++++ .../OhDearTests/CronCheckDefinitionsTest.php | 17 +++ .../DnsBlocklistHistoryItemsTest.php | 37 ++++++ tests/OhDearTests/DomainTest.php | 21 +++ tests/OhDearTests/MonitorsTest.php | 23 ++++ .../NotificationDestinationsTest.php | 121 ++++++++++++++++++ tests/OhDearTests/PortsHistoryItemsTest.php | 36 ++++++ .../RecurringMaintenancePeriodsTest.php | 83 ++++++++++++ .../StatusPageUpdateTemplatesTest.php | 66 ++++++++++ tests/OhDearTests/StatusPagesTest.php | 70 ++++++++++ tests/OhDearTests/TagGroupsTest.php | 63 +++++++++ tests/OhDearTests/TagsTest.php | 38 ++++++ 124 files changed, 2860 insertions(+) create mode 100644 src/Concerns/SupportsAiResponsesEndpoints.php create mode 100644 src/Concerns/SupportsDnsBlocklistHistoryItemsEndpoints.php create mode 100644 src/Concerns/SupportsDomainEndpoints.php create mode 100644 src/Concerns/SupportsNotificationDestinationEndpoints.php create mode 100644 src/Concerns/SupportsPortsHistoryItemsEndpoints.php create mode 100644 src/Concerns/SupportsRecurringMaintenancePeriodEndpoints.php create mode 100644 src/Concerns/SupportsStatusPageUpdateTemplateEndpoints.php create mode 100644 src/Concerns/SupportsTagEndpoints.php create mode 100644 src/Concerns/SupportsTagGroupEndpoints.php create mode 100644 src/Dto/AiResponse.php create mode 100644 src/Dto/DnsBlocklistHistoryItem.php create mode 100644 src/Dto/DomainInfo.php create mode 100644 src/Dto/PortsHistoryItem.php create mode 100644 src/Dto/RecurringMaintenancePeriod.php create mode 100644 src/Dto/StatusPageUpdateTemplate.php create mode 100644 src/Dto/Tag.php create mode 100644 src/Dto/TagGroup.php create mode 100644 src/Requests/AiResponses/GetAiResponseRequest.php create mode 100644 src/Requests/AiResponses/GetAiResponsesRequest.php create mode 100644 src/Requests/AiResponses/GetLatestAiResponseRequest.php create mode 100644 src/Requests/ApplicationHealthChecks/SnoozeApplicationHealthCheckRequest.php create mode 100644 src/Requests/ApplicationHealthChecks/UnsnoozeApplicationHealthCheckRequest.php create mode 100644 src/Requests/CronCheckDefinitions/SyncCronCheckDefinitionsRequest.php create mode 100644 src/Requests/DnsBlocklistHistoryItems/GetDnsBlocklistHistoryItemRequest.php create mode 100644 src/Requests/DnsBlocklistHistoryItems/GetDnsBlocklistHistoryItemsRequest.php create mode 100644 src/Requests/Domain/GetDomainRequest.php create mode 100644 src/Requests/Monitors/AddToBrokenLinksWhitelistRequest.php create mode 100644 src/Requests/Monitors/DeleteNotificationDestinationRequest.php create mode 100644 src/Requests/Monitors/GetMonitorByUrlRequest.php create mode 100644 src/Requests/Monitors/UpdateNotificationDestinationRequest.php create mode 100644 src/Requests/NotificationDestinations/CreateTagGroupNotificationDestinationRequest.php create mode 100644 src/Requests/NotificationDestinations/CreateTagNotificationDestinationRequest.php create mode 100644 src/Requests/NotificationDestinations/CreateTeamNotificationDestinationRequest.php create mode 100644 src/Requests/NotificationDestinations/DeleteTagGroupNotificationDestinationRequest.php create mode 100644 src/Requests/NotificationDestinations/DeleteTagNotificationDestinationRequest.php create mode 100644 src/Requests/NotificationDestinations/DeleteTeamNotificationDestinationRequest.php create mode 100644 src/Requests/NotificationDestinations/GetTagGroupNotificationDestinationsRequest.php create mode 100644 src/Requests/NotificationDestinations/GetTagNotificationDestinationsRequest.php create mode 100644 src/Requests/NotificationDestinations/GetTeamNotificationDestinationsRequest.php create mode 100644 src/Requests/NotificationDestinations/UpdateTagGroupNotificationDestinationRequest.php create mode 100644 src/Requests/NotificationDestinations/UpdateTagNotificationDestinationRequest.php create mode 100644 src/Requests/NotificationDestinations/UpdateTeamNotificationDestinationRequest.php create mode 100644 src/Requests/PortsHistoryItems/GetPortsHistoryItemRequest.php create mode 100644 src/Requests/PortsHistoryItems/GetPortsHistoryItemsRequest.php create mode 100644 src/Requests/RecurringMaintenancePeriods/CreateRecurringMaintenancePeriodRequest.php create mode 100644 src/Requests/RecurringMaintenancePeriods/DeleteRecurringMaintenancePeriodRequest.php create mode 100644 src/Requests/RecurringMaintenancePeriods/GetRecurringMaintenancePeriodRequest.php create mode 100644 src/Requests/RecurringMaintenancePeriods/GetRecurringMaintenancePeriodsRequest.php create mode 100644 src/Requests/RecurringMaintenancePeriods/UpdateRecurringMaintenancePeriodRequest.php create mode 100644 src/Requests/StatusPages/AddStatusPageMonitorsRequest.php create mode 100644 src/Requests/StatusPages/CreateStatusPageRequest.php create mode 100644 src/Requests/StatusPages/CreateStatusPageUpdateTemplateRequest.php create mode 100644 src/Requests/StatusPages/DeleteStatusPageMonitorRequest.php create mode 100644 src/Requests/StatusPages/DeleteStatusPageUpdateTemplateRequest.php create mode 100644 src/Requests/StatusPages/GetStatusPageUpdateTemplatesRequest.php create mode 100644 src/Requests/StatusPages/GetStatusPageUpdatesRequest.php create mode 100644 src/Requests/StatusPages/UpdateStatusPageUpdateRequest.php create mode 100644 src/Requests/StatusPages/UpdateStatusPageUpdateTemplateRequest.php create mode 100644 src/Requests/TagGroups/CreateTagGroupRequest.php create mode 100644 src/Requests/TagGroups/DeleteTagGroupRequest.php create mode 100644 src/Requests/TagGroups/GetTagGroupsRequest.php create mode 100644 src/Requests/TagGroups/UpdateTagGroupRequest.php create mode 100644 src/Requests/Tags/CreateTagRequest.php create mode 100644 src/Requests/Tags/GetTagsRequest.php create mode 100644 tests/Fixtures/Saloon/add-status-page-monitors.json create mode 100644 tests/Fixtures/Saloon/add-to-broken-links-whitelist.json create mode 100644 tests/Fixtures/Saloon/ai-response.json create mode 100644 tests/Fixtures/Saloon/ai-responses.json create mode 100644 tests/Fixtures/Saloon/create-recurring-maintenance-period.json create mode 100644 tests/Fixtures/Saloon/create-status-page-update-template.json create mode 100644 tests/Fixtures/Saloon/create-status-page.json create mode 100644 tests/Fixtures/Saloon/create-tag-group-notification-destination.json create mode 100644 tests/Fixtures/Saloon/create-tag-group.json create mode 100644 tests/Fixtures/Saloon/create-tag-notification-destination.json create mode 100644 tests/Fixtures/Saloon/create-tag.json create mode 100644 tests/Fixtures/Saloon/create-team-notification-destination.json create mode 100644 tests/Fixtures/Saloon/delete-notification-destination.json create mode 100644 tests/Fixtures/Saloon/delete-recurring-maintenance-period.json create mode 100644 tests/Fixtures/Saloon/delete-status-page-monitor.json create mode 100644 tests/Fixtures/Saloon/delete-status-page-update-template.json create mode 100644 tests/Fixtures/Saloon/delete-tag-group.json create mode 100644 tests/Fixtures/Saloon/dns-blocklist-history-item.json create mode 100644 tests/Fixtures/Saloon/dns-blocklist-history-items.json create mode 100644 tests/Fixtures/Saloon/domain.json create mode 100644 tests/Fixtures/Saloon/latest-ai-response.json create mode 100644 tests/Fixtures/Saloon/monitor-by-url.json create mode 100644 tests/Fixtures/Saloon/ports-history-item.json create mode 100644 tests/Fixtures/Saloon/ports-history-items.json create mode 100644 tests/Fixtures/Saloon/recurring-maintenance-period.json create mode 100644 tests/Fixtures/Saloon/recurring-maintenance-periods.json create mode 100644 tests/Fixtures/Saloon/snooze-application-health-check.json create mode 100644 tests/Fixtures/Saloon/status-page-update-templates.json create mode 100644 tests/Fixtures/Saloon/status-page-updates.json create mode 100644 tests/Fixtures/Saloon/sync-cron-check-definitions.json create mode 100644 tests/Fixtures/Saloon/tag-group-notification-destinations.json create mode 100644 tests/Fixtures/Saloon/tag-groups.json create mode 100644 tests/Fixtures/Saloon/tag-notification-destinations.json create mode 100644 tests/Fixtures/Saloon/tags.json create mode 100644 tests/Fixtures/Saloon/team-notification-destinations.json create mode 100644 tests/Fixtures/Saloon/unsnooze-application-health-check.json create mode 100644 tests/Fixtures/Saloon/update-notification-destination.json create mode 100644 tests/Fixtures/Saloon/update-recurring-maintenance-period.json create mode 100644 tests/Fixtures/Saloon/update-status-page-update-template.json create mode 100644 tests/Fixtures/Saloon/update-status-page-update.json create mode 100644 tests/Fixtures/Saloon/update-tag-group.json create mode 100644 tests/OhDearTests/AiResponsesTest.php create mode 100644 tests/OhDearTests/DnsBlocklistHistoryItemsTest.php create mode 100644 tests/OhDearTests/DomainTest.php create mode 100644 tests/OhDearTests/NotificationDestinationsTest.php create mode 100644 tests/OhDearTests/PortsHistoryItemsTest.php create mode 100644 tests/OhDearTests/RecurringMaintenancePeriodsTest.php create mode 100644 tests/OhDearTests/StatusPageUpdateTemplatesTest.php create mode 100644 tests/OhDearTests/TagGroupsTest.php create mode 100644 tests/OhDearTests/TagsTest.php diff --git a/src/Concerns/SupportsAiResponsesEndpoints.php b/src/Concerns/SupportsAiResponsesEndpoints.php new file mode 100644 index 0000000..ae6a290 --- /dev/null +++ b/src/Concerns/SupportsAiResponsesEndpoints.php @@ -0,0 +1,33 @@ +send($request)->dtoOrFail(); + } + + public function aiResponse(int $monitorId, int $aiResponseId): AiResponse + { + $request = new GetAiResponseRequest($monitorId, $aiResponseId); + + return $this->send($request)->dto(); + } + + public function latestAiResponse(int $monitorId): AiResponse + { + $request = new GetLatestAiResponseRequest($monitorId); + + return $this->send($request)->dto(); + } +} diff --git a/src/Concerns/SupportsApplicationHealthChecksEndpoints.php b/src/Concerns/SupportsApplicationHealthChecksEndpoints.php index 92fe5de..3e93a09 100644 --- a/src/Concerns/SupportsApplicationHealthChecksEndpoints.php +++ b/src/Concerns/SupportsApplicationHealthChecksEndpoints.php @@ -2,8 +2,11 @@ namespace OhDear\PhpSdk\Concerns; +use OhDear\PhpSdk\Dto\ApplicationHealthCheck; use OhDear\PhpSdk\Requests\ApplicationHealthChecks\GetApplicationHealthCheckHistoryRequest; use OhDear\PhpSdk\Requests\ApplicationHealthChecks\GetApplicationHealthChecksRequest; +use OhDear\PhpSdk\Requests\ApplicationHealthChecks\SnoozeApplicationHealthCheckRequest; +use OhDear\PhpSdk\Requests\ApplicationHealthChecks\UnsnoozeApplicationHealthCheckRequest; trait SupportsApplicationHealthChecksEndpoints { @@ -20,4 +23,18 @@ public function applicationHealthCheckHistory(int $monitorId, int $applicationHe return $this->send($request)->dtoOrFail(); } + + public function snoozeApplicationHealthCheck(int $monitorId, int $healthCheckId, int $minutes): ApplicationHealthCheck + { + $request = new SnoozeApplicationHealthCheckRequest($monitorId, $healthCheckId, $minutes); + + return $this->send($request)->dto(); + } + + public function unsnoozeApplicationHealthCheck(int $monitorId, int $healthCheckId): ApplicationHealthCheck + { + $request = new UnsnoozeApplicationHealthCheckRequest($monitorId, $healthCheckId); + + return $this->send($request)->dto(); + } } diff --git a/src/Concerns/SupportsCronCheckDefinitionsEndpoints.php b/src/Concerns/SupportsCronCheckDefinitionsEndpoints.php index db0fa20..c9d93c8 100644 --- a/src/Concerns/SupportsCronCheckDefinitionsEndpoints.php +++ b/src/Concerns/SupportsCronCheckDefinitionsEndpoints.php @@ -7,6 +7,7 @@ use OhDear\PhpSdk\Requests\CronCheckDefinitions\DeleteCronCheckDefinitionRequest; use OhDear\PhpSdk\Requests\CronCheckDefinitions\GetCronCheckDefinitionsRequest; use OhDear\PhpSdk\Requests\CronCheckDefinitions\SnoozeCronCheckDefinitionRequest; +use OhDear\PhpSdk\Requests\CronCheckDefinitions\SyncCronCheckDefinitionsRequest; use OhDear\PhpSdk\Requests\CronCheckDefinitions\UnsnoozeCronCheckDefinitionRequest; use OhDear\PhpSdk\Requests\CronCheckDefinitions\UpdateCronCheckDefinitionRequest; @@ -61,4 +62,11 @@ public function unsnoozeCronCheckDefinition(int $cronCheckDefinitionId): CronChe return $this->send($request)->dtoOrFail(); } + + public function syncCronCheckDefinitions(int $monitorId, array $cronChecks): array + { + $request = new SyncCronCheckDefinitionsRequest($monitorId, $cronChecks); + + return $this->send($request)->dtoOrFail(); + } } diff --git a/src/Concerns/SupportsDnsBlocklistHistoryItemsEndpoints.php b/src/Concerns/SupportsDnsBlocklistHistoryItemsEndpoints.php new file mode 100644 index 0000000..7633c00 --- /dev/null +++ b/src/Concerns/SupportsDnsBlocklistHistoryItemsEndpoints.php @@ -0,0 +1,25 @@ +send($request)->dtoOrFail(); + } + + public function dnsBlocklistHistoryItem(int $monitorId, int $dnsBlocklistHistoryItemId): DnsBlocklistHistoryItem + { + $request = new GetDnsBlocklistHistoryItemRequest($monitorId, $dnsBlocklistHistoryItemId); + + return $this->send($request)->dto(); + } +} diff --git a/src/Concerns/SupportsDomainEndpoints.php b/src/Concerns/SupportsDomainEndpoints.php new file mode 100644 index 0000000..8602df8 --- /dev/null +++ b/src/Concerns/SupportsDomainEndpoints.php @@ -0,0 +1,17 @@ +send($request)->dto(); + } +} diff --git a/src/Concerns/SupportsMonitorEndpoints.php b/src/Concerns/SupportsMonitorEndpoints.php index 1415a4f..c9ba3f6 100644 --- a/src/Concerns/SupportsMonitorEndpoints.php +++ b/src/Concerns/SupportsMonitorEndpoints.php @@ -6,14 +6,18 @@ use OhDear\PhpSdk\Dto\Monitor; use OhDear\PhpSdk\Dto\NotificationDestination; use OhDear\PhpSdk\Enums\CheckType; +use OhDear\PhpSdk\Requests\Monitors\AddToBrokenLinksWhitelistRequest; use OhDear\PhpSdk\Requests\Monitors\CreateMonitorRequest; use OhDear\PhpSdk\Requests\Monitors\CreateNotificationDestinationsRequest; use OhDear\PhpSdk\Requests\Monitors\DeleteMonitorRequest; +use OhDear\PhpSdk\Requests\Monitors\DeleteNotificationDestinationRequest; use OhDear\PhpSdk\Requests\Monitors\GetCheckSummaryRequest; +use OhDear\PhpSdk\Requests\Monitors\GetMonitorByUrlRequest; use OhDear\PhpSdk\Requests\Monitors\GetMonitorRequest; use OhDear\PhpSdk\Requests\Monitors\GetMonitorsRequest; use OhDear\PhpSdk\Requests\Monitors\GetNotificationDestinationsRequest; use OhDear\PhpSdk\Requests\Monitors\UpdateMonitorRequest; +use OhDear\PhpSdk\Requests\Monitors\UpdateNotificationDestinationRequest; /** @mixin \OhDear\PhpSdk\OhDear */ trait SupportsMonitorEndpoints @@ -79,4 +83,36 @@ public function createNotificationDestination(int $monitorId, array $properties) return $this->send($request)->dto(); } + + public function monitorByUrl(string $url): Monitor + { + $request = new GetMonitorByUrlRequest($url); + + return $this->send($request)->dto(); + } + + public function addToBrokenLinksWhitelist(int $monitorId, string $url): self + { + $request = new AddToBrokenLinksWhitelistRequest($monitorId, $url); + + $this->send($request); + + return $this; + } + + public function updateNotificationDestination(int $monitorId, int $destinationId, array $data): NotificationDestination + { + $request = new UpdateNotificationDestinationRequest($monitorId, $destinationId, $data); + + return $this->send($request)->dto(); + } + + public function deleteNotificationDestination(int $monitorId, int $destinationId): self + { + $request = new DeleteNotificationDestinationRequest($monitorId, $destinationId); + + $this->send($request); + + return $this; + } } diff --git a/src/Concerns/SupportsNotificationDestinationEndpoints.php b/src/Concerns/SupportsNotificationDestinationEndpoints.php new file mode 100644 index 0000000..1b66490 --- /dev/null +++ b/src/Concerns/SupportsNotificationDestinationEndpoints.php @@ -0,0 +1,111 @@ +send($request)->dto(); + } + + public function createTeamNotificationDestination(int $teamId, array $data): NotificationDestination + { + $request = new CreateTeamNotificationDestinationRequest($teamId, $data); + + return $this->send($request)->dto(); + } + + public function updateTeamNotificationDestination(int $teamId, int $destinationId, array $data): NotificationDestination + { + $request = new UpdateTeamNotificationDestinationRequest($teamId, $destinationId, $data); + + return $this->send($request)->dto(); + } + + public function deleteTeamNotificationDestination(int $teamId, int $destinationId): self + { + $request = new DeleteTeamNotificationDestinationRequest($teamId, $destinationId); + + $this->send($request); + + return $this; + } + + public function tagNotificationDestinations(): array + { + $request = new GetTagNotificationDestinationsRequest(); + + return $this->send($request)->dto(); + } + + public function createTagNotificationDestination(int $tagId, array $data): NotificationDestination + { + $request = new CreateTagNotificationDestinationRequest($tagId, $data); + + return $this->send($request)->dto(); + } + + public function updateTagNotificationDestination(int $tagId, int $destinationId, array $data): NotificationDestination + { + $request = new UpdateTagNotificationDestinationRequest($tagId, $destinationId, $data); + + return $this->send($request)->dto(); + } + + public function deleteTagNotificationDestination(int $tagId, int $destinationId): self + { + $request = new DeleteTagNotificationDestinationRequest($tagId, $destinationId); + + $this->send($request); + + return $this; + } + + public function tagGroupNotificationDestinations(int $tagGroupId): array + { + $request = new GetTagGroupNotificationDestinationsRequest($tagGroupId); + + return $this->send($request)->dto(); + } + + public function createTagGroupNotificationDestination(int $tagGroupId, array $data): NotificationDestination + { + $request = new CreateTagGroupNotificationDestinationRequest($tagGroupId, $data); + + return $this->send($request)->dto(); + } + + public function updateTagGroupNotificationDestination(int $tagGroupId, int $destinationId, array $data): NotificationDestination + { + $request = new UpdateTagGroupNotificationDestinationRequest($tagGroupId, $destinationId, $data); + + return $this->send($request)->dto(); + } + + public function deleteTagGroupNotificationDestination(int $tagGroupId, int $destinationId): self + { + $request = new DeleteTagGroupNotificationDestinationRequest($tagGroupId, $destinationId); + + $this->send($request); + + return $this; + } +} diff --git a/src/Concerns/SupportsPortsHistoryItemsEndpoints.php b/src/Concerns/SupportsPortsHistoryItemsEndpoints.php new file mode 100644 index 0000000..3188178 --- /dev/null +++ b/src/Concerns/SupportsPortsHistoryItemsEndpoints.php @@ -0,0 +1,25 @@ +send($request)->dtoOrFail(); + } + + public function portsHistoryItem(int $monitorId, int $portsHistoryItemId): PortsHistoryItem + { + $request = new GetPortsHistoryItemRequest($monitorId, $portsHistoryItemId); + + return $this->send($request)->dto(); + } +} diff --git a/src/Concerns/SupportsRecurringMaintenancePeriodEndpoints.php b/src/Concerns/SupportsRecurringMaintenancePeriodEndpoints.php new file mode 100644 index 0000000..6e3d249 --- /dev/null +++ b/src/Concerns/SupportsRecurringMaintenancePeriodEndpoints.php @@ -0,0 +1,51 @@ +send($request)->dtoOrFail(); + } + + public function recurringMaintenancePeriod(int $recurringMaintenancePeriodId): RecurringMaintenancePeriod + { + $request = new GetRecurringMaintenancePeriodRequest($recurringMaintenancePeriodId); + + return $this->send($request)->dto(); + } + + public function createRecurringMaintenancePeriod(array $data): RecurringMaintenancePeriod + { + $request = new CreateRecurringMaintenancePeriodRequest($data); + + return $this->send($request)->dto(); + } + + public function updateRecurringMaintenancePeriod(int $id, array $data): RecurringMaintenancePeriod + { + $request = new UpdateRecurringMaintenancePeriodRequest($id, $data); + + return $this->send($request)->dto(); + } + + public function deleteRecurringMaintenancePeriod(int $id): self + { + $request = new DeleteRecurringMaintenancePeriodRequest($id); + + $this->send($request); + + return $this; + } +} diff --git a/src/Concerns/SupportsStatusPageEndpoints.php b/src/Concerns/SupportsStatusPageEndpoints.php index e32fdc7..ba51736 100644 --- a/src/Concerns/SupportsStatusPageEndpoints.php +++ b/src/Concerns/SupportsStatusPageEndpoints.php @@ -4,11 +4,16 @@ use OhDear\PhpSdk\Dto\StatusPage; use OhDear\PhpSdk\Dto\StatusPageUpdate; +use OhDear\PhpSdk\Requests\StatusPages\AddStatusPageMonitorsRequest; +use OhDear\PhpSdk\Requests\StatusPages\CreateStatusPageRequest; use OhDear\PhpSdk\Requests\StatusPages\CreateStatusPageUpdateRequest; +use OhDear\PhpSdk\Requests\StatusPages\DeleteStatusPageMonitorRequest; use OhDear\PhpSdk\Requests\StatusPages\DeleteStatusPageRequest; use OhDear\PhpSdk\Requests\StatusPages\DeleteStatusPageUpdateRequest; use OhDear\PhpSdk\Requests\StatusPages\GetStatusPageRequest; use OhDear\PhpSdk\Requests\StatusPages\GetStatusPagesRequest; +use OhDear\PhpSdk\Requests\StatusPages\GetStatusPageUpdatesRequest; +use OhDear\PhpSdk\Requests\StatusPages\UpdateStatusPageUpdateRequest; /** @mixin \OhDear\PhpSdk\OhDear */ trait SupportsStatusPageEndpoints @@ -55,4 +60,41 @@ public function deleteStatusPageUpdate(int $statusPageUpdateId): self return $this; } + + public function createStatusPage(array $data): StatusPage + { + $request = new CreateStatusPageRequest($data); + + return $this->send($request)->dto(); + } + + public function addStatusPageMonitors(int $statusPageId, array $data): StatusPage + { + $request = new AddStatusPageMonitorsRequest($statusPageId, $data); + + return $this->send($request)->dto(); + } + + public function deleteStatusPageMonitor(int $statusPageId, int $monitorId): self + { + $request = new DeleteStatusPageMonitorRequest($statusPageId, $monitorId); + + $this->send($request); + + return $this; + } + + public function statusPageUpdates(int $statusPageId): array + { + $request = new GetStatusPageUpdatesRequest($statusPageId); + + return $this->send($request)->dtoOrFail(); + } + + public function updateStatusPageUpdate(int $statusPageUpdateId, array $data): StatusPageUpdate + { + $request = new UpdateStatusPageUpdateRequest($statusPageUpdateId, $data); + + return $this->send($request)->dto(); + } } diff --git a/src/Concerns/SupportsStatusPageUpdateTemplateEndpoints.php b/src/Concerns/SupportsStatusPageUpdateTemplateEndpoints.php new file mode 100644 index 0000000..50f100d --- /dev/null +++ b/src/Concerns/SupportsStatusPageUpdateTemplateEndpoints.php @@ -0,0 +1,43 @@ +send($request)->dtoOrFail(); + } + + public function createStatusPageUpdateTemplate(array $data): StatusPageUpdateTemplate + { + $request = new CreateStatusPageUpdateTemplateRequest($data); + + return $this->send($request)->dto(); + } + + public function updateStatusPageUpdateTemplate(int $id, array $data): StatusPageUpdateTemplate + { + $request = new UpdateStatusPageUpdateTemplateRequest($id, $data); + + return $this->send($request)->dto(); + } + + public function deleteStatusPageUpdateTemplate(int $id): self + { + $request = new DeleteStatusPageUpdateTemplateRequest($id); + + $this->send($request); + + return $this; + } +} diff --git a/src/Concerns/SupportsTagEndpoints.php b/src/Concerns/SupportsTagEndpoints.php new file mode 100644 index 0000000..e6f3a5c --- /dev/null +++ b/src/Concerns/SupportsTagEndpoints.php @@ -0,0 +1,25 @@ +send($request)->dtoOrFail(); + } + + public function createTag(array $data): Tag + { + $request = new CreateTagRequest($data); + + return $this->send($request)->dto(); + } +} diff --git a/src/Concerns/SupportsTagGroupEndpoints.php b/src/Concerns/SupportsTagGroupEndpoints.php new file mode 100644 index 0000000..75d742f --- /dev/null +++ b/src/Concerns/SupportsTagGroupEndpoints.php @@ -0,0 +1,43 @@ +send($request)->dtoOrFail(); + } + + public function createTagGroup(array $data): TagGroup + { + $request = new CreateTagGroupRequest($data); + + return $this->send($request)->dto(); + } + + public function updateTagGroup(int $tagGroupId, array $data): TagGroup + { + $request = new UpdateTagGroupRequest($tagGroupId, $data); + + return $this->send($request)->dto(); + } + + public function deleteTagGroup(int $tagGroupId): self + { + $request = new DeleteTagGroupRequest($tagGroupId); + + $this->send($request); + + return $this; + } +} diff --git a/src/Dto/AiResponse.php b/src/Dto/AiResponse.php new file mode 100644 index 0000000..48c91f8 --- /dev/null +++ b/src/Dto/AiResponse.php @@ -0,0 +1,36 @@ + self::fromResponse($item), $items); + } +} diff --git a/src/Dto/DnsBlocklistHistoryItem.php b/src/Dto/DnsBlocklistHistoryItem.php new file mode 100644 index 0000000..4520372 --- /dev/null +++ b/src/Dto/DnsBlocklistHistoryItem.php @@ -0,0 +1,30 @@ + self::fromResponse($item), $items); + } +} diff --git a/src/Dto/DomainInfo.php b/src/Dto/DomainInfo.php new file mode 100644 index 0000000..e8fe045 --- /dev/null +++ b/src/Dto/DomainInfo.php @@ -0,0 +1,29 @@ + self::fromResponse($item), $items); + } +} diff --git a/src/Dto/RecurringMaintenancePeriod.php b/src/Dto/RecurringMaintenancePeriod.php new file mode 100644 index 0000000..6f90d02 --- /dev/null +++ b/src/Dto/RecurringMaintenancePeriod.php @@ -0,0 +1,40 @@ + self::fromResponse($item), $items); + } +} diff --git a/src/Dto/StatusPageUpdateTemplate.php b/src/Dto/StatusPageUpdateTemplate.php new file mode 100644 index 0000000..f19701a --- /dev/null +++ b/src/Dto/StatusPageUpdateTemplate.php @@ -0,0 +1,36 @@ + self::fromResponse($item), $items); + } +} diff --git a/src/Dto/Tag.php b/src/Dto/Tag.php new file mode 100644 index 0000000..ac3202b --- /dev/null +++ b/src/Dto/Tag.php @@ -0,0 +1,32 @@ + self::fromResponse($item), $items); + } +} diff --git a/src/Dto/TagGroup.php b/src/Dto/TagGroup.php new file mode 100644 index 0000000..9d31136 --- /dev/null +++ b/src/Dto/TagGroup.php @@ -0,0 +1,32 @@ + self::fromResponse($item), $items); + } +} diff --git a/src/Enums/CheckType.php b/src/Enums/CheckType.php index 6251843..274859a 100644 --- a/src/Enums/CheckType.php +++ b/src/Enums/CheckType.php @@ -15,4 +15,7 @@ enum CheckType: string case Sitemap = 'sitemap'; case Dns = 'dns'; case Domain = 'domain'; + case DnsBlocklist = 'dns_blocklist'; + case PortScanning = 'port_scanning'; + case Ai = 'ai'; } diff --git a/src/OhDear.php b/src/OhDear.php index 7cc9256..bee098d 100644 --- a/src/OhDear.php +++ b/src/OhDear.php @@ -2,21 +2,30 @@ namespace OhDear\PhpSdk; +use OhDear\PhpSdk\Concerns\SupportsAiResponsesEndpoints; use OhDear\PhpSdk\Concerns\SupportsApplicationHealthChecksEndpoints; use OhDear\PhpSdk\Concerns\SupportsBrokenLinksEndpoints; use OhDear\PhpSdk\Concerns\SupportsCertificateHealthEndpoints; use OhDear\PhpSdk\Concerns\SupportsCheckEndpoints; use OhDear\PhpSdk\Concerns\SupportsCronCheckDefinitionsEndpoints; use OhDear\PhpSdk\Concerns\SupportsDetectedCertificatesEndpoints; +use OhDear\PhpSdk\Concerns\SupportsDnsBlocklistHistoryItemsEndpoints; use OhDear\PhpSdk\Concerns\SupportsDnsHistoryItemsEndpoints; +use OhDear\PhpSdk\Concerns\SupportsDomainEndpoints; use OhDear\PhpSdk\Concerns\SupportsDowntimeEndpoints; use OhDear\PhpSdk\Concerns\SupportsLighthouseReportsEndpoints; use OhDear\PhpSdk\Concerns\SupportsMaintenancePeriodEndpoints; use OhDear\PhpSdk\Concerns\SupportsMeEndpoint; use OhDear\PhpSdk\Concerns\SupportsMixedContentEndpoints; use OhDear\PhpSdk\Concerns\SupportsMonitorEndpoints; +use OhDear\PhpSdk\Concerns\SupportsNotificationDestinationEndpoints; +use OhDear\PhpSdk\Concerns\SupportsPortsHistoryItemsEndpoints; +use OhDear\PhpSdk\Concerns\SupportsRecurringMaintenancePeriodEndpoints; use OhDear\PhpSdk\Concerns\SupportsSitemapEndpoints; use OhDear\PhpSdk\Concerns\SupportsStatusPageEndpoints; +use OhDear\PhpSdk\Concerns\SupportsStatusPageUpdateTemplateEndpoints; +use OhDear\PhpSdk\Concerns\SupportsTagEndpoints; +use OhDear\PhpSdk\Concerns\SupportsTagGroupEndpoints; use OhDear\PhpSdk\Concerns\SupportsUptimeEndpoints; use OhDear\PhpSdk\Concerns\SupportsUptimeMetricsEndpoints; use OhDear\PhpSdk\Exceptions\OhDearException; @@ -36,21 +45,30 @@ class OhDear extends Connector implements HasPagination { use AcceptsJson; use AlwaysThrowOnErrors; + use SupportsAiResponsesEndpoints; use SupportsApplicationHealthChecksEndpoints; use SupportsBrokenLinksEndpoints; use SupportsCertificateHealthEndpoints; use SupportsCheckEndpoints; use SupportsCronCheckDefinitionsEndpoints; use SupportsDetectedCertificatesEndpoints; + use SupportsDnsBlocklistHistoryItemsEndpoints; use SupportsDnsHistoryItemsEndpoints; + use SupportsDomainEndpoints; use SupportsDowntimeEndpoints; use SupportsLighthouseReportsEndpoints; use SupportsMaintenancePeriodEndpoints; use SupportsMeEndpoint; use SupportsMixedContentEndpoints; use SupportsMonitorEndpoints; + use SupportsNotificationDestinationEndpoints; + use SupportsPortsHistoryItemsEndpoints; + use SupportsRecurringMaintenancePeriodEndpoints; use SupportsSitemapEndpoints; use SupportsStatusPageEndpoints; + use SupportsStatusPageUpdateTemplateEndpoints; + use SupportsTagEndpoints; + use SupportsTagGroupEndpoints; use SupportsUptimeEndpoints; use SupportsUptimeMetricsEndpoints; diff --git a/src/Requests/AiResponses/GetAiResponseRequest.php b/src/Requests/AiResponses/GetAiResponseRequest.php new file mode 100644 index 0000000..b35df85 --- /dev/null +++ b/src/Requests/AiResponses/GetAiResponseRequest.php @@ -0,0 +1,28 @@ +monitorId}/ai-responses/{$this->aiResponseId}"; + } + + public function createDtoFromResponse(Response $response): AiResponse + { + return AiResponse::fromResponse($response->json()); + } +} diff --git a/src/Requests/AiResponses/GetAiResponsesRequest.php b/src/Requests/AiResponses/GetAiResponsesRequest.php new file mode 100644 index 0000000..51336dd --- /dev/null +++ b/src/Requests/AiResponses/GetAiResponsesRequest.php @@ -0,0 +1,27 @@ +monitorId}/ai-responses"; + } + + public function createDtoFromResponse(Response $response): array + { + return AiResponse::collect($response->json('data')); + } +} diff --git a/src/Requests/AiResponses/GetLatestAiResponseRequest.php b/src/Requests/AiResponses/GetLatestAiResponseRequest.php new file mode 100644 index 0000000..43f7da8 --- /dev/null +++ b/src/Requests/AiResponses/GetLatestAiResponseRequest.php @@ -0,0 +1,27 @@ +monitorId}/ai-responses/latest"; + } + + public function createDtoFromResponse(Response $response): AiResponse + { + return AiResponse::fromResponse($response->json()); + } +} diff --git a/src/Requests/ApplicationHealthChecks/SnoozeApplicationHealthCheckRequest.php b/src/Requests/ApplicationHealthChecks/SnoozeApplicationHealthCheckRequest.php new file mode 100644 index 0000000..5c2ce25 --- /dev/null +++ b/src/Requests/ApplicationHealthChecks/SnoozeApplicationHealthCheckRequest.php @@ -0,0 +1,40 @@ +monitorId}/application-health-checks/{$this->healthCheckId}/snooze"; + } + + protected function defaultBody(): array + { + return [ + 'minutes' => $this->minutes, + ]; + } + + public function createDtoFromResponse(Response $response): ApplicationHealthCheck + { + return ApplicationHealthCheck::fromResponse($response->json()); + } +} diff --git a/src/Requests/ApplicationHealthChecks/UnsnoozeApplicationHealthCheckRequest.php b/src/Requests/ApplicationHealthChecks/UnsnoozeApplicationHealthCheckRequest.php new file mode 100644 index 0000000..f7d4b48 --- /dev/null +++ b/src/Requests/ApplicationHealthChecks/UnsnoozeApplicationHealthCheckRequest.php @@ -0,0 +1,28 @@ +monitorId}/application-health-checks/{$this->healthCheckId}/unsnooze"; + } + + public function createDtoFromResponse(Response $response): ApplicationHealthCheck + { + return ApplicationHealthCheck::fromResponse($response->json()); + } +} diff --git a/src/Requests/CronCheckDefinitions/SyncCronCheckDefinitionsRequest.php b/src/Requests/CronCheckDefinitions/SyncCronCheckDefinitionsRequest.php new file mode 100644 index 0000000..c319746 --- /dev/null +++ b/src/Requests/CronCheckDefinitions/SyncCronCheckDefinitionsRequest.php @@ -0,0 +1,39 @@ +monitorId}/cron-checks/sync"; + } + + protected function defaultBody(): array + { + return [ + 'cron_checks' => $this->cronChecks, + ]; + } + + public function createDtoFromResponse(Response $response): array + { + return CronCheckDefinition::collect($response->json('data')); + } +} diff --git a/src/Requests/DnsBlocklistHistoryItems/GetDnsBlocklistHistoryItemRequest.php b/src/Requests/DnsBlocklistHistoryItems/GetDnsBlocklistHistoryItemRequest.php new file mode 100644 index 0000000..9f2063b --- /dev/null +++ b/src/Requests/DnsBlocklistHistoryItems/GetDnsBlocklistHistoryItemRequest.php @@ -0,0 +1,28 @@ +monitorId}/dns-blocklist-history-items/{$this->dnsBlocklistHistoryItemId}"; + } + + public function createDtoFromResponse(Response $response): DnsBlocklistHistoryItem + { + return DnsBlocklistHistoryItem::fromResponse($response->json()); + } +} diff --git a/src/Requests/DnsBlocklistHistoryItems/GetDnsBlocklistHistoryItemsRequest.php b/src/Requests/DnsBlocklistHistoryItems/GetDnsBlocklistHistoryItemsRequest.php new file mode 100644 index 0000000..d3e7011 --- /dev/null +++ b/src/Requests/DnsBlocklistHistoryItems/GetDnsBlocklistHistoryItemsRequest.php @@ -0,0 +1,27 @@ +monitorId}/dns-blocklist-history-items"; + } + + public function createDtoFromResponse(Response $response): array + { + return DnsBlocklistHistoryItem::collect($response->json('data')); + } +} diff --git a/src/Requests/Domain/GetDomainRequest.php b/src/Requests/Domain/GetDomainRequest.php new file mode 100644 index 0000000..772656a --- /dev/null +++ b/src/Requests/Domain/GetDomainRequest.php @@ -0,0 +1,27 @@ +monitorId}/domain"; + } + + public function createDtoFromResponse(Response $response): DomainInfo + { + return DomainInfo::fromResponse($response->json()); + } +} diff --git a/src/Requests/Monitors/AddToBrokenLinksWhitelistRequest.php b/src/Requests/Monitors/AddToBrokenLinksWhitelistRequest.php new file mode 100644 index 0000000..42ed440 --- /dev/null +++ b/src/Requests/Monitors/AddToBrokenLinksWhitelistRequest.php @@ -0,0 +1,32 @@ +monitorId}/add-to-broken-links-whitelist"; + } + + protected function defaultBody(): array + { + return [ + 'url' => $this->url, + ]; + } +} diff --git a/src/Requests/Monitors/DeleteNotificationDestinationRequest.php b/src/Requests/Monitors/DeleteNotificationDestinationRequest.php new file mode 100644 index 0000000..8e0c084 --- /dev/null +++ b/src/Requests/Monitors/DeleteNotificationDestinationRequest.php @@ -0,0 +1,21 @@ +monitorId}/notification-destinations/{$this->destinationId}"; + } +} diff --git a/src/Requests/Monitors/GetMonitorByUrlRequest.php b/src/Requests/Monitors/GetMonitorByUrlRequest.php new file mode 100644 index 0000000..8e10632 --- /dev/null +++ b/src/Requests/Monitors/GetMonitorByUrlRequest.php @@ -0,0 +1,27 @@ +monitorUrl); + } + + public function createDtoFromResponse(Response $response): Monitor + { + return Monitor::fromResponse($response->json()); + } +} diff --git a/src/Requests/Monitors/UpdateNotificationDestinationRequest.php b/src/Requests/Monitors/UpdateNotificationDestinationRequest.php new file mode 100644 index 0000000..ceaa2ff --- /dev/null +++ b/src/Requests/Monitors/UpdateNotificationDestinationRequest.php @@ -0,0 +1,38 @@ +monitorId}/notification-destinations/{$this->destinationId}"; + } + + protected function defaultBody(): array + { + return $this->data; + } + + public function createDtoFromResponse(Response $response): NotificationDestination + { + return NotificationDestination::fromResponse($response->json()); + } +} diff --git a/src/Requests/NotificationDestinations/CreateTagGroupNotificationDestinationRequest.php b/src/Requests/NotificationDestinations/CreateTagGroupNotificationDestinationRequest.php new file mode 100644 index 0000000..cef5b0b --- /dev/null +++ b/src/Requests/NotificationDestinations/CreateTagGroupNotificationDestinationRequest.php @@ -0,0 +1,37 @@ +tagGroupId}/notification-destinations"; + } + + protected function defaultBody(): array + { + return $this->data; + } + + public function createDtoFromResponse(Response $response): NotificationDestination + { + return NotificationDestination::fromResponse($response->json()); + } +} diff --git a/src/Requests/NotificationDestinations/CreateTagNotificationDestinationRequest.php b/src/Requests/NotificationDestinations/CreateTagNotificationDestinationRequest.php new file mode 100644 index 0000000..eae43b5 --- /dev/null +++ b/src/Requests/NotificationDestinations/CreateTagNotificationDestinationRequest.php @@ -0,0 +1,37 @@ +tagId}/notification-destinations"; + } + + protected function defaultBody(): array + { + return $this->data; + } + + public function createDtoFromResponse(Response $response): NotificationDestination + { + return NotificationDestination::fromResponse($response->json()); + } +} diff --git a/src/Requests/NotificationDestinations/CreateTeamNotificationDestinationRequest.php b/src/Requests/NotificationDestinations/CreateTeamNotificationDestinationRequest.php new file mode 100644 index 0000000..64b5f62 --- /dev/null +++ b/src/Requests/NotificationDestinations/CreateTeamNotificationDestinationRequest.php @@ -0,0 +1,37 @@ +teamId}"; + } + + protected function defaultBody(): array + { + return $this->data; + } + + public function createDtoFromResponse(Response $response): NotificationDestination + { + return NotificationDestination::fromResponse($response->json()); + } +} diff --git a/src/Requests/NotificationDestinations/DeleteTagGroupNotificationDestinationRequest.php b/src/Requests/NotificationDestinations/DeleteTagGroupNotificationDestinationRequest.php new file mode 100644 index 0000000..ae93ca6 --- /dev/null +++ b/src/Requests/NotificationDestinations/DeleteTagGroupNotificationDestinationRequest.php @@ -0,0 +1,21 @@ +tagGroupId}/notification-destinations/{$this->destinationId}"; + } +} diff --git a/src/Requests/NotificationDestinations/DeleteTagNotificationDestinationRequest.php b/src/Requests/NotificationDestinations/DeleteTagNotificationDestinationRequest.php new file mode 100644 index 0000000..8bf9cb0 --- /dev/null +++ b/src/Requests/NotificationDestinations/DeleteTagNotificationDestinationRequest.php @@ -0,0 +1,21 @@ +tagId}/notification-destinations/destination/{$this->destinationId}"; + } +} diff --git a/src/Requests/NotificationDestinations/DeleteTeamNotificationDestinationRequest.php b/src/Requests/NotificationDestinations/DeleteTeamNotificationDestinationRequest.php new file mode 100644 index 0000000..c881d1d --- /dev/null +++ b/src/Requests/NotificationDestinations/DeleteTeamNotificationDestinationRequest.php @@ -0,0 +1,21 @@ +teamId}/destination/{$this->destinationId}"; + } +} diff --git a/src/Requests/NotificationDestinations/GetTagGroupNotificationDestinationsRequest.php b/src/Requests/NotificationDestinations/GetTagGroupNotificationDestinationsRequest.php new file mode 100644 index 0000000..0307fa6 --- /dev/null +++ b/src/Requests/NotificationDestinations/GetTagGroupNotificationDestinationsRequest.php @@ -0,0 +1,27 @@ +tagGroupId}/notification-destinations"; + } + + public function createDtoFromResponse(Response $response): array + { + return NotificationDestination::collect($response); + } +} diff --git a/src/Requests/NotificationDestinations/GetTagNotificationDestinationsRequest.php b/src/Requests/NotificationDestinations/GetTagNotificationDestinationsRequest.php new file mode 100644 index 0000000..56fbf36 --- /dev/null +++ b/src/Requests/NotificationDestinations/GetTagNotificationDestinationsRequest.php @@ -0,0 +1,23 @@ +tagGroupId}/notification-destinations/{$this->destinationId}"; + } + + protected function defaultBody(): array + { + return $this->data; + } + + public function createDtoFromResponse(Response $response): NotificationDestination + { + return NotificationDestination::fromResponse($response->json()); + } +} diff --git a/src/Requests/NotificationDestinations/UpdateTagNotificationDestinationRequest.php b/src/Requests/NotificationDestinations/UpdateTagNotificationDestinationRequest.php new file mode 100644 index 0000000..ee2bfe4 --- /dev/null +++ b/src/Requests/NotificationDestinations/UpdateTagNotificationDestinationRequest.php @@ -0,0 +1,38 @@ +tagId}/notification-destinations/{$this->destinationId}"; + } + + protected function defaultBody(): array + { + return $this->data; + } + + public function createDtoFromResponse(Response $response): NotificationDestination + { + return NotificationDestination::fromResponse($response->json()); + } +} diff --git a/src/Requests/NotificationDestinations/UpdateTeamNotificationDestinationRequest.php b/src/Requests/NotificationDestinations/UpdateTeamNotificationDestinationRequest.php new file mode 100644 index 0000000..a9a58b4 --- /dev/null +++ b/src/Requests/NotificationDestinations/UpdateTeamNotificationDestinationRequest.php @@ -0,0 +1,38 @@ +teamId}/destination/{$this->destinationId}"; + } + + protected function defaultBody(): array + { + return $this->data; + } + + public function createDtoFromResponse(Response $response): NotificationDestination + { + return NotificationDestination::fromResponse($response->json()); + } +} diff --git a/src/Requests/PortsHistoryItems/GetPortsHistoryItemRequest.php b/src/Requests/PortsHistoryItems/GetPortsHistoryItemRequest.php new file mode 100644 index 0000000..33f075e --- /dev/null +++ b/src/Requests/PortsHistoryItems/GetPortsHistoryItemRequest.php @@ -0,0 +1,28 @@ +monitorId}/ports-history-items/{$this->portsHistoryItemId}"; + } + + public function createDtoFromResponse(Response $response): PortsHistoryItem + { + return PortsHistoryItem::fromResponse($response->json()); + } +} diff --git a/src/Requests/PortsHistoryItems/GetPortsHistoryItemsRequest.php b/src/Requests/PortsHistoryItems/GetPortsHistoryItemsRequest.php new file mode 100644 index 0000000..0c3b6d8 --- /dev/null +++ b/src/Requests/PortsHistoryItems/GetPortsHistoryItemsRequest.php @@ -0,0 +1,27 @@ +monitorId}/ports-history-items"; + } + + public function createDtoFromResponse(Response $response): array + { + return PortsHistoryItem::collect($response->json('data')); + } +} diff --git a/src/Requests/RecurringMaintenancePeriods/CreateRecurringMaintenancePeriodRequest.php b/src/Requests/RecurringMaintenancePeriods/CreateRecurringMaintenancePeriodRequest.php new file mode 100644 index 0000000..c36c74b --- /dev/null +++ b/src/Requests/RecurringMaintenancePeriods/CreateRecurringMaintenancePeriodRequest.php @@ -0,0 +1,36 @@ +data; + } + + public function createDtoFromResponse(Response $response): RecurringMaintenancePeriod + { + return RecurringMaintenancePeriod::fromResponse($response->json()); + } +} diff --git a/src/Requests/RecurringMaintenancePeriods/DeleteRecurringMaintenancePeriodRequest.php b/src/Requests/RecurringMaintenancePeriods/DeleteRecurringMaintenancePeriodRequest.php new file mode 100644 index 0000000..ba95850 --- /dev/null +++ b/src/Requests/RecurringMaintenancePeriods/DeleteRecurringMaintenancePeriodRequest.php @@ -0,0 +1,20 @@ +recurringMaintenancePeriodId}"; + } +} diff --git a/src/Requests/RecurringMaintenancePeriods/GetRecurringMaintenancePeriodRequest.php b/src/Requests/RecurringMaintenancePeriods/GetRecurringMaintenancePeriodRequest.php new file mode 100644 index 0000000..7fbd18d --- /dev/null +++ b/src/Requests/RecurringMaintenancePeriods/GetRecurringMaintenancePeriodRequest.php @@ -0,0 +1,27 @@ +recurringMaintenancePeriodId}"; + } + + public function createDtoFromResponse(Response $response): RecurringMaintenancePeriod + { + return RecurringMaintenancePeriod::fromResponse($response->json()); + } +} diff --git a/src/Requests/RecurringMaintenancePeriods/GetRecurringMaintenancePeriodsRequest.php b/src/Requests/RecurringMaintenancePeriods/GetRecurringMaintenancePeriodsRequest.php new file mode 100644 index 0000000..40cfb2f --- /dev/null +++ b/src/Requests/RecurringMaintenancePeriods/GetRecurringMaintenancePeriodsRequest.php @@ -0,0 +1,27 @@ +monitorId}/recurring-maintenance-periods"; + } + + public function createDtoFromResponse(Response $response): array + { + return RecurringMaintenancePeriod::collect($response->json('data')); + } +} diff --git a/src/Requests/RecurringMaintenancePeriods/UpdateRecurringMaintenancePeriodRequest.php b/src/Requests/RecurringMaintenancePeriods/UpdateRecurringMaintenancePeriodRequest.php new file mode 100644 index 0000000..7ddf64b --- /dev/null +++ b/src/Requests/RecurringMaintenancePeriods/UpdateRecurringMaintenancePeriodRequest.php @@ -0,0 +1,37 @@ +recurringMaintenancePeriodId}"; + } + + protected function defaultBody(): array + { + return $this->data; + } + + public function createDtoFromResponse(Response $response): RecurringMaintenancePeriod + { + return RecurringMaintenancePeriod::fromResponse($response->json()); + } +} diff --git a/src/Requests/StatusPages/AddStatusPageMonitorsRequest.php b/src/Requests/StatusPages/AddStatusPageMonitorsRequest.php new file mode 100644 index 0000000..81bd93e --- /dev/null +++ b/src/Requests/StatusPages/AddStatusPageMonitorsRequest.php @@ -0,0 +1,37 @@ +statusPageId}/monitors"; + } + + protected function defaultBody(): array + { + return $this->data; + } + + public function createDtoFromResponse(Response $response): StatusPage + { + return StatusPage::fromResponse($response->json()); + } +} diff --git a/src/Requests/StatusPages/CreateStatusPageRequest.php b/src/Requests/StatusPages/CreateStatusPageRequest.php new file mode 100644 index 0000000..fae154e --- /dev/null +++ b/src/Requests/StatusPages/CreateStatusPageRequest.php @@ -0,0 +1,36 @@ +data; + } + + public function createDtoFromResponse(Response $response): StatusPage + { + return StatusPage::fromResponse($response->json()); + } +} diff --git a/src/Requests/StatusPages/CreateStatusPageUpdateTemplateRequest.php b/src/Requests/StatusPages/CreateStatusPageUpdateTemplateRequest.php new file mode 100644 index 0000000..8684131 --- /dev/null +++ b/src/Requests/StatusPages/CreateStatusPageUpdateTemplateRequest.php @@ -0,0 +1,36 @@ +data; + } + + public function createDtoFromResponse(Response $response): StatusPageUpdateTemplate + { + return StatusPageUpdateTemplate::fromResponse($response->json()); + } +} diff --git a/src/Requests/StatusPages/DeleteStatusPageMonitorRequest.php b/src/Requests/StatusPages/DeleteStatusPageMonitorRequest.php new file mode 100644 index 0000000..6b96865 --- /dev/null +++ b/src/Requests/StatusPages/DeleteStatusPageMonitorRequest.php @@ -0,0 +1,21 @@ +statusPageId}/monitors/{$this->monitorId}"; + } +} diff --git a/src/Requests/StatusPages/DeleteStatusPageUpdateTemplateRequest.php b/src/Requests/StatusPages/DeleteStatusPageUpdateTemplateRequest.php new file mode 100644 index 0000000..05a0de0 --- /dev/null +++ b/src/Requests/StatusPages/DeleteStatusPageUpdateTemplateRequest.php @@ -0,0 +1,20 @@ +templateId}"; + } +} diff --git a/src/Requests/StatusPages/GetStatusPageUpdateTemplatesRequest.php b/src/Requests/StatusPages/GetStatusPageUpdateTemplatesRequest.php new file mode 100644 index 0000000..88917e7 --- /dev/null +++ b/src/Requests/StatusPages/GetStatusPageUpdateTemplatesRequest.php @@ -0,0 +1,23 @@ +json('data')); + } +} diff --git a/src/Requests/StatusPages/GetStatusPageUpdatesRequest.php b/src/Requests/StatusPages/GetStatusPageUpdatesRequest.php new file mode 100644 index 0000000..7e9896d --- /dev/null +++ b/src/Requests/StatusPages/GetStatusPageUpdatesRequest.php @@ -0,0 +1,30 @@ +statusPageId}/updates"; + } + + public function createDtoFromResponse(Response $response): array + { + return array_map( + fn (array $item) => StatusPageUpdate::fromResponse($item), + $response->json('data') + ); + } +} diff --git a/src/Requests/StatusPages/UpdateStatusPageUpdateRequest.php b/src/Requests/StatusPages/UpdateStatusPageUpdateRequest.php new file mode 100644 index 0000000..e6ab928 --- /dev/null +++ b/src/Requests/StatusPages/UpdateStatusPageUpdateRequest.php @@ -0,0 +1,37 @@ +statusPageUpdateId}"; + } + + protected function defaultBody(): array + { + return $this->data; + } + + public function createDtoFromResponse(Response $response): StatusPageUpdate + { + return StatusPageUpdate::fromResponse($response->json()); + } +} diff --git a/src/Requests/StatusPages/UpdateStatusPageUpdateTemplateRequest.php b/src/Requests/StatusPages/UpdateStatusPageUpdateTemplateRequest.php new file mode 100644 index 0000000..66e3dc8 --- /dev/null +++ b/src/Requests/StatusPages/UpdateStatusPageUpdateTemplateRequest.php @@ -0,0 +1,37 @@ +templateId}"; + } + + protected function defaultBody(): array + { + return $this->data; + } + + public function createDtoFromResponse(Response $response): StatusPageUpdateTemplate + { + return StatusPageUpdateTemplate::fromResponse($response->json()); + } +} diff --git a/src/Requests/TagGroups/CreateTagGroupRequest.php b/src/Requests/TagGroups/CreateTagGroupRequest.php new file mode 100644 index 0000000..d837c53 --- /dev/null +++ b/src/Requests/TagGroups/CreateTagGroupRequest.php @@ -0,0 +1,36 @@ +data; + } + + public function createDtoFromResponse(Response $response): TagGroup + { + return TagGroup::fromResponse($response->json()); + } +} diff --git a/src/Requests/TagGroups/DeleteTagGroupRequest.php b/src/Requests/TagGroups/DeleteTagGroupRequest.php new file mode 100644 index 0000000..1c6a23d --- /dev/null +++ b/src/Requests/TagGroups/DeleteTagGroupRequest.php @@ -0,0 +1,20 @@ +tagGroupId}"; + } +} diff --git a/src/Requests/TagGroups/GetTagGroupsRequest.php b/src/Requests/TagGroups/GetTagGroupsRequest.php new file mode 100644 index 0000000..b36445a --- /dev/null +++ b/src/Requests/TagGroups/GetTagGroupsRequest.php @@ -0,0 +1,23 @@ +json('data')); + } +} diff --git a/src/Requests/TagGroups/UpdateTagGroupRequest.php b/src/Requests/TagGroups/UpdateTagGroupRequest.php new file mode 100644 index 0000000..f9308db --- /dev/null +++ b/src/Requests/TagGroups/UpdateTagGroupRequest.php @@ -0,0 +1,37 @@ +tagGroupId}"; + } + + protected function defaultBody(): array + { + return $this->data; + } + + public function createDtoFromResponse(Response $response): TagGroup + { + return TagGroup::fromResponse($response->json()); + } +} diff --git a/src/Requests/Tags/CreateTagRequest.php b/src/Requests/Tags/CreateTagRequest.php new file mode 100644 index 0000000..60bac99 --- /dev/null +++ b/src/Requests/Tags/CreateTagRequest.php @@ -0,0 +1,36 @@ +data; + } + + public function createDtoFromResponse(Response $response): Tag + { + return Tag::fromResponse($response->json()); + } +} diff --git a/src/Requests/Tags/GetTagsRequest.php b/src/Requests/Tags/GetTagsRequest.php new file mode 100644 index 0000000..0dcf08a --- /dev/null +++ b/src/Requests/Tags/GetTagsRequest.php @@ -0,0 +1,23 @@ +json('data')); + } +} diff --git a/tests/Fixtures/Saloon/add-status-page-monitors.json b/tests/Fixtures/Saloon/add-status-page-monitors.json new file mode 100644 index 0000000..4851ad9 --- /dev/null +++ b/tests/Fixtures/Saloon/add-status-page-monitors.json @@ -0,0 +1 @@ +{"statusCode":200,"headers":{"Content-Type":"application/json"},"data":"{\"id\":9338,\"team\":{\"id\":19245},\"title\":\"First status page\",\"domain\":null,\"secret\":null,\"badge_id\":null,\"slug\":\"first-status-page\",\"full_url\":\"https://status.example.com\",\"timezone\":\"UTC\",\"summarized_status\":\"up\",\"updates\":[],\"monitors\":[{\"id\":82060}],\"created_at\":\"2025-01-01 00:00:00\",\"updated_at\":\"2025-01-01 00:00:00\"}","context":[]} diff --git a/tests/Fixtures/Saloon/add-to-broken-links-whitelist.json b/tests/Fixtures/Saloon/add-to-broken-links-whitelist.json new file mode 100644 index 0000000..6ee6354 --- /dev/null +++ b/tests/Fixtures/Saloon/add-to-broken-links-whitelist.json @@ -0,0 +1 @@ +{"statusCode":200,"headers":{"Content-Type":"application/json"},"data":"{}","context":[]} diff --git a/tests/Fixtures/Saloon/ai-response.json b/tests/Fixtures/Saloon/ai-response.json new file mode 100644 index 0000000..16e3d7e --- /dev/null +++ b/tests/Fixtures/Saloon/ai-response.json @@ -0,0 +1 @@ +{"statusCode":200,"headers":{"Content-Type":"application/json"},"data":"{\"id\":1,\"monitor_id\":82060,\"prompt\":\"Check if the site is accessible\",\"response\":\"The site is accessible and responding normally.\",\"raw_response\":\"The site is accessible and responding normally.\",\"token_usage\":{\"input\":100,\"output\":50},\"tool_invocations\":[],\"created_at\":\"2025-01-01 00:00:00\"}","context":[]} diff --git a/tests/Fixtures/Saloon/ai-responses.json b/tests/Fixtures/Saloon/ai-responses.json new file mode 100644 index 0000000..76870d0 --- /dev/null +++ b/tests/Fixtures/Saloon/ai-responses.json @@ -0,0 +1 @@ +{"statusCode":200,"headers":{"Content-Type":"application/json"},"data":"{\"data\":[{\"id\":1,\"monitor_id\":82060,\"prompt\":\"Check if the site is accessible\",\"response\":\"The site is accessible and responding normally.\",\"raw_response\":\"The site is accessible and responding normally.\",\"token_usage\":{\"input\":100,\"output\":50},\"tool_invocations\":[],\"created_at\":\"2025-01-01 00:00:00\"}]}","context":[]} diff --git a/tests/Fixtures/Saloon/create-recurring-maintenance-period.json b/tests/Fixtures/Saloon/create-recurring-maintenance-period.json new file mode 100644 index 0000000..5b360d0 --- /dev/null +++ b/tests/Fixtures/Saloon/create-recurring-maintenance-period.json @@ -0,0 +1 @@ +{"statusCode":201,"headers":{"Content-Type":"application/json"},"data":"{\"id\":2,\"monitor_id\":82060,\"name\":\"Daily Maintenance\",\"recurrence_type\":\"daily\",\"start_time\":\"03:00\",\"end_time\":\"05:00\",\"days_of_week\":[],\"day_of_month\":null,\"created_at\":\"2025-01-01 00:00:00\",\"updated_at\":\"2025-01-01 00:00:00\"}","context":[]} diff --git a/tests/Fixtures/Saloon/create-status-page-update-template.json b/tests/Fixtures/Saloon/create-status-page-update-template.json new file mode 100644 index 0000000..ee801d5 --- /dev/null +++ b/tests/Fixtures/Saloon/create-status-page-update-template.json @@ -0,0 +1 @@ +{"statusCode":201,"headers":{"Content-Type":"application/json"},"data":"{\"id\":2,\"team_id\":19245,\"name\":\"Incident Template\",\"title\":\"Service Incident\",\"text\":\"We are investigating an issue.\",\"severity\":\"high\",\"created_at\":\"2025-01-01 00:00:00\",\"updated_at\":\"2025-01-01 00:00:00\"}","context":[]} diff --git a/tests/Fixtures/Saloon/create-status-page.json b/tests/Fixtures/Saloon/create-status-page.json new file mode 100644 index 0000000..718de69 --- /dev/null +++ b/tests/Fixtures/Saloon/create-status-page.json @@ -0,0 +1 @@ +{"statusCode":201,"headers":{"Content-Type":"application/json"},"data":"{\"id\":9339,\"team\":{\"id\":19245},\"title\":\"New Status Page\",\"domain\":null,\"secret\":null,\"badge_id\":null,\"slug\":\"new-status-page\",\"full_url\":\"https://status.example.com\",\"timezone\":\"UTC\",\"summarized_status\":\"up\",\"updates\":[],\"monitors\":[],\"created_at\":\"2025-01-01 00:00:00\",\"updated_at\":\"2025-01-01 00:00:00\"}","context":[]} diff --git a/tests/Fixtures/Saloon/create-tag-group-notification-destination.json b/tests/Fixtures/Saloon/create-tag-group-notification-destination.json new file mode 100644 index 0000000..5f8b6d1 --- /dev/null +++ b/tests/Fixtures/Saloon/create-tag-group-notification-destination.json @@ -0,0 +1 @@ +{"statusCode":201,"headers":{"Content-Type":"application/json"},"data":"{\"id\":301,\"label\":null,\"channel\":\"mail\",\"destination\":{\"mail\":\"taggroup@example.com\"},\"notification_types\":[]}","context":[]} diff --git a/tests/Fixtures/Saloon/create-tag-group.json b/tests/Fixtures/Saloon/create-tag-group.json new file mode 100644 index 0000000..27042d4 --- /dev/null +++ b/tests/Fixtures/Saloon/create-tag-group.json @@ -0,0 +1 @@ +{"statusCode":201,"headers":{"Content-Type":"application/json"},"data":"{\"id\":2,\"team_id\":19245,\"label\":\"Region\",\"tags\":[],\"created_at\":\"2025-01-01 00:00:00\",\"updated_at\":\"2025-01-01 00:00:00\"}","context":[]} diff --git a/tests/Fixtures/Saloon/create-tag-notification-destination.json b/tests/Fixtures/Saloon/create-tag-notification-destination.json new file mode 100644 index 0000000..c01275c --- /dev/null +++ b/tests/Fixtures/Saloon/create-tag-notification-destination.json @@ -0,0 +1 @@ +{"statusCode":201,"headers":{"Content-Type":"application/json"},"data":"{\"id\":201,\"label\":null,\"channel\":\"mail\",\"destination\":{\"mail\":\"newtag@example.com\"},\"notification_types\":[]}","context":[]} diff --git a/tests/Fixtures/Saloon/create-tag.json b/tests/Fixtures/Saloon/create-tag.json new file mode 100644 index 0000000..ed02c55 --- /dev/null +++ b/tests/Fixtures/Saloon/create-tag.json @@ -0,0 +1 @@ +{"statusCode":201,"headers":{"Content-Type":"application/json"},"data":"{\"id\":2,\"team_id\":19245,\"name\":\"staging\",\"monitors\":[],\"created_at\":\"2025-01-01 00:00:00\",\"updated_at\":\"2025-01-01 00:00:00\"}","context":[]} diff --git a/tests/Fixtures/Saloon/create-team-notification-destination.json b/tests/Fixtures/Saloon/create-team-notification-destination.json new file mode 100644 index 0000000..96942fa --- /dev/null +++ b/tests/Fixtures/Saloon/create-team-notification-destination.json @@ -0,0 +1 @@ +{"statusCode":201,"headers":{"Content-Type":"application/json"},"data":"{\"id\":101,\"label\":null,\"channel\":\"mail\",\"destination\":{\"mail\":\"team@example.com\"},\"notification_types\":[]}","context":[]} diff --git a/tests/Fixtures/Saloon/delete-notification-destination.json b/tests/Fixtures/Saloon/delete-notification-destination.json new file mode 100644 index 0000000..2c5dce8 --- /dev/null +++ b/tests/Fixtures/Saloon/delete-notification-destination.json @@ -0,0 +1 @@ +{"statusCode":204,"headers":{},"data":"","context":[]} diff --git a/tests/Fixtures/Saloon/delete-recurring-maintenance-period.json b/tests/Fixtures/Saloon/delete-recurring-maintenance-period.json new file mode 100644 index 0000000..2c5dce8 --- /dev/null +++ b/tests/Fixtures/Saloon/delete-recurring-maintenance-period.json @@ -0,0 +1 @@ +{"statusCode":204,"headers":{},"data":"","context":[]} diff --git a/tests/Fixtures/Saloon/delete-status-page-monitor.json b/tests/Fixtures/Saloon/delete-status-page-monitor.json new file mode 100644 index 0000000..2c5dce8 --- /dev/null +++ b/tests/Fixtures/Saloon/delete-status-page-monitor.json @@ -0,0 +1 @@ +{"statusCode":204,"headers":{},"data":"","context":[]} diff --git a/tests/Fixtures/Saloon/delete-status-page-update-template.json b/tests/Fixtures/Saloon/delete-status-page-update-template.json new file mode 100644 index 0000000..2c5dce8 --- /dev/null +++ b/tests/Fixtures/Saloon/delete-status-page-update-template.json @@ -0,0 +1 @@ +{"statusCode":204,"headers":{},"data":"","context":[]} diff --git a/tests/Fixtures/Saloon/delete-tag-group.json b/tests/Fixtures/Saloon/delete-tag-group.json new file mode 100644 index 0000000..2c5dce8 --- /dev/null +++ b/tests/Fixtures/Saloon/delete-tag-group.json @@ -0,0 +1 @@ +{"statusCode":204,"headers":{},"data":"","context":[]} diff --git a/tests/Fixtures/Saloon/dns-blocklist-history-item.json b/tests/Fixtures/Saloon/dns-blocklist-history-item.json new file mode 100644 index 0000000..7607946 --- /dev/null +++ b/tests/Fixtures/Saloon/dns-blocklist-history-item.json @@ -0,0 +1 @@ +{"statusCode":200,"headers":{"Content-Type":"application/json"},"data":"{\"id\":1,\"domain\":\"example.com\",\"resolved_ips\":[\"93.184.216.34\"],\"blocklists\":[{\"name\":\"zen.spamhaus.org\",\"listed\":false}],\"created_at\":\"2025-01-01 00:00:00\"}","context":[]} diff --git a/tests/Fixtures/Saloon/dns-blocklist-history-items.json b/tests/Fixtures/Saloon/dns-blocklist-history-items.json new file mode 100644 index 0000000..a1fd46f --- /dev/null +++ b/tests/Fixtures/Saloon/dns-blocklist-history-items.json @@ -0,0 +1 @@ +{"statusCode":200,"headers":{"Content-Type":"application/json"},"data":"{\"data\":[{\"id\":1,\"domain\":\"example.com\",\"resolved_ips\":[\"93.184.216.34\"],\"blocklists\":[{\"name\":\"zen.spamhaus.org\",\"listed\":false}],\"created_at\":\"2025-01-01 00:00:00\"}]}","context":[]} diff --git a/tests/Fixtures/Saloon/domain.json b/tests/Fixtures/Saloon/domain.json new file mode 100644 index 0000000..155b22d --- /dev/null +++ b/tests/Fixtures/Saloon/domain.json @@ -0,0 +1 @@ +{"statusCode":200,"headers":{"Content-Type":"application/json"},"data":"{\"expires_at\":\"2026-01-01 00:00:00\",\"registered_at\":\"2020-01-01 00:00:00\",\"last_changed_at\":\"2024-06-01 00:00:00\",\"last_updated_in_rdap_db_at\":\"2025-01-01 00:00:00\",\"domain_statuses\":[\"clientTransferProhibited\"],\"rdap_domain_response\":{},\"created_at\":\"2025-01-01 00:00:00\"}","context":[]} diff --git a/tests/Fixtures/Saloon/latest-ai-response.json b/tests/Fixtures/Saloon/latest-ai-response.json new file mode 100644 index 0000000..16e3d7e --- /dev/null +++ b/tests/Fixtures/Saloon/latest-ai-response.json @@ -0,0 +1 @@ +{"statusCode":200,"headers":{"Content-Type":"application/json"},"data":"{\"id\":1,\"monitor_id\":82060,\"prompt\":\"Check if the site is accessible\",\"response\":\"The site is accessible and responding normally.\",\"raw_response\":\"The site is accessible and responding normally.\",\"token_usage\":{\"input\":100,\"output\":50},\"tool_invocations\":[],\"created_at\":\"2025-01-01 00:00:00\"}","context":[]} diff --git a/tests/Fixtures/Saloon/monitor-by-url.json b/tests/Fixtures/Saloon/monitor-by-url.json new file mode 100644 index 0000000..5a48dea --- /dev/null +++ b/tests/Fixtures/Saloon/monitor-by-url.json @@ -0,0 +1 @@ +{"statusCode":200,"headers":{"Content-Type":"application/json"},"data":"{\"id\":82063,\"team_id\":19245,\"type\":\"http\",\"url\":\"https://laravel.com\",\"uses_https\":true,\"sort_url\":\"laravel.com\",\"label\":\"laravel.com\",\"group_name\":\"\",\"tags\":[],\"description\":null,\"notes\":null,\"latest_run_date\":null,\"summarized_check_result\":\"succeeded\",\"checks\":[],\"uptime_check_settings\":{},\"certificate_health_check_settings\":{},\"broken_links_check_settings\":{},\"dns_check_settings\":{},\"lighthouse_check_settings\":{},\"application_health_check_settings\":{},\"domain_check_settings\":{},\"performance_check_settings\":{},\"sitemap_check_settings\":{},\"crawler_headers\":[],\"send_report_to_emails\":[],\"include_check_types_in_report\":[],\"badge_id\":null,\"marked_for_deletion_at\":null,\"created_at\":\"2025-08-08 14:13:52\",\"updated_at\":\"2025-08-08 14:41:01\"}","context":[]} diff --git a/tests/Fixtures/Saloon/ports-history-item.json b/tests/Fixtures/Saloon/ports-history-item.json new file mode 100644 index 0000000..609d0eb --- /dev/null +++ b/tests/Fixtures/Saloon/ports-history-item.json @@ -0,0 +1 @@ +{"statusCode":200,"headers":{"Content-Type":"application/json"},"data":"{\"id\":1,\"scanned_host\":\"example.com\",\"expected_open_results\":[{\"port\":80,\"status\":\"open\"}],\"expected_closed_results\":[{\"port\":23,\"status\":\"closed\"}],\"issues\":[],\"scan_time_ms\":1500,\"created_at\":\"2025-01-01 00:00:00\"}","context":[]} diff --git a/tests/Fixtures/Saloon/ports-history-items.json b/tests/Fixtures/Saloon/ports-history-items.json new file mode 100644 index 0000000..ba2af1a --- /dev/null +++ b/tests/Fixtures/Saloon/ports-history-items.json @@ -0,0 +1 @@ +{"statusCode":200,"headers":{"Content-Type":"application/json"},"data":"{\"data\":[{\"id\":1,\"scanned_host\":\"example.com\",\"expected_open_results\":[{\"port\":80,\"status\":\"open\"}],\"expected_closed_results\":[{\"port\":23,\"status\":\"closed\"}],\"issues\":[],\"scan_time_ms\":1500,\"created_at\":\"2025-01-01 00:00:00\"}]}","context":[]} diff --git a/tests/Fixtures/Saloon/recurring-maintenance-period.json b/tests/Fixtures/Saloon/recurring-maintenance-period.json new file mode 100644 index 0000000..951307f --- /dev/null +++ b/tests/Fixtures/Saloon/recurring-maintenance-period.json @@ -0,0 +1 @@ +{"statusCode":200,"headers":{"Content-Type":"application/json"},"data":"{\"id\":1,\"monitor_id\":82060,\"name\":\"Weekly Maintenance\",\"recurrence_type\":\"weekly\",\"start_time\":\"02:00\",\"end_time\":\"04:00\",\"days_of_week\":[1,3,5],\"day_of_month\":null,\"created_at\":\"2025-01-01 00:00:00\",\"updated_at\":\"2025-01-01 00:00:00\"}","context":[]} diff --git a/tests/Fixtures/Saloon/recurring-maintenance-periods.json b/tests/Fixtures/Saloon/recurring-maintenance-periods.json new file mode 100644 index 0000000..b88c184 --- /dev/null +++ b/tests/Fixtures/Saloon/recurring-maintenance-periods.json @@ -0,0 +1 @@ +{"statusCode":200,"headers":{"Content-Type":"application/json"},"data":"{\"data\":[{\"id\":1,\"monitor_id\":82060,\"name\":\"Weekly Maintenance\",\"recurrence_type\":\"weekly\",\"start_time\":\"02:00\",\"end_time\":\"04:00\",\"days_of_week\":[1,3,5],\"day_of_month\":null,\"created_at\":\"2025-01-01 00:00:00\",\"updated_at\":\"2025-01-01 00:00:00\"}]}","context":[]} diff --git a/tests/Fixtures/Saloon/snooze-application-health-check.json b/tests/Fixtures/Saloon/snooze-application-health-check.json new file mode 100644 index 0000000..6efb318 --- /dev/null +++ b/tests/Fixtures/Saloon/snooze-application-health-check.json @@ -0,0 +1 @@ +{"statusCode":200,"headers":{"Content-Type":"application/json"},"data":"{\"id\":2608325,\"name\":\"Database\",\"label\":\"Database\",\"status\":\"ok\",\"message\":\"Connected\",\"meta\":[],\"short_summary\":\"OK\",\"detected_at\":\"2025-01-01 00:00:00\",\"updated_at\":\"2025-01-01 00:00:00\",\"active_snooze\":{\"minutes\":60}}","context":[]} diff --git a/tests/Fixtures/Saloon/status-page-update-templates.json b/tests/Fixtures/Saloon/status-page-update-templates.json new file mode 100644 index 0000000..625bbc0 --- /dev/null +++ b/tests/Fixtures/Saloon/status-page-update-templates.json @@ -0,0 +1 @@ +{"statusCode":200,"headers":{"Content-Type":"application/json"},"data":"{\"data\":[{\"id\":1,\"team_id\":19245,\"name\":\"Maintenance Template\",\"title\":\"Scheduled Maintenance\",\"text\":\"We are performing scheduled maintenance.\",\"severity\":\"info\",\"created_at\":\"2025-01-01 00:00:00\",\"updated_at\":\"2025-01-01 00:00:00\"}]}","context":[]} diff --git a/tests/Fixtures/Saloon/status-page-updates.json b/tests/Fixtures/Saloon/status-page-updates.json new file mode 100644 index 0000000..d2d0144 --- /dev/null +++ b/tests/Fixtures/Saloon/status-page-updates.json @@ -0,0 +1 @@ +{"statusCode":200,"headers":{"Content-Type":"application/json"},"data":"{\"data\":[{\"id\":1234,\"title\":\"Our site is down\",\"text\":\"We are working on it!\",\"pinned\":true,\"severity\":\"high\",\"time\":\"2025-01-01 00:00:00\",\"status_page_url\":\"https://status.example.com\"}]}","context":[]} diff --git a/tests/Fixtures/Saloon/sync-cron-check-definitions.json b/tests/Fixtures/Saloon/sync-cron-check-definitions.json new file mode 100644 index 0000000..688b72f --- /dev/null +++ b/tests/Fixtures/Saloon/sync-cron-check-definitions.json @@ -0,0 +1 @@ +{"statusCode":200,"headers":{"Content-Type":"application/json"},"data":"{\"data\":[{\"id\":208283,\"uuid\":\"abc-123\",\"name\":\"Sync Test\",\"type\":\"simple\",\"description\":null,\"frequency_in_minutes\":60,\"grace_time_in_minutes\":10,\"cron_expression\":null,\"human_readable_cron_expression\":\"\",\"server_timezone\":null,\"ping_url\":\"https://ping.ohdear.app/abc-123\",\"created_at\":\"2025-01-01 00:00:00\",\"latest_result\":\"\",\"latest_result_label\":\"\",\"latest_result_label_color\":\"\",\"latest_ping_at\":null,\"human_readable_latest_ping_at\":\"\",\"active_snooze\":null}]}","context":[]} diff --git a/tests/Fixtures/Saloon/tag-group-notification-destinations.json b/tests/Fixtures/Saloon/tag-group-notification-destinations.json new file mode 100644 index 0000000..79a0a89 --- /dev/null +++ b/tests/Fixtures/Saloon/tag-group-notification-destinations.json @@ -0,0 +1 @@ +{"statusCode":200,"headers":{"Content-Type":"application/json"},"data":"{\"data\":[{\"id\":300,\"label\":\"TagGroup Slack\",\"channel\":\"slack\",\"destination\":{\"webhook_url\":\"https://hooks.slack.com/tg\"},\"notification_types\":[]}]}","context":[]} diff --git a/tests/Fixtures/Saloon/tag-groups.json b/tests/Fixtures/Saloon/tag-groups.json new file mode 100644 index 0000000..7d5c3f5 --- /dev/null +++ b/tests/Fixtures/Saloon/tag-groups.json @@ -0,0 +1 @@ +{"statusCode":200,"headers":{"Content-Type":"application/json"},"data":"{\"data\":[{\"id\":1,\"team_id\":19245,\"label\":\"Environment\",\"tags\":[],\"created_at\":\"2025-01-01 00:00:00\",\"updated_at\":\"2025-01-01 00:00:00\"}]}","context":[]} diff --git a/tests/Fixtures/Saloon/tag-notification-destinations.json b/tests/Fixtures/Saloon/tag-notification-destinations.json new file mode 100644 index 0000000..b76f11c --- /dev/null +++ b/tests/Fixtures/Saloon/tag-notification-destinations.json @@ -0,0 +1 @@ +{"statusCode":200,"headers":{"Content-Type":"application/json"},"data":"{\"data\":[{\"id\":200,\"label\":\"Tag Email\",\"channel\":\"mail\",\"destination\":{\"mail\":\"tag@example.com\"},\"notification_types\":[]}]}","context":[]} diff --git a/tests/Fixtures/Saloon/tags.json b/tests/Fixtures/Saloon/tags.json new file mode 100644 index 0000000..25fa48b --- /dev/null +++ b/tests/Fixtures/Saloon/tags.json @@ -0,0 +1 @@ +{"statusCode":200,"headers":{"Content-Type":"application/json"},"data":"{\"data\":[{\"id\":1,\"team_id\":19245,\"name\":\"production\",\"monitors\":[],\"created_at\":\"2025-01-01 00:00:00\",\"updated_at\":\"2025-01-01 00:00:00\"}]}","context":[]} diff --git a/tests/Fixtures/Saloon/team-notification-destinations.json b/tests/Fixtures/Saloon/team-notification-destinations.json new file mode 100644 index 0000000..e938e2e --- /dev/null +++ b/tests/Fixtures/Saloon/team-notification-destinations.json @@ -0,0 +1 @@ +{"statusCode":200,"headers":{"Content-Type":"application/json"},"data":"{\"data\":[{\"id\":100,\"label\":\"Team Slack\",\"channel\":\"slack\",\"destination\":{\"webhook_url\":\"https://hooks.slack.com/test\"},\"notification_types\":[]}]}","context":[]} diff --git a/tests/Fixtures/Saloon/unsnooze-application-health-check.json b/tests/Fixtures/Saloon/unsnooze-application-health-check.json new file mode 100644 index 0000000..97f56d8 --- /dev/null +++ b/tests/Fixtures/Saloon/unsnooze-application-health-check.json @@ -0,0 +1 @@ +{"statusCode":200,"headers":{"Content-Type":"application/json"},"data":"{\"id\":2608325,\"name\":\"Database\",\"label\":\"Database\",\"status\":\"ok\",\"message\":\"Connected\",\"meta\":[],\"short_summary\":\"OK\",\"detected_at\":\"2025-01-01 00:00:00\",\"updated_at\":\"2025-01-01 00:00:00\",\"active_snooze\":null}","context":[]} diff --git a/tests/Fixtures/Saloon/update-notification-destination.json b/tests/Fixtures/Saloon/update-notification-destination.json new file mode 100644 index 0000000..3bcaecf --- /dev/null +++ b/tests/Fixtures/Saloon/update-notification-destination.json @@ -0,0 +1 @@ +{"statusCode":200,"headers":{"Content-Type":"application/json"},"data":"{\"id\":456,\"label\":\"Updated\",\"channel\":\"mail\",\"destination\":{\"mail\":\"updated@example.com\"},\"notification_types\":[]}","context":[]} diff --git a/tests/Fixtures/Saloon/update-recurring-maintenance-period.json b/tests/Fixtures/Saloon/update-recurring-maintenance-period.json new file mode 100644 index 0000000..c165103 --- /dev/null +++ b/tests/Fixtures/Saloon/update-recurring-maintenance-period.json @@ -0,0 +1 @@ +{"statusCode":200,"headers":{"Content-Type":"application/json"},"data":"{\"id\":1,\"monitor_id\":82060,\"name\":\"Updated Maintenance\",\"recurrence_type\":\"weekly\",\"start_time\":\"01:00\",\"end_time\":\"03:00\",\"days_of_week\":[1,2,3,4,5],\"day_of_month\":null,\"created_at\":\"2025-01-01 00:00:00\",\"updated_at\":\"2025-01-02 00:00:00\"}","context":[]} diff --git a/tests/Fixtures/Saloon/update-status-page-update-template.json b/tests/Fixtures/Saloon/update-status-page-update-template.json new file mode 100644 index 0000000..6d9d142 --- /dev/null +++ b/tests/Fixtures/Saloon/update-status-page-update-template.json @@ -0,0 +1 @@ +{"statusCode":200,"headers":{"Content-Type":"application/json"},"data":"{\"id\":1,\"team_id\":19245,\"name\":\"Updated Template\",\"title\":\"Updated Title\",\"text\":\"Updated text.\",\"severity\":\"warning\",\"created_at\":\"2025-01-01 00:00:00\",\"updated_at\":\"2025-01-02 00:00:00\"}","context":[]} diff --git a/tests/Fixtures/Saloon/update-status-page-update.json b/tests/Fixtures/Saloon/update-status-page-update.json new file mode 100644 index 0000000..221d552 --- /dev/null +++ b/tests/Fixtures/Saloon/update-status-page-update.json @@ -0,0 +1 @@ +{"statusCode":200,"headers":{"Content-Type":"application/json"},"data":"{\"id\":1234,\"title\":\"Updated title\",\"text\":\"Updated text\",\"pinned\":false,\"severity\":\"info\",\"time\":\"2025-01-01 00:00:00\",\"status_page_url\":\"https://status.example.com\"}","context":[]} diff --git a/tests/Fixtures/Saloon/update-tag-group.json b/tests/Fixtures/Saloon/update-tag-group.json new file mode 100644 index 0000000..c346ad6 --- /dev/null +++ b/tests/Fixtures/Saloon/update-tag-group.json @@ -0,0 +1 @@ +{"statusCode":200,"headers":{"Content-Type":"application/json"},"data":"{\"id\":1,\"team_id\":19245,\"label\":\"Updated Environment\",\"tags\":[],\"created_at\":\"2025-01-01 00:00:00\",\"updated_at\":\"2025-01-02 00:00:00\"}","context":[]} diff --git a/tests/OhDearTests/AiResponsesTest.php b/tests/OhDearTests/AiResponsesTest.php new file mode 100644 index 0000000..cc27f2a --- /dev/null +++ b/tests/OhDearTests/AiResponsesTest.php @@ -0,0 +1,48 @@ +ohDear = ohDearMock(); +}); + +it('can get ai responses', function () { + MockClient::global([ + GetAiResponsesRequest::class => MockResponse::fixture('ai-responses'), + ]); + + $responses = $this->ohDear->aiResponses(82060); + + expect($responses)->toBeArray(); + foreach ($responses as $response) { + expect($response->id)->toBeInt(); + expect($response->monitorId)->toBe(82060); + } +}); + +it('can get a single ai response', function () { + MockClient::global([ + GetAiResponseRequest::class => MockResponse::fixture('ai-response'), + ]); + + $response = $this->ohDear->aiResponse(82060, 1); + + expect($response->id)->toBe(1); + expect($response->monitorId)->toBe(82060); + expect($response->prompt)->toBeString(); +}); + +it('can get the latest ai response', function () { + MockClient::global([ + GetLatestAiResponseRequest::class => MockResponse::fixture('latest-ai-response'), + ]); + + $response = $this->ohDear->latestAiResponse(82060); + + expect($response->id)->toBe(1); + expect($response->monitorId)->toBe(82060); +}); diff --git a/tests/OhDearTests/ApplicationHealthChecksTest.php b/tests/OhDearTests/ApplicationHealthChecksTest.php index b5a1df5..bb40765 100644 --- a/tests/OhDearTests/ApplicationHealthChecksTest.php +++ b/tests/OhDearTests/ApplicationHealthChecksTest.php @@ -2,6 +2,8 @@ use OhDear\PhpSdk\Requests\ApplicationHealthChecks\GetApplicationHealthCheckHistoryRequest; use OhDear\PhpSdk\Requests\ApplicationHealthChecks\GetApplicationHealthChecksRequest; +use OhDear\PhpSdk\Requests\ApplicationHealthChecks\SnoozeApplicationHealthCheckRequest; +use OhDear\PhpSdk\Requests\ApplicationHealthChecks\UnsnoozeApplicationHealthCheckRequest; use Saloon\Http\Faking\MockClient; use Saloon\Http\Faking\MockResponse; @@ -46,3 +48,27 @@ expect($historyItem->updatedAt)->toBeString(); } }); + +it('can snooze an application health check', function () { + MockClient::global([ + SnoozeApplicationHealthCheckRequest::class => MockResponse::fixture('snooze-application-health-check'), + ]); + + $healthCheck = $this->ohDear->snoozeApplicationHealthCheck(82060, 2608325, 60); + + expect($healthCheck->id)->toBe(2608325); + expect($healthCheck->name)->toBe('Database'); + expect($healthCheck->activeSnooze)->toBeArray(); +}); + +it('can unsnooze an application health check', function () { + MockClient::global([ + UnsnoozeApplicationHealthCheckRequest::class => MockResponse::fixture('unsnooze-application-health-check'), + ]); + + $healthCheck = $this->ohDear->unsnoozeApplicationHealthCheck(82060, 2608325); + + expect($healthCheck->id)->toBe(2608325); + expect($healthCheck->name)->toBe('Database'); + expect($healthCheck->activeSnooze)->toBeNull(); +}); diff --git a/tests/OhDearTests/CronCheckDefinitionsTest.php b/tests/OhDearTests/CronCheckDefinitionsTest.php index 58e9cb1..ba2e9db 100644 --- a/tests/OhDearTests/CronCheckDefinitionsTest.php +++ b/tests/OhDearTests/CronCheckDefinitionsTest.php @@ -5,6 +5,7 @@ use OhDear\PhpSdk\Requests\CronCheckDefinitions\DeleteCronCheckDefinitionRequest; use OhDear\PhpSdk\Requests\CronCheckDefinitions\GetCronCheckDefinitionsRequest; use OhDear\PhpSdk\Requests\CronCheckDefinitions\SnoozeCronCheckDefinitionRequest; +use OhDear\PhpSdk\Requests\CronCheckDefinitions\SyncCronCheckDefinitionsRequest; use OhDear\PhpSdk\Requests\CronCheckDefinitions\UnsnoozeCronCheckDefinitionRequest; use OhDear\PhpSdk\Requests\CronCheckDefinitions\UpdateCronCheckDefinitionRequest; use Saloon\Http\Faking\MockClient; @@ -102,3 +103,19 @@ expect($cronCheckDefinition->id)->toBeInt(); expect($cronCheckDefinition->name)->toBeString(); }); + +it('can sync cron check definitions', function () { + MockClient::global([ + SyncCronCheckDefinitionsRequest::class => MockResponse::fixture('sync-cron-check-definitions'), + ]); + + $cronCheckDefinitions = $this->ohDear->syncCronCheckDefinitions(82060, [ + ['name' => 'Sync Test', 'type' => 'simple', 'frequency_in_minutes' => 60], + ]); + + expect($cronCheckDefinitions)->toBeArray(); + foreach ($cronCheckDefinitions as $cronCheckDefinition) { + expect($cronCheckDefinition->id)->toBeInt(); + expect($cronCheckDefinition->name)->toBeString(); + } +}); diff --git a/tests/OhDearTests/DnsBlocklistHistoryItemsTest.php b/tests/OhDearTests/DnsBlocklistHistoryItemsTest.php new file mode 100644 index 0000000..313b55d --- /dev/null +++ b/tests/OhDearTests/DnsBlocklistHistoryItemsTest.php @@ -0,0 +1,37 @@ +ohDear = ohDearMock(); +}); + +it('can get dns blocklist history items', function () { + MockClient::global([ + GetDnsBlocklistHistoryItemsRequest::class => MockResponse::fixture('dns-blocklist-history-items'), + ]); + + $items = $this->ohDear->dnsBlocklistHistoryItems(82060); + + expect($items)->toBeArray(); + foreach ($items as $item) { + expect($item->id)->toBeInt(); + expect($item->domain)->toBeString(); + } +}); + +it('can get a single dns blocklist history item', function () { + MockClient::global([ + GetDnsBlocklistHistoryItemRequest::class => MockResponse::fixture('dns-blocklist-history-item'), + ]); + + $item = $this->ohDear->dnsBlocklistHistoryItem(82060, 1); + + expect($item->id)->toBe(1); + expect($item->domain)->toBe('example.com'); + expect($item->resolvedIps)->toBeArray(); + expect($item->blocklists)->toBeArray(); +}); diff --git a/tests/OhDearTests/DomainTest.php b/tests/OhDearTests/DomainTest.php new file mode 100644 index 0000000..6557e35 --- /dev/null +++ b/tests/OhDearTests/DomainTest.php @@ -0,0 +1,21 @@ +ohDear = ohDearMock(); +}); + +it('can get domain info for a monitor', function () { + MockClient::global([ + GetDomainRequest::class => MockResponse::fixture('domain'), + ]); + + $domain = $this->ohDear->domain(82060); + + expect($domain->expiresAt)->toBe('2026-01-01 00:00:00'); + expect($domain->registeredAt)->toBe('2020-01-01 00:00:00'); + expect($domain->domainStatuses)->toBeArray(); +}); diff --git a/tests/OhDearTests/MonitorsTest.php b/tests/OhDearTests/MonitorsTest.php index 82fb06e..10021c0 100644 --- a/tests/OhDearTests/MonitorsTest.php +++ b/tests/OhDearTests/MonitorsTest.php @@ -1,10 +1,12 @@ channel)->toBe('mail'); expect($notificationDestination->destination['mail'])->toBe('example@example.com'); }); + +it('can get a monitor by url', function () { + MockClient::global([ + GetMonitorByUrlRequest::class => MockResponse::fixture('monitor-by-url'), + ]); + + $monitor = $this->ohDear->monitorByUrl('https://laravel.com'); + + expect($monitor->id)->toBe(82063); + expect($monitor->url)->toBe('https://laravel.com'); +}); + +it('can add a url to broken links whitelist', function () { + MockClient::global([ + AddToBrokenLinksWhitelistRequest::class => MockResponse::fixture('add-to-broken-links-whitelist'), + ]); + + $this->ohDear->addToBrokenLinksWhitelist(82060, 'https://example.com/skip'); + + markTestComplete(); +}); diff --git a/tests/OhDearTests/NotificationDestinationsTest.php b/tests/OhDearTests/NotificationDestinationsTest.php new file mode 100644 index 0000000..725311d --- /dev/null +++ b/tests/OhDearTests/NotificationDestinationsTest.php @@ -0,0 +1,121 @@ +ohDear = ohDearMock(); +}); + +it('can update a monitor notification destination', function () { + MockClient::global([ + UpdateNotificationDestinationRequest::class => MockResponse::fixture('update-notification-destination'), + ]); + + $destination = $this->ohDear->updateNotificationDestination(82060, 456, [ + 'channel' => 'mail', + 'destination' => ['mail' => 'updated@example.com'], + ]); + + expect($destination->id)->toBe(456); + expect($destination->channel)->toBe('mail'); +}); + +it('can delete a monitor notification destination', function () { + MockClient::global([ + DeleteNotificationDestinationRequest::class => MockResponse::fixture('delete-notification-destination'), + ]); + + $this->ohDear->deleteNotificationDestination(82060, 456); + + markTestComplete(); +}); + +it('can get team notification destinations', function () { + MockClient::global([ + GetTeamNotificationDestinationsRequest::class => MockResponse::fixture('team-notification-destinations'), + ]); + + $destinations = $this->ohDear->teamNotificationDestinations(); + + expect($destinations)->toBeArray(); + foreach ($destinations as $destination) { + expect($destination->id)->toBeInt(); + } +}); + +it('can create a team notification destination', function () { + MockClient::global([ + CreateTeamNotificationDestinationRequest::class => MockResponse::fixture('create-team-notification-destination'), + ]); + + $destination = $this->ohDear->createTeamNotificationDestination(19245, [ + 'channel' => 'mail', + 'destination' => ['mail' => 'team@example.com'], + ]); + + expect($destination->id)->toBe(101); + expect($destination->channel)->toBe('mail'); +}); + +it('can get tag notification destinations', function () { + MockClient::global([ + GetTagNotificationDestinationsRequest::class => MockResponse::fixture('tag-notification-destinations'), + ]); + + $destinations = $this->ohDear->tagNotificationDestinations(); + + expect($destinations)->toBeArray(); + foreach ($destinations as $destination) { + expect($destination->id)->toBeInt(); + } +}); + +it('can create a tag notification destination', function () { + MockClient::global([ + CreateTagNotificationDestinationRequest::class => MockResponse::fixture('create-tag-notification-destination'), + ]); + + $destination = $this->ohDear->createTagNotificationDestination(1, [ + 'channel' => 'mail', + 'destination' => ['mail' => 'newtag@example.com'], + ]); + + expect($destination->id)->toBe(201); + expect($destination->channel)->toBe('mail'); +}); + +it('can get tag group notification destinations', function () { + MockClient::global([ + GetTagGroupNotificationDestinationsRequest::class => MockResponse::fixture('tag-group-notification-destinations'), + ]); + + $destinations = $this->ohDear->tagGroupNotificationDestinations(1); + + expect($destinations)->toBeArray(); + foreach ($destinations as $destination) { + expect($destination->id)->toBeInt(); + } +}); + +it('can create a tag group notification destination', function () { + MockClient::global([ + CreateTagGroupNotificationDestinationRequest::class => MockResponse::fixture('create-tag-group-notification-destination'), + ]); + + $destination = $this->ohDear->createTagGroupNotificationDestination(1, [ + 'channel' => 'mail', + 'destination' => ['mail' => 'taggroup@example.com'], + ]); + + expect($destination->id)->toBe(301); + expect($destination->channel)->toBe('mail'); +}); diff --git a/tests/OhDearTests/PortsHistoryItemsTest.php b/tests/OhDearTests/PortsHistoryItemsTest.php new file mode 100644 index 0000000..8ca85b1 --- /dev/null +++ b/tests/OhDearTests/PortsHistoryItemsTest.php @@ -0,0 +1,36 @@ +ohDear = ohDearMock(); +}); + +it('can get ports history items', function () { + MockClient::global([ + GetPortsHistoryItemsRequest::class => MockResponse::fixture('ports-history-items'), + ]); + + $items = $this->ohDear->portsHistoryItems(82060); + + expect($items)->toBeArray(); + foreach ($items as $item) { + expect($item->id)->toBeInt(); + expect($item->scannedHost)->toBeString(); + } +}); + +it('can get a single ports history item', function () { + MockClient::global([ + GetPortsHistoryItemRequest::class => MockResponse::fixture('ports-history-item'), + ]); + + $item = $this->ohDear->portsHistoryItem(82060, 1); + + expect($item->id)->toBe(1); + expect($item->scannedHost)->toBe('example.com'); + expect($item->scanTimeMs)->toBe(1500); +}); diff --git a/tests/OhDearTests/RecurringMaintenancePeriodsTest.php b/tests/OhDearTests/RecurringMaintenancePeriodsTest.php new file mode 100644 index 0000000..fb6c7f9 --- /dev/null +++ b/tests/OhDearTests/RecurringMaintenancePeriodsTest.php @@ -0,0 +1,83 @@ +ohDear = ohDearMock(); +}); + +it('can get recurring maintenance periods', function () { + MockClient::global([ + GetRecurringMaintenancePeriodsRequest::class => MockResponse::fixture('recurring-maintenance-periods'), + ]); + + $periods = $this->ohDear->recurringMaintenancePeriods(82060); + + expect($periods)->toBeArray(); + foreach ($periods as $period) { + expect($period->id)->toBeInt(); + expect($period->monitorId)->toBe(82060); + } +}); + +it('can get a single recurring maintenance period', function () { + MockClient::global([ + GetRecurringMaintenancePeriodRequest::class => MockResponse::fixture('recurring-maintenance-period'), + ]); + + $period = $this->ohDear->recurringMaintenancePeriod(1); + + expect($period->id)->toBe(1); + expect($period->monitorId)->toBe(82060); + expect($period->name)->toBe('Weekly Maintenance'); + expect($period->recurrenceType)->toBe('weekly'); +}); + +it('can create a recurring maintenance period', function () { + MockClient::global([ + CreateRecurringMaintenancePeriodRequest::class => MockResponse::fixture('create-recurring-maintenance-period'), + ]); + + $period = $this->ohDear->createRecurringMaintenancePeriod([ + 'monitor_id' => 82060, + 'name' => 'Daily Maintenance', + 'recurrence_type' => 'daily', + 'start_time' => '03:00', + 'end_time' => '05:00', + ]); + + expect($period->id)->toBe(2); + expect($period->name)->toBe('Daily Maintenance'); + expect($period->recurrenceType)->toBe('daily'); +}); + +it('can update a recurring maintenance period', function () { + MockClient::global([ + UpdateRecurringMaintenancePeriodRequest::class => MockResponse::fixture('update-recurring-maintenance-period'), + ]); + + $period = $this->ohDear->updateRecurringMaintenancePeriod(1, [ + 'name' => 'Updated Maintenance', + 'start_time' => '01:00', + 'end_time' => '03:00', + ]); + + expect($period->id)->toBe(1); + expect($period->name)->toBe('Updated Maintenance'); +}); + +it('can delete a recurring maintenance period', function () { + MockClient::global([ + DeleteRecurringMaintenancePeriodRequest::class => MockResponse::fixture('delete-recurring-maintenance-period'), + ]); + + $this->ohDear->deleteRecurringMaintenancePeriod(1); + + markTestComplete(); +}); diff --git a/tests/OhDearTests/StatusPageUpdateTemplatesTest.php b/tests/OhDearTests/StatusPageUpdateTemplatesTest.php new file mode 100644 index 0000000..758d5b5 --- /dev/null +++ b/tests/OhDearTests/StatusPageUpdateTemplatesTest.php @@ -0,0 +1,66 @@ +ohDear = ohDearMock(); +}); + +it('can get status page update templates', function () { + MockClient::global([ + GetStatusPageUpdateTemplatesRequest::class => MockResponse::fixture('status-page-update-templates'), + ]); + + $templates = $this->ohDear->statusPageUpdateTemplates(); + + expect($templates)->toBeArray(); + foreach ($templates as $template) { + expect($template->id)->toBeInt(); + expect($template->name)->toBeString(); + } +}); + +it('can create a status page update template', function () { + MockClient::global([ + CreateStatusPageUpdateTemplateRequest::class => MockResponse::fixture('create-status-page-update-template'), + ]); + + $template = $this->ohDear->createStatusPageUpdateTemplate([ + 'name' => 'Incident Template', + 'title' => 'Service Incident', + 'text' => 'We are investigating an issue.', + 'severity' => 'high', + ]); + + expect($template->id)->toBe(2); + expect($template->name)->toBe('Incident Template'); + expect($template->severity)->toBe('high'); +}); + +it('can update a status page update template', function () { + MockClient::global([ + UpdateStatusPageUpdateTemplateRequest::class => MockResponse::fixture('update-status-page-update-template'), + ]); + + $template = $this->ohDear->updateStatusPageUpdateTemplate(1, [ + 'name' => 'Updated Template', + ]); + + expect($template->id)->toBe(1); + expect($template->name)->toBe('Updated Template'); +}); + +it('can delete a status page update template', function () { + MockClient::global([ + DeleteStatusPageUpdateTemplateRequest::class => MockResponse::fixture('delete-status-page-update-template'), + ]); + + $this->ohDear->deleteStatusPageUpdateTemplate(1); + + markTestComplete(); +}); diff --git a/tests/OhDearTests/StatusPagesTest.php b/tests/OhDearTests/StatusPagesTest.php index 62305b0..915161a 100644 --- a/tests/OhDearTests/StatusPagesTest.php +++ b/tests/OhDearTests/StatusPagesTest.php @@ -1,10 +1,15 @@ MockResponse::fixture('create-status-page'), + ]); + + $statusPage = $this->ohDear->createStatusPage([ + 'title' => 'New Status Page', + 'team_id' => 19245, + ]); + + expect($statusPage->id)->toBe(9339); + expect($statusPage->title)->toBe('New Status Page'); +}); + +it('can add monitors to a status page', function () { + MockClient::global([ + AddStatusPageMonitorsRequest::class => MockResponse::fixture('add-status-page-monitors'), + ]); + + $statusPage = $this->ohDear->addStatusPageMonitors(9338, [ + 'monitors' => [82060], + ]); + + expect($statusPage->id)->toBe(9338); + expect($statusPage->monitors)->toBeArray(); +}); + +it('can delete a monitor from a status page', function () { + MockClient::global([ + DeleteStatusPageMonitorRequest::class => MockResponse::fixture('delete-status-page-monitor'), + ]); + + $this->ohDear->deleteStatusPageMonitor(9338, 82060); + + markTestComplete(); +}); + +it('can get status page updates', function () { + MockClient::global([ + GetStatusPageUpdatesRequest::class => MockResponse::fixture('status-page-updates'), + ]); + + $updates = $this->ohDear->statusPageUpdates(9338); + + expect($updates)->toBeArray(); + foreach ($updates as $update) { + expect($update->id)->toBeInt(); + expect($update->title)->toBeString(); + } +}); + +it('can update a status page update', function () { + MockClient::global([ + UpdateStatusPageUpdateRequest::class => MockResponse::fixture('update-status-page-update'), + ]); + + $update = $this->ohDear->updateStatusPageUpdate(1234, [ + 'title' => 'Updated title', + 'text' => 'Updated text', + ]); + + expect($update->id)->toBe(1234); + expect($update->title)->toBe('Updated title'); +}); diff --git a/tests/OhDearTests/TagGroupsTest.php b/tests/OhDearTests/TagGroupsTest.php new file mode 100644 index 0000000..9d27299 --- /dev/null +++ b/tests/OhDearTests/TagGroupsTest.php @@ -0,0 +1,63 @@ +ohDear = ohDearMock(); +}); + +it('can get tag groups', function () { + MockClient::global([ + GetTagGroupsRequest::class => MockResponse::fixture('tag-groups'), + ]); + + $tagGroups = $this->ohDear->tagGroups(); + + expect($tagGroups)->toBeArray(); + foreach ($tagGroups as $tagGroup) { + expect($tagGroup->id)->toBeInt(); + expect($tagGroup->label)->toBeString(); + } +}); + +it('can create a tag group', function () { + MockClient::global([ + CreateTagGroupRequest::class => MockResponse::fixture('create-tag-group'), + ]); + + $tagGroup = $this->ohDear->createTagGroup([ + 'label' => 'Region', + 'team_id' => 19245, + ]); + + expect($tagGroup->id)->toBe(2); + expect($tagGroup->label)->toBe('Region'); +}); + +it('can update a tag group', function () { + MockClient::global([ + UpdateTagGroupRequest::class => MockResponse::fixture('update-tag-group'), + ]); + + $tagGroup = $this->ohDear->updateTagGroup(1, [ + 'label' => 'Updated Environment', + ]); + + expect($tagGroup->id)->toBe(1); + expect($tagGroup->label)->toBe('Updated Environment'); +}); + +it('can delete a tag group', function () { + MockClient::global([ + DeleteTagGroupRequest::class => MockResponse::fixture('delete-tag-group'), + ]); + + $this->ohDear->deleteTagGroup(1); + + markTestComplete(); +}); diff --git a/tests/OhDearTests/TagsTest.php b/tests/OhDearTests/TagsTest.php new file mode 100644 index 0000000..d42e2ae --- /dev/null +++ b/tests/OhDearTests/TagsTest.php @@ -0,0 +1,38 @@ +ohDear = ohDearMock(); +}); + +it('can get tags', function () { + MockClient::global([ + GetTagsRequest::class => MockResponse::fixture('tags'), + ]); + + $tags = $this->ohDear->tags(); + + expect($tags)->toBeArray(); + foreach ($tags as $tag) { + expect($tag->id)->toBeInt(); + expect($tag->name)->toBeString(); + } +}); + +it('can create a tag', function () { + MockClient::global([ + CreateTagRequest::class => MockResponse::fixture('create-tag'), + ]); + + $tag = $this->ohDear->createTag([ + 'name' => 'staging', + 'team_id' => 19245, + ]); + + expect($tag->id)->toBe(2); + expect($tag->name)->toBe('staging'); +}); From b1afc010673f349318db6ea58e57c28c21901111 Mon Sep 17 00:00:00 2001 From: mattiasgeniar Date: Sat, 14 Feb 2026 13:33:05 +0000 Subject: [PATCH 02/10] Fix styling --- src/Concerns/SupportsNotificationDestinationEndpoints.php | 4 ++-- src/Concerns/SupportsStatusPageUpdateTemplateEndpoints.php | 2 +- src/Concerns/SupportsTagEndpoints.php | 2 +- src/Concerns/SupportsTagGroupEndpoints.php | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Concerns/SupportsNotificationDestinationEndpoints.php b/src/Concerns/SupportsNotificationDestinationEndpoints.php index 1b66490..2da0670 100644 --- a/src/Concerns/SupportsNotificationDestinationEndpoints.php +++ b/src/Concerns/SupportsNotificationDestinationEndpoints.php @@ -21,7 +21,7 @@ trait SupportsNotificationDestinationEndpoints { public function teamNotificationDestinations(): array { - $request = new GetTeamNotificationDestinationsRequest(); + $request = new GetTeamNotificationDestinationsRequest; return $this->send($request)->dto(); } @@ -51,7 +51,7 @@ public function deleteTeamNotificationDestination(int $teamId, int $destinationI public function tagNotificationDestinations(): array { - $request = new GetTagNotificationDestinationsRequest(); + $request = new GetTagNotificationDestinationsRequest; return $this->send($request)->dto(); } diff --git a/src/Concerns/SupportsStatusPageUpdateTemplateEndpoints.php b/src/Concerns/SupportsStatusPageUpdateTemplateEndpoints.php index 50f100d..976f965 100644 --- a/src/Concerns/SupportsStatusPageUpdateTemplateEndpoints.php +++ b/src/Concerns/SupportsStatusPageUpdateTemplateEndpoints.php @@ -13,7 +13,7 @@ trait SupportsStatusPageUpdateTemplateEndpoints { public function statusPageUpdateTemplates(): array { - $request = new GetStatusPageUpdateTemplatesRequest(); + $request = new GetStatusPageUpdateTemplatesRequest; return $this->send($request)->dtoOrFail(); } diff --git a/src/Concerns/SupportsTagEndpoints.php b/src/Concerns/SupportsTagEndpoints.php index e6f3a5c..fd3ac95 100644 --- a/src/Concerns/SupportsTagEndpoints.php +++ b/src/Concerns/SupportsTagEndpoints.php @@ -11,7 +11,7 @@ trait SupportsTagEndpoints { public function tags(): array { - $request = new GetTagsRequest(); + $request = new GetTagsRequest; return $this->send($request)->dtoOrFail(); } diff --git a/src/Concerns/SupportsTagGroupEndpoints.php b/src/Concerns/SupportsTagGroupEndpoints.php index 75d742f..4c6ba6c 100644 --- a/src/Concerns/SupportsTagGroupEndpoints.php +++ b/src/Concerns/SupportsTagGroupEndpoints.php @@ -13,7 +13,7 @@ trait SupportsTagGroupEndpoints { public function tagGroups(): array { - $request = new GetTagGroupsRequest(); + $request = new GetTagGroupsRequest; return $this->send($request)->dtoOrFail(); } From c828d1a9aa20bb9c6ddd1242b2919e0f62c777e8 Mon Sep 17 00:00:00 2001 From: Mattias Geniar Date: Sat, 14 Feb 2026 14:37:26 +0100 Subject: [PATCH 03/10] Update README --- README.md | 276 ++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 258 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index c9da6b9..98f8ccc 100644 --- a/README.md +++ b/README.md @@ -104,37 +104,40 @@ foreach($monitors as $monitor) { #### Create a monitor -You can use the `createMonitor` method to create a monitor. - -```php +```php $monitor = $ohDear->createMonitor([ 'url' => 'https://example.com', 'type' => 'http', 'team_id' => 1, ]); - -echo $monitor->url; // returns https://example.com ``` -You can find a list of attributes you can pass to the `createMonitor` method in the [Oh Dear API documentation](#oh-dear-documentation). +See the [Oh Dear API documentation](#oh-dear-documentation) for all available attributes. #### Getting a single monitor -You can use the `monitor` method to get a single monitor. - ```php -// returns OhDear\PhpSdk\Dto\Monitor $monitor = $ohDear->monitor($monitorId); ``` #### Deleting a monitor -You can use the `deleteMonitor` method to delete a monitor. - ```php $ohDear->deleteMonitor($monitorId); ``` +#### Getting a monitor by URL + +```php +$monitor = $ohDear->monitorByUrl('https://example.com'); +``` + +#### Adding a URL to the broken links whitelist + +```php +$ohDear->addToBrokenLinksWhitelist($monitorId, 'https://example.com/skip'); +``` + #### Getting a check summary for a monitor You can get a summary of a specific check type for a monitor, which provides the current status and a human-readable summary: @@ -211,12 +214,75 @@ You can use the `statusPage` method to get a single status page. $statusPage = $ohDear->statusPage($statusPageId); ``` +#### Creating a status page + +```php +$statusPage = $ohDear->createStatusPage([ + 'title' => 'My Status Page', + 'team_id' => 1, +]); +``` + #### Deleting a status page -You can use the `deleteStatusPage` method to delete a status page. +```php +$ohDear->deleteStatusPage($statusPageId); +``` + +#### Managing monitors on a status page + +```php +// Add monitors +$statusPage = $ohDear->addStatusPageMonitors($statusPageId, [ + 'monitors' => [82060], +]); + +// Remove a monitor +$ohDear->deleteStatusPageMonitor($statusPageId, $monitorId); +``` + +#### Status page updates + +```php +// List updates +$updates = $ohDear->statusPageUpdates($statusPageId); + +// Create an update +$update = $ohDear->createStatusPageUpdate([ + 'status_page_id' => $statusPageId, + 'title' => 'Our site is down', + 'text' => 'We are working on it!', + 'severity' => 'high', + 'time' => '2025-01-01 00:00:00', + 'pinned' => true, +]); + +// Update an existing update +$update = $ohDear->updateStatusPageUpdate($updateId, [ + 'title' => 'Issue resolved', +]); + +// Delete an update +$ohDear->deleteStatusPageUpdate($updateId); +``` + +#### Status page update templates ```php -$ohDear->deleteStatusPage($statusPageId) +$templates = $ohDear->statusPageUpdateTemplates(); + +$template = $ohDear->createStatusPageUpdateTemplate([ + 'name' => 'Maintenance', + 'title' => 'Scheduled maintenance', + 'text' => 'We are performing scheduled maintenance.', + 'severity' => 'info', +]); + +$template = $ohDear->updateStatusPageUpdateTemplate($templateId, [ + 'name' => 'Updated template', +]); + +$ohDear->deleteStatusPageUpdateTemplate($templateId); ``` ### Checks @@ -499,6 +565,17 @@ echo $cronCheckDefinition->activeSnooze['ends_at']; $cronCheckDefinition = $ohDear->unsnoozeCronCheckDefinition($cronCheckDefinitionId); ``` +#### Syncing cron check definitions + +Bulk sync cron check definitions for a monitor — creates, updates, or removes definitions to match the provided list: + +```php +$cronCheckDefinitions = $ohDear->syncCronCheckDefinitions($monitorId, [ + ['name' => 'Backup', 'type' => 'simple', 'frequency_in_minutes' => 60], + ['name' => 'Cleanup', 'type' => 'simple', 'frequency_in_minutes' => 1440], +]); +``` + ### Broken Links The broken links feature crawls your website and identifies links that return HTTP error status codes, helping you maintain a healthy website. @@ -689,19 +766,24 @@ foreach ($healthChecks as $healthCheck) { #### Getting history for a specific application health check ```php -// returns an array of OhDear\PhpSdk\Dto\ApplicationHealthCheckHistoryItem $history = $ohDear->applicationHealthCheckHistory($monitorId, $healthCheckId); foreach ($history as $historyItem) { - echo "History Item ID: {$historyItem->id}"; echo "Status: {$historyItem->status}"; echo "Short summary: {$historyItem->shortSummary}"; - echo "Message: {$historyItem->message}"; - echo "Detected at: {$historyItem->detectedAt}"; - echo "Updated at: {$historyItem->updatedAt}"; } ``` +#### Snoozing and unsnoozing application health checks + +```php +// Snooze for 60 minutes +$healthCheck = $ohDear->snoozeApplicationHealthCheck($monitorId, $healthCheckId, 60); + +// Unsnooze +$healthCheck = $ohDear->unsnoozeApplicationHealthCheck($monitorId, $healthCheckId); +``` + ### Sitemap The sitemap check analyzes your website's XML sitemap(s) to ensure they're accessible and properly formatted, and can also check the reachability of URLs within the sitemaps. @@ -819,6 +901,164 @@ You can delete downtime periods that were recorded incorrectly or are no longer $ohDear->deleteDowntimePeriod($downtimePeriodId); ``` +### Domain Monitoring + +```php +$domainInfo = $ohDear->domain($monitorId); + +echo "Expires at: {$domainInfo->expiresAt}"; +echo "Registered at: {$domainInfo->registeredAt}"; +``` + +### AI Responses + +```php +// List all AI responses +$aiResponses = $ohDear->aiResponses($monitorId); + +// Get a specific AI response +$aiResponse = $ohDear->aiResponse($monitorId, $aiResponseId); + +// Get the latest AI response +$aiResponse = $ohDear->latestAiResponse($monitorId); + +echo "Prompt: {$aiResponse->prompt}"; +echo "Response: {$aiResponse->response}"; +``` + +### Port Scanning + +```php +// List port scan results +$items = $ohDear->portsHistoryItems($monitorId); + +// Get a specific port scan +$item = $ohDear->portsHistoryItem($monitorId, $portsHistoryItemId); + +echo "Scanned host: {$item->scannedHost}"; +echo "Scan time: {$item->scanTimeMs}ms"; +``` + +### DNS Blocklist + +```php +// List blocklist check results +$items = $ohDear->dnsBlocklistHistoryItems($monitorId); + +// Get a specific blocklist check +$item = $ohDear->dnsBlocklistHistoryItem($monitorId, $dnsBlocklistHistoryItemId); + +echo "Domain: {$item->domain}"; +``` + +### Tags + +```php +$tags = $ohDear->tags(); + +$tag = $ohDear->createTag([ + 'name' => 'production', + 'team_id' => 1, +]); +``` + +### Tag Groups + +```php +$tagGroups = $ohDear->tagGroups(); + +$tagGroup = $ohDear->createTagGroup([ + 'label' => 'Environment', + 'team_id' => 1, +]); + +$tagGroup = $ohDear->updateTagGroup($tagGroupId, [ + 'label' => 'Updated label', +]); + +$ohDear->deleteTagGroup($tagGroupId); +``` + +### Recurring Maintenance Periods + +```php +// List recurring periods for a monitor +$periods = $ohDear->recurringMaintenancePeriods($monitorId); + +// Get a single recurring period +$period = $ohDear->recurringMaintenancePeriod($recurringMaintenancePeriodId); + +// Create +$period = $ohDear->createRecurringMaintenancePeriod([ + 'monitor_id' => $monitorId, + 'name' => 'Weekly maintenance', + 'recurrence_type' => 'weekly', + 'start_time' => '02:00', + 'end_time' => '04:00', + 'days_of_week' => [0], // Sunday +]); + +// Update +$period = $ohDear->updateRecurringMaintenancePeriod($id, [ + 'name' => 'Updated schedule', +]); + +// Delete +$ohDear->deleteRecurringMaintenancePeriod($id); +``` + +### Notification Destinations + +Notification destinations can be managed at the monitor, team, tag, and tag group level. + +#### Monitor-level notification destinations + +```php +$destinations = $ohDear->notificationDestinations($monitorId); + +$destination = $ohDear->createNotificationDestination($monitorId, [ + 'channel' => 'mail', + 'destination' => ['mail' => 'alerts@example.com'], +]); + +$destination = $ohDear->updateNotificationDestination($monitorId, $destinationId, [ + 'destination' => ['mail' => 'new@example.com'], +]); + +$ohDear->deleteNotificationDestination($monitorId, $destinationId); +``` + +#### Team-level notification destinations + +```php +$destinations = $ohDear->teamNotificationDestinations(); + +$destination = $ohDear->createTeamNotificationDestination($teamId, [ + 'channel' => 'slack', + 'destination' => ['url' => 'https://hooks.slack.com/...'], +]); + +$destination = $ohDear->updateTeamNotificationDestination($teamId, $destinationId, [...]); + +$ohDear->deleteTeamNotificationDestination($teamId, $destinationId); +``` + +#### Tag and tag group notification destinations + +```php +// Tag destinations +$destinations = $ohDear->tagNotificationDestinations(); +$destination = $ohDear->createTagNotificationDestination($tagId, [...]); +$destination = $ohDear->updateTagNotificationDestination($tagId, $destinationId, [...]); +$ohDear->deleteTagNotificationDestination($tagId, $destinationId); + +// Tag group destinations +$destinations = $ohDear->tagGroupNotificationDestinations($tagGroupId); +$destination = $ohDear->createTagGroupNotificationDestination($tagGroupId, [...]); +$destination = $ohDear->updateTagGroupNotificationDestination($tagGroupId, $destinationId, [...]); +$ohDear->deleteTagGroupNotificationDestination($tagGroupId, $destinationId); +``` + ### Using Saloon requests directly This SDK uses [Saloon](https://docs.saloon.dev) to make the HTTP requests. Instead of using the `OhDear` class, you can the underlying request classes directly. This way, you have full power to customize the requests. From f7fd0ffd7da28b2bccc55410d15b7655282e37c0 Mon Sep 17 00:00:00 2001 From: Mattias Geniar Date: Sat, 14 Feb 2026 14:38:04 +0100 Subject: [PATCH 04/10] Drop 8.1 from CI --- .github/workflows/run-tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/run-tests.yml b/.github/workflows/run-tests.yml index bad6db7..7178377 100644 --- a/.github/workflows/run-tests.yml +++ b/.github/workflows/run-tests.yml @@ -9,7 +9,7 @@ jobs: fail-fast: false matrix: os: [ubuntu-latest] - php: [8.4, 8.3, 8.2, 8.1] + php: [8.4, 8.3, 8.2] dependency-version: [prefer-lowest, prefer-stable] name: P${{ matrix.php }} - ${{ matrix.dependency-version }} - ${{ matrix.os }} From c386bdb001b068c3cab88e0c1768d26cf4c3f3f6 Mon Sep 17 00:00:00 2001 From: Mattias Geniar Date: Sat, 14 Feb 2026 15:05:32 +0100 Subject: [PATCH 05/10] Update README --- README.md | 48 +++++++++++++++++++++++++----------------------- 1 file changed, 25 insertions(+), 23 deletions(-) diff --git a/README.md b/README.md index 98f8ccc..85e3924 100644 --- a/README.md +++ b/README.md @@ -78,7 +78,7 @@ try { For all other errors, the SDK will throw an `\OhDear\PhpSdk\Exceptions\OhDearException`. -### Get user info +### [Get user info](https://ohdear.app/docs/api/user-info) ```php // returns OhDear\PhpSdk\Dto\User @@ -87,10 +87,12 @@ $user = $ohDear->me(); echo $user->email; // returns the email address of the authenticated user ``` -### Monitors +### [Monitors](https://ohdear.app/docs/api/monitors) Monitors are the core of Oh Dear - they watch your websites, APIs, and services for uptime, performance, SSL certificates, broken links, and more. You can create different types of monitors (HTTP, ping, TCP) and configure various checks for each one. +[View all monitor API documentation](https://ohdear.app/docs/api/monitors) + #### Get all monitors ```php @@ -190,7 +192,7 @@ foreach ($certificateHealth->certificateChainIssuers as $issuer) { } ``` -### Status pages +### [Status pages](https://ohdear.app/docs/api/status-pages) Status pages provide a public way to communicate the status of your services to your users. They automatically reflect the health of your monitors and allow you to post updates during incidents or maintenance windows. @@ -285,7 +287,7 @@ $template = $ohDear->updateStatusPageUpdateTemplate($templateId, [ $ohDear->deleteStatusPageUpdateTemplate($templateId); ``` -### Checks +### [Checks](https://ohdear.app/docs/api/checks) Checks are individual monitoring tasks that belong to monitors (like uptime, SSL certificate, performance, broken links, etc.). You can control each check independently - enabling, disabling, requesting immediate runs, and temporarily snoozing notifications. @@ -348,7 +350,7 @@ $check = $ohDear->unsnoozeCheck($checkId); echo $check->activeSnooze ? 'Check is still snoozed' : 'Check is now active'; ``` -### Maintenance Periods +### [Maintenance Periods](https://ohdear.app/docs/api/maintenance-windows) Maintenance periods allow you to temporarily disable notifications for monitors during planned maintenance windows. @@ -425,7 +427,7 @@ You can delete a maintenance period: $ohDear->deleteMaintenancePeriod($maintenancePeriodId); ``` -### Uptime Metrics +### [Uptime Metrics](https://ohdear.app/docs/api/uptime-metrics) Uptime metrics provide detailed performance and timing data for your monitors over time. Different monitor types (Http, Ping, TCP) provide different metrics. @@ -485,7 +487,7 @@ foreach ($metrics as $metric) { } ``` -### Cron Check Definitions +### [Cron Check Definitions](https://ohdear.app/docs/api/cron-job-monitoring) Cron check definitions allow you to monitor scheduled tasks and ensure they execute on time. You can create different types of cron checks including traditional cron expressions and simple frequency-based checks. @@ -576,7 +578,7 @@ $cronCheckDefinitions = $ohDear->syncCronCheckDefinitions($monitorId, [ ]); ``` -### Broken Links +### [Broken Links](https://ohdear.app/docs/api/broken-links) The broken links feature crawls your website and identifies links that return HTTP error status codes, helping you maintain a healthy website. @@ -595,7 +597,7 @@ foreach ($brokenLinks as $brokenLink) { } ``` -### Detected Certificates +### [Detected Certificates](https://ohdear.app/docs/api/certificate-health) Detected certificates provide information about SSL certificates that Oh Dear has discovered while monitoring your site, including their details, validity, and fingerprints. @@ -637,7 +639,7 @@ echo "Certificate fingerprint: {$certificate->fingerprint}"; echo "Created at: {$certificate->createdAt}"; ``` -### DNS History Items +### [DNS History Items](https://ohdear.app/docs/api/dns-records) DNS history items track changes to your domain's DNS records over time, helping you monitor DNS propagation and detect unauthorized changes. @@ -664,7 +666,7 @@ foreach ($dnsHistoryItems as $historyItem) { $historyItem = $ohDear->dnsHistoryItem($monitorId, $historyItemId); ``` -### Lighthouse Reports +### [Lighthouse Reports](https://ohdear.app/docs/api/lighthouse) Lighthouse reports provide detailed performance, accessibility, SEO, and best practices analysis of your web pages using Google's Lighthouse auditing tool. @@ -727,7 +729,7 @@ echo "Latest performance score: {$latestReport->performanceScore}/100"; echo "Report generated: {$latestReport->createdAt}"; ``` -### Application Health Checks +### [Application Health Checks](https://ohdear.app/docs/api/application-health) Application health checks monitor custom endpoints in your application to ensure they're responding correctly and returning expected health status information. @@ -784,7 +786,7 @@ $healthCheck = $ohDear->snoozeApplicationHealthCheck($monitorId, $healthCheckId, $healthCheck = $ohDear->unsnoozeApplicationHealthCheck($monitorId, $healthCheckId); ``` -### Sitemap +### [Sitemap](https://ohdear.app/docs/api/sitemap) The sitemap check analyzes your website's XML sitemap(s) to ensure they're accessible and properly formatted, and can also check the reachability of URLs within the sitemaps. @@ -835,7 +837,7 @@ if (!empty($sitemap->sitemaps)) { } ``` -### Mixed Content +### [Mixed Content](https://ohdear.app/docs/api/mixed-content) The mixed content check identifies elements on your HTTPS pages that are loaded over HTTP, which can cause security warnings in browsers and degrade user experience. @@ -853,7 +855,7 @@ foreach ($mixedContentItems as $mixedContent) { } ``` -### Downtime +### [Downtime](https://ohdear.app/docs/api/uptime) Downtime periods track when your monitored sites were unavailable, providing historical data about outages and their duration. @@ -901,7 +903,7 @@ You can delete downtime periods that were recorded incorrectly or are no longer $ohDear->deleteDowntimePeriod($downtimePeriodId); ``` -### Domain Monitoring +### [Domain Monitoring](https://ohdear.app/docs/api/domain-monitoring) ```php $domainInfo = $ohDear->domain($monitorId); @@ -910,7 +912,7 @@ echo "Expires at: {$domainInfo->expiresAt}"; echo "Registered at: {$domainInfo->registeredAt}"; ``` -### AI Responses +### [AI Responses](https://ohdear.app/docs/api/ai-monitoring) ```php // List all AI responses @@ -926,7 +928,7 @@ echo "Prompt: {$aiResponse->prompt}"; echo "Response: {$aiResponse->response}"; ``` -### Port Scanning +### [Port Scanning](https://ohdear.app/docs/api/port-scanning) ```php // List port scan results @@ -939,7 +941,7 @@ echo "Scanned host: {$item->scannedHost}"; echo "Scan time: {$item->scanTimeMs}ms"; ``` -### DNS Blocklist +### [DNS Blocklist](https://ohdear.app/docs/api/dns-blocklist) ```php // List blocklist check results @@ -951,7 +953,7 @@ $item = $ohDear->dnsBlocklistHistoryItem($monitorId, $dnsBlocklistHistoryItemId) echo "Domain: {$item->domain}"; ``` -### Tags +### [Tags](https://ohdear.app/docs/api/tags-and-tag-groups) ```php $tags = $ohDear->tags(); @@ -962,7 +964,7 @@ $tag = $ohDear->createTag([ ]); ``` -### Tag Groups +### [Tag Groups](https://ohdear.app/docs/api/tags-and-tag-groups) ```php $tagGroups = $ohDear->tagGroups(); @@ -979,7 +981,7 @@ $tagGroup = $ohDear->updateTagGroup($tagGroupId, [ $ohDear->deleteTagGroup($tagGroupId); ``` -### Recurring Maintenance Periods +### [Recurring Maintenance Periods](https://ohdear.app/docs/api/maintenance-windows) ```php // List recurring periods for a monitor @@ -1007,7 +1009,7 @@ $period = $ohDear->updateRecurringMaintenancePeriod($id, [ $ohDear->deleteRecurringMaintenancePeriod($id); ``` -### Notification Destinations +### [Notification Destinations](https://ohdear.app/docs/api/notification-destinations) Notification destinations can be managed at the monitor, team, tag, and tag group level. From e23b7540be44176218ccacea509f31eefb4873d6 Mon Sep 17 00:00:00 2001 From: Mattias Geniar Date: Sun, 15 Feb 2026 12:03:26 +0100 Subject: [PATCH 06/10] Fixes for accuracy --- src/Dto/AiResponse.php | 28 +++++++++++++------ src/Dto/Check.php | 2 ++ src/Dto/DnsBlocklistHistoryItem.php | 10 ++++--- src/Dto/Monitor.php | 8 ++++++ src/Dto/RecurringMaintenancePeriod.php | 4 +++ src/Dto/StatusPage.php | 12 +++++--- src/Dto/Tag.php | 8 ++++-- src/Dto/TagGroup.php | 2 ++ src/Enums/CheckType.php | 2 +- .../AddToBrokenLinksWhitelistRequest.php | 2 +- tests/Fixtures/Saloon/ai-response.json | 2 +- tests/Fixtures/Saloon/ai-responses.json | 2 +- .../create-recurring-maintenance-period.json | 2 +- tests/Fixtures/Saloon/create-tag-group.json | 2 +- tests/Fixtures/Saloon/create-tag.json | 2 +- .../Saloon/dns-blocklist-history-item.json | 2 +- .../Saloon/dns-blocklist-history-items.json | 2 +- tests/Fixtures/Saloon/latest-ai-response.json | 2 +- .../Saloon/recurring-maintenance-period.json | 2 +- .../Saloon/recurring-maintenance-periods.json | 2 +- tests/Fixtures/Saloon/tag-groups.json | 2 +- tests/Fixtures/Saloon/tags.json | 2 +- .../update-recurring-maintenance-period.json | 2 +- tests/Fixtures/Saloon/update-tag-group.json | 2 +- tests/OhDearTests/AiResponsesTest.php | 10 +++++-- .../DnsBlocklistHistoryItemsTest.php | 6 ++-- 26 files changed, 82 insertions(+), 40 deletions(-) diff --git a/src/Dto/AiResponse.php b/src/Dto/AiResponse.php index 48c91f8..66af510 100644 --- a/src/Dto/AiResponse.php +++ b/src/Dto/AiResponse.php @@ -6,12 +6,18 @@ class AiResponse { public function __construct( public int $id, - public int $monitorId, + public ?string $result, + public ?string $finishReason, public ?string $prompt, - public ?string $response, + public ?string $text, + public ?string $notificationTitle, + public ?string $notificationBody, + public array $usedTools, + public ?int $usedPromptTokens, + public ?int $usedCompletionTokens, public ?string $rawResponse, - public array $tokenUsage, - public array $toolInvocations, + public ?string $startedAt, + public ?string $endedAt, public ?string $createdAt, ) {} @@ -19,12 +25,18 @@ public static function fromResponse(array $data): self { return new self( id: $data['id'], - monitorId: $data['monitor_id'], + result: $data['result'] ?? null, + finishReason: $data['finish_reason'] ?? null, prompt: $data['prompt'] ?? null, - response: $data['response'] ?? null, + text: $data['text'] ?? null, + notificationTitle: $data['notification_title'] ?? null, + notificationBody: $data['notification_body'] ?? null, + usedTools: $data['used_tools'] ?? [], + usedPromptTokens: $data['used_prompt_tokens'] ?? null, + usedCompletionTokens: $data['used_completion_tokens'] ?? null, rawResponse: $data['raw_response'] ?? null, - tokenUsage: $data['token_usage'] ?? [], - toolInvocations: $data['tool_invocations'] ?? [], + startedAt: $data['started_at'] ?? null, + endedAt: $data['ended_at'] ?? null, createdAt: $data['created_at'] ?? null, ); } diff --git a/src/Dto/Check.php b/src/Dto/Check.php index fe2f2b2..da090c1 100644 --- a/src/Dto/Check.php +++ b/src/Dto/Check.php @@ -13,6 +13,7 @@ public function __construct( public ?string $latestRunResult, public ?string $summary, public array $settings, + public ?float $averageResponseTimeInMs, public ?array $activeSnooze, ) {} @@ -27,6 +28,7 @@ public static function fromResponse(array $data): self latestRunResult: $data['latest_run_result'] ?? null, summary: $data['summary'] ?? null, settings: $data['settings'] ?? [], + averageResponseTimeInMs: $data['average_response_time_in_ms'] ?? null, activeSnooze: $data['active_snooze'] ?? null, ); } diff --git a/src/Dto/DnsBlocklistHistoryItem.php b/src/Dto/DnsBlocklistHistoryItem.php index 4520372..1448263 100644 --- a/src/Dto/DnsBlocklistHistoryItem.php +++ b/src/Dto/DnsBlocklistHistoryItem.php @@ -6,9 +6,10 @@ class DnsBlocklistHistoryItem { public function __construct( public int $id, - public ?string $domain, + public ?string $checkedDomain, public array $resolvedIps, - public array $blocklists, + public array $blocklistResults, + public mixed $issues, public ?string $createdAt, ) {} @@ -16,9 +17,10 @@ public static function fromResponse(array $data): self { return new self( id: $data['id'], - domain: $data['domain'] ?? null, + checkedDomain: $data['checked_domain'] ?? null, resolvedIps: $data['resolved_ips'] ?? [], - blocklists: $data['blocklists'] ?? [], + blocklistResults: $data['blocklist_results'] ?? [], + issues: $data['issues'] ?? null, createdAt: $data['created_at'] ?? null, ); } diff --git a/src/Dto/Monitor.php b/src/Dto/Monitor.php index 90b25b3..77fc585 100644 --- a/src/Dto/Monitor.php +++ b/src/Dto/Monitor.php @@ -7,6 +7,7 @@ class Monitor public function __construct( public int $id, public ?int $teamId, + public string $type, public string $url, public bool $usesHttps, public string $sortUrl, @@ -27,6 +28,9 @@ public function __construct( public array $domainCheckSettings = [], public array $performanceCheckSettings = [], public array $sitemapCheckSettings = [], + public ?array $portsCheckSettings = null, + public ?array $dnsBlocklistCheckSettings = null, + public ?array $aiCheckSettings = null, public array $crawlerHeaders = [], public array $sendReportToEmails = [], public array $includeCheckTypesInReport = [], @@ -41,6 +45,7 @@ public static function fromResponse(array $data): self return new self( id: $data['id'], teamId: $data['team_id'], + type: $data['type'] ?? 'http', url: $data['url'], usesHttps: $data['uses_https'] ?? false, sortUrl: $data['sort_url'] ?? $data['url'], @@ -61,6 +66,9 @@ public static function fromResponse(array $data): self domainCheckSettings: $data['domain_check_settings'] ?? [], performanceCheckSettings: $data['performance_check_settings'] ?? [], sitemapCheckSettings: $data['sitemap_check_settings'] ?? [], + portsCheckSettings: $data['ports_check_settings'] ?? null, + dnsBlocklistCheckSettings: $data['dns_blocklist_check_settings'] ?? null, + aiCheckSettings: $data['ai_check_settings'] ?? null, crawlerHeaders: $data['crawler_headers'] ?? [], sendReportToEmails: $data['send_report_to_emails'] ?? [], includeCheckTypesInReport: $data['include_check_types_in_report'] ?? [], diff --git a/src/Dto/RecurringMaintenancePeriod.php b/src/Dto/RecurringMaintenancePeriod.php index 6f90d02..3eee8ea 100644 --- a/src/Dto/RecurringMaintenancePeriod.php +++ b/src/Dto/RecurringMaintenancePeriod.php @@ -13,6 +13,8 @@ public function __construct( public ?string $endTime, public array $daysOfWeek, public ?int $dayOfMonth, + public ?string $humanReadableSchedule, + public ?string $lastGeneratedUntil, public ?string $createdAt, public ?string $updatedAt, ) {} @@ -28,6 +30,8 @@ public static function fromResponse(array $data): self endTime: $data['end_time'] ?? null, daysOfWeek: $data['days_of_week'] ?? [], dayOfMonth: $data['day_of_month'] ?? null, + humanReadableSchedule: $data['human_readable_schedule'] ?? null, + lastGeneratedUntil: $data['last_generated_until'] ?? null, createdAt: $data['created_at'] ?? null, updatedAt: $data['updated_at'] ?? null, ); diff --git a/src/Dto/StatusPage.php b/src/Dto/StatusPage.php index 0f3ae39..115d4e6 100644 --- a/src/Dto/StatusPage.php +++ b/src/Dto/StatusPage.php @@ -17,8 +17,10 @@ public function __construct( public ?string $summarizedStatus, public ?array $updates, public ?array $monitors, - public string $createdAt, - public string $updatedAt, + public bool $preventIndexing = false, + public bool $addHstsHeader = false, + public string $createdAt = '', + public string $updatedAt = '', ) {} public static function fromResponse(array $data): self @@ -36,8 +38,10 @@ public static function fromResponse(array $data): self summarizedStatus: $data['summarized_status'] ?? null, updates: $data['updates'] ?? [], monitors: $data['monitors'] ?? [], - createdAt: $data['created_at'], - updatedAt: $data['updated_at'], + preventIndexing: $data['prevent_indexing'] ?? false, + addHstsHeader: $data['add_hsts_header'] ?? false, + createdAt: $data['created_at'] ?? '', + updatedAt: $data['updated_at'] ?? '', ); } diff --git a/src/Dto/Tag.php b/src/Dto/Tag.php index ac3202b..ccec132 100644 --- a/src/Dto/Tag.php +++ b/src/Dto/Tag.php @@ -7,8 +7,10 @@ class Tag public function __construct( public int $id, public ?int $teamId, + public ?string $teamName, public string $name, - public array $monitors, + public ?string $slug, + public array $sites, public ?string $createdAt, public ?string $updatedAt, ) {} @@ -18,8 +20,10 @@ public static function fromResponse(array $data): self return new self( id: $data['id'], teamId: $data['team_id'] ?? null, + teamName: $data['team_name'] ?? null, name: $data['name'], - monitors: $data['monitors'] ?? [], + slug: $data['slug'] ?? null, + sites: $data['sites'] ?? [], createdAt: $data['created_at'] ?? null, updatedAt: $data['updated_at'] ?? null, ); diff --git a/src/Dto/TagGroup.php b/src/Dto/TagGroup.php index 9d31136..0bb3917 100644 --- a/src/Dto/TagGroup.php +++ b/src/Dto/TagGroup.php @@ -7,6 +7,7 @@ class TagGroup public function __construct( public int $id, public ?int $teamId, + public ?string $teamName, public string $label, public array $tags, public ?string $createdAt, @@ -18,6 +19,7 @@ public static function fromResponse(array $data): self return new self( id: $data['id'], teamId: $data['team_id'] ?? null, + teamName: $data['team_name'] ?? null, label: $data['label'], tags: $data['tags'] ?? [], createdAt: $data['created_at'] ?? null, diff --git a/src/Enums/CheckType.php b/src/Enums/CheckType.php index 274859a..af7be1b 100644 --- a/src/Enums/CheckType.php +++ b/src/Enums/CheckType.php @@ -16,6 +16,6 @@ enum CheckType: string case Dns = 'dns'; case Domain = 'domain'; case DnsBlocklist = 'dns_blocklist'; - case PortScanning = 'port_scanning'; + case Ports = 'ports'; case Ai = 'ai'; } diff --git a/src/Requests/Monitors/AddToBrokenLinksWhitelistRequest.php b/src/Requests/Monitors/AddToBrokenLinksWhitelistRequest.php index 42ed440..0dc81a8 100644 --- a/src/Requests/Monitors/AddToBrokenLinksWhitelistRequest.php +++ b/src/Requests/Monitors/AddToBrokenLinksWhitelistRequest.php @@ -26,7 +26,7 @@ public function resolveEndpoint(): string protected function defaultBody(): array { return [ - 'url' => $this->url, + 'whitelistUrl' => $this->url, ]; } } diff --git a/tests/Fixtures/Saloon/ai-response.json b/tests/Fixtures/Saloon/ai-response.json index 16e3d7e..d342962 100644 --- a/tests/Fixtures/Saloon/ai-response.json +++ b/tests/Fixtures/Saloon/ai-response.json @@ -1 +1 @@ -{"statusCode":200,"headers":{"Content-Type":"application/json"},"data":"{\"id\":1,\"monitor_id\":82060,\"prompt\":\"Check if the site is accessible\",\"response\":\"The site is accessible and responding normally.\",\"raw_response\":\"The site is accessible and responding normally.\",\"token_usage\":{\"input\":100,\"output\":50},\"tool_invocations\":[],\"created_at\":\"2025-01-01 00:00:00\"}","context":[]} +{"statusCode":200,"headers":{"Content-Type":"application/json"},"data":"{\"id\":1,\"result\":\"ok\",\"finish_reason\":\"stop\",\"prompt\":\"Check if the site is accessible\",\"text\":\"The site is accessible and responding normally.\",\"notification_title\":null,\"notification_body\":null,\"used_tools\":[],\"used_prompt_tokens\":100,\"used_completion_tokens\":50,\"raw_response\":\"{\\\"message\\\": \\\"All good\\\"}\",\"started_at\":\"2025-01-01 00:00:00\",\"ended_at\":\"2025-01-01 00:00:05\",\"created_at\":\"2025-01-01 00:00:05\"}","context":[]} diff --git a/tests/Fixtures/Saloon/ai-responses.json b/tests/Fixtures/Saloon/ai-responses.json index 76870d0..8c64e7b 100644 --- a/tests/Fixtures/Saloon/ai-responses.json +++ b/tests/Fixtures/Saloon/ai-responses.json @@ -1 +1 @@ -{"statusCode":200,"headers":{"Content-Type":"application/json"},"data":"{\"data\":[{\"id\":1,\"monitor_id\":82060,\"prompt\":\"Check if the site is accessible\",\"response\":\"The site is accessible and responding normally.\",\"raw_response\":\"The site is accessible and responding normally.\",\"token_usage\":{\"input\":100,\"output\":50},\"tool_invocations\":[],\"created_at\":\"2025-01-01 00:00:00\"}]}","context":[]} +{"statusCode":200,"headers":{"Content-Type":"application/json"},"data":"{\"data\":[{\"id\":1,\"result\":\"ok\",\"finish_reason\":\"stop\",\"prompt\":\"Check if the site is accessible\",\"text\":\"The site is accessible and responding normally.\",\"notification_title\":null,\"notification_body\":null,\"used_tools\":[{\"name\":\"http_check\",\"arguments\":{},\"displayName\":\"HTTP Check\",\"displayArguments\":[]}],\"used_prompt_tokens\":100,\"used_completion_tokens\":50,\"started_at\":\"2025-01-01 00:00:00\",\"ended_at\":\"2025-01-01 00:00:05\",\"created_at\":\"2025-01-01 00:00:05\"}]}","context":[]} diff --git a/tests/Fixtures/Saloon/create-recurring-maintenance-period.json b/tests/Fixtures/Saloon/create-recurring-maintenance-period.json index 5b360d0..5bc5186 100644 --- a/tests/Fixtures/Saloon/create-recurring-maintenance-period.json +++ b/tests/Fixtures/Saloon/create-recurring-maintenance-period.json @@ -1 +1 @@ -{"statusCode":201,"headers":{"Content-Type":"application/json"},"data":"{\"id\":2,\"monitor_id\":82060,\"name\":\"Daily Maintenance\",\"recurrence_type\":\"daily\",\"start_time\":\"03:00\",\"end_time\":\"05:00\",\"days_of_week\":[],\"day_of_month\":null,\"created_at\":\"2025-01-01 00:00:00\",\"updated_at\":\"2025-01-01 00:00:00\"}","context":[]} +{"statusCode":201,"headers":{"Content-Type":"application/json"},"data":"{\"id\":2,\"monitor_id\":82060,\"name\":\"Daily Maintenance\",\"recurrence_type\":\"daily\",\"start_time\":\"03:00\",\"end_time\":\"05:00\",\"days_of_week\":[],\"day_of_month\":null,\"human_readable_schedule\":\"Every day from 03:00 to 05:00\",\"last_generated_until\":\"2025-02-01\",\"created_at\":\"2025-01-01 00:00:00\",\"updated_at\":\"2025-01-01 00:00:00\"}","context":[]} diff --git a/tests/Fixtures/Saloon/create-tag-group.json b/tests/Fixtures/Saloon/create-tag-group.json index 27042d4..80a3c74 100644 --- a/tests/Fixtures/Saloon/create-tag-group.json +++ b/tests/Fixtures/Saloon/create-tag-group.json @@ -1 +1 @@ -{"statusCode":201,"headers":{"Content-Type":"application/json"},"data":"{\"id\":2,\"team_id\":19245,\"label\":\"Region\",\"tags\":[],\"created_at\":\"2025-01-01 00:00:00\",\"updated_at\":\"2025-01-01 00:00:00\"}","context":[]} +{"statusCode":201,"headers":{"Content-Type":"application/json"},"data":"{\"id\":2,\"team_id\":19245,\"team_name\":\"Oh Dear\",\"label\":\"Region\",\"tags\":[],\"created_at\":\"2025-01-01 00:00:00\",\"updated_at\":\"2025-01-01 00:00:00\"}","context":[]} diff --git a/tests/Fixtures/Saloon/create-tag.json b/tests/Fixtures/Saloon/create-tag.json index ed02c55..34cdf43 100644 --- a/tests/Fixtures/Saloon/create-tag.json +++ b/tests/Fixtures/Saloon/create-tag.json @@ -1 +1 @@ -{"statusCode":201,"headers":{"Content-Type":"application/json"},"data":"{\"id\":2,\"team_id\":19245,\"name\":\"staging\",\"monitors\":[],\"created_at\":\"2025-01-01 00:00:00\",\"updated_at\":\"2025-01-01 00:00:00\"}","context":[]} +{"statusCode":201,"headers":{"Content-Type":"application/json"},"data":"{\"id\":2,\"team_id\":19245,\"team_name\":\"Oh Dear\",\"name\":\"staging\",\"slug\":\"staging\",\"sites\":[],\"created_at\":\"2025-01-01 00:00:00\",\"updated_at\":\"2025-01-01 00:00:00\"}","context":[]} diff --git a/tests/Fixtures/Saloon/dns-blocklist-history-item.json b/tests/Fixtures/Saloon/dns-blocklist-history-item.json index 7607946..437b1d3 100644 --- a/tests/Fixtures/Saloon/dns-blocklist-history-item.json +++ b/tests/Fixtures/Saloon/dns-blocklist-history-item.json @@ -1 +1 @@ -{"statusCode":200,"headers":{"Content-Type":"application/json"},"data":"{\"id\":1,\"domain\":\"example.com\",\"resolved_ips\":[\"93.184.216.34\"],\"blocklists\":[{\"name\":\"zen.spamhaus.org\",\"listed\":false}],\"created_at\":\"2025-01-01 00:00:00\"}","context":[]} +{"statusCode":200,"headers":{"Content-Type":"application/json"},"data":"{\"id\":1,\"checked_domain\":\"example.com\",\"resolved_ips\":[\"93.184.216.34\"],\"blocklist_results\":[{\"provider\":\"zen.spamhaus.org\",\"listed\":false,\"query_target\":null,\"return_code\":null,\"reason\":null,\"timed_out\":false}],\"issues\":null,\"created_at\":\"2025-01-01 00:00:00\"}","context":[]} diff --git a/tests/Fixtures/Saloon/dns-blocklist-history-items.json b/tests/Fixtures/Saloon/dns-blocklist-history-items.json index a1fd46f..361d4f7 100644 --- a/tests/Fixtures/Saloon/dns-blocklist-history-items.json +++ b/tests/Fixtures/Saloon/dns-blocklist-history-items.json @@ -1 +1 @@ -{"statusCode":200,"headers":{"Content-Type":"application/json"},"data":"{\"data\":[{\"id\":1,\"domain\":\"example.com\",\"resolved_ips\":[\"93.184.216.34\"],\"blocklists\":[{\"name\":\"zen.spamhaus.org\",\"listed\":false}],\"created_at\":\"2025-01-01 00:00:00\"}]}","context":[]} +{"statusCode":200,"headers":{"Content-Type":"application/json"},"data":"{\"data\":[{\"id\":1,\"checked_domain\":\"example.com\",\"resolved_ips\":[\"93.184.216.34\"],\"blocklist_results\":[{\"provider\":\"zen.spamhaus.org\",\"listed\":false,\"query_target\":null,\"return_code\":null,\"reason\":null,\"timed_out\":false}],\"issues\":null,\"created_at\":\"2025-01-01 00:00:00\"}]}","context":[]} diff --git a/tests/Fixtures/Saloon/latest-ai-response.json b/tests/Fixtures/Saloon/latest-ai-response.json index 16e3d7e..d342962 100644 --- a/tests/Fixtures/Saloon/latest-ai-response.json +++ b/tests/Fixtures/Saloon/latest-ai-response.json @@ -1 +1 @@ -{"statusCode":200,"headers":{"Content-Type":"application/json"},"data":"{\"id\":1,\"monitor_id\":82060,\"prompt\":\"Check if the site is accessible\",\"response\":\"The site is accessible and responding normally.\",\"raw_response\":\"The site is accessible and responding normally.\",\"token_usage\":{\"input\":100,\"output\":50},\"tool_invocations\":[],\"created_at\":\"2025-01-01 00:00:00\"}","context":[]} +{"statusCode":200,"headers":{"Content-Type":"application/json"},"data":"{\"id\":1,\"result\":\"ok\",\"finish_reason\":\"stop\",\"prompt\":\"Check if the site is accessible\",\"text\":\"The site is accessible and responding normally.\",\"notification_title\":null,\"notification_body\":null,\"used_tools\":[],\"used_prompt_tokens\":100,\"used_completion_tokens\":50,\"raw_response\":\"{\\\"message\\\": \\\"All good\\\"}\",\"started_at\":\"2025-01-01 00:00:00\",\"ended_at\":\"2025-01-01 00:00:05\",\"created_at\":\"2025-01-01 00:00:05\"}","context":[]} diff --git a/tests/Fixtures/Saloon/recurring-maintenance-period.json b/tests/Fixtures/Saloon/recurring-maintenance-period.json index 951307f..b28941b 100644 --- a/tests/Fixtures/Saloon/recurring-maintenance-period.json +++ b/tests/Fixtures/Saloon/recurring-maintenance-period.json @@ -1 +1 @@ -{"statusCode":200,"headers":{"Content-Type":"application/json"},"data":"{\"id\":1,\"monitor_id\":82060,\"name\":\"Weekly Maintenance\",\"recurrence_type\":\"weekly\",\"start_time\":\"02:00\",\"end_time\":\"04:00\",\"days_of_week\":[1,3,5],\"day_of_month\":null,\"created_at\":\"2025-01-01 00:00:00\",\"updated_at\":\"2025-01-01 00:00:00\"}","context":[]} +{"statusCode":200,"headers":{"Content-Type":"application/json"},"data":"{\"id\":1,\"monitor_id\":82060,\"name\":\"Weekly Maintenance\",\"recurrence_type\":\"weekly\",\"start_time\":\"02:00\",\"end_time\":\"04:00\",\"days_of_week\":[1,3,5],\"day_of_month\":null,\"human_readable_schedule\":\"Every Monday, Wednesday and Friday from 02:00 to 04:00\",\"last_generated_until\":\"2025-02-01\",\"created_at\":\"2025-01-01 00:00:00\",\"updated_at\":\"2025-01-01 00:00:00\"}","context":[]} diff --git a/tests/Fixtures/Saloon/recurring-maintenance-periods.json b/tests/Fixtures/Saloon/recurring-maintenance-periods.json index b88c184..222eb3b 100644 --- a/tests/Fixtures/Saloon/recurring-maintenance-periods.json +++ b/tests/Fixtures/Saloon/recurring-maintenance-periods.json @@ -1 +1 @@ -{"statusCode":200,"headers":{"Content-Type":"application/json"},"data":"{\"data\":[{\"id\":1,\"monitor_id\":82060,\"name\":\"Weekly Maintenance\",\"recurrence_type\":\"weekly\",\"start_time\":\"02:00\",\"end_time\":\"04:00\",\"days_of_week\":[1,3,5],\"day_of_month\":null,\"created_at\":\"2025-01-01 00:00:00\",\"updated_at\":\"2025-01-01 00:00:00\"}]}","context":[]} +{"statusCode":200,"headers":{"Content-Type":"application/json"},"data":"{\"data\":[{\"id\":1,\"monitor_id\":82060,\"name\":\"Weekly Maintenance\",\"recurrence_type\":\"weekly\",\"start_time\":\"02:00\",\"end_time\":\"04:00\",\"days_of_week\":[1,3,5],\"day_of_month\":null,\"human_readable_schedule\":\"Every Monday, Wednesday and Friday from 02:00 to 04:00\",\"last_generated_until\":\"2025-02-01\",\"created_at\":\"2025-01-01 00:00:00\",\"updated_at\":\"2025-01-01 00:00:00\"}]}","context":[]} diff --git a/tests/Fixtures/Saloon/tag-groups.json b/tests/Fixtures/Saloon/tag-groups.json index 7d5c3f5..627590f 100644 --- a/tests/Fixtures/Saloon/tag-groups.json +++ b/tests/Fixtures/Saloon/tag-groups.json @@ -1 +1 @@ -{"statusCode":200,"headers":{"Content-Type":"application/json"},"data":"{\"data\":[{\"id\":1,\"team_id\":19245,\"label\":\"Environment\",\"tags\":[],\"created_at\":\"2025-01-01 00:00:00\",\"updated_at\":\"2025-01-01 00:00:00\"}]}","context":[]} +{"statusCode":200,"headers":{"Content-Type":"application/json"},"data":"{\"data\":[{\"id\":1,\"team_id\":19245,\"team_name\":\"Oh Dear\",\"label\":\"Environment\",\"tags\":[],\"created_at\":\"2025-01-01 00:00:00\",\"updated_at\":\"2025-01-01 00:00:00\"}]}","context":[]} diff --git a/tests/Fixtures/Saloon/tags.json b/tests/Fixtures/Saloon/tags.json index 25fa48b..5f5b1cf 100644 --- a/tests/Fixtures/Saloon/tags.json +++ b/tests/Fixtures/Saloon/tags.json @@ -1 +1 @@ -{"statusCode":200,"headers":{"Content-Type":"application/json"},"data":"{\"data\":[{\"id\":1,\"team_id\":19245,\"name\":\"production\",\"monitors\":[],\"created_at\":\"2025-01-01 00:00:00\",\"updated_at\":\"2025-01-01 00:00:00\"}]}","context":[]} +{"statusCode":200,"headers":{"Content-Type":"application/json"},"data":"{\"data\":[{\"id\":1,\"team_id\":19245,\"team_name\":\"Oh Dear\",\"name\":\"production\",\"slug\":\"production\",\"sites\":[],\"created_at\":\"2025-01-01 00:00:00\",\"updated_at\":\"2025-01-01 00:00:00\"}]}","context":[]} diff --git a/tests/Fixtures/Saloon/update-recurring-maintenance-period.json b/tests/Fixtures/Saloon/update-recurring-maintenance-period.json index c165103..09c6f28 100644 --- a/tests/Fixtures/Saloon/update-recurring-maintenance-period.json +++ b/tests/Fixtures/Saloon/update-recurring-maintenance-period.json @@ -1 +1 @@ -{"statusCode":200,"headers":{"Content-Type":"application/json"},"data":"{\"id\":1,\"monitor_id\":82060,\"name\":\"Updated Maintenance\",\"recurrence_type\":\"weekly\",\"start_time\":\"01:00\",\"end_time\":\"03:00\",\"days_of_week\":[1,2,3,4,5],\"day_of_month\":null,\"created_at\":\"2025-01-01 00:00:00\",\"updated_at\":\"2025-01-02 00:00:00\"}","context":[]} +{"statusCode":200,"headers":{"Content-Type":"application/json"},"data":"{\"id\":1,\"monitor_id\":82060,\"name\":\"Updated Maintenance\",\"recurrence_type\":\"weekly\",\"start_time\":\"01:00\",\"end_time\":\"03:00\",\"days_of_week\":[1,2,3,4,5],\"day_of_month\":null,\"human_readable_schedule\":\"Every weekday from 01:00 to 03:00\",\"last_generated_until\":\"2025-02-01\",\"created_at\":\"2025-01-01 00:00:00\",\"updated_at\":\"2025-01-02 00:00:00\"}","context":[]} diff --git a/tests/Fixtures/Saloon/update-tag-group.json b/tests/Fixtures/Saloon/update-tag-group.json index c346ad6..daa42fa 100644 --- a/tests/Fixtures/Saloon/update-tag-group.json +++ b/tests/Fixtures/Saloon/update-tag-group.json @@ -1 +1 @@ -{"statusCode":200,"headers":{"Content-Type":"application/json"},"data":"{\"id\":1,\"team_id\":19245,\"label\":\"Updated Environment\",\"tags\":[],\"created_at\":\"2025-01-01 00:00:00\",\"updated_at\":\"2025-01-02 00:00:00\"}","context":[]} +{"statusCode":200,"headers":{"Content-Type":"application/json"},"data":"{\"id\":1,\"team_id\":19245,\"team_name\":\"Oh Dear\",\"label\":\"Updated Environment\",\"tags\":[],\"created_at\":\"2025-01-01 00:00:00\",\"updated_at\":\"2025-01-02 00:00:00\"}","context":[]} diff --git a/tests/OhDearTests/AiResponsesTest.php b/tests/OhDearTests/AiResponsesTest.php index cc27f2a..58da90c 100644 --- a/tests/OhDearTests/AiResponsesTest.php +++ b/tests/OhDearTests/AiResponsesTest.php @@ -20,7 +20,8 @@ expect($responses)->toBeArray(); foreach ($responses as $response) { expect($response->id)->toBeInt(); - expect($response->monitorId)->toBe(82060); + expect($response->result)->toBe('ok'); + expect($response->text)->toBeString(); } }); @@ -32,8 +33,10 @@ $response = $this->ohDear->aiResponse(82060, 1); expect($response->id)->toBe(1); - expect($response->monitorId)->toBe(82060); + expect($response->result)->toBe('ok'); + expect($response->finishReason)->toBe('stop'); expect($response->prompt)->toBeString(); + expect($response->text)->toBeString(); }); it('can get the latest ai response', function () { @@ -44,5 +47,6 @@ $response = $this->ohDear->latestAiResponse(82060); expect($response->id)->toBe(1); - expect($response->monitorId)->toBe(82060); + expect($response->result)->toBe('ok'); + expect($response->rawResponse)->toBeString(); }); diff --git a/tests/OhDearTests/DnsBlocklistHistoryItemsTest.php b/tests/OhDearTests/DnsBlocklistHistoryItemsTest.php index 313b55d..6fa600f 100644 --- a/tests/OhDearTests/DnsBlocklistHistoryItemsTest.php +++ b/tests/OhDearTests/DnsBlocklistHistoryItemsTest.php @@ -19,7 +19,7 @@ expect($items)->toBeArray(); foreach ($items as $item) { expect($item->id)->toBeInt(); - expect($item->domain)->toBeString(); + expect($item->checkedDomain)->toBeString(); } }); @@ -31,7 +31,7 @@ $item = $this->ohDear->dnsBlocklistHistoryItem(82060, 1); expect($item->id)->toBe(1); - expect($item->domain)->toBe('example.com'); + expect($item->checkedDomain)->toBe('example.com'); expect($item->resolvedIps)->toBeArray(); - expect($item->blocklists)->toBeArray(); + expect($item->blocklistResults)->toBeArray(); }); From 197c7a596c675bf6f4232b9a7435e061413f58c3 Mon Sep 17 00:00:00 2001 From: Mattias Geniar Date: Tue, 17 Feb 2026 21:01:44 +0100 Subject: [PATCH 07/10] Use dev dependency of pint for the github action --- .../workflows/fix-php-code-style-issues.yml | 21 +++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/.github/workflows/fix-php-code-style-issues.yml b/.github/workflows/fix-php-code-style-issues.yml index 39a77e7..467d9f1 100644 --- a/.github/workflows/fix-php-code-style-issues.yml +++ b/.github/workflows/fix-php-code-style-issues.yml @@ -5,20 +5,33 @@ on: paths: - '**.php' +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + jobs: php-code-styling: runs-on: ubuntu-latest + timeout-minutes: 10 steps: - - name: Checkout code - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: ref: ${{ github.head_ref }} + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: 8.4 + coverage: none + + - name: Run composer install + run: composer install -n --prefer-dist + - name: Fix PHP code style issues - uses: aglipanci/laravel-pint-action@2.1.0 + run: composer format - name: Commit changes - uses: stefanzweifel/git-auto-commit-action@v4 + uses: stefanzweifel/git-auto-commit-action@v5 with: commit_message: Fix styling From d0e08091b42f60ee7294293c6bccfc96c761046b Mon Sep 17 00:00:00 2001 From: Mattias Geniar Date: Tue, 17 Feb 2026 21:04:32 +0100 Subject: [PATCH 08/10] Remove old 'real' scripts used in dev --- .gitignore | 6 ---- composer.json | 7 ++-- scripts/real-test.php | 20 ----------- tests/TestSupport/.env.example | 2 -- tests/TestSupport/scripts/real-test.php | 45 ------------------------- 5 files changed, 3 insertions(+), 77 deletions(-) delete mode 100644 scripts/real-test.php delete mode 100644 tests/TestSupport/.env.example delete mode 100644 tests/TestSupport/scripts/real-test.php diff --git a/.gitignore b/.gitignore index 6dd160e..5969f79 100644 --- a/.gitignore +++ b/.gitignore @@ -2,11 +2,5 @@ build composer.lock docs vendor -tests/ApiTest.php -.phpunit.result.cache .env -.php_cs.cache -.php-cs-fixer.cache .phpunit.cache -tests/TestSupport/.env - diff --git a/composer.json b/composer.json index b15a0f7..b56d824 100644 --- a/composer.json +++ b/composer.json @@ -23,9 +23,9 @@ "saloonphp/saloon": "^3.14" }, "require-dev": { + "laravel/pint": "^1.27", "pestphp/pest": "^2.35|^3.8.2", - "phpstan/phpstan": "^2.1", - "vlucas/phpdotenv": "^5.6.2" + "phpstan/phpstan": "^2.1" }, "autoload": { "psr-4": { @@ -40,7 +40,6 @@ "scripts": { "format": "vendor/bin/pint", "test": "vendor/bin/pest -p", - "real": "php tests/TestSupport/scripts/real-test.php", "analyse": "vendor/bin/phpstan analyse", "baseline": "vendor/bin/phpstan analyse --generate-baseline" }, @@ -54,7 +53,7 @@ }, "extra": { "branch-alias": { - "dev-monitors": "4.0.x-dev" + "dev-master": "4.0.x-dev" } } } diff --git a/scripts/real-test.php b/scripts/real-test.php deleted file mode 100644 index c61bd94..0000000 --- a/scripts/real-test.php +++ /dev/null @@ -1,20 +0,0 @@ -safeLoad(); - -$token = $_ENV['OH_DEAR_API_TOKEN'] ?? null; -$baseUrl = $_ENV['OH_DEAR_BASE_URL'] ?? null; - -$ohDear = new OhDear($token, $baseUrl); - -$monitors = $ohDear->monitors(teamId: 1); - -foreach ($monitors as $monitor) { - dump($monitor->teamId); -} diff --git a/tests/TestSupport/.env.example b/tests/TestSupport/.env.example deleted file mode 100644 index ba7e5fa..0000000 --- a/tests/TestSupport/.env.example +++ /dev/null @@ -1,2 +0,0 @@ -OH_DEAR_API_TOKEN=your_api_token_here -OH_DEAR_BASE_URL=https://ohdear.app/api/ diff --git a/tests/TestSupport/scripts/real-test.php b/tests/TestSupport/scripts/real-test.php deleted file mode 100644 index 9a241cf..0000000 --- a/tests/TestSupport/scripts/real-test.php +++ /dev/null @@ -1,45 +0,0 @@ -safeLoad(); - -$token = $_ENV['OH_DEAR_API_TOKEN'] ?? null; -$baseUrl = $_ENV['OH_DEAR_BASE_URL'] ?? null; - -$ohDear = new OhDear($token, $baseUrl); - -/* -dump($ohDear->me()); - -$updated = $ohDear->updateMonitor(82063, [ - 'uptime_check_settings' => [ - 'look_for_string' => 'a string', - ], -]); - -dd($updated); - -$monitors = $ohDear->monitors(); - - -foreach ($monitors as $monitor) { - // dump($monitor->teamId); - // dump($monitor->id); -} - -// dump($ohDear->monitor(82062)); - -*/ - -$monitor = $ohDear->createMonitor([ - 'team_id' => 19245, - 'type' => 'http', - 'url' => 'https://laravel.com', -]); - -dump($monitor); From de99a661b38e23c3b2ded59477a32626cdbbfb59 Mon Sep 17 00:00:00 2001 From: Mattias Geniar Date: Tue, 17 Feb 2026 21:04:51 +0100 Subject: [PATCH 09/10] Cleanup, phpstan, pint --- ...pportsApplicationHealthChecksEndpoints.php | 1 + .../SupportsCronCheckDefinitionsEndpoints.php | 1 - .../SupportsDetectedCertificatesEndpoints.php | 1 + .../SupportsDnsHistoryItemsEndpoints.php | 1 + src/Concerns/SupportsDowntimeEndpoints.php | 1 + .../SupportsLighthouseReportsEndpoints.php | 1 + .../SupportsMixedContentEndpoints.php | 1 + src/Concerns/SupportsSitemapEndpoints.php | 1 + src/Concerns/SupportsUptimeEndpoints.php | 1 + src/Dto/ApplicationHealthCheck.php | 12 ++++----- src/Dto/ApplicationHealthCheckHistoryItem.php | 4 +-- src/Dto/BrokenLink.php | 2 +- src/Dto/CertificateHealth.php | 18 ------------- src/Dto/DetectedCertificate.php | 2 +- src/Dto/DnsBlocklistHistoryItem.php | 2 +- src/Dto/DnsHistoryItem.php | 4 +-- src/Dto/DowntimePeriod.php | 6 ++--- src/Dto/LighthouseReport.php | 26 +++++++++---------- src/Dto/StatusPage.php | 2 +- src/Dto/StatusPageUpdate.php | 2 -- src/Dto/Uptime.php | 2 -- src/Enums/UptimeSplit.php | 2 -- src/Exceptions/OhDearException.php | 11 ++++---- src/Exceptions/ValidationException.php | 8 +----- src/Requests/MeRequest.php | 3 --- .../Monitors/GetCheckSummaryRequest.php | 6 ++--- 26 files changed, 46 insertions(+), 75 deletions(-) diff --git a/src/Concerns/SupportsApplicationHealthChecksEndpoints.php b/src/Concerns/SupportsApplicationHealthChecksEndpoints.php index 3e93a09..6798cdd 100644 --- a/src/Concerns/SupportsApplicationHealthChecksEndpoints.php +++ b/src/Concerns/SupportsApplicationHealthChecksEndpoints.php @@ -8,6 +8,7 @@ use OhDear\PhpSdk\Requests\ApplicationHealthChecks\SnoozeApplicationHealthCheckRequest; use OhDear\PhpSdk\Requests\ApplicationHealthChecks\UnsnoozeApplicationHealthCheckRequest; +/** @mixin \OhDear\PhpSdk\OhDear */ trait SupportsApplicationHealthChecksEndpoints { public function applicationHealthChecks(int $monitorId): array diff --git a/src/Concerns/SupportsCronCheckDefinitionsEndpoints.php b/src/Concerns/SupportsCronCheckDefinitionsEndpoints.php index c9d93c8..0d2ea74 100644 --- a/src/Concerns/SupportsCronCheckDefinitionsEndpoints.php +++ b/src/Concerns/SupportsCronCheckDefinitionsEndpoints.php @@ -46,7 +46,6 @@ public function deleteCronCheckDefinition(int $cronCheckDefinitionId): self $this->send($request); return $this; - } public function snoozeCronCheckDefinition(int $cronCheckDefinitionId, int $minutes): CronCheckDefinition diff --git a/src/Concerns/SupportsDetectedCertificatesEndpoints.php b/src/Concerns/SupportsDetectedCertificatesEndpoints.php index 821373d..f4c178c 100644 --- a/src/Concerns/SupportsDetectedCertificatesEndpoints.php +++ b/src/Concerns/SupportsDetectedCertificatesEndpoints.php @@ -6,6 +6,7 @@ use OhDear\PhpSdk\Requests\DetectedCertificates\GetDetectedCertificateRequest; use OhDear\PhpSdk\Requests\DetectedCertificates\GetDetectedCertificatesRequest; +/** @mixin \OhDear\PhpSdk\OhDear */ trait SupportsDetectedCertificatesEndpoints { public function detectedCertificates(int $monitorId): array diff --git a/src/Concerns/SupportsDnsHistoryItemsEndpoints.php b/src/Concerns/SupportsDnsHistoryItemsEndpoints.php index a675216..b45c745 100644 --- a/src/Concerns/SupportsDnsHistoryItemsEndpoints.php +++ b/src/Concerns/SupportsDnsHistoryItemsEndpoints.php @@ -6,6 +6,7 @@ use OhDear\PhpSdk\Requests\DnsHistoryItems\GetDnsHistoryItemRequest; use OhDear\PhpSdk\Requests\DnsHistoryItems\GetDnsHistoryItemsRequest; +/** @mixin \OhDear\PhpSdk\OhDear */ trait SupportsDnsHistoryItemsEndpoints { public function dnsHistoryItems(int $monitorId): array diff --git a/src/Concerns/SupportsDowntimeEndpoints.php b/src/Concerns/SupportsDowntimeEndpoints.php index d8ccc4a..2cb1ef0 100644 --- a/src/Concerns/SupportsDowntimeEndpoints.php +++ b/src/Concerns/SupportsDowntimeEndpoints.php @@ -5,6 +5,7 @@ use OhDear\PhpSdk\Requests\Downtime\DeleteDowntimePeriodRequest; use OhDear\PhpSdk\Requests\Downtime\GetDowntimeRequest; +/** @mixin \OhDear\PhpSdk\OhDear */ trait SupportsDowntimeEndpoints { public function downtime(int $monitorId, string $startedAt, string $endedAt): array diff --git a/src/Concerns/SupportsLighthouseReportsEndpoints.php b/src/Concerns/SupportsLighthouseReportsEndpoints.php index cd2c242..01e7722 100644 --- a/src/Concerns/SupportsLighthouseReportsEndpoints.php +++ b/src/Concerns/SupportsLighthouseReportsEndpoints.php @@ -7,6 +7,7 @@ use OhDear\PhpSdk\Requests\LighthouseReports\GetLighthouseReportRequest; use OhDear\PhpSdk\Requests\LighthouseReports\GetLighthouseReportsRequest; +/** @mixin \OhDear\PhpSdk\OhDear */ trait SupportsLighthouseReportsEndpoints { public function lighthouseReports(int $monitorId): array diff --git a/src/Concerns/SupportsMixedContentEndpoints.php b/src/Concerns/SupportsMixedContentEndpoints.php index 9bf7ab6..6f3b818 100644 --- a/src/Concerns/SupportsMixedContentEndpoints.php +++ b/src/Concerns/SupportsMixedContentEndpoints.php @@ -4,6 +4,7 @@ use OhDear\PhpSdk\Requests\MixedContent\GetMixedContentRequest; +/** @mixin \OhDear\PhpSdk\OhDear */ trait SupportsMixedContentEndpoints { public function mixedContent(int $monitorId): array diff --git a/src/Concerns/SupportsSitemapEndpoints.php b/src/Concerns/SupportsSitemapEndpoints.php index aaec19f..642de57 100644 --- a/src/Concerns/SupportsSitemapEndpoints.php +++ b/src/Concerns/SupportsSitemapEndpoints.php @@ -5,6 +5,7 @@ use OhDear\PhpSdk\Dto\Sitemap; use OhDear\PhpSdk\Requests\Sitemap\GetSitemapRequest; +/** @mixin \OhDear\PhpSdk\OhDear */ trait SupportsSitemapEndpoints { public function sitemap(int $monitorId): Sitemap diff --git a/src/Concerns/SupportsUptimeEndpoints.php b/src/Concerns/SupportsUptimeEndpoints.php index 82ec7bf..59b5e56 100644 --- a/src/Concerns/SupportsUptimeEndpoints.php +++ b/src/Concerns/SupportsUptimeEndpoints.php @@ -6,6 +6,7 @@ use OhDear\PhpSdk\Enums\UptimeSplit; use OhDear\PhpSdk\Requests\Uptime\GetUptimeRequest; +/** @mixin \OhDear\PhpSdk\OhDear */ trait SupportsUptimeEndpoints { /** @return list */ diff --git a/src/Dto/ApplicationHealthCheck.php b/src/Dto/ApplicationHealthCheck.php index 2febfab..44bde2e 100644 --- a/src/Dto/ApplicationHealthCheck.php +++ b/src/Dto/ApplicationHealthCheck.php @@ -25,13 +25,13 @@ public static function fromResponse(array $data): self id: $data['id'], name: $data['name'], label: $data['label'], - status: $data['status'], - message: $data['message'], + status: $data['status'] ?? null, + message: $data['message'] ?? null, meta: $data['meta'] ?? [], - shortSummary: $data['short_summary'], - detectedAt: $data['detected_at'], - updatedAt: $data['updated_at'], - activeSnooze: $data['active_snooze'], + shortSummary: $data['short_summary'] ?? null, + detectedAt: $data['detected_at'] ?? null, + updatedAt: $data['updated_at'] ?? null, + activeSnooze: $data['active_snooze'] ?? null, ); } diff --git a/src/Dto/ApplicationHealthCheckHistoryItem.php b/src/Dto/ApplicationHealthCheckHistoryItem.php index b1b7a3a..418f960 100644 --- a/src/Dto/ApplicationHealthCheckHistoryItem.php +++ b/src/Dto/ApplicationHealthCheckHistoryItem.php @@ -22,8 +22,8 @@ public static function fromResponse(array $data): self id: $data['id'], status: $data['status'], shortSummary: $data['short_summary'], - message: $data['message'], - meta: $data['meta'], + message: $data['message'] ?? null, + meta: $data['meta'] ?? null, detectedAt: $data['detected_at'], updatedAt: $data['updated_at'], ); diff --git a/src/Dto/BrokenLink.php b/src/Dto/BrokenLink.php index 690ad8b..159afb7 100644 --- a/src/Dto/BrokenLink.php +++ b/src/Dto/BrokenLink.php @@ -17,7 +17,7 @@ public function __construct( public static function fromResponse(array $data): self { return new self( - statusCode: $data['status_code'], + statusCode: $data['status_code'] ?? null, crawledUrl: $data['crawled_url'], relativeCrawledUrl: $data['relative_crawled_url'], foundOnUrl: $data['found_on_url'], diff --git a/src/Dto/CertificateHealth.php b/src/Dto/CertificateHealth.php index 7e9ec32..802be6b 100644 --- a/src/Dto/CertificateHealth.php +++ b/src/Dto/CertificateHealth.php @@ -19,33 +19,21 @@ public static function fromResponse(array $data): self ); } - /** - * Get certificate issuer - */ public function getIssuer(): ?string { return $this->certificateDetails['issuer'] ?? null; } - /** - * Get certificate valid from date - */ public function getValidFrom(): ?string { return $this->certificateDetails['valid_from'] ?? null; } - /** - * Get certificate valid until date - */ public function getValidUntil(): ?string { return $this->certificateDetails['valid_until'] ?? null; } - /** - * Check if a specific certificate check passed - */ public function checkPassed(string $checkType): bool { foreach ($this->certificateChecks as $check) { @@ -57,17 +45,11 @@ public function checkPassed(string $checkType): bool return false; } - /** - * Get all failed certificate checks - */ public function getFailedChecks(): array { return array_filter($this->certificateChecks, fn ($check) => ! ($check['passed'] ?? false)); } - /** - * Check if certificate is healthy (all checks passed) - */ public function isHealthy(): bool { return empty($this->getFailedChecks()); diff --git a/src/Dto/DetectedCertificate.php b/src/Dto/DetectedCertificate.php index cada93e..4740a22 100644 --- a/src/Dto/DetectedCertificate.php +++ b/src/Dto/DetectedCertificate.php @@ -21,7 +21,7 @@ public static function fromResponse(array $data): self id: $data['id'], monitorId: $data['monitor_id'], fingerprint: $data['fingerprint'], - certificateDetails: $data['certificate_details'], + certificateDetails: $data['certificate_details'] ?? null, createdAt: $data['created_at'], updatedAt: $data['updated_at'], ); diff --git a/src/Dto/DnsBlocklistHistoryItem.php b/src/Dto/DnsBlocklistHistoryItem.php index 1448263..706dd14 100644 --- a/src/Dto/DnsBlocklistHistoryItem.php +++ b/src/Dto/DnsBlocklistHistoryItem.php @@ -9,7 +9,7 @@ public function __construct( public ?string $checkedDomain, public array $resolvedIps, public array $blocklistResults, - public mixed $issues, + public ?array $issues, public ?string $createdAt, ) {} diff --git a/src/Dto/DnsHistoryItem.php b/src/Dto/DnsHistoryItem.php index 9d4063e..e612889 100644 --- a/src/Dto/DnsHistoryItem.php +++ b/src/Dto/DnsHistoryItem.php @@ -11,7 +11,7 @@ public function __construct( public array $authoritativeNameservers, public array $dnsRecords, public array $rawDnsRecords, - public mixed $issues, + public ?array $issues, public string $diffSummary, public string $createdAt, ) {} @@ -23,7 +23,7 @@ public static function fromResponse(array $data): self authoritativeNameservers: $data['authoritative_nameservers'] ?? [], dnsRecords: $data['dns_records'] ?? [], rawDnsRecords: $data['raw_dns_records'] ?? [], - issues: $data['issues'], + issues: $data['issues'] ?? null, diffSummary: $data['diff_summary'], createdAt: $data['created_at'], ); diff --git a/src/Dto/DowntimePeriod.php b/src/Dto/DowntimePeriod.php index 2da89fd..8e7542e 100644 --- a/src/Dto/DowntimePeriod.php +++ b/src/Dto/DowntimePeriod.php @@ -19,9 +19,9 @@ public static function fromResponse(array $data): self return new self( id: $data['id'], startedAt: $data['started_at'], - endedAt: $data['ended_at'], - notesHtml: $data['notes_html'], - notesMarkdown: $data['notes_markdown'], + endedAt: $data['ended_at'] ?? null, + notesHtml: $data['notes_html'] ?? null, + notesMarkdown: $data['notes_markdown'] ?? null, ); } diff --git a/src/Dto/LighthouseReport.php b/src/Dto/LighthouseReport.php index d24aa1b..c692adf 100644 --- a/src/Dto/LighthouseReport.php +++ b/src/Dto/LighthouseReport.php @@ -29,20 +29,20 @@ public static function fromResponse(array $data): self { return new self( id: $data['id'], - performanceScore: $data['performance_score'], - accessibilityScore: $data['accessibility_score'], - bestPracticesScore: $data['best_practices_score'], - seoScore: $data['seo_score'], - progressiveWebAppScore: $data['progressive_web_app_score'], - firstContentfulPaintInMs: $data['first_contentful_paint_in_ms'], - speedIndexInMs: $data['speed_index_in_ms'], - largestContentfulPaintInMs: $data['largest_contentful_paint_in_ms'], - timeToInteractiveInMs: $data['time_to_interactive_in_ms'], - totalBlockingTimeInMs: $data['total_blocking_time_in_ms'], - cumulativeLayoutShift: $data['cumulative_layout_shift'], - performedOnCheckerServer: $data['performed_on_checker_server'], + performanceScore: $data['performance_score'] ?? null, + accessibilityScore: $data['accessibility_score'] ?? null, + bestPracticesScore: $data['best_practices_score'] ?? null, + seoScore: $data['seo_score'] ?? null, + progressiveWebAppScore: $data['progressive_web_app_score'] ?? null, + firstContentfulPaintInMs: $data['first_contentful_paint_in_ms'] ?? null, + speedIndexInMs: $data['speed_index_in_ms'] ?? null, + largestContentfulPaintInMs: $data['largest_contentful_paint_in_ms'] ?? null, + timeToInteractiveInMs: $data['time_to_interactive_in_ms'] ?? null, + totalBlockingTimeInMs: $data['total_blocking_time_in_ms'] ?? null, + cumulativeLayoutShift: $data['cumulative_layout_shift'] ?? null, + performedOnCheckerServer: $data['performed_on_checker_server'] ?? null, jsonReport: $data['json_report'] ?? null, - issues: $data['issues'], + issues: $data['issues'] ?? null, createdAt: $data['created_at'], ); } diff --git a/src/Dto/StatusPage.php b/src/Dto/StatusPage.php index 115d4e6..4694916 100644 --- a/src/Dto/StatusPage.php +++ b/src/Dto/StatusPage.php @@ -28,7 +28,7 @@ public static function fromResponse(array $data): self return new self( id: $data['id'], team: $data['team'] ?? null, - title: $data['title'], + title: $data['title'] ?? null, domain: $data['domain'] ?? null, secret: $data['secret'] ?? null, badgeId: $data['badge_id'] ?? null, diff --git a/src/Dto/StatusPageUpdate.php b/src/Dto/StatusPageUpdate.php index e251e50..d05126a 100644 --- a/src/Dto/StatusPageUpdate.php +++ b/src/Dto/StatusPageUpdate.php @@ -1,7 +1,5 @@ response = $response; } } diff --git a/src/Exceptions/ValidationException.php b/src/Exceptions/ValidationException.php index 2d3fea1..f0d09ad 100644 --- a/src/Exceptions/ValidationException.php +++ b/src/Exceptions/ValidationException.php @@ -56,12 +56,6 @@ public function hasErrorsForField(string $field): bool /** @return array */ public function getAllErrorMessages(): array { - $messages = []; - - foreach ($this->errors as $fieldErrors) { - $messages = array_merge($messages, $fieldErrors); - } - - return $messages; + return array_merge(...array_values($this->errors)); } } diff --git a/src/Requests/MeRequest.php b/src/Requests/MeRequest.php index 31132bd..34039a3 100644 --- a/src/Requests/MeRequest.php +++ b/src/Requests/MeRequest.php @@ -11,9 +11,6 @@ class MeRequest extends Request { protected Method $method = Method::GET; - public function __construct( - ) {} - public function resolveEndpoint(): string { return '/me'; diff --git a/src/Requests/Monitors/GetCheckSummaryRequest.php b/src/Requests/Monitors/GetCheckSummaryRequest.php index cce675d..1ad0681 100644 --- a/src/Requests/Monitors/GetCheckSummaryRequest.php +++ b/src/Requests/Monitors/GetCheckSummaryRequest.php @@ -19,13 +19,11 @@ public function __construct( public function resolveEndpoint(): string { - return "monitors/{$this->monitorId}/check-summary/{$this->checkType->value}"; + return "/monitors/{$this->monitorId}/check-summary/{$this->checkType->value}"; } public function createDtoFromResponse(Response $response): CheckSummary { - $data = $response->json(); - - return CheckSummary::fromResponse($data); + return CheckSummary::fromResponse($response->json()); } } From e00631d1c6ae03cb0d7a461d8286151cc647f4b7 Mon Sep 17 00:00:00 2001 From: Mattias Geniar Date: Tue, 17 Feb 2026 21:11:16 +0100 Subject: [PATCH 10/10] Fix tests --- tests/Pest.php | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/tests/Pest.php b/tests/Pest.php index 51acc4b..b768953 100644 --- a/tests/Pest.php +++ b/tests/Pest.php @@ -1,6 +1,5 @@ safeLoad(); - - $token = $_ENV['OH_DEAR_API_TOKEN'] ?? 'fake-token'; - $baseUrl = $_ENV['OH_DEAR_BASE_URL'] ?? 'https://ohdear.app/api/'; - - return new OhDear($token, $baseUrl); + return new OhDear('fake-token', 'https://ohdear.app/api/'); } function markTestComplete()