HttpClientGateway::send()   A
last analyzed

Complexity

Conditions 3
Paths 4

Size

Total Lines 25
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 3.072

Importance

Changes 0
Metric Value
eloc 9
dl 0
loc 25
ccs 8
cts 10
cp 0.8
rs 9.9666
c 0
b 0
f 0
cc 3
nc 4
nop 8
crap 3.072

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
<?php
2
3
namespace TarfinLabs\Parasut\API;
4
5
use Illuminate\Http\Client\Response;
6
use Illuminate\Support\Carbon;
7
use Illuminate\Support\Facades\Http;
8
use RuntimeException;
9
use TarfinLabs\Parasut\Enums\ResourceNames;
10
use TarfinLabs\Parasut\Exceptions\BadRequestException;
11
use TarfinLabs\Parasut\Exceptions\ForbiddenException;
12
use TarfinLabs\Parasut\Exceptions\NotFoundException;
13
use TarfinLabs\Parasut\Exceptions\TooManyRequestsException;
14
use TarfinLabs\Parasut\Exceptions\UnauthorizedException;
15
use TarfinLabs\Parasut\Exceptions\UnprocessableEntityException;
16
17
class HttpClientGateway implements ClientGateway
18
{
19
    // TODO: Cache tokens
20
21
    private string $grantType;
22
    private string $clientId;
23
    private string $clientSecret;
24
    private string $username;
25
    private string $password;
26
    private string $redirectUri;
27
28
    private string $accessToken;
29
    private string $refreshToken;
30
    private Carbon $expiresAt;
31
32
    private string $baseEntpoint;
33
34 11
    public function __construct(
35
        string $grantType,
36
        string $clientId,
37
        string $clientSecret,
38
        string $username,
39
        string $password,
40
        string $redirectUri
41
    ) {
42 11
        $this->grantType = $grantType;
43 11
        $this->clientId = $clientId;
44 11
        $this->clientSecret = $clientSecret;
45 11
        $this->username = $username;
46 11
        $this->password = $password;
47 11
        $this->redirectUri = $redirectUri;
48
49 11
        $this->baseEntpoint = ResourceNames::buildEndpoint(
50 11
            config('parasut.api_url'),
51 11
            config('parasut.api_version'),
52 11
            config('parasut.company_id')
53
        );
54
55 11
        $this->authenticate();
56 11
    }
57
58 11
    public function getAccessToken(): string
59
    {
60 11
        return $this->accessToken;
61
    }
62
63 1
    public function getRefreshToken(): string
64
    {
65 1
        return $this->refreshToken;
66
    }
67
68 1
    public function getExpiresAt(): ?Carbon
69
    {
70 1
        return $this->expiresAt;
71
    }
72
73
    /**
74
     * Authenticate user and get API tokens from parasut.com.
75
     *
76
     * @return bool
77
     * @throws \TarfinLabs\Parasut\Exceptions\BadRequestException
78
     * @throws \TarfinLabs\Parasut\Exceptions\ForbiddenException
79
     * @throws \TarfinLabs\Parasut\Exceptions\NotFoundException
80
     * @throws \TarfinLabs\Parasut\Exceptions\TooManyRequestsException
81
     * @throws \TarfinLabs\Parasut\Exceptions\UnauthorizedException
82
     * @throws \TarfinLabs\Parasut\Exceptions\UnprocessableEntityException
83
     */
84 11
    public function authenticate(): bool
85
    {
86 11
        $response = Http::asForm()
87 11
                        ->post(
88
                            ResourceNames::buildEndpoint(
89 11
                                config('parasut.api_url'),
90 11
                                config('parasut.token_url')
91
                            ),
92
                            [
93 11
                                'grant_type'    => $this->grantType,
94 11
                                'client_id'     => $this->clientId,
95 11
                                'client_secret' => $this->clientSecret,
96 11
                                'username'      => $this->username,
97 11
                                'password'      => $this->password,
98 11
                                'redirect_uri'  => $this->redirectUri,
99
                            ]
100
                        );
101
102 11
        if ($response->successful()) {
103 11
            $this->accessToken = $response->json()['access_token'];
104 11
            $this->refreshToken = $response->json()['refresh_token'];
105 11
            $this->expiresAt = Carbon::now()->addSeconds($response->json()['expires_in']);
106
107 11
            return true;
108
        }
109
110
        $this->catchException($response);
111
    }
112
113 10
    protected function buildHttpQuery(
114
        $filters = null,
115
        $sorts = null,
116
        $includes = null,
117
        $page = null,
118
        $pageSize = null
119
    ): string {
120 10
        return http_build_query(
121
            array_filter([
122 10
                'filter'       => $filters,
123 10
                'sort'         => ! empty($sorts) ? implode(',', $sorts) : null,
124 10
                'include'      => ! empty($includes) ? implode(',', $includes) : null,
125 10
                'page[number]' => $page,
126 10
                'page[size]'   => $pageSize,
127
            ]));
128
    }
129
130 10
    public function send(
131
        string $method,
132
        array $endpoints,
133
        array $filters = null,
134
        array $sorts = null,
135
        array $includes = null,
136
        array $body = null,
137
        ?int $page,
138
        ?int $pageSize
139
    ): ?array {
140 10
        $url = ResourceNames::buildEndpoint($this->baseEntpoint, $endpoints);
141 10
        $queryString = $this->buildHttpQuery($filters, $sorts, $includes, $page, $pageSize);
142
143 10
        if (! empty($queryString)) {
144
            $url = implode('?', [$url, $queryString]);
145
        }
146
147 10
        $response = Http::withToken($this->getAccessToken())
148 10
                        ->send($method, $url, ['json' => $body]);
149
150 10
        if ($response->successful()) {
151 10
            return $response->json();
152
        }
153
154
        $this->catchException($response);
155
    }
156
157
    /**
158
     * Catches the status code and throws appropriate exception.
159
     *
160
     * @param  \Illuminate\Http\Client\Response  $response
161
     */
162
    protected function catchException(Response $response): void
163
    {
164
        switch ($response->status()) {
165
            case BadRequestException::$statusCode:
166
                $exceptionClass = BadRequestException::class;
167
                break;
168
            case ForbiddenException::$statusCode:
169
                $exceptionClass = ForbiddenException::class;
170
                break;
171
            case NotFoundException::$statusCode:
172
                $exceptionClass = NotFoundException::class;
173
                break;
174
            case TooManyRequestsException::$statusCode:
175
                $exceptionClass = TooManyRequestsException::class;
176
                break;
177
            case UnauthorizedException::$statusCode:
178
                $exceptionClass = UnauthorizedException::class;
179
                break;
180
            case UnprocessableEntityException::$statusCode:
181
                $exceptionClass = UnprocessableEntityException::class;
182
                break;
183
            default:
184
                $exceptionClass = RuntimeException::class;
185
                break;
186
        }
187
188
        throw new $exceptionClass($response);
189
    }
190
}
191