Passed
Push — master ( 0facf0...5efa68 )
by Yunus Emre
03:38
created

HttpClientGateway::send()   A

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('?', [$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
     * @throws \TarfinLabs\Parasut\Exceptions\BadRequestException
163
     * @throws \TarfinLabs\Parasut\Exceptions\ForbiddenException
164
     * @throws \TarfinLabs\Parasut\Exceptions\NotFoundException
165
     * @throws \TarfinLabs\Parasut\Exceptions\TooManyRequestsException
166
     * @throws \TarfinLabs\Parasut\Exceptions\UnauthorizedException
167
     * @throws \TarfinLabs\Parasut\Exceptions\UnprocessableEntityException
168
     */
169
    protected function catchException(Response $response): void
170
    {
171
        switch ($response->status()) {
172
            case BadRequestException::$statusCode:
173
                throw new BadRequestException($response);
174
                break;
175
            case ForbiddenException::$statusCode:
176
                throw new ForbiddenException($response);
177
                break;
178
            case NotFoundException::$statusCode:
179
                throw new NotFoundException($response);
180
                break;
181
            case TooManyRequestsException::$statusCode:
182
                throw new TooManyRequestsException($response);
183
                break;
184
            case UnauthorizedException::$statusCode:
185
                throw new UnauthorizedException($response);
186
                break;
187
            case UnprocessableEntityException::$statusCode:
188
                throw new UnprocessableEntityException($response);
189
                break;
190
            default:
191
                throw new RuntimeException("Unknown Paraşüt Exception: {$response->status()}");
192
                break;
193
        }
194
    }
195
}
196