Passed
Push — master ( e0ab5f...89e278 )
by Yunus Emre
03:45
created

HttpClientGateway::call()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 26
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 3.072

Importance

Changes 6
Bugs 0 Features 0
Metric Value
eloc 9
c 6
b 0
f 0
dl 0
loc 26
ccs 8
cts 10
cp 0.8
rs 9.9666
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 RuntimeException;
6
use Illuminate\Http\Client\Response;
7
use Illuminate\Support\Carbon;
8
use Illuminate\Support\Facades\Http;
9
use TarfinLabs\Parasut\Exceptions\BadRequestException;
10
use TarfinLabs\Parasut\Exceptions\ForbiddenException;
11
use TarfinLabs\Parasut\Exceptions\NotFoundException;
12
use TarfinLabs\Parasut\Exceptions\TooManyRequestsException;
13
use TarfinLabs\Parasut\Exceptions\UnauthorizedException;
14
use TarfinLabs\Parasut\Exceptions\UnprocessableEntityException;
15
16
class HttpClientGateway implements ClientGateway
17
{
18
    // TODO: Cache tokens
19
    // TODO: Move URL's from config to consts
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 6
    public function __construct(
35
        string $grantType,
36
        string $clientId,
37
        string $clientSecret,
38
        string $username,
39
        string $password,
40
        string $redirectUri
41
    ) {
42 6
        $this->grantType = $grantType;
43 6
        $this->clientId = $clientId;
44 6
        $this->clientSecret = $clientSecret;
45 6
        $this->username = $username;
46 6
        $this->password = $password;
47 6
        $this->redirectUri = $redirectUri;
48
49 6
        $this->baseEntpoint = implode('/', [
50 6
            config('parasut.api_url'),
51 6
            config('parasut.api_version'),
52 6
            config('parasut.company_id'),
53
        ]);
54
55 6
        $this->authenticate();
56 6
    }
57
58 6
    public function getAccessToken(): string
59
    {
60 6
        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 6
    public function authenticate(): bool
85
    {
86 6
        $response = Http::asForm()
87 6
                        ->post(
88 6
                            implode('/', [
89 6
                                config('parasut.api_url'), config('parasut.token_url'),
90
                            ]),
91
                            [
92 6
                                'grant_type'    => $this->grantType,
93 6
                                'client_id'     => $this->clientId,
94 6
                                'client_secret' => $this->clientSecret,
95 6
                                'username'      => $this->username,
96 6
                                'password'      => $this->password,
97 6
                                'redirect_uri'  => $this->redirectUri,
98
                            ]
99
                        );
100
101 6
        if ($response->successful()) {
102 6
            $this->accessToken = $response->json()['access_token'];
103 6
            $this->refreshToken = $response->json()['refresh_token'];
104 6
            $this->expiresAt = Carbon::now()->addSeconds($response->json()['expires_in']);
105
106 6
            return true;
107
        }
108
109
        $this->catchException($response);
110
    }
111
112 5
    protected function buildHttpQuery(
113
        $filters = null,
114
        $sorts = null,
115
        $includes = null,
116
        $page = null,
117
        $pageSize = null
118
    ): string {
119 5
        return http_build_query(
120
            array_filter([
121 5
                'filter'       => $filters,
122 5
                'sort'         => ! empty($sorts) ? implode(',', $sorts) : null,
123 5
                'include'      => ! empty($includes) ? implode(',', $includes) : null,
124 5
                'page[number]' => $page,
125 5
                'page[size]'   => $pageSize,
126
            ]));
127
    }
128
129 5
    public function send(
130
        string $method,
131
        string $endpoint,
132
        array $filters = null,
133
        array $sorts = null,
134
        array $includes = null,
135
        array $body = null,
136
        ?int $page,
137
        ?int $pageSize
138
    ): ?array {
139 5
        $url = implode('/', [$this->baseEntpoint, $endpoint]);
140
141 5
        $queryString = $this->buildHttpQuery($filters, $sorts, $includes, $page, $pageSize);
142
143 5
        if (! empty($queryString)) {
144
            $url = implode('?', [$queryString]);
145
        }
146
147 5
        $response = Http::withToken($this->getAccessToken())
148 5
                        ->send($method, $url, ['json' => $body]);
149
150 5
        if ($response->successful()) {
151 5
            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