Test Failed
Push — master ( 257d98...3364ef )
by Yunus Emre
06:12
created

HttpClientGateway::call()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 26
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 6
Bugs 0 Features 0
Metric Value
eloc 9
c 6
b 0
f 0
dl 0
loc 26
rs 9.9666
cc 3
nc 4
nop 8

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