Passed
Push — master ( e0ab5f...89e278 )
by Yunus Emre
03:45
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 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