Skip to content

Commit 1a8fc0b

Browse files
committed
chore: use custom exceptions
1 parent 4b1d98d commit 1a8fc0b

9 files changed

+176
-149
lines changed

README.md

+21-2
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@ You can publish the config file with:
2121
php artisan vendor:publish --tag="laravel-directadmin-config"
2222
```
2323

24-
This is the contents of the published config file:
24+
The configuration file that will be published to your application's config
25+
directory is as follows:
2526

2627
```php
2728
return [
@@ -33,9 +34,27 @@ return [
3334

3435
## Usage
3536

37+
Configure the DirectAdmin service by specifying the following environment
38+
variables:
39+
40+
- `DIRECTADMIN_USERNAME`
41+
- `DIRECTADMIN_PASSWORD`
42+
- `DIRECTADMIN_BASE_URL`
43+
44+
Then you can call any DirectAdmin API command by using the `DirectAdmin` facade:
45+
46+
```php
47+
$result = DirectAdmin::call('{DIRECTADMIN_API_CALL}');
48+
```
49+
50+
This will return a `Collection` of the response data. You can also call any
51+
DirectAdmin API command by passing it as method to the `DirectAdmin` facade:
52+
3653
```php
37-
$result = Sensson\DirectAdmin\Facades\DirectAdmin::call('{DIRECTADMIN_API_CALL}');
54+
$result = DirectAdmin::CMD_API_DOMAIN_OWNERS();
3855
```
56+
For more information on the available commands, please refer to the
57+
[DirectAdmin API documentation](https://docs.directadmin.com/api/index.html).
3958

4059
## Testing
4160

src/Api.php

-127
This file was deleted.

src/DirectAdmin.php

+104-9
Original file line numberDiff line numberDiff line change
@@ -2,33 +2,128 @@
22

33
namespace Sensson\DirectAdmin;
44

5+
use Illuminate\Http\Client\ConnectionException;
6+
use Illuminate\Http\Client\Response;
57
use Illuminate\Support\Collection;
6-
use Illuminate\Support\Traits\ForwardsCalls;
8+
use Illuminate\Support\Facades\Http;
79
use Illuminate\Support\Traits\Tappable;
10+
use JsonException;
11+
use Sensson\DirectAdmin\Exceptions\AuthenticationFailed;
12+
use Sensson\DirectAdmin\Exceptions\CommandNotFound;
813
use Sensson\DirectAdmin\Exceptions\ConnectionFailed;
914
use Sensson\DirectAdmin\Exceptions\InvalidResponse;
15+
use Sensson\DirectAdmin\Exceptions\Unauthorized;
1016

1117
class DirectAdmin
1218
{
13-
use ForwardsCalls;
1419
use Tappable;
1520

16-
public function __construct(public Api $api)
21+
public bool $debug = false;
22+
23+
/**
24+
* Call the DirectAdmin API by giving it an API command and some
25+
* parameters. This will return an array with processed data.
26+
*/
27+
public function call(string $command, array $params = []): Collection
1728
{
18-
//
29+
try {
30+
$response = Http::acceptJson()
31+
->withBasicAuth(config('directadmin.username'), config('directadmin.password'))
32+
->withOptions($this->getHttpOptions())
33+
->withQueryParameters($this->getQueryParams())
34+
->post(config('directadmin.baseUrl').'/'.strtoupper($command), $params);
35+
} catch (ConnectionException $e) {
36+
throw ConnectionFailed::create($e->getMessage());
37+
}
38+
39+
return $this->processResponse(
40+
response: $response,
41+
command: $command,
42+
);
1943
}
2044

2145
/**
22-
* @throws ConnectionFailed
23-
* @throws InvalidResponse
46+
* Enable debug mode for HTTP requests. This can help identify
47+
* issues with the DirectAdmin server.
2448
*/
25-
public function call(string $command, array $params = []): Collection
49+
public function debug(): static
50+
{
51+
$this->debug = true;
52+
53+
return $this;
54+
}
55+
56+
/**
57+
* Process the response that's returned by the DirectAdmin API
58+
* and prepare it for further processing by third party code.
59+
*
60+
*/
61+
protected function processResponse(Response $response, string $command = ''): Collection
2662
{
27-
return $this->api->call($command, $params);
63+
if (! $response->successful() && $response->status() !== 500) {
64+
match ($response->status()) {
65+
401 => throw AuthenticationFailed::create(),
66+
403 => throw Unauthorized::create(),
67+
405 => throw CommandNotFound::create($command),
68+
default => throw ConnectionFailed::create($response->body()),
69+
};
70+
}
71+
72+
try {
73+
$result = json_decode($response->body(), associative: true, flags: JSON_THROW_ON_ERROR);
74+
$result = collect($result);
75+
} catch (JsonException) {
76+
throw InvalidResponse::create('Invalid JSON returned by server: '.$response->body());
77+
}
78+
79+
$this->validateResult($result);
80+
81+
return $result;
2882
}
2983

84+
/**
85+
* Validate the content returned by DirectAdmin. Even though the
86+
* API can return a successfull response to our HTTP-request
87+
* the actual call may have failed.
88+
*/
89+
protected function validateResult(Collection $result): void
90+
{
91+
if ($result->has('error')) {
92+
$error = $result->get('error');
93+
$description = $result->get('result');
94+
95+
if (! empty($description)) {
96+
$description = ': '.$description;
97+
}
98+
99+
throw InvalidResponse::create($error.$description);
100+
}
101+
}
102+
103+
protected function getHttpOptions(): array
104+
{
105+
return [
106+
'debug' => $this->debug,
107+
];
108+
}
109+
110+
protected function getQueryParams(): array
111+
{
112+
return [
113+
'json' => 'yes',
114+
];
115+
}
116+
117+
/**
118+
* @throws ConnectionFailed
119+
* @throws InvalidResponse
120+
*/
30121
public function __call(string $name, array $arguments)
31122
{
32-
return $this->forwardCallTo($this->api, $name, $arguments);
123+
if (method_exists($this, $name)) {
124+
return $this->{$name}(...$arguments);
125+
}
126+
127+
return $this->call($name, $arguments);
33128
}
34129
}
+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<?php
2+
3+
namespace Sensson\DirectAdmin\Exceptions;
4+
5+
use Symfony\Component\HttpKernel\Exception\HttpException;
6+
7+
class AuthenticationFailed extends HttpException
8+
{
9+
public static function create(): static
10+
{
11+
return new static(401, 'Unauthorized. Please check the credentials.');
12+
}
13+
}

src/Exceptions/CommandNotFound.php

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<?php
2+
3+
namespace Sensson\DirectAdmin\Exceptions;
4+
5+
use Symfony\Component\HttpKernel\Exception\HttpException;
6+
7+
class CommandNotFound extends HttpException
8+
{
9+
public static function create(string $command): static
10+
{
11+
return new static(405, 'Command `'.$command.'` does not exist.');
12+
}
13+
}

src/Exceptions/ConnectionFailed.php

+6-3
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,12 @@
22

33
namespace Sensson\DirectAdmin\Exceptions;
44

5-
use Exception;
5+
use Symfony\Component\HttpKernel\Exception\HttpException;
66

7-
class ConnectionFailed extends Exception
7+
class ConnectionFailed extends HttpException
88
{
9-
//
9+
public static function create(string $message): static
10+
{
11+
return new static(500, $message);
12+
}
1013
}

src/Exceptions/InvalidResponse.php

+6-3
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,12 @@
22

33
namespace Sensson\DirectAdmin\Exceptions;
44

5-
use Exception;
5+
use Symfony\Component\HttpKernel\Exception\HttpException;
66

7-
class InvalidResponse extends Exception
7+
class InvalidResponse extends HttpException
88
{
9-
//
9+
public static function create(string $message): static
10+
{
11+
return new static(500, $message);
12+
}
1013
}

src/Exceptions/Unauthorized.php

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<?php
2+
3+
namespace Sensson\DirectAdmin\Exceptions;
4+
5+
use Symfony\Component\HttpKernel\Exception\HttpException;
6+
7+
class Unauthorized extends HttpException
8+
{
9+
public static function create(): static
10+
{
11+
return new static(403, 'You do not have access to this resource.');
12+
}
13+
}

tests/ExampleTest.php

-5
This file was deleted.

0 commit comments

Comments
 (0)