Completed
Push — master ( 6ec9b7...36c30a )
by Raza
01:51
created

DropboxClient::doDropboxApiContentRequest()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 13
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 13
rs 9.4285
c 0
b 0
f 0
cc 3
eloc 8
nc 2
nop 0
1
<?php
2
3
namespace Srmklive\Dropbox\Client;
4
5
use GuzzleHttp\Client as HttpClient;
6
use GuzzleHttp\Exception\ClientException as HttpClientException;
7
use GuzzleHttp\Psr7\StreamWrapper;
8
use Illuminate\Support\Collection;
9
use Srmklive\Dropbox\Exceptions\BadRequest;
10
11
class DropboxClient
12
{
13
    const THUMBNAIL_FORMAT_JPEG = 'jpeg';
14
    const THUMBNAIL_FORMAT_PNG = 'png';
15
16
    const THUMBNAIL_SIZE_XS = 'w32h32';
17
    const THUMBNAIL_SIZE_S = 'w64h64';
18
    const THUMBNAIL_SIZE_M = 'w128h128';
19
    const THUMBNAIL_SIZE_L = 'w640h480';
20
    const THUMBNAIL_SIZE_XL = 'w1024h768';
21
22
    /** @var \GuzzleHttp\Client */
23
    protected $client;
24
25
    /**
26
     * Dropbox OAuth access token.
27
     *
28
     * @var string
29
     */
30
    protected $accessToken;
31
32
    /**
33
     * Dropbox API v2 Url.
34
     *
35
     * @var string
36
     */
37
    protected $apiUrl;
38
39
    /**
40
     * Dropbox content API v2 url for uploading content.
41
     *
42
     * @var string
43
     */
44
    protected $apiContentUrl;
45
46
    /**
47
     * Dropbox API v2 endpoint.
48
     *
49
     * @var string
50
     */
51
    protected $apiEndpoint;
52
53
    /**
54
     * @var mixed
55
     */
56
    protected $content;
57
58
    /**
59
     * Collection containing Dropbox API request data.
60
     *
61
     * @var \Illuminate\Support\Collection
62
     */
63
    protected $request;
64
65
    /**
66
     * DropboxClient constructor.
67
     *
68
     * @param string             $token
69
     * @param \GuzzleHttp\Client $client
70
     */
71
    public function __construct($token, HttpClient $client = null)
72
    {
73
        $this->setAccessToken($token);
74
75
        $this->setClient($client);
76
77
        $this->apiUrl = 'https://api.dropboxapi.com/2/';
78
        $this->apiContentUrl = 'https://content.dropboxapi.com/2/';
79
    }
80
81
    /**
82
     * Set Http Client.
83
     *
84
     * @param \GuzzleHttp\Client $client
85
     */
86
    protected function setClient(HttpClient $client = null)
87
    {
88
        if ($client instanceof HttpClient) {
89
            $this->client = $client;
90
        } else {
91
            $this->client = new HttpClient([
92
                'headers' => [
93
                    'Authorization' => "Bearer {$this->accessToken}",
94
                ],
95
            ]);
96
        }
97
    }
98
99
    /**
100
     * Set Dropbox OAuth access token.
101
     *
102
     * @param string $token
103
     */
104
    protected function setAccessToken($token)
105
    {
106
        $this->accessToken = $token;
107
    }
108
109
    /**
110
     * Copy a file or folder to a different location in the user's Dropbox.
111
     *
112
     * If the source path is a folder all its contents will be copied.
113
     *
114
     * @param string $fromPath
115
     * @param string $toPath
116
     *
117
     * @return \Psr\Http\Message\ResponseInterface
118
     *
119
     * @link https://www.dropbox.com/developers/documentation/http/documentation#files-copy
120
     */
121 View Code Duplication
    public function copy($fromPath, $toPath)
122
    {
123
        $this->setupRequest([
124
            'from_path' => $this->normalizePath($fromPath),
125
            'to_path'   => $this->normalizePath($toPath),
126
        ]);
127
128
        $this->apiEndpoint = 'files/copy';
129
130
        return $this->doDropboxApiRequest();
131
    }
132
133
    /**
134
     * Create a folder at a given path.
135
     *
136
     * @param string $path
137
     *
138
     * @return \Psr\Http\Message\ResponseInterface
139
     *
140
     * @link https://www.dropbox.com/developers/documentation/http/documentation#files-create_folder
141
     */
142
    public function createFolder($path)
143
    {
144
        $this->setupRequest([
145
            'path' => $this->normalizePath($path),
146
        ]);
147
148
        $this->apiEndpoint = 'files/create_folder';
149
150
        $response = $this->doDropboxApiRequest();
151
        $response['.tag'] = 'folder';
152
153
        return $response;
154
    }
155
156
    /**
157
     * Delete the file or folder at a given path.
158
     *
159
     * If the path is a folder, all its contents will be deleted too.
160
     * A successful response indicates that the file or folder was deleted.
161
     *
162
     * @param string $path
163
     *
164
     * @return \Psr\Http\Message\ResponseInterface
165
     *
166
     * @link https://www.dropbox.com/developers/documentation/http/documentation#files-delete
167
     */
168
    public function delete($path)
169
    {
170
        $this->setupRequest([
171
            'path' => $this->normalizePath($path),
172
        ]);
173
174
        $this->apiEndpoint = 'files/delete';
175
176
        return $this->doDropboxApiRequest();
177
    }
178
179
    /**
180
     * Download a file from a user's Dropbox.
181
     *
182
     * @param string $path
183
     *
184
     * @return resource
185
     *
186
     * @link https://www.dropbox.com/developers/documentation/http/documentation#files-download
187
     */
188
    public function download($path)
189
    {
190
        $this->setupRequest([
191
            'path' => $this->normalizePath($path),
192
        ]);
193
194
        $this->apiEndpoint = 'files/download';
195
196
        $response = $this->doDropboxApiContentRequest();
197
198
        return StreamWrapper::getResource($response->getBody());
199
    }
200
201
    /**
202
     * Returns the metadata for a file or folder.
203
     *
204
     * Note: Metadata for the root folder is unsupported.
205
     *
206
     * @param string $path
207
     *
208
     * @return \Psr\Http\Message\ResponseInterface
209
     *
210
     * @link https://www.dropbox.com/developers/documentation/http/documentation#files-get_metadata
211
     */
212
    public function getMetaData($path)
213
    {
214
        $this->setupRequest([
215
            'path' => $this->normalizePath($path),
216
        ]);
217
218
        $this->apiEndpoint = 'files/get_metadata';
219
220
        return $this->doDropboxApiRequest();
221
    }
222
223
    /**
224
     * Get a temporary link to stream content of a file.
225
     *
226
     * This link will expire in four hours and afterwards you will get 410 Gone.
227
     * Content-Type of the link is determined automatically by the file's mime type.
228
     *
229
     * @param string $path
230
     *
231
     * @return string
232
     *
233
     * @link https://www.dropbox.com/developers/documentation/http/documentation#files-get_temporary_link
234
     */
235 View Code Duplication
    public function getTemporaryLink($path)
236
    {
237
        $this->setupRequest([
238
            'path' => $this->normalizePath($path),
239
        ]);
240
241
        $this->apiEndpoint = 'files/get_temporary_link';
242
243
        $response = $this->doDropboxApiRequest();
244
245
        return $response['link'];
246
    }
247
248
    /**
249
     * Get a thumbnail for an image.
250
     *
251
     * This method currently supports files with the following file extensions:
252
     * jpg, jpeg, png, tiff, tif, gif and bmp.
253
     *
254
     * Photos that are larger than 20MB in size won't be converted to a thumbnail.
255
     *
256
     * @param string $path
257
     * @param string $format
258
     * @param string $size
259
     *
260
     * @return string
261
     */
262
    public function getThumbnail($path, $format = 'jpeg', $size = 'w64h64')
263
    {
264
        $this->setupRequest([
265
            'path'   => $this->normalizePath($path),
266
            'format' => $format,
267
            'size'   => $size,
268
        ]);
269
270
        $this->apiEndpoint = 'files/get_thumbnail';
271
272
        $response = $this->doDropboxApiContentRequest();
273
274
        return (string) $response->getBody();
275
    }
276
277
    /**
278
     * Starts returning the contents of a folder.
279
     *
280
     * If the result's ListFolderResult.has_more field is true, call
281
     * list_folder/continue with the returned ListFolderResult.cursor to retrieve more entries.
282
     *
283
     * Note: auth.RateLimitError may be returned if multiple list_folder or list_folder/continue calls
284
     * with same parameters are made simultaneously by same API app for same user. If your app implements
285
     * retry logic, please hold off the retry until the previous request finishes.
286
     *
287
     * @param string $path
288
     * @param bool   $recursive
289
     *
290
     * @return \Psr\Http\Message\ResponseInterface
291
     *
292
     * @link https://www.dropbox.com/developers/documentation/http/documentation#files-list_folder
293
     */
294 View Code Duplication
    public function listFolder($path = '', $recursive = false)
295
    {
296
        $this->setupRequest([
297
            'path'      => $this->normalizePath($path),
298
            'recursive' => $recursive,
299
        ]);
300
301
        $this->apiEndpoint = 'files/list_folder';
302
303
        return $this->doDropboxApiRequest();
304
    }
305
306
    /**
307
     * Once a cursor has been retrieved from list_folder, use this to paginate through all files and
308
     * retrieve updates to the folder, following the same rules as documented for list_folder.
309
     *
310
     * @param string $cursor
311
     *
312
     * @return \Psr\Http\Message\ResponseInterface
313
     *
314
     * @link https://www.dropbox.com/developers/documentation/http/documentation#files-list_folder-continue
315
     */
316
    public function listFolderContinue($cursor = '')
317
    {
318
        $this->setupRequest([
319
            'cursor' => $cursor,
320
        ]);
321
322
        $this->apiEndpoint = 'files/list_folder/continue';
323
324
        return $this->doDropboxApiRequest();
325
    }
326
327
    /**
328
     * Move a file or folder to a different location in the user's Dropbox.
329
     *
330
     * If the source path is a folder all its contents will be moved.
331
     *
332
     * @param string $fromPath
333
     * @param string $toPath
334
     *
335
     * @return \Psr\Http\Message\ResponseInterface
336
     *
337
     * @link https://www.dropbox.com/developers/documentation/http/documentation#files-move
338
     */
339 View Code Duplication
    public function move($fromPath, $toPath)
340
    {
341
        $this->setupRequest([
342
            'from_path' => $this->normalizePath($fromPath),
343
            'to_path'   => $this->normalizePath($toPath),
344
        ]);
345
346
        $this->apiEndpoint = 'files/move';
347
348
        return $this->doDropboxApiRequest();
349
    }
350
351
    /**
352
     * Create a new file with the contents provided in the request.
353
     *
354
     * Do not use this to upload a file larger than 150 MB. Instead, create an upload session with upload_session/start.
355
     *
356
     * @link https://www.dropbox.com/developers/documentation/http/documentation#files-upload
357
     *
358
     * @param string          $path
359
     * @param string|resource $contents
360
     * @param string|array    $mode
361
     *
362
     * @return array
363
     */
364
    public function upload($path, $contents, $mode = 'add')
365
    {
366
        $this->setupRequest([
367
            'path' => $this->normalizePath($path),
368
            'mode' => $mode,
369
        ]);
370
371
        $this->content = $contents;
372
373
        $this->apiEndpoint = 'files/upload';
374
375
        $response = $this->doDropboxApiContentRequest();
376
377
        $metadata = \GuzzleHttp\json_decode($response->getBody(), true);
378
        $metadata['.tag'] = 'file';
379
380
        return $metadata;
381
    }
382
383
    /**
384
     * Set Dropbox API request data.
385
     *
386
     * @param array $request
387
     */
388
    protected function setupRequest($request)
389
    {
390
        $this->request = new Collection($request);
391
    }
392
393
    /**
394
     * Perform Dropbox API request.
395
     *
396
     * @throws \Exception
397
     *
398
     * @return \Psr\Http\Message\ResponseInterface
399
     */
400
    protected function doDropboxApiRequest()
401
    {
402
        try {
403
            $response = $this->client->post("{$this->apiUrl}{$this->apiEndpoint}", [
404
                'json' => $this->request->toArray(),
405
            ]);
406
        } catch (HttpClientException $exception) {
407
            throw $this->determineException($exception);
408
        }
409
410
        return json_decode($response->getBody(), true);
411
    }
412
413
    /**
414
     * Setup headers for Dropbox API request.
415
     *
416
     * @return array
417
     */
418
    protected function setupDropboxHeaders()
419
    {
420
        $headers = [
421
            'Dropbox-API-Arg' => json_encode(
422
                $this->request->toArray()
423
            )
424
        ];
425
426
        if (!empty($this->content)) {
427
            $headers['Content-Type'] = 'application/octet-stream';
428
        }
429
430
        return $headers;
431
    }
432
433
    /**
434
     * Perform Dropbox API request.
435
     *
436
     * @throws \Exception
437
     *
438
     * @return \Psr\Http\Message\ResponseInterface
439
     */
440
    protected function doDropboxApiContentRequest()
441
    {
442
        try {
443
            $response = $this->client->post("{$this->apiContentUrl}{$this->apiEndpoint}", [
444
                'headers' => $this->setupDropboxHeaders(),
445
                'body'    => !empty($this->content) ? $this->content : '',
446
            ]);
447
        } catch (HttpClientException $exception) {
448
            throw $this->determineException($exception);
449
        }
450
451
        return $response;
452
    }
453
454
    /**
455
     * Normalize path.
456
     *
457
     * @param string $path
458
     *
459
     * @return string
460
     */
461
    protected function normalizePath($path)
462
    {
463
        $path = (trim($path, '/') === '') ? '' : '/'.$path;
464
465
        return str_replace('//', '/', $path);
466
    }
467
468
    /**
469
     * Catch Dropbox API request exception.
470
     *
471
     * @param HttpClientException $exception
472
     *
473
     * @return \Exception
474
     */
475
    protected function determineException(HttpClientException $exception)
476
    {
477
        if (!empty($exception->getResponse()) && in_array($exception->getResponse()->getStatusCode(), [400, 409])) {
478
            return new BadRequest($exception->getResponse());
479
        }
480
481
        return $exception;
482
    }
483
}
484