1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace Bavix\SDK; |
4
|
|
|
|
5
|
|
|
use Bavix\Exceptions\Invalid; |
6
|
|
|
use Bavix\Helpers\Arr; |
7
|
|
|
use Bavix\Helpers\JSON; |
8
|
|
|
use Bavix\Helpers\Str; |
9
|
|
|
use Bavix\Slice\Slice; |
10
|
|
|
use Carbon\Carbon; |
11
|
|
|
use Bavix\SDK\Helpers\Curl; |
12
|
|
|
use GuzzleHttp\Client; |
13
|
|
|
use Psr\Http\Message\ResponseInterface; |
14
|
|
|
|
15
|
|
|
class Corundum |
16
|
|
|
{ |
17
|
|
|
|
18
|
|
|
/** |
19
|
|
|
* @var array |
20
|
|
|
*/ |
21
|
|
|
protected $tokens = []; |
22
|
|
|
|
23
|
|
|
/** |
24
|
|
|
* @var string |
25
|
|
|
*/ |
26
|
|
|
protected $urlToken; |
27
|
|
|
|
28
|
|
|
/** |
29
|
|
|
* @var string |
30
|
|
|
*/ |
31
|
|
|
protected $basic; |
32
|
|
|
|
33
|
|
|
/** |
34
|
|
|
* @var Slice |
35
|
|
|
*/ |
36
|
|
|
protected $slice; |
37
|
|
|
|
38
|
|
|
/** |
39
|
|
|
* @var Slice |
40
|
|
|
*/ |
41
|
|
|
protected $fake; |
42
|
|
|
|
43
|
|
|
/** |
44
|
|
|
* @var ResponseInterface |
45
|
|
|
*/ |
46
|
|
|
protected $response; |
47
|
|
|
|
48
|
|
|
/** |
49
|
|
|
* @var Slice |
50
|
|
|
*/ |
51
|
|
|
protected $results; |
52
|
|
|
|
53
|
|
|
/** |
54
|
|
|
* Corundum constructor. |
55
|
|
|
* |
56
|
|
|
* @param Slice $slice |
57
|
|
|
*/ |
58
|
|
|
public function __construct(Slice $slice) |
59
|
|
|
{ |
60
|
|
|
$clientId = $slice->getRequired('app.client_id'); |
61
|
|
|
$secret = $slice->getRequired('app.client_secret'); |
62
|
|
|
|
63
|
|
|
$this->slice = $slice; |
64
|
|
|
$this->basic = \base64_encode($clientId . ':' . $secret); |
65
|
|
|
$this->urlToken = $slice->getRequired('app.url.token'); |
66
|
|
|
} |
67
|
|
|
|
68
|
|
|
/** |
69
|
|
|
* @return array |
70
|
|
|
*/ |
71
|
|
|
public function getTokens(): array |
72
|
|
|
{ |
73
|
|
|
return $this->tokens; |
74
|
|
|
} |
75
|
|
|
|
76
|
|
|
/** |
77
|
|
|
* @param array $tokens |
78
|
|
|
*/ |
79
|
|
|
public function setTokens(array $tokens) |
80
|
|
|
{ |
81
|
|
|
$this->tokens = $tokens; |
82
|
|
|
} |
83
|
|
|
|
84
|
|
|
/** |
85
|
|
|
* @return Slice |
86
|
|
|
*/ |
87
|
|
|
protected function fake(): Slice |
88
|
|
|
{ |
89
|
|
|
if (!$this->fake) |
90
|
|
|
{ |
91
|
|
|
$this->fake = new Slice([]); |
92
|
|
|
} |
93
|
|
|
|
94
|
|
|
return $this->fake; |
95
|
|
|
} |
96
|
|
|
|
97
|
|
|
/** |
98
|
|
|
* @return string |
99
|
|
|
* |
100
|
|
|
* @throws \RuntimeException |
101
|
|
|
*/ |
102
|
|
|
public function getBody(): string |
103
|
|
|
{ |
104
|
|
|
return $this->response->getBody() |
105
|
|
|
->getContents(); |
106
|
|
|
} |
107
|
|
|
|
108
|
|
|
/** |
109
|
|
|
* @return Slice|null |
110
|
|
|
*/ |
111
|
|
|
public function getResults() |
112
|
|
|
{ |
113
|
|
|
return $this->results; |
114
|
|
|
} |
115
|
|
|
|
116
|
|
|
/** |
117
|
|
|
* @return int|null |
118
|
|
|
*/ |
119
|
|
|
public function getCode() |
120
|
|
|
{ |
121
|
|
|
if ($this->response) |
122
|
|
|
{ |
123
|
|
|
return $this->response->getStatusCode(); |
124
|
|
|
} |
125
|
|
|
|
126
|
|
|
return null; |
127
|
|
|
} |
128
|
|
|
|
129
|
|
|
/** |
130
|
|
|
* @param mixed $value |
131
|
|
|
* |
132
|
|
|
* @return mixed |
133
|
|
|
*/ |
134
|
|
|
protected function value($value) |
135
|
|
|
{ |
136
|
|
|
if (Str::first($value) === '@') |
137
|
|
|
{ |
138
|
|
|
return fopen(Str::withoutFirst($value), 'rb'); |
139
|
|
|
} |
140
|
|
|
|
141
|
|
|
return $value; |
142
|
|
|
} |
143
|
|
|
|
144
|
|
|
/** |
145
|
|
|
* @param array $params |
146
|
|
|
* |
147
|
|
|
* @return array |
148
|
|
|
*/ |
149
|
|
|
protected function multipart(array $params): array |
150
|
|
|
{ |
151
|
|
|
$results = []; |
152
|
|
|
|
153
|
|
|
foreach ($params as $key => $value) |
154
|
|
|
{ |
155
|
|
|
$content = [ |
156
|
|
|
'name' => $key, |
157
|
|
|
'contents' => $this->value($value) |
158
|
|
|
]; |
159
|
|
|
|
160
|
|
|
if (\is_resource($content['contents'])) |
161
|
|
|
{ |
162
|
|
|
$content['filename'] = basename($value); |
163
|
|
|
} |
164
|
|
|
|
165
|
|
|
$results[] = $content; |
166
|
|
|
} |
167
|
|
|
|
168
|
|
|
return $results; |
169
|
|
|
} |
170
|
|
|
|
171
|
|
|
/** |
172
|
|
|
* @param Slice $options |
173
|
|
|
* |
174
|
|
|
* @return Slice |
175
|
|
|
* |
176
|
|
|
* @throws Invalid |
177
|
|
|
*/ |
178
|
|
|
protected function apiRequest(Slice $options): Slice |
179
|
|
|
{ |
180
|
|
|
$type = $options->getData('token_type', 'Basic'); |
181
|
|
|
$method = $options->getData('method', 'POST'); |
182
|
|
|
$token = $options->getData('access_token', $this->basic); |
183
|
|
|
$url = $options->getData('url', $this->urlToken); |
184
|
|
|
$params = $options->getData('params', []); |
185
|
|
|
$headers = $options->getData('headers', []); |
186
|
|
|
|
187
|
|
|
// headers |
188
|
|
|
$headers['Authorization'] = $type . ' ' . $token; |
189
|
|
|
|
190
|
|
|
$client = new Client(); |
191
|
|
|
|
192
|
|
|
$data = [ |
193
|
|
|
'headers' => $headers, |
194
|
|
|
'multipart' => $this->multipart($params), |
195
|
|
|
]; |
196
|
|
|
|
197
|
|
|
$this->response = $client->request( |
198
|
|
|
Str::upp($method), |
199
|
|
|
$url, |
200
|
|
|
$data |
201
|
|
|
); |
202
|
|
|
|
203
|
|
|
$this->results = null; |
204
|
|
|
|
205
|
|
|
$response = JSON::decode( |
206
|
|
|
$this->getBody() |
207
|
|
|
); |
208
|
|
|
|
209
|
|
|
if (JSON::errorNone()) |
210
|
|
|
{ |
211
|
|
|
$this->results = new Slice($response); |
212
|
|
|
} |
213
|
|
|
|
214
|
|
|
$code = $this->getCode(); |
215
|
|
|
|
216
|
|
|
if ($code < 200 || $code > 299) |
217
|
|
|
{ |
218
|
|
|
throw new Invalid( |
219
|
|
|
'Error: ' . $this->response->getReasonPhrase(), |
220
|
|
|
$code |
221
|
|
|
); |
222
|
|
|
} |
223
|
|
|
|
224
|
|
|
return $this->getResults(); |
225
|
|
|
} |
226
|
|
|
|
227
|
|
|
/** |
228
|
|
|
* @param string $user |
229
|
|
|
* @param array $params |
230
|
|
|
* |
231
|
|
|
* @return Slice |
232
|
|
|
* |
233
|
|
|
* @throws Invalid |
234
|
|
|
*/ |
235
|
|
|
protected function authorize(string $user, array $params = []): Slice |
236
|
|
|
{ |
237
|
|
|
$grantType = $this->slice->getData('grant_type', 'password'); |
238
|
|
|
$userData = $this->slice->getSlice('users.' . $user); |
239
|
|
|
$defaults = [ |
240
|
|
|
'username' => $userData->getRequired('username'), |
241
|
|
|
'password' => $userData->getRequired('password'), |
242
|
|
|
'grant_type' => $grantType, |
243
|
|
|
]; |
244
|
|
|
|
245
|
|
|
$response = $this->apiRequest(new Slice([ |
246
|
|
|
'params' => Arr::merge($defaults, $params) |
247
|
|
|
])); |
248
|
|
|
|
249
|
|
|
$response->expires = Carbon::now() |
250
|
|
|
->addSeconds($response->expires_in); |
251
|
|
|
|
252
|
|
|
return $response; |
253
|
|
|
} |
254
|
|
|
|
255
|
|
|
/** |
256
|
|
|
* @param string $user |
257
|
|
|
* @param string $scope |
258
|
|
|
* |
259
|
|
|
* @return Slice |
260
|
|
|
* |
261
|
|
|
* @throws Invalid |
262
|
|
|
*/ |
263
|
|
|
protected function getToken(string $user, string $scope = ''): Slice |
264
|
|
|
{ |
265
|
|
|
if (!Arr::keyExists($this->tokens, $user)) |
266
|
|
|
{ |
267
|
|
|
$this->tokens[$user] = $this->authorize($user, [ |
268
|
|
|
'scope' => $scope |
269
|
|
|
]); |
270
|
|
|
} |
271
|
|
|
|
272
|
|
|
return $this->tokens[$user]; |
273
|
|
|
} |
274
|
|
|
|
275
|
|
|
/** |
276
|
|
|
* @param string $user |
277
|
|
|
* |
278
|
|
|
* @return Slice |
279
|
|
|
* |
280
|
|
|
* @throws Invalid |
281
|
|
|
*/ |
282
|
|
|
protected function refreshToken(string $user): Slice |
283
|
|
|
{ |
284
|
|
|
/** |
285
|
|
|
* @var $token Slice |
286
|
|
|
*/ |
287
|
|
|
$token = $this->tokens[$user]; |
288
|
|
|
|
289
|
|
|
return $this->tokens[$user] = $this->authorize($user, [ |
290
|
|
|
'grant_type' => 'refresh_token', |
291
|
|
|
'refresh_token' => $token->getRequired('refresh_token'), |
292
|
|
|
]); |
293
|
|
|
} |
294
|
|
|
|
295
|
|
|
/** |
296
|
|
|
* @param string $user |
297
|
|
|
* @param string $file |
298
|
|
|
* @param Slice $options |
299
|
|
|
* |
300
|
|
|
* @return Slice |
301
|
|
|
* |
302
|
|
|
* @throws Invalid |
303
|
|
|
*/ |
304
|
|
|
public function upload(string $user, string $file, Slice $options = null): Slice |
305
|
|
|
{ |
306
|
|
|
if (!$options) |
307
|
|
|
{ |
308
|
|
|
$options = $this->fake(); |
309
|
|
|
} |
310
|
|
|
|
311
|
|
|
$token = $this->getToken( |
312
|
|
|
$user, |
313
|
|
|
$options->getData('scope', '') |
314
|
|
|
); |
315
|
|
|
|
316
|
|
|
try |
317
|
|
|
{ |
318
|
|
|
return $this->apiRequest( |
319
|
|
|
$this->uploadSlice($token, $options, $file) |
320
|
|
|
); |
321
|
|
|
} |
322
|
|
|
catch (\Throwable $throwable) |
|
|
|
|
323
|
|
|
{ |
324
|
|
|
return $this->apiRequest( |
325
|
|
|
$this->uploadSlice( |
326
|
|
|
$this->tokenUpdate($user, $options), |
327
|
|
|
$options, |
328
|
|
|
$file |
329
|
|
|
) |
330
|
|
|
); |
331
|
|
|
} |
332
|
|
|
|
333
|
|
|
} |
334
|
|
|
|
335
|
|
|
/** |
336
|
|
|
* @param Slice $token |
337
|
|
|
* @param Slice $options |
338
|
|
|
* |
339
|
|
|
* @return Slice |
340
|
|
|
*/ |
341
|
|
|
protected function uploadSlice(Slice $token, Slice $options, string $file): Slice |
342
|
|
|
{ |
343
|
|
|
return new Slice([ |
344
|
|
|
'token_type' => $token->getRequired('token_type'), |
345
|
|
|
'access_token' => $token->getRequired('access_token'), |
346
|
|
|
'method' => $options->getData('method', 'post'), |
347
|
|
|
'url' => $this->slice->getRequired('app.url.upload'), |
348
|
|
|
|
349
|
|
|
'headers' => Arr::merge($options->getData('headers', []), [ |
350
|
|
|
'Accept' => 'application/json' |
351
|
|
|
]), |
352
|
|
|
|
353
|
|
|
'params' => Arr::merge($options->getData('params', []), [ |
354
|
|
|
'file' => '@' . \ltrim($file, '@') |
355
|
|
|
]) |
356
|
|
|
]); |
357
|
|
|
} |
358
|
|
|
|
359
|
|
|
/** |
360
|
|
|
* @param Slice $token |
361
|
|
|
* |
362
|
|
|
* @return Slice |
363
|
|
|
* |
364
|
|
|
* @throws Invalid |
365
|
|
|
*/ |
366
|
|
|
protected function verify(Slice $token): Slice |
367
|
|
|
{ |
368
|
|
|
return $this->apiRequest(new Slice([ |
369
|
|
|
'token_type' => $token->getRequired('token_type'), |
370
|
|
|
'access_token' => $token->getRequired('access_token'), |
371
|
|
|
'url' => $this->slice->getRequired('app.url.verify'), |
372
|
|
|
'headers' => [ |
373
|
|
|
'Accept' => 'application/json' |
374
|
|
|
] |
375
|
|
|
])); |
376
|
|
|
} |
377
|
|
|
|
378
|
|
|
/** |
379
|
|
|
* @param string $user |
380
|
|
|
* @param Slice $slice |
381
|
|
|
* |
382
|
|
|
* @return Slice |
383
|
|
|
* |
384
|
|
|
* @throws Invalid |
385
|
|
|
*/ |
386
|
|
|
protected function tokenUpdate(string $user, Slice $slice): Slice |
387
|
|
|
{ |
388
|
|
|
try |
389
|
|
|
{ |
390
|
|
|
$token = $this->refreshToken($user); |
391
|
|
|
|
392
|
|
|
if (!$this->verify($token)) |
393
|
|
|
{ |
394
|
|
|
throw new Invalid('The token isn\'t verified'); |
395
|
|
|
} |
396
|
|
|
} |
397
|
|
|
catch (Invalid $invalid) |
398
|
|
|
{ |
399
|
|
|
$this->tokens[$user] = null; |
400
|
|
|
|
401
|
|
|
$token = $this->getToken( |
402
|
|
|
$user, |
403
|
|
|
$slice->getData('scope', '') |
404
|
|
|
); |
405
|
|
|
} |
406
|
|
|
|
407
|
|
|
return $token; |
408
|
|
|
} |
409
|
|
|
|
410
|
|
|
} |
411
|
|
|
|
Scrutinizer analyzes your
composer.json
/composer.lock
file if available to determine the classes, and functions that are defined by your dependencies.It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.