|
4 | 4 |
|
5 | 5 | use Illuminate\Http\Client\ConnectionException;
|
6 | 6 | use Illuminate\Http\Client\Response;
|
| 7 | +use Illuminate\Support\Collection; |
7 | 8 | use Illuminate\Support\Facades\Http;
|
8 | 9 | use JsonException;
|
9 | 10 | use Sensson\DirectAdmin\Exceptions\ConnectionFailed;
|
| 11 | +use Sensson\DirectAdmin\Exceptions\InvalidResponse; |
10 | 12 |
|
11 | 13 | class Api
|
12 | 14 | {
|
13 | 15 | public bool $debug = false;
|
14 | 16 |
|
15 |
| - public bool $json = true; |
16 |
| - |
17 | 17 | /**
|
| 18 | + * Call the DirectAdmin API by giving it an API command and some |
| 19 | + * parameters. This will return an array with processed data. |
| 20 | + * |
18 | 21 | * @throws ConnectionFailed
|
| 22 | + * @throws InvalidResponse |
19 | 23 | */
|
20 |
| - public function call(string $command, array $params = []): array |
| 24 | + public function call(string $command, array $params = []): Collection |
21 | 25 | {
|
22 |
| - $queryParams = $this->json |
23 |
| - ? ['json' => true] |
24 |
| - : []; |
25 |
| - |
26 | 26 | try {
|
27 | 27 | $response = Http::acceptJson()
|
28 | 28 | ->withBasicAuth(config('directadmin.username'), config('directadmin.password'))
|
29 |
| - ->withQueryParameters($queryParams) |
| 29 | + ->withOptions($this->getHttpOptions()) |
| 30 | + ->withQueryParameters($this->getQueryParams()) |
30 | 31 | ->post(config('directadmin.baseUrl').'/'.strtoupper($command), $params);
|
31 | 32 | } catch (ConnectionException $e) {
|
32 | 33 | throw new ConnectionFailed('Connection failed: '.$e->getMessage());
|
33 | 34 | }
|
34 | 35 |
|
35 |
| - return $this->process($response); |
| 36 | + return $this->processResponse($response); |
36 | 37 | }
|
37 | 38 |
|
38 |
| - public function withoutJson(): static |
| 39 | + /** |
| 40 | + * Enable debug mode for HTTP requests. This can help identify |
| 41 | + * issues with the DirectAdmin server. |
| 42 | + */ |
| 43 | + public function debug(): static |
39 | 44 | {
|
40 |
| - $this->json = false; |
| 45 | + $this->debug = true; |
41 | 46 |
|
42 | 47 | return $this;
|
43 | 48 | }
|
44 | 49 |
|
45 | 50 | /**
|
| 51 | + * Process the response that's returned by the DirectAdmin API |
| 52 | + * and prepare it for further processing by third party code. |
| 53 | + * |
46 | 54 | * @throws ConnectionFailed
|
| 55 | + * @throws InvalidResponse |
47 | 56 | */
|
48 |
| - protected function process(Response $response): array |
| 57 | + protected function processResponse(Response $response): Collection |
49 | 58 | {
|
50 |
| - if (! $response->successful()) { |
| 59 | + if (! $response->successful() && $response->status() !== 500) { |
51 | 60 | match ($response->status()) {
|
52 | 61 | 401 => throw new ConnectionFailed('Unauthorized. Please check the credentials.'),
|
53 | 62 | 403 => throw new ConnectionFailed('Unauthorized. You do not have access to this resource.'),
|
54 | 63 | 405 => throw new ConnectionFailed('Command does not exist.'),
|
55 |
| - default => throw new ConnectionFailed('Something went wrong.'), |
| 64 | + default => throw new ConnectionFailed('Something went wrong: '.$response->body()), |
56 | 65 | };
|
57 | 66 | }
|
58 | 67 |
|
59 | 68 | try {
|
60 |
| - $content = json_decode($response->body(), associative: true, flags: JSON_THROW_ON_ERROR); |
| 69 | + $result = json_decode($response->body(), associative: true, flags: JSON_THROW_ON_ERROR); |
| 70 | + $result = collect($result); |
61 | 71 | } catch (JsonException) {
|
62 |
| - $content = collect(explode('&', urldecode($response->body()))) |
63 |
| - ->map(function ($item) { |
64 |
| - [$value, $key] = explode('=', $item); |
| 72 | + throw new InvalidResponse('Invalid JSON returned by server: '.$response->body()); |
| 73 | + } |
| 74 | + |
| 75 | + $this->validate($result); |
| 76 | + |
| 77 | + return $result; |
| 78 | + } |
| 79 | + |
| 80 | + /** |
| 81 | + * Validate the content returned by DirectAdmin. Even though the |
| 82 | + * API can return a successfull response to our HTTP-request |
| 83 | + * the actual call may have failed. |
| 84 | + * |
| 85 | + * @throws InvalidResponse |
| 86 | + */ |
| 87 | + protected function validate(Collection $result): void |
| 88 | + { |
| 89 | + if ($result->has('error')) { |
| 90 | + $error = $result->get('error'); |
| 91 | + $description = $result->get('result'); |
65 | 92 |
|
66 |
| - return [$key => $value]; |
67 |
| - }) |
68 |
| - ->toArray(); |
| 93 | + if (! empty($description)) { |
| 94 | + $description = ': '.$description; |
| 95 | + } |
| 96 | + |
| 97 | + throw new InvalidResponse($error.$description); |
69 | 98 | }
|
| 99 | + } |
70 | 100 |
|
71 |
| - return $content; |
| 101 | + protected function getHttpOptions(): array |
| 102 | + { |
| 103 | + return [ |
| 104 | + 'debug' => $this->debug, |
| 105 | + ]; |
| 106 | + } |
| 107 | + |
| 108 | + protected function getQueryParams(): array |
| 109 | + { |
| 110 | + return [ |
| 111 | + 'json' => 'yes', |
| 112 | + ]; |
72 | 113 | }
|
73 | 114 |
|
74 | 115 | /**
|
75 | 116 | * @throws ConnectionFailed
|
| 117 | + * @throws InvalidResponse |
76 | 118 | */
|
77 | 119 | public function __call(string $name, array $arguments)
|
78 | 120 | {
|
|
0 commit comments