Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
8 / 8
100.00% covered (success)
100.00%
1 / 1
CRAP
100.00% covered (success)
100.00%
1 / 1
NotificationFailureClassifier
100.00% covered (success)
100.00%
8 / 8
100.00% covered (success)
100.00%
1 / 1
5
100.00% covered (success)
100.00%
1 / 1
 classify
100.00% covered (success)
100.00%
8 / 8
100.00% covered (success)
100.00%
1 / 1
5
1<?php
2
3declare(strict_types=1);
4/**
5 * SPDX-FileCopyrightText: 2026 LibreCode coop and contributors
6 * SPDX-License-Identifier: AGPL-3.0-or-later
7 */
8
9namespace OCA\Libresign\Service\Notification;
10
11use OCA\Libresign\Enum\NotificationDeliveryState;
12use OCA\Libresign\Exception\NotificationPreparationException;
13use OCA\Libresign\Exception\NotificationTransportException;
14
15final class NotificationFailureClassifier {
16    /** @return array{NotificationDeliveryState, string} */
17    public function classify(\Exception $error): array {
18        // Only an explicit top-level preparation failure proves the provider
19        // was not contacted. Nested causes can come from an ambiguous transport.
20        if ($error instanceof NotificationPreparationException) {
21            return [NotificationDeliveryState::TEMPORARY_FAILURE, $error->reasonCode];
22        }
23        for ($current = $error; $current !== null; $current = $current->getPrevious()) {
24            if ($current instanceof NotificationTransportException) {
25                // A transport exception alone never proves non-submission.
26                if ($current->outcome === NotificationDeliveryState::TEMPORARY_FAILURE) {
27                    return [NotificationDeliveryState::UNKNOWN, 'transport_outcome_unknown'];
28                }
29                return [$current->outcome, $current->reasonCode];
30            }
31        }
32        return [NotificationDeliveryState::UNKNOWN, 'transport_outcome_unknown'];
33    }
34}