Completed
Pull Request — master (#153)
by
unknown
03:58
created

Dropbox::setAccessToken()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 6
ccs 0
cts 5
cp 0
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 1
crap 2
1
<?php
2
3
namespace Kunnu\Dropbox;
4
5
use Kunnu\Dropbox\Exceptions\DropboxClientUnableToOpenTempFileException;
6
use Kunnu\Dropbox\Exceptions\DropboxClientUnableToWriteToTempException;
7
use Kunnu\Dropbox\Models\DeletedMetadata;
8
use Kunnu\Dropbox\Models\File;
9
use Kunnu\Dropbox\Models\Account;
10
use Kunnu\Dropbox\Models\Thumbnail;
11
use Kunnu\Dropbox\Models\AccountList;
12
use Kunnu\Dropbox\Models\ModelFactory;
13
use Kunnu\Dropbox\Models\FileMetadata;
14
use Kunnu\Dropbox\Models\CopyReference;
15
use Kunnu\Dropbox\Models\FolderMetadata;
16
use Kunnu\Dropbox\Models\ModelCollection;
17
use Kunnu\Dropbox\Authentication\OAuth2Client;
18
use Kunnu\Dropbox\Store\PersistentDataStoreFactory;
19
use Kunnu\Dropbox\Authentication\DropboxAuthHelper;
20
use Kunnu\Dropbox\Exceptions\DropboxClientException;
21
use Kunnu\Dropbox\Security\RandomStringGeneratorFactory;
22
use Kunnu\Dropbox\Http\Clients\DropboxHttpClientFactory;
23
24
/**
25
 * Dropbox
26
 */
27
class Dropbox
28
{
29
    /**
30
     * Uploading a file with the 'uploadFile' method, with the file's
31
     * size less than this value (~8 MB), the simple `upload` method will be
32
     * used, if the file size exceed this value (~8 MB), the `startUploadSession`,
33
     * `appendUploadSession` & `finishUploadSession` methods will be used
34
     * to upload the file in chunks.
35
     *
36
     * @const int
37
     */
38
    const AUTO_CHUNKED_UPLOAD_THRESHOLD = 8000000;
39
40
    /**
41
     * The Chunk Size the file will be
42
     * split into and uploaded (~4 MB)
43
     *
44
     * @const int
45
     */
46
    const DEFAULT_CHUNK_SIZE = 4000000;
47
48
    /**
49
     * Response header containing file metadata
50
     *
51
     * @const string
52
     */
53
    const METADATA_HEADER = 'dropbox-api-result';
54
55
    /**
56
     * Prefix for writable temporary file
57
     *
58
     * @const string
59
     */
60
    const TMP_PREFIX = 'dropbox-temp-file';
61
62
    /**
63
     * The Dropbox App
64
     *
65
     * @var \Kunnu\Dropbox\DropboxApp
66
     */
67
    protected $app;
68
69
    /**
70
     * OAuth2 Access Token
71
     *
72
     * @var string
73
     */
74
    protected $accessToken;
75
76
    /**
77
     * Dropbox Client
78
     *
79
     * @var \Kunnu\Dropbox\DropboxClient
80
     */
81
    protected $client;
82
83
    /**
84
     * OAuth2 Client
85
     *
86
     * @var \Kunnu\Dropbox\Authentication\OAuth2Client
87
     */
88
    protected $oAuth2Client;
89
90
    /**
91
     * Random String Generator
92
     *
93
     * @var \Kunnu\Dropbox\Security\RandomStringGeneratorInterface
94
     */
95
    protected $randomStringGenerator;
96
97
    /**
98
     * Persistent Data Store
99
     *
100
     * @var \Kunnu\Dropbox\Store\PersistentDataStoreInterface
101
     */
102
    protected $persistentDataStore;
103
104
    /**
105
     * Create a new Dropbox instance
106
     *
107
     * @param \Kunnu\Dropbox\DropboxApp
108
     * @param array $config Configuration Array
109
     */
110
    public function __construct(DropboxApp $app, array $config = [])
111
    {
112
        //Configuration
113
        $config = array_merge([
114
            'http_client_handler' => null,
115
            'random_string_generator' => null,
116
            'persistent_data_store' => null
117
        ], $config);
118
119
        //Set the app
120
        $this->app = $app;
121
122
        //Set the access token
123
        $this->setAccessToken($app->getAccessToken());
124
125
        //Make the HTTP Client
126
        $httpClient = DropboxHttpClientFactory::make($config['http_client_handler']);
127
128
        //Make and Set the DropboxClient
129
        $this->client = new DropboxClient($httpClient);
130
131
        //Make and Set the Random String Generator
132
        $this->randomStringGenerator = RandomStringGeneratorFactory::makeRandomStringGenerator($config['random_string_generator']);
133
134
        //Make and Set the Persistent Data Store
135
        $this->persistentDataStore = PersistentDataStoreFactory::makePersistentDataStore($config['persistent_data_store']);
136
    }
137
138
    /**
139
     * Get Dropbox Auth Helper
140
     *
141
     * @return \Kunnu\Dropbox\Authentication\DropboxAuthHelper
142
     */
143
    public function getAuthHelper()
144
    {
145
        return new DropboxAuthHelper(
146
            $this->getOAuth2Client(),
147
            $this->getRandomStringGenerator(),
148
            $this->getPersistentDataStore()
149
        );
150
    }
151
152
    /**
153
     * Get OAuth2Client
154
     *
155
     * @return \Kunnu\Dropbox\Authentication\OAuth2Client
156
     */
157
    public function getOAuth2Client()
158
    {
159
        if (!$this->oAuth2Client instanceof OAuth2Client) {
160
            return new OAuth2Client(
161
                $this->getApp(),
162
                $this->getClient(),
163
                $this->getRandomStringGenerator()
164
            );
165
        }
166
167
        return $this->oAuth2Client;
168
    }
169
170
    /**
171
     * Get the Dropbox App.
172
     *
173
     * @return \Kunnu\Dropbox\DropboxApp Dropbox App
174
     */
175
    public function getApp()
176
    {
177
        return $this->app;
178
    }
179
180
    /**
181
     * Get the Client
182
     *
183
     * @return \Kunnu\Dropbox\DropboxClient
184
     */
185
    public function getClient()
186
    {
187
        return $this->client;
188
    }
189
190
    /**
191
     * Get the Random String Generator
192
     *
193
     * @return \Kunnu\Dropbox\Security\RandomStringGeneratorInterface
194
     */
195
    public function getRandomStringGenerator()
196
    {
197
        return $this->randomStringGenerator;
198
    }
199
200
    /**
201
     * Get Persistent Data Store
202
     *
203
     * @return \Kunnu\Dropbox\Store\PersistentDataStoreInterface
204
     */
205
    public function getPersistentDataStore()
206
    {
207
        return $this->persistentDataStore;
208
    }
209
210
    /**
211
     * Get the Metadata for a file or folder
212
     *
213
     * @param  string $path   Path of the file or folder
214
     * @param  array  $params Additional Params
215
     *
216
     * @return \Kunnu\Dropbox\Models\FileMetadata | \Kunnu\Dropbox\Models\FolderMetadata
217
     * @throws \Kunnu\Dropbox\Exceptions\DropboxClientException
218
     *
219
     * @link https://www.dropbox.com/developers/documentation/http/documentation#files-get_metadata
220
     *
221
     */
222
    public function getMetadata($path, array $params = [])
223
    {
224
        //Root folder is unsupported
225
        if ($path === '/') {
226
            throw new DropboxClientException("Metadata for the root folder is unsupported.");
227
        }
228
229
        //Set the path
230
        $params['path'] = $path;
231
232
        //Get File Metadata
233
        $response = $this->postToAPI('/files/get_metadata', $params);
234
235
        //Make and Return the Model
236
        return $this->makeModelFromResponse($response);
237
    }
238
239
    /**
240
     * Make a HTTP POST Request to the API endpoint type
241
     *
242
     * @param  string $endpoint    API Endpoint to send Request to
243
     * @param  array  $params      Request Query Params
244
     * @param  string $accessToken Access Token to send with the Request
245
     *
246
     * @return \Kunnu\Dropbox\DropboxResponse
247
     */
248
    public function postToAPI($endpoint, array $params = [], $accessToken = null)
249
    {
250
        return $this->sendRequest("POST", $endpoint, 'api', $params, $accessToken);
251
    }
252
253
    /**
254
     * Make Request to the API
255
     *
256
     * @param  string      $method       HTTP Request Method
257
     * @param  string      $endpoint     API Endpoint to send Request to
258
     * @param  string      $endpointType Endpoint type ['api'|'content']
259
     * @param  array       $params       Request Query Params
260
     * @param  string      $accessToken  Access Token to send with the Request
261
     * @param  DropboxFile $responseFile Save response to the file
262
     *
263
     * @return \Kunnu\Dropbox\DropboxResponse
264
     *
265
     * @throws \Kunnu\Dropbox\Exceptions\DropboxClientException
266
     */
267
    public function sendRequest($method, $endpoint, $endpointType = 'api', array $params = [], $accessToken = null, DropboxFile $responseFile = null)
268
    {
269
        //Access Token
270
        $accessToken = $this->getAccessToken() ? $this->getAccessToken() : $accessToken;
271
272
        //Make a DropboxRequest object
273
        $request = new DropboxRequest($method, $endpoint, $accessToken, $endpointType, $params);
274
275
        //Make a DropboxResponse object if a response should be saved to the file
276
        $response = $responseFile ? new DropboxResponseToFile($request, $responseFile) : null;
277
278
        //Send Request through the DropboxClient
279
        //Fetch and return the Response
280
        return $this->getClient()->sendRequest($request, $response);
281
    }
282
283
    /**
284
     * Get the Access Token.
285
     *
286
     * @return string Access Token
287
     */
288
    public function getAccessToken()
289
    {
290
        return $this->accessToken;
291
    }
292
293
    /**
294
     * Set the Access Token.
295
     *
296
     * @param string $accessToken Access Token
297
     *
298
     * @return \Kunnu\Dropbox\Dropbox Dropbox Client
299
     */
300
    public function setAccessToken($accessToken)
301
    {
302
        $this->accessToken = $accessToken;
303
304
        return $this;
305
    }
306
307
    /**
308
     * Make Model from DropboxResponse
309
     *
310
     * @param  DropboxResponse $response
311
     *
312
     * @return \Kunnu\Dropbox\Models\ModelInterface
313
     *
314
     * @throws \Kunnu\Dropbox\Exceptions\DropboxClientException
315
     */
316
    public function makeModelFromResponse(DropboxResponse $response)
317
    {
318
        //Get the Decoded Body
319
        $body = $response->getDecodedBody();
320
321
        if (is_null($body)) {
322
            $body = [];
323
        }
324
325
        //Make and Return the Model
326
        return ModelFactory::make($body);
327
    }
328
329
    /**
330
     * Get the contents of a Folder
331
     *
332
     * @param  string $path   Path to the folder. Defaults to root.
333
     * @param  array  $params Additional Params
334
     *
335
     * @link https://www.dropbox.com/developers/documentation/http/documentation#files-list_folder
336
     *
337
     * @return \Kunnu\Dropbox\Models\MetadataCollection
338
     */
339 View Code Duplication
    public function listFolder($path = null, array $params = [])
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
340
    {
341
        //Specify the root folder as an
342
        //empty string rather than as "/"
343
        if ($path === '/') {
344
            $path = "";
345
        }
346
347
        //Set the path
348
        $params['path'] = $path;
349
350
        //Get File Metadata
351
        $response = $this->postToAPI('/files/list_folder', $params);
352
353
        //Make and Return the Model
354
        return $this->makeModelFromResponse($response);
355
    }
356
357
    /**
358
     * Paginate through all files and retrieve updates to the folder,
359
     * using the cursor retrieved from listFolder or listFolderContinue
360
     *
361
     * @param  string $cursor The cursor returned by your
362
     *                        last call to listFolder or listFolderContinue
363
     *
364
     * @link https://www.dropbox.com/developers/documentation/http/documentation#files-list_folder-continue
365
     *
366
     * @return \Kunnu\Dropbox\Models\MetadataCollection
367
     */
368
    public function listFolderContinue($cursor)
369
    {
370
        $response = $this->postToAPI('/files/list_folder/continue', ['cursor' => $cursor]);
371
372
        //Make and Return the Model
373
        return $this->makeModelFromResponse($response);
374
    }
375
376
    /**
377
     * Get a cursor for the folder's state.
378
     *
379
     * @param  string $path   Path to the folder. Defaults to root.
380
     * @param  array  $params Additional Params
381
     *
382
     * @return string The Cursor for the folder's state
383
     *
384
     * @throws \Kunnu\Dropbox\Exceptions\DropboxClientException
385
     *
386
     * @link https://www.dropbox.com/developers/documentation/http/documentation#files-list_folder-get_latest_cursor
387
     *
388
     */
389
    public function listFolderLatestCursor($path, array $params = [])
390
    {
391
        //Specify the root folder as an
392
        //empty string rather than as "/"
393
        if ($path === '/') {
394
            $path = "";
395
        }
396
397
        //Set the path
398
        $params['path'] = $path;
399
400
        //Fetch the cursor
401
        $response = $this->postToAPI('/files/list_folder/get_latest_cursor', $params);
402
403
        //Retrieve the cursor
404
        $body = $response->getDecodedBody();
405
        $cursor = isset($body['cursor']) ? $body['cursor'] : false;
406
407
        //No cursor returned
408
        if (!$cursor) {
409
            throw new DropboxClientException("Could not retrieve cursor. Something went wrong.");
410
        }
411
412
        //Return the cursor
413
        return $cursor;
414
    }
415
416
    /**
417
     * Get Revisions of a File
418
     *
419
     * @param  string $path   Path to the file
420
     * @param  array  $params Additional Params
421
     *
422
     * @link https://www.dropbox.com/developers/documentation/http/documentation#files-list_revisions
423
     *
424
     * @return \Kunnu\Dropbox\Models\ModelCollection
425
     */
426
    public function listRevisions($path, array $params = [])
427
    {
428
        //Set the Path
429
        $params['path'] = $path;
430
431
        //Fetch the Revisions
432
        $response = $this->postToAPI('/files/list_revisions', $params);
433
434
        //The file metadata of the entries, returned by this
435
        //endpoint doesn't include a '.tag' attribute, which
436
        //is used by the ModelFactory to resolve the correct
437
        //model. But since we know that revisions returned
438
        //are file metadata objects, we can explicitly cast
439
        //them as \Kunnu\Dropbox\Models\FileMetadata manually.
440
        $body = $response->getDecodedBody();
441
        $entries = isset($body['entries']) ? $body['entries'] : [];
442
        $processedEntries = [];
443
444
        foreach ($entries as $entry) {
445
            $processedEntries[] = new FileMetadata($entry);
446
        }
447
448
        return new ModelCollection($processedEntries);
449
    }
450
451
    /**
452
     * Search a folder for files/folders
453
     *
454
     * @param  string $path   Path to search
455
     * @param  string $query  Search Query
456
     * @param  array  $params Additional Params
457
     *
458
     * @link https://www.dropbox.com/developers/documentation/http/documentation#files-search
459
     *
460
     * @return \Kunnu\Dropbox\Models\SearchResults
461
     */
462 View Code Duplication
    public function search($path, $query, array $params = [])
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
463
    {
464
        //Specify the root folder as an
465
        //empty string rather than as "/"
466
        if ($path === '/') {
467
            $path = "";
468
        }
469
470
        //Set the path and query
471
        $params['path'] = $path;
472
        $params['query'] = $query;
473
474
        //Fetch Search Results
475
        $response = $this->postToAPI('/files/search', $params);
476
477
        //Make and Return the Model
478
        return $this->makeModelFromResponse($response);
479
    }
480
481
    /**
482
     * Create a folder at the given path
483
     *
484
     * @param  string  $path       Path to create
485
     * @param  boolean $autorename Auto Rename File
486
     *
487
     * @return \Kunnu\Dropbox\Models\FolderMetadata
488
     *
489
     * @throws \Kunnu\Dropbox\Exceptions\DropboxClientException
490
     *
491
     * @link https://www.dropbox.com/developers/documentation/http/documentation#files-create_folder
492
     *
493
     */
494 View Code Duplication
    public function createFolder($path, $autorename = false)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
495
    {
496
        //Path cannot be null
497
        if (is_null($path)) {
498
            throw new DropboxClientException("Path cannot be null.");
499
        }
500
501
        //Create Folder
502
        $response = $this->postToAPI('/files/create_folder', ['path' => $path, 'autorename' => $autorename]);
503
504
        //Fetch the Metadata
505
        $body = $response->getDecodedBody();
506
507
        //Make and Return the Model
508
        return new FolderMetadata($body);
509
    }
510
511
    /**
512
     * Delete a file or folder at the given path
513
     *
514
     * @param  string $path Path to file/folder to delete
515
     *
516
     * @return \Kunnu\Dropbox\Models\DeletedMetadata
517
     *
518
     * @throws \Kunnu\Dropbox\Exceptions\DropboxClientException
519
     *
520
     * @link https://www.dropbox.com/developers/documentation/http/documentation#files-delete
521
     *
522
     */
523 View Code Duplication
    public function delete($path)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
524
    {
525
        //Path cannot be null
526
        if (is_null($path)) {
527
            throw new DropboxClientException("Path cannot be null.");
528
        }
529
530
        //Delete
531
        $response = $this->postToAPI('/files/delete_v2', ['path' => $path]);
532
        $body = $response->getDecodedBody();
533
534
        //Response doesn't have Metadata
535
        if (!isset($body['metadata']) || !is_array($body['metadata'])) {
536
            throw new DropboxClientException("Invalid Response.");
537
        }
538
539
        return new DeletedMetadata($body['metadata']);
540
    }
541
542
    /**
543
     * Move a file or folder to a different location
544
     *
545
     * @param  string $fromPath Path to be moved
546
     * @param  string $toPath   Path to be moved to
547
     *
548
     * @return \Kunnu\Dropbox\Models\DeletedMetadata|\Kunnu\Dropbox\Models\FileMetadata
549
     *
550
     * @throws \Kunnu\Dropbox\Exceptions\DropboxClientException
551
     *
552
     * @link https://www.dropbox.com/developers/documentation/http/documentation#files-move
553
     *
554
     */
555 View Code Duplication
    public function move($fromPath, $toPath)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
556
    {
557
        //From and To paths cannot be null
558
        if (is_null($fromPath) || is_null($toPath)) {
559
            throw new DropboxClientException("From and To paths cannot be null.");
560
        }
561
562
        //Response
563
        $response = $this->postToAPI('/files/move', ['from_path' => $fromPath, 'to_path' => $toPath]);
564
565
        //Make and Return the Model
566
        return $this->makeModelFromResponse($response);
567
    }
568
569
    /**
570
     * Copy a file or folder to a different location
571
     *
572
     * @param  string $fromPath Path to be copied
573
     * @param  string $toPath   Path to be copied to
574
     *
575
     * @return \Kunnu\Dropbox\Models\DeletedMetadata|\Kunnu\Dropbox\Models\FileMetadata
576
     *
577
     * @throws \Kunnu\Dropbox\Exceptions\DropboxClientException
578
     *
579
     * @link https://www.dropbox.com/developers/documentation/http/documentation#files-copy
580
     *
581
     */
582 View Code Duplication
    public function copy($fromPath, $toPath)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
583
    {
584
        //From and To paths cannot be null
585
        if (is_null($fromPath) || is_null($toPath)) {
586
            throw new DropboxClientException("From and To paths cannot be null.");
587
        }
588
589
        //Response
590
        $response = $this->postToAPI('/files/copy', ['from_path' => $fromPath, 'to_path' => $toPath]);
591
592
        //Make and Return the Model
593
        return $this->makeModelFromResponse($response);
594
    }
595
596
    /**
597
     * Restore a file to the specific version
598
     *
599
     * @param  string $path Path to the file to restore
600
     * @param  string $rev  Revision to store for the file
601
     *
602
     * @return \Kunnu\Dropbox\Models\DeletedMetadata|\Kunnu\Dropbox\Models\FileMetadata|\Kunnu\Dropbox\Models\FolderMetadata
603
     *
604
     * @throws \Kunnu\Dropbox\Exceptions\DropboxClientException
605
     *
606
     * @link https://www.dropbox.com/developers/documentation/http/documentation#files-restore
607
     *
608
     */
609 View Code Duplication
    public function restore($path, $rev)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
610
    {
611
        //Path and Revision cannot be null
612
        if (is_null($path) || is_null($rev)) {
613
            throw new DropboxClientException("Path and Revision cannot be null.");
614
        }
615
616
        //Response
617
        $response = $this->postToAPI('/files/restore', ['path' => $path, 'rev' => $rev]);
618
619
        //Fetch the Metadata
620
        $body = $response->getDecodedBody();
621
622
        //Make and Return the Model
623
        return new FileMetadata($body);
624
    }
625
626
    /**
627
     * Get Copy Reference
628
     *
629
     * @param  string $path Path to the file or folder to get a copy reference to
630
     *
631
     * @return \Kunnu\Dropbox\Models\CopyReference
632
     *
633
     * @throws \Kunnu\Dropbox\Exceptions\DropboxClientException
634
     *
635
     * @link https://www.dropbox.com/developers/documentation/http/documentation#files-copy_reference-get
636
     *
637
     */
638 View Code Duplication
    public function getCopyReference($path)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
639
    {
640
        //Path cannot be null
641
        if (is_null($path)) {
642
            throw new DropboxClientException("Path cannot be null.");
643
        }
644
645
        //Get Copy Reference
646
        $response = $this->postToAPI('/files/copy_reference/get', ['path' => $path]);
647
        $body = $response->getDecodedBody();
648
649
        //Make and Return the Model
650
        return new CopyReference($body);
651
    }
652
653
    /**
654
     * Save Copy Reference
655
     *
656
     * @param  string $path          Path to the file or folder to get a copy reference to
657
     * @param  string $copyReference Copy reference returned by getCopyReference
658
     *
659
     * @return \Kunnu\Dropbox\Models\FileMetadata|\Kunnu\Dropbox\Models\FolderMetadata
660
     *
661
     * @throws \Kunnu\Dropbox\Exceptions\DropboxClientException
662
     *
663
     * @link https://www.dropbox.com/developers/documentation/http/documentation#files-copy_reference-save
664
     *
665
     */
666
    public function saveCopyReference($path, $copyReference)
667
    {
668
        //Path and Copy Reference cannot be null
669
        if (is_null($path) || is_null($copyReference)) {
670
            throw new DropboxClientException("Path and Copy Reference cannot be null.");
671
        }
672
673
        //Save Copy Reference
674
        $response = $this->postToAPI('/files/copy_reference/save', ['path' => $path, 'copy_reference' => $copyReference]);
675
        $body = $response->getDecodedBody();
676
677
        //Response doesn't have Metadata
678
        if (!isset($body['metadata']) || !is_array($body['metadata'])) {
679
            throw new DropboxClientException("Invalid Response.");
680
        }
681
682
        //Make and return the Model
683
        return ModelFactory::make($body['metadata']);
684
    }
685
686
    /**
687
     * Get a temporary link to stream contents of a file
688
     *
689
     * @param  string $path Path to the file you want a temporary link to
690
     *
691
     * https://www.dropbox.com/developers/documentation/http/documentation#files-get_temporary_link
692
     *
693
     * @return \Kunnu\Dropbox\Models\TemporaryLink
694
     *
695
     * @throws \Kunnu\Dropbox\Exceptions\DropboxClientException
696
     */
697 View Code Duplication
    public function getTemporaryLink($path)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
698
    {
699
        //Path cannot be null
700
        if (is_null($path)) {
701
            throw new DropboxClientException("Path cannot be null.");
702
        }
703
704
        //Get Temporary Link
705
        $response = $this->postToAPI('/files/get_temporary_link', ['path' => $path]);
706
707
        //Make and Return the Model
708
        return $this->makeModelFromResponse($response);
709
    }
710
711
    /**
712
     * Save a specified URL into a file in user's Dropbox
713
     *
714
     * @param  string $path Path where the URL will be saved
715
     * @param  string $url  URL to be saved
716
     *
717
     * @return string Async Job ID
718
     *
719
     * @throws \Kunnu\Dropbox\Exceptions\DropboxClientException
720
     *
721
     * @link https://www.dropbox.com/developers/documentation/http/documentation#files-save_url
722
     *
723
     */
724 View Code Duplication
    public function saveUrl($path, $url)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
725
    {
726
        //Path and URL cannot be null
727
        if (is_null($path) || is_null($url)) {
728
            throw new DropboxClientException("Path and URL cannot be null.");
729
        }
730
731
        //Save URL
732
        $response = $this->postToAPI('/files/save_url', ['path' => $path, 'url' => $url]);
733
        $body = $response->getDecodedBody();
734
735
        if (!isset($body['async_job_id'])) {
736
            throw new DropboxClientException("Could not retrieve Async Job ID.");
737
        }
738
739
        //Return the Async Job ID
740
        return $body['async_job_id'];
741
    }
742
743
    /**
744
     * Save a specified URL into a file in user's Dropbox
745
     *
746
     * @param $asyncJobId
747
     *
748
     * @return \Kunnu\Dropbox\Models\FileMetadata|string Status (failed|in_progress) or FileMetadata (if complete)
749
     *
750
     * @throws \Kunnu\Dropbox\Exceptions\DropboxClientException
751
     *
752
     * @link     https://www.dropbox.com/developers/documentation/http/documentation#files-save_url-check_job_status
753
     *
754
     */
755
    public function checkJobStatus($asyncJobId)
756
    {
757
        //Async Job ID cannot be null
758
        if (is_null($asyncJobId)) {
759
            throw new DropboxClientException("Async Job ID cannot be null.");
760
        }
761
762
        //Get Job Status
763
        $response = $this->postToAPI('/files/save_url/check_job_status', ['async_job_id' => $asyncJobId]);
764
        $body = $response->getDecodedBody();
765
766
        //Status
767
        $status = isset($body['.tag']) ? $body['.tag'] : '';
768
769
        //If status is complete
770
        if ($status === 'complete') {
771
            return new FileMetadata($body);
772
        }
773
774
        //Return the status
775
        return $status;
776
    }
777
778
    /**
779
     * Upload a File to Dropbox
780
     *
781
     * @param  string|DropboxFile $dropboxFile DropboxFile object or Path to file
782
     * @param  string             $path        Path to upload the file to
783
     * @param  array              $params      Additional Params
784
     *
785
     * @link https://www.dropbox.com/developers/documentation/http/documentation#files-upload
786
     *
787
     * @return \Kunnu\Dropbox\Models\FileMetadata
788
     */
789
    public function upload($dropboxFile, $path, array $params = [])
790
    {
791
        //Make Dropbox File
792
        $dropboxFile = $this->makeDropboxFile($dropboxFile);
793
794
        //If the file is larger than the Chunked Upload Threshold
795
        if ($dropboxFile->getSize() > static::AUTO_CHUNKED_UPLOAD_THRESHOLD) {
796
            //Upload the file in sessions/chunks
797
            return $this->uploadChunked($dropboxFile, $path, null, null, $params);
798
        }
799
800
        //Simple file upload
801
        return $this->simpleUpload($dropboxFile, $path, $params);
802
    }
803
804
805
    /**
806
     * Make DropboxFile Object using the given $data string as the file contents.
807
     * @param $path
808
     * @param $data
809
     * @return DropboxFile
810
     * @throws DropboxClientException
811
     * @throws DropboxClientUnableToWriteToTempException
812
     */
813
    public function makeDropboxFileFromString($path, $data) {
814
        //create a temp file with a prefix
815
        $tmpfname = tempnam(sys_get_temp_dir(), static::TMP_PREFIX);
816
817
        if (!is_writable($tmpfname))
818
        { // Test if the file is writable
819
            throw new DropboxClientUnableToWriteToTempException("Cannot write to {$tmpfname}");
820
        }
821
822
        $handle = fopen( $tmpfname, DropboxFile::MODE_WRITE);
823
824
        if (!is_resource($handle))
825
        { // Test if PHP could open the file
826
            throw new DropboxClientUnableToOpenTempFileException("Could not open {$tmpfname} on writing mode.");
827
        }
828
829
        fwrite($handle, $data);
830
831
        return DropboxFile::createByStream($path, $handle, DropboxFile::MODE_WRITE);
832
    }
833
834
    /**
835
     * Make DropboxFile Object
836
     *
837
     * @param  string|DropboxFile $dropboxFile DropboxFile object or Path to file
838
     * @param  int                $maxLength   Max Bytes to read from the file
839
     * @param  int                $offset      Seek to specified offset before reading
840
     * @param  string             $mode        The type of access
841
     *
842
     * @return \Kunnu\Dropbox\DropboxFile
843
     */
844
    public function makeDropboxFile($dropboxFile, $maxLength = null, $offset = null, $mode = DropboxFile::MODE_READ)
845
    {
846
        //Uploading file by file path
847
        if (!$dropboxFile instanceof DropboxFile) {
848
            //Create a DropboxFile Object
849
            $dropboxFile = new DropboxFile($dropboxFile, $mode);
850
        } elseif ($mode !== $dropboxFile->getMode()) {
851
            //Reopen the file with expected mode
852
            $dropboxFile->close();
853
            $dropboxFile = new DropboxFile($dropboxFile->getFilePath(), $mode);
854
        }
855
856
        if (!is_null($offset)) {
857
            $dropboxFile->setOffset($offset);
858
        }
859
860
        if (!is_null($maxLength)) {
861
            $dropboxFile->setMaxLength($maxLength);
862
        }
863
864
        //Return the DropboxFile Object
865
        return $dropboxFile;
866
    }
867
868
    /**
869
     * Upload file in sessions/chunks
870
     *
871
     * @param  string|DropboxFile $dropboxFile DropboxFile object or Path to file
872
     * @param  string             $path        Path to save the file to, on Dropbox
873
     * @param  int                $fileSize    The size of the file
874
     * @param  int                $chunkSize   The amount of data to upload in each chunk
875
     * @param  array              $params      Additional Params
876
     *
877
     * @link https://www.dropbox.com/developers/documentation/http/documentation#files-upload_session-start
878
     * @link https://www.dropbox.com/developers/documentation/http/documentation#files-upload_session-finish
879
     * @link https://www.dropbox.com/developers/documentation/http/documentation#files-upload_session-append_v2
880
     *
881
     * @return \Kunnu\Dropbox\Models\FileMetadata
882
     */
883
    public function uploadChunked($dropboxFile, $path, $fileSize = null, $chunkSize = null, array $params = array())
884
    {
885
        //Make Dropbox File
886
        $dropboxFile = $this->makeDropboxFile($dropboxFile);
887
888
        //No file size specified explicitly
889
        if (is_null($fileSize)) {
890
            $fileSize = $dropboxFile->getSize();
891
        }
892
893
        //No chunk size specified, use default size
894
        if (is_null($chunkSize)) {
895
            $chunkSize = static::DEFAULT_CHUNK_SIZE;
896
        }
897
898
        //If the fileSize is smaller
899
        //than the chunk size, we'll
900
        //make the chunk size relatively
901
        //smaller than the file size
902
        if ($fileSize <= $chunkSize) {
903
            $chunkSize = intval($fileSize / 2);
904
        }
905
906
        //Start the Upload Session with the file path
907
        //since the DropboxFile object will be created
908
        //again using the new chunk size.
909
        $sessionId = $this->startUploadSession($dropboxFile->getFilePath(), $chunkSize);
910
911
        //Uploaded
912
        $uploaded = $chunkSize;
913
914
        //Remaining
915
        $remaining = $fileSize - $chunkSize;
916
917
        //While the remaining bytes are
918
        //more than the chunk size, append
919
        //the chunk to the upload session.
920
        while ($remaining > $chunkSize) {
921
            //Append the next chunk to the Upload session
922
            $sessionId = $this->appendUploadSession($dropboxFile, $sessionId, $uploaded, $chunkSize);
923
924
            //Update remaining and uploaded
925
            $uploaded = $uploaded + $chunkSize;
926
            $remaining = $remaining - $chunkSize;
927
        }
928
929
        //Finish the Upload Session and return the Uploaded File Metadata
930
        return $this->finishUploadSession($dropboxFile, $sessionId, $uploaded, $remaining, $path, $params);
931
    }
932
933
    /**
934
     * Start an Upload Session
935
     *
936
     * @param  string|DropboxFile $dropboxFile DropboxFile object or Path to file
937
     * @param  int                $chunkSize   Size of file chunk to upload
938
     * @param  boolean            $close       Closes the session for "appendUploadSession"
939
     *
940
     * @return string Unique identifier for the upload session
941
     *
942
     * @throws \Kunnu\Dropbox\Exceptions\DropboxClientException
943
     *
944
     * @link https://www.dropbox.com/developers/documentation/http/documentation#files-upload_session-start
945
     *
946
     */
947
    public function startUploadSession($dropboxFile, $chunkSize = -1, $close = false)
948
    {
949
        //Make Dropbox File with the given chunk size
950
        $dropboxFile = $this->makeDropboxFile($dropboxFile, $chunkSize);
951
952
        //Set the close param
953
        $params = [
954
            'close' => $close ? true : false,
955
            'file' => $dropboxFile
956
        ];
957
958
        //Upload File
959
        $file = $this->postToContent('/files/upload_session/start', $params);
960
        $body = $file->getDecodedBody();
961
962
        //Cannot retrieve Session ID
963
        if (!isset($body['session_id'])) {
964
            throw new DropboxClientException("Could not retrieve Session ID.");
965
        }
966
967
        //Return the Session ID
968
        return $body['session_id'];
969
    }
970
971
    /**
972
     * Make a HTTP POST Request to the Content endpoint type
973
     *
974
     * @param  string      $endpoint     Content Endpoint to send Request to
975
     * @param  array       $params       Request Query Params
976
     * @param  string      $accessToken  Access Token to send with the Request
977
     * @param  DropboxFile $responseFile Save response to the file
978
     *
979
     * @return \Kunnu\Dropbox\DropboxResponse
980
     */
981
    public function postToContent($endpoint, array $params = [], $accessToken = null, DropboxFile $responseFile = null)
982
    {
983
        return $this->sendRequest("POST", $endpoint, 'content', $params, $accessToken, $responseFile);
984
    }
985
986
    /**
987
     * Append more data to an Upload Session
988
     *
989
     * @param  string|DropboxFile $dropboxFile DropboxFile object or Path to file
990
     * @param  string             $sessionId   Session ID returned by `startUploadSession`
991
     * @param  int                $offset      The amount of data that has been uploaded so far
992
     * @param  int                $chunkSize   The amount of data to upload
993
     * @param  boolean            $close       Closes the session for futher "appendUploadSession" calls
994
     *
995
     * @return string Unique identifier for the upload session
996
     *
997
     * @throws \Kunnu\Dropbox\Exceptions\DropboxClientException
998
     *
999
     * @link https://www.dropbox.com/developers/documentation/http/documentation#files-upload_session-append_v2
1000
     *
1001
     */
1002
    public function appendUploadSession($dropboxFile, $sessionId, $offset, $chunkSize, $close = false)
1003
    {
1004
        //Make Dropbox File
1005
        $dropboxFile = $this->makeDropboxFile($dropboxFile, $chunkSize, $offset);
1006
1007
        //Session ID, offset, chunkSize and path cannot be null
1008 View Code Duplication
        if (is_null($sessionId) || is_null($offset) || is_null($chunkSize)) {
1009
            throw new DropboxClientException("Session ID, offset and chunk size cannot be null");
1010
        }
1011
1012
        $params = [];
1013
1014
        //Set the File
1015
        $params['file'] = $dropboxFile;
1016
1017
        //Set the Cursor: Session ID and Offset
1018
        $params['cursor'] = ['session_id' => $sessionId, 'offset' => $offset];
1019
1020
        //Set the close param
1021
        $params['close'] = $close ? true : false;
1022
1023
        //Since this endpoint doesn't have
1024
        //any return values, we'll disable the
1025
        //response validation for this request.
1026
        $params['validateResponse'] = false;
1027
1028
        //Upload File
1029
        $this->postToContent('/files/upload_session/append_v2', $params);
1030
1031
        //Make and Return the Model
1032
        return $sessionId;
1033
    }
1034
1035
    /**
1036
     * Finish an upload session and save the uploaded data to the given file path
1037
     *
1038
     * @param  string|DropboxFile $dropboxFile DropboxFile object or Path to file
1039
     * @param  string             $sessionId   Session ID returned by `startUploadSession`
1040
     * @param  int                $offset      The amount of data that has been uploaded so far
1041
     * @param  int                $remaining   The amount of data that is remaining
1042
     * @param  string             $path        Path to save the file to, on Dropbox
1043
     * @param  array              $params      Additional Params
1044
     *
1045
     * @return \Kunnu\Dropbox\Models\FileMetadata
1046
     *
1047
     * @throws \Kunnu\Dropbox\Exceptions\DropboxClientException
1048
     *
1049
     * @link https://www.dropbox.com/developers/documentation/http/documentation#files-upload_session-finish
1050
     *
1051
     */
1052
    public function finishUploadSession($dropboxFile, $sessionId, $offset, $remaining, $path, array $params = [])
1053
    {
1054
        //Make Dropbox File
1055
        $dropboxFile = $this->makeDropboxFile($dropboxFile, $remaining, $offset);
1056
1057
        //Session ID, offset, remaining and path cannot be null
1058 View Code Duplication
        if (is_null($sessionId) || is_null($path) || is_null($offset) || is_null($remaining)) {
1059
            throw new DropboxClientException("Session ID, offset, remaining and path cannot be null");
1060
        }
1061
1062
        $queryParams = [];
1063
1064
        //Set the File
1065
        $queryParams['file'] = $dropboxFile;
1066
1067
        //Set the Cursor: Session ID and Offset
1068
        $queryParams['cursor'] = ['session_id' => $sessionId, 'offset' => $offset];
1069
1070
        //Set the path
1071
        $params['path'] = $path;
1072
        //Set the Commit
1073
        $queryParams['commit'] = $params;
1074
1075
        //Upload File
1076
        $file = $this->postToContent('/files/upload_session/finish', $queryParams);
1077
        $body = $file->getDecodedBody();
1078
1079
        //Make and Return the Model
1080
        return new FileMetadata($body);
1081
    }
1082
1083
    /**
1084
     * Upload a File to Dropbox in a single request
1085
     *
1086
     * @param  string|DropboxFile $dropboxFile DropboxFile object or Path to file
1087
     * @param  string             $path        Path to upload the file to
1088
     * @param  array              $params      Additional Params
1089
     *
1090
     * @link https://www.dropbox.com/developers/documentation/http/documentation#files-upload
1091
     *
1092
     * @return \Kunnu\Dropbox\Models\FileMetadata
1093
     */
1094
    public function simpleUpload($dropboxFile, $path, array $params = [])
1095
    {
1096
        //Make Dropbox File
1097
        $dropboxFile = $this->makeDropboxFile($dropboxFile);
1098
1099
        //Set the path and file
1100
        $params['path'] = $path;
1101
        $params['file'] = $dropboxFile;
1102
1103
        //Upload File
1104
        $file = $this->postToContent('/files/upload', $params);
1105
        $body = $file->getDecodedBody();
1106
1107
        //Make and Return the Model
1108
        return new FileMetadata($body);
1109
    }
1110
1111
    /**
1112
     * Get a thumbnail for an image
1113
     *
1114
     * @param  string $path   Path to the file you want a thumbnail to
1115
     * @param  string $size   Size for the thumbnail image ['thumb','small','medium','large','huge']
1116
     * @param  string $format Format for the thumbnail image ['jpeg'|'png']
1117
     *
1118
     * @return \Kunnu\Dropbox\Models\Thumbnail
1119
     *
1120
     * @throws \Kunnu\Dropbox\Exceptions\DropboxClientException
1121
     *
1122
     * @link https://www.dropbox.com/developers/documentation/http/documentation#files-get_thumbnail
1123
     *
1124
     */
1125
    public function getThumbnail($path, $size = 'small', $format = 'jpeg')
1126
    {
1127
        //Path cannot be null
1128
        if (is_null($path)) {
1129
            throw new DropboxClientException("Path cannot be null.");
1130
        }
1131
1132
        //Invalid Format
1133
        if (!in_array($format, ['jpeg', 'png'])) {
1134
            throw new DropboxClientException("Invalid format. Must either be 'jpeg' or 'png'.");
1135
        }
1136
1137
        //Thumbnail size
1138
        $size = $this->getThumbnailSize($size);
1139
1140
        //Get Thumbnail
1141
        $response = $this->postToContent('/files/get_thumbnail', ['path' => $path, 'format' => $format, 'size' => $size]);
1142
1143
        //Get file metadata from response headers
1144
        $metadata = $this->getMetadataFromResponseHeaders($response);
1145
1146
        //File Contents
1147
        $contents = $response->getBody();
1148
1149
        //Make and return a Thumbnail model
1150
        return new Thumbnail($metadata, $contents);
1151
    }
1152
1153
    /**
1154
     * Get thumbnail size
1155
     *
1156
     * @param  string $size Thumbnail Size
1157
     *
1158
     * @return string
1159
     */
1160
    protected function getThumbnailSize($size)
1161
    {
1162
        $thumbnailSizes = [
1163
            'thumb' => 'w32h32',
1164
            'small' => 'w64h64',
1165
            'medium' => 'w128h128',
1166
            'large' => 'w640h480',
1167
            'huge' => 'w1024h768'
1168
        ];
1169
1170
        return isset($thumbnailSizes[$size]) ? $thumbnailSizes[$size] : $thumbnailSizes['small'];
1171
    }
1172
1173
    /**
1174
     * Get metadata from response headers
1175
     *
1176
     * @param  DropboxResponse $response
1177
     *
1178
     * @return array
1179
     */
1180
    protected function getMetadataFromResponseHeaders(DropboxResponse $response)
1181
    {
1182
        //Response Headers
1183
        $headers = $response->getHeaders();
1184
1185
        //Empty metadata for when
1186
        //metadata isn't returned
1187
        $metadata = [];
1188
1189
        //If metadata is available
1190
        if (isset($headers[static::METADATA_HEADER])) {
1191
            //File Metadata
1192
            $data = $headers[static::METADATA_HEADER];
1193
1194
            //The metadata is present in the first index
1195
            //of the metadata response header array
1196
            if (is_array($data) && isset($data[0])) {
1197
                $data = $data[0];
1198
            }
1199
1200
            //Since the metadata is returned as a json string
1201
            //it needs to be decoded into an associative array
1202
            $metadata = json_decode((string)$data, true);
1203
        }
1204
1205
        //Return the metadata
1206
        return $metadata;
1207
    }
1208
1209
    /**
1210
     * Download a File
1211
     *
1212
     * @param  string                  $path        Path to the file you want to download
1213
     * @param  null|string|DropboxFile $dropboxFile DropboxFile object or Path to target file
1214
     *
1215
     * @return \Kunnu\Dropbox\Models\File
1216
     *
1217
     * @throws \Kunnu\Dropbox\Exceptions\DropboxClientException
1218
     *
1219
     * @link https://www.dropbox.com/developers/documentation/http/documentation#files-download
1220
     *
1221
     */
1222
    public function download($path, $dropboxFile = null)
1223
    {
1224
        //Path cannot be null
1225
        if (is_null($path)) {
1226
            throw new DropboxClientException("Path cannot be null.");
1227
        }
1228
1229
        //Make Dropbox File if target is specified
1230
        $dropboxFile = $dropboxFile ? $this->makeDropboxFile($dropboxFile, null, null, DropboxFile::MODE_WRITE) : null;
1231
1232
        //Download File
1233
        $response = $this->postToContent('/files/download', ['path' => $path], null, $dropboxFile);
1234
1235
        //Get file metadata from response headers
1236
        $metadata = $this->getMetadataFromResponseHeaders($response);
1237
1238
        //File Contents
1239
        $contents = $dropboxFile ? $this->makeDropboxFile($dropboxFile) : $response->getBody();
1240
1241
        //Make and return a File model
1242
        return new File($metadata, $contents);
1243
    }
1244
1245
    /**
1246
     * Get Current Account
1247
     *
1248
     * @link https://www.dropbox.com/developers/documentation/http/documentation#users-get_current_account
1249
     *
1250
     * @return \Kunnu\Dropbox\Models\Account
1251
     */
1252
    public function getCurrentAccount()
1253
    {
1254
        //Get current account
1255
        $response = $this->postToAPI('/users/get_current_account', []);
1256
        $body = $response->getDecodedBody();
1257
1258
        //Make and return the model
1259
        return new Account($body);
1260
    }
1261
1262
    /**
1263
     * Get Account
1264
     *
1265
     * @param string $account_id Account ID of the account to get details for
1266
     *
1267
     * @link https://www.dropbox.com/developers/documentation/http/documentation#users-get_account
1268
     *
1269
     * @return \Kunnu\Dropbox\Models\Account
1270
     */
1271
    public function getAccount($account_id)
1272
    {
1273
        //Get account
1274
        $response = $this->postToAPI('/users/get_account', ['account_id' => $account_id]);
1275
        $body = $response->getDecodedBody();
1276
1277
        //Make and return the model
1278
        return new Account($body);
1279
    }
1280
1281
    /**
1282
     * Get Multiple Accounts in one call
1283
     *
1284
     * @param array $account_ids IDs of the accounts to get details for
1285
     *
1286
     * @link https://www.dropbox.com/developers/documentation/http/documentation#users-get_account_batch
1287
     *
1288
     * @return \Kunnu\Dropbox\Models\AccountList
1289
     */
1290
    public function getAccounts(array $account_ids = [])
1291
    {
1292
        //Get account
1293
        $response = $this->postToAPI('/users/get_account_batch', ['account_ids' => $account_ids]);
1294
        $body = $response->getDecodedBody();
1295
1296
        //Make and return the model
1297
        return new AccountList($body);
1298
    }
1299
1300
    /**
1301
     * Get Space Usage for the current user's account
1302
     *
1303
     * @link https://www.dropbox.com/developers/documentation/http/documentation#users-get_space_usage
1304
     *
1305
     * @return array
1306
     */
1307
    public function getSpaceUsage()
1308
    {
1309
        //Get space usage
1310
        $response = $this->postToAPI('/users/get_space_usage', []);
1311
        $body = $response->getDecodedBody();
1312
1313
        //Return the decoded body
1314
        return $body;
1315
    }
1316
}
1317