1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace Spatie\Dropbox; |
4
|
|
|
|
5
|
|
|
use GuzzleHttp\Client as GuzzleClient; |
6
|
|
|
use GuzzleHttp\Exception\ClientException; |
7
|
|
|
use GuzzleHttp\Psr7\StreamWrapper; |
8
|
|
|
use Psr\Http\Message\ResponseInterface; |
9
|
|
|
use Spatie\Dropbox\Exceptions\BadRequest; |
10
|
|
|
|
11
|
|
|
class Client |
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
|
|
|
const HTTP_BAD_REQUEST = 400 |
23
|
|
|
const HTTP_CONFLICT = 409 |
|
|
|
|
24
|
|
|
|
25
|
|
|
protected $accessToken; |
26
|
|
|
|
27
|
|
|
protected $client; |
28
|
|
|
|
29
|
|
|
public function __construct(string $accessToken) |
30
|
|
|
{ |
31
|
|
|
$this->accessToken = $accessToken; |
32
|
|
|
|
33
|
|
|
$this->client = new GuzzleClient([ |
34
|
|
|
'headers' => [ |
35
|
|
|
'Authorization' => "Bearer {$this->accessToken}", |
36
|
|
|
], |
37
|
|
|
]); |
38
|
|
|
} |
39
|
|
|
|
40
|
|
|
/** |
41
|
|
|
* Copy a file or folder to a different location in the user's Dropbox. |
42
|
|
|
* |
43
|
|
|
* If the source path is a folder all its contents will be copied. |
44
|
|
|
* |
45
|
|
|
* @link https://www.dropbox.com/developers/documentation/http/documentation#files-copy |
46
|
|
|
*/ |
47
|
|
|
public function copy(string $path, string $newPath): array |
48
|
|
|
{ |
49
|
|
|
$parameters = [ |
50
|
|
|
'from_path' => $this->normalizePath($path), |
51
|
|
|
'to_path' => $this->normalizePath($newPath), |
52
|
|
|
]; |
53
|
|
|
|
54
|
|
|
return $this->rpcEndpointRequest('files/copy', $parameters); |
55
|
|
|
} |
56
|
|
|
|
57
|
|
|
/** |
58
|
|
|
* Create a folder at a given path.Create a folder at a given path. |
59
|
|
|
* |
60
|
|
|
* @link https://www.dropbox.com/developers/documentation/http/documentation#files-create_folder |
61
|
|
|
*/ |
62
|
|
|
public function createFolder(string $path): array |
63
|
|
|
{ |
64
|
|
|
$parameters = [ |
65
|
|
|
'path' => $this->normalizePath($path), |
66
|
|
|
]; |
67
|
|
|
|
68
|
|
|
$object = $this->rpcEndpointRequest('files/create_folder', $parameters); |
69
|
|
|
|
70
|
|
|
$object['.tag'] = 'folder'; |
71
|
|
|
|
72
|
|
|
return $object; |
73
|
|
|
} |
74
|
|
|
|
75
|
|
|
/** |
76
|
|
|
* Delete the file or folder at a given path. |
77
|
|
|
* |
78
|
|
|
* If the path is a folder, all its contents will be deleted too. |
79
|
|
|
* A successful response indicates that the file or folder was deleted. |
80
|
|
|
* |
81
|
|
|
* @link https://www.dropbox.com/developers/documentation/http/documentation#files-delete |
82
|
|
|
*/ |
83
|
|
|
public function delete(string $path): array |
84
|
|
|
{ |
85
|
|
|
$parameters = [ |
86
|
|
|
'path' => $this->normalizePath($path), |
87
|
|
|
]; |
88
|
|
|
|
89
|
|
|
return $this->rpcEndpointRequest('files/delete', $parameters); |
90
|
|
|
} |
91
|
|
|
|
92
|
|
|
/** |
93
|
|
|
* Download a file from a user's Dropbox. |
94
|
|
|
* |
95
|
|
|
* @param string $path |
96
|
|
|
* |
97
|
|
|
* @return resource |
98
|
|
|
* |
99
|
|
|
* @link https://www.dropbox.com/developers/documentation/http/documentation#files-download |
100
|
|
|
*/ |
101
|
|
|
public function download(string $path) |
102
|
|
|
{ |
103
|
|
|
$arguments = [ |
104
|
|
|
'path' => $this->normalizePath($path), |
105
|
|
|
]; |
106
|
|
|
|
107
|
|
|
$response = $this->contentEndpointRequest('files/download', $arguments); |
108
|
|
|
|
109
|
|
|
return StreamWrapper::getResource($response->getBody()); |
110
|
|
|
} |
111
|
|
|
|
112
|
|
|
/** |
113
|
|
|
* Returns the metadata for a file or folder. |
114
|
|
|
* |
115
|
|
|
* Note: Metadata for the root folder is unsupported. |
116
|
|
|
* |
117
|
|
|
* @link https://www.dropbox.com/developers/documentation/http/documentation#files-get_metadata |
118
|
|
|
*/ |
119
|
|
|
public function getMetadata(string $path): array |
120
|
|
|
{ |
121
|
|
|
$parameters = [ |
122
|
|
|
'path' => $this->normalizePath($path), |
123
|
|
|
]; |
124
|
|
|
|
125
|
|
|
return $this->rpcEndpointRequest('files/get_metadata', $parameters); |
126
|
|
|
} |
127
|
|
|
|
128
|
|
|
/** |
129
|
|
|
* Get a temporary link to stream content of a file. |
130
|
|
|
* |
131
|
|
|
* This link will expire in four hours and afterwards you will get 410 Gone. |
132
|
|
|
* Content-Type of the link is determined automatically by the file's mime type. |
133
|
|
|
* |
134
|
|
|
* @link https://www.dropbox.com/developers/documentation/http/documentation#files-get_temporary_link |
135
|
|
|
*/ |
136
|
|
|
public function getTemporaryLink(string $path): string |
137
|
|
|
{ |
138
|
|
|
$parameters = [ |
139
|
|
|
'path' => $this->normalizePath($path), |
140
|
|
|
]; |
141
|
|
|
|
142
|
|
|
$body = $this->rpcEndpointRequest('files/get_temporary_link', $parameters); |
143
|
|
|
|
144
|
|
|
return $body['link']; |
145
|
|
|
} |
146
|
|
|
|
147
|
|
|
/** |
148
|
|
|
* Get a thumbnail for an image. |
149
|
|
|
* |
150
|
|
|
* This method currently supports files with the following file extensions:jpg, jpeg, |
151
|
|
|
* png, tiff, tif, gif and bmp. |
152
|
|
|
* Photos that are larger than 20MB in size won't be converted to a thumbnail. |
153
|
|
|
* |
154
|
|
|
* @link https://www.dropbox.com/developers/documentation/http/documentation#files-get_thumbnail |
155
|
|
|
*/ |
156
|
|
|
public function getThumbnail(string $path, string $format = 'jpeg', string $size = 'w64h64'): string |
157
|
|
|
{ |
158
|
|
|
$arguments = [ |
159
|
|
|
'path' => $this->normalizePath($path), |
160
|
|
|
'format' => $format, |
161
|
|
|
'size' => $size |
162
|
|
|
]; |
163
|
|
|
|
164
|
|
|
$response = $this->contentEndpointRequest('files/get_thumbnail', $arguments); |
165
|
|
|
|
166
|
|
|
return (string)$response->getBody(); |
167
|
|
|
} |
168
|
|
|
|
169
|
|
|
/** |
170
|
|
|
* Starts returning the contents of a folder. |
171
|
|
|
* |
172
|
|
|
* If the result's ListFolderResult.has_more field is true, call |
173
|
|
|
* list_folder/continue with the returned ListFolderResult.cursor to retrieve more entries. |
174
|
|
|
* |
175
|
|
|
* Note: auth.RateLimitError may be returned if multiple list_folder or list_folder/continue calls |
176
|
|
|
* with same parameters are made simultaneously by same API app for same user. If your app implements |
177
|
|
|
* retry logic, please hold off the retry until the previous request finishes. |
178
|
|
|
* |
179
|
|
|
* @link https://www.dropbox.com/developers/documentation/http/documentation#files-list_folder |
180
|
|
|
*/ |
181
|
|
|
public function listFolder(string $path = '', bool $recursive = false): array |
182
|
|
|
{ |
183
|
|
|
$parameters = [ |
184
|
|
|
'path' => $this->normalizePath($path), |
185
|
|
|
'recursive' => $recursive, |
186
|
|
|
]; |
187
|
|
|
|
188
|
|
|
return $this->rpcEndpointRequest('files/list_folder', $parameters); |
189
|
|
|
} |
190
|
|
|
|
191
|
|
|
/** |
192
|
|
|
* Move a file or folder to a different location in the user's Dropbox. |
193
|
|
|
* |
194
|
|
|
* If the source path is a folder all its contents will be moved. |
195
|
|
|
* |
196
|
|
|
* @link https://www.dropbox.com/developers/documentation/http/documentation#files-move |
197
|
|
|
*/ |
198
|
|
|
public function move(string $path, string $newPath): array |
199
|
|
|
{ |
200
|
|
|
$parameters = [ |
201
|
|
|
'from_path' => $this->normalizePath($path), |
202
|
|
|
'to_path' => $this->normalizePath($newPath), |
203
|
|
|
]; |
204
|
|
|
|
205
|
|
|
return $this->rpcEndpointRequest('files/move', $parameters); |
206
|
|
|
} |
207
|
|
|
|
208
|
|
|
/** |
209
|
|
|
* Create a new file with the contents provided in the request. |
210
|
|
|
* |
211
|
|
|
* Do not use this to upload a file larger than 150 MB. Instead, create an upload session with upload_session/start. |
212
|
|
|
* |
213
|
|
|
* @link https://www.dropbox.com/developers/documentation/http/documentation#files-upload |
214
|
|
|
* |
215
|
|
|
* @param string $path |
216
|
|
|
* @param string $mode |
217
|
|
|
* @param string|resource $contents |
218
|
|
|
* |
219
|
|
|
* @return array |
220
|
|
|
*/ |
221
|
|
|
public function upload(string $path, string $mode, $contents): array |
222
|
|
|
{ |
223
|
|
|
$arguments = [ |
224
|
|
|
'path' => $this->normalizePath($path), |
225
|
|
|
'mode' => $mode, |
226
|
|
|
]; |
227
|
|
|
|
228
|
|
|
$response = $this->contentEndpointRequest('files/upload', $arguments, $contents); |
229
|
|
|
|
230
|
|
|
$metadata = json_decode($response->getBody(), true); |
231
|
|
|
|
232
|
|
|
$metadata['.tag'] = 'file'; |
233
|
|
|
|
234
|
|
|
return $metadata; |
235
|
|
|
} |
236
|
|
|
|
237
|
|
|
protected function normalizePath(string $path): string |
238
|
|
|
{ |
239
|
|
|
$path = trim($path, '/'); |
240
|
|
|
|
241
|
|
|
if ($path === '') { |
242
|
|
|
return ''; |
243
|
|
|
} |
244
|
|
|
|
245
|
|
|
return '/' . $path; |
246
|
|
|
} |
247
|
|
|
|
248
|
|
|
/** |
249
|
|
|
* @param string $endpoint |
250
|
|
|
* @param array $arguments |
251
|
|
|
* @param string|resource $body |
252
|
|
|
* |
253
|
|
|
* @return \Psr\Http\Message\ResponseInterface |
254
|
|
|
* |
255
|
|
|
* @throws \Spatie\Dropbox\Exceptions\BadRequest |
256
|
|
|
*/ |
257
|
|
|
protected function contentEndpointRequest(string $endpoint, array $arguments, $body = ''): ResponseInterface |
258
|
|
|
{ |
259
|
|
|
$headers['Dropbox-API-Arg'] = json_encode($arguments); |
260
|
|
|
|
261
|
|
|
if ($body !== '') { |
262
|
|
|
$headers['Content-Type'] = 'application/octet-stream'; |
263
|
|
|
} |
264
|
|
|
|
265
|
|
|
try { |
266
|
|
|
$response = $this->client->post("https://content.dropboxapi.com/2/{$endpoint}", [ |
267
|
|
|
'headers' => $headers, |
268
|
|
|
'body' => $body, |
269
|
|
|
]); |
270
|
|
|
|
271
|
|
|
} catch (ClientException $exception) { |
272
|
|
|
if (in_array($exception->getResponse()->getStatusCode(), [ |
273
|
|
|
static::HTTP_BAD_REQUEST, |
274
|
|
|
static::HTTP_CONFLICT, |
275
|
|
|
])) { |
276
|
|
|
throw new BadRequest($exception->getResponse()); |
277
|
|
|
} |
278
|
|
|
|
279
|
|
|
throw $exception; |
280
|
|
|
} |
281
|
|
|
|
282
|
|
|
return $response; |
283
|
|
|
} |
284
|
|
|
|
285
|
|
|
protected function rpcEndpointRequest(string $endpoint, array $parameters): array |
286
|
|
|
{ |
287
|
|
|
try { |
288
|
|
|
$response = $this->client->post("https://api.dropboxapi.com/2/{$endpoint}", [ |
289
|
|
|
'json' => $parameters |
290
|
|
|
]); |
291
|
|
|
} catch (ClientException $exception) { |
292
|
|
|
if (in_array($exception->getResponse()->getStatusCode(), [ |
293
|
|
|
static::HTTP_BAD_REQUEST, |
294
|
|
|
static::HTTP_CONFLICT, |
295
|
|
|
])) { |
296
|
|
|
throw new BadRequest($exception->getResponse()); |
297
|
|
|
} |
298
|
|
|
|
299
|
|
|
throw $exception; |
300
|
|
|
} |
301
|
|
|
|
302
|
|
|
return json_decode($response->getBody(), true); |
303
|
|
|
} |
304
|
|
|
} |
305
|
|
|
|