Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 87
0.00% covered (danger)
0.00%
0 / 15
CRAP
0.00% covered (danger)
0.00%
0 / 1
IntegrationException
0.00% covered (danger)
0.00%
0 / 87
0.00% covered (danger)
0.00%
0 / 15
306
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 5
0.00% covered (danger)
0.00%
0 / 1
2
 getIntegrationType
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getOperation
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getForeignId
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getContext
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getDetailedMessage
0.00% covered (danger)
0.00%
0 / 10
0.00% covered (danger)
0.00%
0 / 1
12
 toArray
0.00% covered (danger)
0.00%
0 / 7
0.00% covered (danger)
0.00%
0 / 1
2
 createFailed
0.00% covered (danger)
0.00%
0 / 8
0.00% covered (danger)
0.00%
0 / 1
2
 syncDatesFailed
0.00% covered (danger)
0.00%
0 / 8
0.00% covered (danger)
0.00%
0 / 1
2
 activateFailed
0.00% covered (danger)
0.00%
0 / 8
0.00% covered (danger)
0.00%
0 / 1
2
 deactivateFailed
0.00% covered (danger)
0.00%
0 / 8
0.00% covered (danger)
0.00%
0 / 1
2
 deleteFailed
0.00% covered (danger)
0.00%
0 / 8
0.00% covered (danger)
0.00%
0 / 1
2
 getStatusFailed
0.00% covered (danger)
0.00%
0 / 8
0.00% covered (danger)
0.00%
0 / 1
2
 invalidConfig
0.00% covered (danger)
0.00%
0 / 7
0.00% covered (danger)
0.00%
0 / 1
2
 targetNotFound
0.00% covered (danger)
0.00%
0 / 6
0.00% covered (danger)
0.00%
0 / 1
2
1<?php
2
3namespace BuyerKiosk\EventManagement\Adapters;
4
5use RuntimeException;
6
7/**
8 * IntegrationException - Exception thrown by integration adapters
9 *
10 * Provides detailed information about integration failures including:
11 * - The integration type that failed
12 * - The operation being performed
13 * - The underlying cause
14 *
15 * @package BuyerKiosk\EventManagement\Adapters
16 */
17class IntegrationException extends RuntimeException
18{
19    /**
20     * @var string The integration type that failed
21     */
22    private string $integrationType;
23
24    /**
25     * @var string The operation being performed when failure occurred
26     */
27    private string $operation;
28
29    /**
30     * @var int|null The foreign ID of the affected record (if applicable)
31     */
32    private ?int $foreignId;
33
34    /**
35     * @var array Additional context about the failure
36     */
37    private array $context;
38
39    /**
40     * Constructor
41     *
42     * @param string $message Human-readable error message
43     * @param string $integrationType The integration type (e.g., 'backstock', 'sms_blast')
44     * @param string $operation The operation (e.g., 'create', 'syncDates', 'delete')
45     * @param int|null $foreignId The foreign ID if applicable
46     * @param array $context Additional context data
47     * @param \Throwable|null $previous Previous exception for chaining
48     */
49    public function __construct(
50        string $message,
51        string $integrationType,
52        string $operation,
53        ?int $foreignId = null,
54        array $context = [],
55        ?\Throwable $previous = null
56    ) {
57        parent::__construct($message, 0, $previous);
58
59        $this->integrationType = $integrationType;
60        $this->operation = $operation;
61        $this->foreignId = $foreignId;
62        $this->context = $context;
63    }
64
65    /**
66     * Get the integration type
67     *
68     * @return string
69     */
70    public function getIntegrationType(): string
71    {
72        return $this->integrationType;
73    }
74
75    /**
76     * Get the operation that failed
77     *
78     * @return string
79     */
80    public function getOperation(): string
81    {
82        return $this->operation;
83    }
84
85    /**
86     * Get the foreign ID
87     *
88     * @return int|null
89     */
90    public function getForeignId(): ?int
91    {
92        return $this->foreignId;
93    }
94
95    /**
96     * Get the context data
97     *
98     * @return array
99     */
100    public function getContext(): array
101    {
102        return $this->context;
103    }
104
105    /**
106     * Get a detailed error message for logging
107     *
108     * @return string
109     */
110    public function getDetailedMessage(): string
111    {
112        $parts = [
113            "IntegrationException: {$this->getMessage()}",
114            "Type: {$this->integrationType}",
115            "Operation: {$this->operation}",
116        ];
117
118        if ($this->foreignId !== null) {
119            $parts[] = "ForeignId: {$this->foreignId}";
120        }
121
122        if (!empty($this->context)) {
123            $parts[] = "Context: " . json_encode($this->context);
124        }
125
126        return implode(' | ', $parts);
127    }
128
129    /**
130     * Convert to array for API responses
131     *
132     * @return array
133     */
134    public function toArray(): array
135    {
136        return [
137            'error' => true,
138            'message' => $this->getMessage(),
139            'integrationType' => $this->integrationType,
140            'operation' => $this->operation,
141            'foreignId' => $this->foreignId,
142        ];
143    }
144
145    /**
146     * Create exception for a create operation failure
147     *
148     * @param string $integrationType
149     * @param string $reason
150     * @param array $context
151     * @param \Throwable|null $previous
152     * @return self
153     */
154    public static function createFailed(
155        string $integrationType,
156        string $reason,
157        array $context = [],
158        ?\Throwable $previous = null
159    ): self {
160        return new self(
161            "Failed to create {$integrationType} integration: {$reason}",
162            $integrationType,
163            'create',
164            null,
165            $context,
166            $previous
167        );
168    }
169
170    /**
171     * Create exception for a sync dates operation failure
172     *
173     * @param string $integrationType
174     * @param int $foreignId
175     * @param string $reason
176     * @param \Throwable|null $previous
177     * @return self
178     */
179    public static function syncDatesFailed(
180        string $integrationType,
181        int $foreignId,
182        string $reason,
183        ?\Throwable $previous = null
184    ): self {
185        return new self(
186            "Failed to sync dates for {$integrationType} integration: {$reason}",
187            $integrationType,
188            'syncDates',
189            $foreignId,
190            [],
191            $previous
192        );
193    }
194
195    /**
196     * Create exception for an activate operation failure
197     *
198     * @param string $integrationType
199     * @param int $foreignId
200     * @param string $reason
201     * @param \Throwable|null $previous
202     * @return self
203     */
204    public static function activateFailed(
205        string $integrationType,
206        int $foreignId,
207        string $reason,
208        ?\Throwable $previous = null
209    ): self {
210        return new self(
211            "Failed to activate {$integrationType} integration: {$reason}",
212            $integrationType,
213            'activate',
214            $foreignId,
215            [],
216            $previous
217        );
218    }
219
220    /**
221     * Create exception for a deactivate operation failure
222     *
223     * @param string $integrationType
224     * @param int $foreignId
225     * @param string $reason
226     * @param \Throwable|null $previous
227     * @return self
228     */
229    public static function deactivateFailed(
230        string $integrationType,
231        int $foreignId,
232        string $reason,
233        ?\Throwable $previous = null
234    ): self {
235        return new self(
236            "Failed to deactivate {$integrationType} integration: {$reason}",
237            $integrationType,
238            'deactivate',
239            $foreignId,
240            [],
241            $previous
242        );
243    }
244
245    /**
246     * Create exception for a delete operation failure
247     *
248     * @param string $integrationType
249     * @param int $foreignId
250     * @param string $reason
251     * @param \Throwable|null $previous
252     * @return self
253     */
254    public static function deleteFailed(
255        string $integrationType,
256        int $foreignId,
257        string $reason,
258        ?\Throwable $previous = null
259    ): self {
260        return new self(
261            "Failed to delete {$integrationType} integration: {$reason}",
262            $integrationType,
263            'delete',
264            $foreignId,
265            [],
266            $previous
267        );
268    }
269
270    /**
271     * Create exception for a get status operation failure
272     *
273     * @param string $integrationType
274     * @param int $foreignId
275     * @param string $reason
276     * @param \Throwable|null $previous
277     * @return self
278     */
279    public static function getStatusFailed(
280        string $integrationType,
281        int $foreignId,
282        string $reason,
283        ?\Throwable $previous = null
284    ): self {
285        return new self(
286            "Failed to get status for {$integrationType} integration: {$reason}",
287            $integrationType,
288            'getStatus',
289            $foreignId,
290            [],
291            $previous
292        );
293    }
294
295    /**
296     * Create exception for configuration validation failure
297     *
298     * @param string $integrationType
299     * @param array $errors
300     * @return self
301     */
302    public static function invalidConfig(string $integrationType, array $errors): self
303    {
304        return new self(
305            "Invalid configuration for {$integrationType} integration: " . implode('; ', $errors),
306            $integrationType,
307            'validateConfig',
308            null,
309            ['validationErrors' => $errors]
310        );
311    }
312
313    /**
314     * Create exception for when target record is not found
315     *
316     * @param string $integrationType
317     * @param int $foreignId
318     * @return self
319     */
320    public static function targetNotFound(string $integrationType, int $foreignId): self
321    {
322        return new self(
323            "Target record not found for {$integrationType} integration",
324            $integrationType,
325            'lookup',
326            $foreignId
327        );
328    }
329}