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

HttpClientGateway::getAccessToken()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 1
c 1
b 0
f 0
dl 0
loc 3
ccs 2
cts 2
cp 1
rs 10
cc 1
nc 1
nop 0
crap 1
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