diff --git a/src/Migration/Destinations/Appwrite.php b/src/Migration/Destinations/Appwrite.php index 98a4e94..82025f5 100644 --- a/src/Migration/Destinations/Appwrite.php +++ b/src/Migration/Destinations/Appwrite.php @@ -224,7 +224,7 @@ public function report(array $resources = [], array $resourceIds = []): array } catch (AppwriteException $e) { if ($e->getCode() === 403) { - throw new \Exception('Missing scope: ' . $scope, previous: $e); + throw new \Exception('Missing scope: ' . $scope, $e->getCode(), $e); } throw $e; } diff --git a/src/Migration/Destinations/JSON.php b/src/Migration/Destinations/JSON.php index 9166047..91016ef 100644 --- a/src/Migration/Destinations/JSON.php +++ b/src/Migration/Destinations/JSON.php @@ -139,6 +139,7 @@ protected function import(array $resources, callable $callback): void resourceGroup: $resource->getGroup(), resourceId: $resource->getId(), message: $e->getMessage(), + code: MigrationException::CODE_VALIDATION, previous: $e, )); continue; diff --git a/src/Migration/Exception.php b/src/Migration/Exception.php index 86eb2e2..ff599a0 100644 --- a/src/Migration/Exception.php +++ b/src/Migration/Exception.php @@ -4,6 +4,14 @@ class Exception extends \Exception implements \JsonSerializable { + public const CODE_VALIDATION = 400; + public const CODE_UNAUTHORIZED = 401; + public const CODE_FORBIDDEN = 403; + public const CODE_NOT_FOUND = 404; + public const CODE_CONFLICT = 409; + public const CODE_RATE_LIMITED = 429; + public const CODE_INTERNAL = 500; + public string $resourceName; public string $resourceGroup; @@ -26,7 +34,7 @@ public function __construct( if (\is_numeric($code)) { $code = (int) $code; } else { - $code = 500; // PDOException + $code = self::CODE_INTERNAL; // PDOException } } diff --git a/src/Migration/Sources/Appwrite.php b/src/Migration/Sources/Appwrite.php index 2844bcf..56bb07d 100644 --- a/src/Migration/Sources/Appwrite.php +++ b/src/Migration/Sources/Appwrite.php @@ -207,9 +207,9 @@ public function report(array $resources = [], array $resourceIds = []): array )['version']; } catch (\Throwable $e) { if ($e->getCode() === 403) { - throw new \Exception("Missing required scopes."); + throw new \Exception('Missing required scopes.', $e->getCode(), $e); } else { - throw new \Exception($e->getMessage(), previous: $e); + throw new \Exception($e->getMessage(), $e->getCode(), $e); } } diff --git a/src/Migration/Sources/CSV.php b/src/Migration/Sources/CSV.php index 3cd227c..821db4b 100644 --- a/src/Migration/Sources/CSV.php +++ b/src/Migration/Sources/CSV.php @@ -208,7 +208,7 @@ private function exportRows(int $batchSize): void while (($row = \fgetcsv($stream, 0, $delimiter, '"', '"')) !== false) { if (\count($row) !== \count($headers)) { - throw new \Exception('CSV row does not match the number of header columns.'); + throw new \Exception('CSV row does not match the number of header columns.', Exception::CODE_VALIDATION); } $data = \array_combine($headers, $row); @@ -257,7 +257,7 @@ private function exportRows(int $batchSize): void } if (!\is_array($arrayValues)) { - throw new \Exception("Invalid array format for column '$key': $parsedValue"); + throw new \Exception("Invalid array format for column '$key': $parsedValue", Exception::CODE_VALIDATION); } $parsedData[$key] = array_map(function ($item) use ($type) { @@ -436,7 +436,7 @@ private function validateCSVHeaders(array $headers, array $columnTypes, array $r $messages[] = "$label: '" . \implode("', '", $missingRequired) . "'"; } if (!empty($missingRequired)) { - throw new \Exception('CSV header validation failed: ' . \implode('. ', $messages)); + throw new \Exception('CSV header validation failed: ' . \implode('. ', $messages), Exception::CODE_VALIDATION); } // If there are unknown columns but no missing required columns, just log a warning @@ -479,7 +479,11 @@ private function downloadToLocal( } if (!$success) { - throw new \Exception('Failed to transfer CSV file from device to local storage.', previous: $e ?? null); + throw new \Exception( + 'Failed to transfer CSV file from device to local storage.', + Exception::CODE_INTERNAL, + $e ?? null + ); } $this->downloaded = true; diff --git a/src/Migration/Sources/JSON.php b/src/Migration/Sources/JSON.php index 8abf63d..4fd0c8e 100644 --- a/src/Migration/Sources/JSON.php +++ b/src/Migration/Sources/JSON.php @@ -129,7 +129,7 @@ private function exportRows(int $batchSize): void foreach ($items as $index => $item) { if (!\is_array($item)) { - throw new \Exception("JSON item at index $index is not an object."); + throw new \Exception("JSON item at index $index is not an object.", Exception::CODE_VALIDATION); } $rowId = $item['$id'] ?? 'unique()'; @@ -257,7 +257,11 @@ private function downloadToLocal( } if (!$success) { - throw new \Exception('Failed to transfer JSON file from device to local storage.', previous: $e ?? null); + throw new \Exception( + 'Failed to transfer JSON file from device to local storage.', + Exception::CODE_INTERNAL, + $e ?? null + ); } $this->downloaded = true; @@ -270,12 +274,12 @@ private function downloadToLocal( private function validatePermissions(mixed $permissions): array { if (!\is_array($permissions)) { - throw new \Exception('Invalid permissions format; expected an array of strings.'); + throw new \Exception('Invalid permissions format; expected an array of strings.', Exception::CODE_VALIDATION); } foreach ($permissions as $value) { if (!\is_string($value)) { - throw new \Exception('Invalid permission value; expected string.'); + throw new \Exception('Invalid permission value; expected string.', Exception::CODE_VALIDATION); } } diff --git a/src/Migration/Target.php b/src/Migration/Target.php index 8fab14c..8dbc5a8 100644 --- a/src/Migration/Target.php +++ b/src/Migration/Target.php @@ -147,16 +147,16 @@ protected function call( } if (\curl_errno($ch)) { - throw new \Exception(\curl_error($ch)); + throw new \Exception(\curl_error($ch), Exception::CODE_INTERNAL); } \curl_close($ch); if ($responseStatus >= 400) { if (\is_array($responseBody)) { - throw new \Exception(\json_encode($responseBody)); + throw new \Exception(\json_encode($responseBody), $responseStatus); } else { - throw new \Exception($responseStatus.': '.$responseBody); + throw new \Exception($responseStatus.': '.$responseBody, $responseStatus); } }