PluginProbe
InfiniteWP Client / trunk
InfiniteWP Client vtrunk
1.13.10 1.13.7 trunk 0.1.4 0.1.5 1.0.0 1.0.1 1.0.2 1.0.3 1.0.4 1.1.0 1.1.1 1.1.10 1.1.2 1.1.3 1.1.4 1.1.5 1.1.6 1.1.7 1.1.8 1.1.9 1.11.0 1.11.1 1.12.1 1.12.3 All 92 releases
iwp-client / lib / Dropbox / API.php

API.php in InfiniteWP Client trunk, at lib/Dropbox/API.php

803 lines 26.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 /**
4 * Dropbox API base class
5 * @author Ben Tadiar <ben@handcraftedbyben.co.uk>
6 * @link https://github.com/benthedesigner/dropbox
7 * @link https://www.dropbox.com/developers
8 * @link https://status.dropbox.com Dropbox status
9 * @package Dropbox
10 */
11
12 class IWP_Dropbox_API {
13 // API Endpoints
14 const API_URL = 'https://api.dropbox.com/1/';
15 const API_URL_V2 = 'https://api.dropboxapi.com/';
16 const CONTENT_URL = 'https://api-content.dropbox.com/1/';
17 const CONTENT_URL_V2 = 'https://content.dropboxapi.com/2/';
18
19 /**
20 * OAuth consumer object
21 * @var null|OAuth\Consumer
22 */
23 private $OAuth;
24
25 /**
26 * The root level for file paths
27 * Either `dropbox` or `sandbox` (preferred)
28 * @var null|string
29 */
30 private $root;
31
32 /**
33 * Chunk size used for chunked uploads
34 * @see \Dropbox_API::chunkedUpload()
35 */
36 private $chunkSize = 4194304;
37
38 private $responseFormat = 'php';
39
40 private $callback = 'dropboxCallback';
41 /**
42 * Object to track uploads
43 */
44 private $tracker;
45
46 private $base;
47
48 /**
49 * Set the OAuth consumer object
50 * See 'General Notes' at the link below for information on access type
51 * @link https://www.dropbox.com/developers/reference/api
52 * @param OAuth\Consumer\ConsumerAbstract $OAuth
53 * @param string $root Dropbox app access type
54 */
55 public function __construct($OAuth, $root = 'dropbox') {
56 $this->OAuth = $OAuth;
57 $this->setRoot($root);
58 }
59
60 /**
61 * Set the root level
62 * @param mixed $root
63 * @throws Exception
64 * @return void
65 */
66 public function setRoot($root) {
67 if ($root !== 'sandbox' && $root !== 'dropbox') {
68 throw new Exception("Expected a root of either 'dropbox' or 'sandbox', got '$root'");
69 } else {
70 $this->root = $root;
71 }
72 }
73
74 /**
75 * Set the tracker
76 * @param Tracker $tracker
77 */
78 public function setTracker($tracker) {
79 $this->tracker = $tracker;
80 }
81
82 /**
83 * Retrieves information about the user's account
84 * @return object stdClass
85 */
86 public function accountInfo() {
87 //API V1
88 // return $this->fetch('POST', self::API_URL, 'account/info');
89
90 $call = '2/users/get_current_account';
91 $params = array('api_v2' => true);
92 $response = $this->fetch('POST', self::API_URL_V2, $call, $params);
93 return $response;
94 }
95
96 /**
97 * Retrieves information about the user's quota
98 * @return object stdClass
99 */
100 public function quotaInfo() {
101 $call = '2/users/get_space_usage';
102 $params = array('api_v2' => true);
103 $response = $this->fetch('POST', self::API_URL_V2, $call, $params);
104 return $response;
105 }
106
107 /**
108 * Uploads a physical file from disk
109 * Dropbox impose a 150MB limit to files uploaded via the API. If the file
110 * exceeds this limit or does not exist, an Exception will be thrown
111 * @param string $file Absolute path to the file to be uploaded
112 * @param string|bool $filename The destination filename of the uploaded file
113 * @param string $path Path to upload the file to, relative to root
114 * @param boolean $overwrite Should the file be overwritten? (Default: true)
115 * @return object stdClass
116 */
117 public function putFile($file, $path = '', $overwrite = true) {
118 if (!file_exists($file)) {
119 // Throw an Exception if the file does not exist
120 throw new Exception('Local file ' . $file . ' does not exist');
121 }
122 $filesize = iwp_mmb_get_file_size($file);
123 if ($filesize >= 157286400) {
124 $output = $this->chunked_upload_single_call_new($file, $path,$overwrite);
125 return $output;
126
127 }else{
128 $handle = @fopen($file, 'r');
129 //Set the file content to $this->InFile
130 $this->OAuth->setInFile(fread($handle, filesize($file)));
131 fclose($handle);
132
133 $filename = (is_string($filename)) ? $filename : basename($file);
134 $path = '/' . $this->encodePath($path .'/'. $filename);
135 $params = array(
136 'path' => $path,
137 'mute' => true,
138 'mode' => 'overwrite',
139 'api_v2' => true,
140 'content_upload' => true
141 );
142 $response = $this->fetch('POST', self::CONTENT_URL_V2, 'files/upload', $params);
143 return $response;
144 }
145
146 }
147
148 public function chunked_upload_single_call_new($file, $path = '',$overwrite=true){
149 $file = str_replace("\\", "/",$file);
150 if (!is_readable($file) or !is_file($file))
151 throw new IWP_DropboxException("Error: File \"$file\" is not readable or doesn't exist.");
152 $file_handle=fopen($file,'r');
153 $uploadID=null;
154 $offset=0;
155 $ProgressFunction=null;
156 while ($data=fread($file_handle, (1024*1024*30))) { //1024*1024*30 = 30MB
157 $firstCommit = (0 == $offset);
158 iwp_mmb_auto_print('dropbox_chucked_upload');
159 $this->OAuth->setInFile($data);
160
161 if ($firstCommit) {
162 $params = array(
163 'close' => false,
164 'api_v2' => true,
165 'content_upload' => true
166 );
167 $response = $this->fetch('POST', self::CONTENT_URL_V2, 'files/upload_session/start', $params);
168 $firstCommit = false;
169
170 } else {
171 $params = array(
172 'cursor' => array(
173 'session_id' => $uploadID,
174 // If you send it as a string, Dropbox will be unhappy
175 'offset' => (int)$offset
176 ),
177 'api_v2' => true,
178 'content_upload' => true
179 );
180 $response = $this->append_upload($params, false);
181 }
182
183 // On subsequent chunks, use the upload ID returned by the previous request
184 if (isset($response['body']->session_id)) {
185 $uploadID = $response['body']->session_id;
186 }
187
188 /*
189 API v2 no longer returns the offset, we need to manually work this out. So check that there are no errors and update the offset as well as calling the callback method.
190 */
191 if (!isset($response['body']->error)) {
192 $offset = ftell($file_handle);
193 $output['response']= $response;
194 if($isCommit ==false){
195
196 $output['offset']= $offset;
197 $output['upload_id']= $uploadID;
198 }
199 $this->OAuth->setInFile(null);
200 }
201 fseek($file_handle, $offset);
202 }
203 fclose($file_handle);
204 $filename = (is_string($filename)) ? $filename : basename($file);
205 $params = array(
206 'cursor' => array(
207 'session_id' => $uploadID,
208 'offset' => (int)$offset
209 ),
210 'commit' => array(
211 'path' => '/' . $this->encodePath($path .'/'. $filename),
212 'mode' => 'overwrite'
213 ),
214 'api_v2' => true,
215 'content_upload' => true
216 );
217 $response = $this->append_upload($params, true);
218
219 return $response;
220 }
221
222 /**
223 * Not used
224 * Uploads file data from a stream
225 * Note: This function is experimental and requires further testing
226 * @todo Add filesize check
227 *@ param resource $stream A readable stream created using fopen()
228 * @param string $filename The destination filename, including path
229 * @param boolean $overwrite Should the file be overwritten? (Default: true)
230 * @return array
231 */
232 // public function putStream($stream, $filename, $overwrite = true) {
233 // $this->OAuth->setInFile($stream);
234 // $path = $this->encodePath($filename);
235 // $call = 'files_put/' . $this->root . '/' . $path;
236 // $params = array('overwrite' => (int) $overwrite);
237
238 // return $this->fetch('PUT', self::CONTENT_URL, $call, $params);
239 // }
240
241 /**
242 * Uploads large files to Dropbox in mulitple chunks
243 * @param string $file Absolute path to the file to be uploaded
244 * @param string|bool $filename The destination filename of the uploaded file
245 * @param string $path Path to upload the file to, relative to root
246 * @param boolean $overwrite Should the file be overwritten? (Default: true)
247 * @return stdClass
248 */
249 public function chunked_upload($file, $path = '', $overwrite = true, $uploadID = null, $offset = 0, $isCommit = false) {
250 $starting_backup_path_time = time();
251
252 $file = str_replace("\\", "/",$file);
253 if (!file_exists($file)) throw new Exception('Local file ' . $file . ' does not exist');
254
255 if (!($handle = @fopen($file, 'r'))) throw new Exception('Could not open ' . $file . ' for reading');
256
257 // Seek to the correct position on the file pointer
258 fseek($handle, $offset);
259 $to_exit = false;
260
261 //Set firstCommit to true so that the upload session start endpoint is called.
262 $firstCommit = (0 == $offset);
263
264 // Read from the file handle until EOF, uploading each chunk
265 if ($data = fread($handle, $this->chunkSize)) {
266
267 // Set the file, request parameters and send the request
268 $this->OAuth->setInFile($data);
269
270 if ($firstCommit) {
271 $params = array(
272 'close' => false,
273 'api_v2' => true,
274 'content_upload' => true
275 );
276 $response = $this->fetch('POST', self::CONTENT_URL_V2, 'files/upload_session/start', $params);
277 $firstCommit = false;
278
279 } else {
280 $params = array(
281 'cursor' => array(
282 'session_id' => $uploadID,
283 // If you send it as a string, Dropbox will be unhappy
284 'offset' => (int)$offset
285 ),
286 'api_v2' => true,
287 'content_upload' => true
288 );
289 $response = $this->append_upload($params, false);
290 }
291
292 // On subsequent chunks, use the upload ID returned by the previous request
293 if (isset($response['body']->session_id)) {
294 $uploadID = $response['body']->session_id;
295 }
296
297 /*
298 API v2 no longer returns the offset, we need to manually work this out. So check that there are no errors and update the offset as well as calling the callback method.
299 */
300 if (!isset($response['body']->error)) {
301 $offset = ftell($handle);
302 $output['response']= $response;
303 if($isCommit ==false){
304
305 $output['offset']= $offset;
306 $output['upload_id']= $uploadID;
307 }
308 $this->OAuth->setInFile(null);
309 }
310
311 }
312 // Complete the chunked upload
313 if ($isCommit) {
314 $filename = (is_string($filename)) ? $filename : basename($file);
315 $params = array(
316 'cursor' => array(
317 'session_id' => $uploadID,
318 'offset' => (int)$offset
319 ),
320 'commit' => array(
321 'path' => '/' . $this->encodePath($path .'/'. $filename),
322 'mode' => 'overwrite'
323 ),
324 'api_v2' => true,
325 'content_upload' => true
326 );
327 $response = $this->append_upload($params, true);
328 $offset = ftell($handle);
329 $output['response']= $response;
330 }
331
332 fclose($handle);
333 return $output;
334 }
335
336 private function append_upload($params, $last_call) {
337 try {
338 if ($last_call){
339 $response = $this->fetch('POST', self::CONTENT_URL_V2, 'files/upload_session/finish', $params);
340 } else {
341 $response = $this->fetch('POST', self::CONTENT_URL_V2, 'files/upload_session/append_v2', $params);
342 }
343 } catch (Exception $e) {
344 $responseCheck = json_decode($e->getMessage());
345 if (isset($responseCheck) && strpos($responseCheck[0] , 'incorrect_offset') !== false) {
346 $expected_offset = $responseCheck[1];
347 throw new Exception('Submitted input out of alignment: got ['.$params['cursor']['offset'].'] expected ['.$expected_offset.']');
348 //$params['cursor']['offset'] = $responseCheck[1];
349 //$response = $this->append_upload($params, $last_call);
350 } else {
351 throw $e;
352 }
353 }
354 return $response;
355 }
356
357 /**
358 * Downloads a file
359 * Returns the base filename, raw file data and mime type returned by Fileinfo
360 * @param string $file Path to file, relative to root, including path
361 * @param string $outFile Filename to write the downloaded file to
362 * @param string $revision The revision of the file to retrieve
363 * @return array
364 */
365 public function getFile($file, $outFile = false, $revision = null, $allow_resume = array()) {
366 $handle = null;
367 // $tempFolder = $this->getTempFolderFromOutFile(wp_normalize_path($outFile));
368 if ($outFile !== false) {
369 // Create a file handle if $outFile is specified
370 $this->prepareSetOutFile($outFile, 'w');
371 }
372
373 // $file = $this->encodePath($file);
374 $call = 'files/download';
375 $params = array('path' => '/'.$this->normalisePath($file), 'api_v2' => true, 'content_download' => true);
376 $response = $this->fetch('GET', self::CONTENT_URL_V2, $call, $params);
377 // Close the file handle if one was opened
378 if ($handle) fclose($handle);
379
380 return array(
381 'name' => ($outFile) ? $outFile : basename($file),
382 'mime' => $this->getMimeType(($outFile) ? $outFile : $response['body'], $outFile),
383 'meta' => json_decode($response['headers']['dropbox-api-result']),
384 'data' => $response['body'],
385 );
386 }
387
388 public function prepareSetOutFile($outFile, $mode) {
389 // $tempFolderFile = $this->getTempFolderFromOutFile(wp_normalize_path($outFile));
390 $tempFolderFile = wp_normalize_path($outFile);
391
392 //setting chmod from filesystem
393
394 if (!$handle = @fopen($tempFolderFile, $mode)) {
395 throw new Exception("Unable to open file handle for $tempFolderFile");
396 } else {
397 $this->OAuth->setOutFile($handle);
398 return $handle;
399 }
400 }
401
402 public function getTempFolderFromOutFile($outFile, $mode = '') {
403 //this function creates the file and its respective folders ; this function also create the exact file path from the DB values
404 $config = WPTC_Factory::get('config');
405 $is_staging_running = $config->get_option('is_staging_running');
406 if($is_staging_running){
407 $site_abspath = $config->get_option('site_abspath');
408 $this_absbath_length = (strlen($site_abspath) - 1);
409 } else{
410 $this_absbath_length = (strlen(ABSPATH) - 1);
411 }
412
413 $this_temp_file = $config->get_option('backup_db_path');
414 $this_temp_file = $config->wp_filesystem_safe_abspath_replace($this_temp_file);
415 $this_temp_file = $this_temp_file. '/tCapsule' . substr($outFile, $this_absbath_length);
416
417 //get the folder name from the full file path
418 $base_file_name = basename($this_temp_file);
419 $base_file_name_pos = strrpos($this_temp_file, $base_file_name);
420 $base_file_name_pos = $base_file_name_pos - 1;
421 $this_temp_folder = substr($this_temp_file, 0, $base_file_name_pos);
422
423 $this_temp_folder = $config->wp_filesystem_safe_abspath_replace($this_temp_folder);
424
425 $this->base->createRecursiveFileSystemFolder($this_temp_folder);
426 return $this_temp_file;
427 }
428
429 /**
430 * Downloads a file
431 * Returns the base filename, raw file data and mime type returned by Fileinfo
432 * @param string $file Path to file, relative to root, including path
433 * @param string $outFile Filename to write the downloaded file to
434 * @param string $revision The revision of the file to retrieve
435 * @return array
436 */
437 public function chunkedDownload($file, $outFile = false, $revision = null, $isChunkDownload = array(), $meta_file_download = null) {
438 global $start_time_tc;
439 $start_time_tc = time();
440 $handle = null;
441 if ($outFile !== false) {
442 // Create a file handle if $outFile is specified
443 if ($isChunkDownload['c_offset'] == 0) {
444 //while restoring ... first
445 $handle = $this->prepareSetOutFile($outFile, 'w');
446 } else {
447 $handle = $this->prepareSetOutFile($outFile, 'a');
448 }
449 }
450
451 $outFilePath = wp_normalize_path($outFile);
452 $call = 'files/download';
453 $params = array('path' =>'/'.$file, 'api_v2' => true, 'content_download' => true);
454 $response = $this->fetch('GET', self::CONTENT_URL_V2, $call, $params, $isChunkDownload);
455
456 // Set the data offset
457 if ($response) {
458 $offset = filesize($outFilePath);
459 }
460
461 if (empty($meta_file_download)) {
462 if ($this->tracker) {
463 $this->tracker->track_download($outFile, false, $offset, $isChunkDownload);
464 }
465 } else {
466 $this->tracker->track_meta_download($offset, $isChunkDownload);
467 }
468
469 // Close the file handle if one was opened
470 if ($handle) {
471 fclose($handle);
472 }
473
474 $data = array(
475 'name' => ($outFile) ? $outFile : basename($file),
476 'mime' => $this->getMimeType(($outFile) ? $outFile : $response['body'], $outFile),
477 'meta' => json_decode($response['headers']['dropbox-api-result']),
478 'data' => $response['body'],
479 'chunked' => true,
480 );
481 return $data;
482 }
483
484 public function delete($path) {
485 $call = '2/files/delete';
486 $params = array('path' => '/' . $this->normalisePath($path), 'api_v2' => true);
487 $response = $this->fetch('POST', self::API_URL_V2, $call, $params);
488 return $response;
489 }
490 /**
491 * Not used
492 * Retrieves file and folder metadata
493 * @param string $path The path to the file/folder, relative to root
494 * @param string $rev Return metadata for a specific revision (Default: latest rev)
495 * @param int $limit Maximum number of listings to return
496 * @param string $hash Metadata hash to compare against
497 * @param bool $list Return contents field with response
498 * @param bool $deleted Include files/folders that have been deleted
499 * @return object stdClass
500 */
501 public function metaData($path = null, $rev = null, $limit = 10000, $hash = false, $list = true, $deleted = false) {
502 $call = '2/files/get_metadata' ;
503 $params = array(
504 'path' => '/' . $this->normalisePath($path),
505 'api_v2' => true
506 );
507
508 return $this->fetch('POST', self::API_URL_V2, $call, $params);
509 }
510
511 /**
512 * Not used
513 * Return "delta entries", intructing you how to update
514 * your application state to match the server's state
515 * Important: This method does not make changes to the application state
516 * @param null|string $cursor Used to keep track of your current state
517 * @return array Array of delta entries
518 */
519 // public function delta($cursor = null) {
520 // $call = 'delta';
521 // $params = array('cursor' => $cursor);
522
523 // return $this->fetch('POST', self::API_URL, $call, $params);
524 // }
525
526 /**
527 * Not used
528 * Obtains metadata for the previous revisions of a file
529 * @param string Path to the file, relative to root
530 * @param integer Number of revisions to return (1-1000)
531 * @return array
532 */
533 // public function revisions($file, $limit = 10) {
534 // $call = 'revisions/' . $this->root . '/' . $this->encodePath($file);
535 // $params = array(
536 // 'rev_limit' => ($limit < 1) ? 1 : (($limit > 1000) ? 1000 : (int) $limit),
537 // );
538
539 // return $this->fetch('GET', self::API_URL, $call, $params);
540 // }
541
542 /**
543 * Not used
544 * Restores a file path to a previous revision
545 * @param string $file Path to the file, relative to root
546 * @param string $revision The revision of the file to restore
547 * @return object stdClass
548 */
549 // public function restore($file, $revision) {
550 // $call = 'restore/' . $this->root . '/' . $this->encodePath($file);
551 // $params = array('rev' => $revision);
552
553 // return $this->fetch('POST', self::API_URL, $call, $params);
554 // }
555
556 /**
557 * Returns metadata for all files and folders that match the search query
558 * @param mixed $query The search string. Must be at least 3 characters long
559 * @param string $path The path to the folder you want to search in
560 * @param integer $limit Maximum number of results to return (1-1000)
561 * @param boolean $deleted Include deleted files/folders in the search
562 * @return array
563 */
564 //Not used
565 // public function search($query, $path = '', $limit = 1000, $deleted = false) {
566 // $call = 'search/' . $this->root . '/' . $this->encodePath($path);
567 // $params = array(
568 // 'query' => $query,
569 // 'file_limit' => ($limit < 1) ? 1 : (($limit > 1000) ? 1000 : (int) $limit),
570 // 'include_deleted' => (int) $deleted,
571 // );
572
573 // return $this->fetch('GET', self::API_URL, $call, $params);
574 // }
575
576 /**
577 * Not used
578 * Creates and returns a shareable link to files or folders
579 * The link returned is for a preview page from which the user an choose to
580 * download the file if they wish. For direct download links, see media().
581 * @param string $path The path to the file/folder you want a sharable link to
582 * @return object stdClass
583 */
584 // public function shares($path, $shortUrl = true) {
585 // $call = 'shares/' . $this->root . '/' . $this->encodePath($path);
586 // $params = array('short_url' => ($shortUrl) ? 1 : 0);
587
588 // return $this->fetch('POST', self::API_URL, $call, $params);
589 // }
590
591 /**
592 * Not used
593 * Returns a link directly to a file
594 * @param string $path The path to the media file you want a direct link to
595 * @return object stdClass
596 */
597 // public function media($path) {
598 // $call = 'media/' . $this->root . '/' . $this->encodePath($path);
599
600 // return $this->fetch('POST', self::API_URL, $call);
601 // }
602
603 /**
604 * Not used
605 * Gets a thumbnail for an image
606 * @param string $file The path to the image you wish to thumbnail
607 * @param string $format The thumbnail format, either JPEG or PNG
608 * @param string $size The size of the thumbnail
609 * @return array
610 */
611 // public function thumbnails($file, $format = 'JPEG', $size = 'small') {
612 // $format = strtoupper($format);
613 // // If $format is not 'PNG', default to 'JPEG'
614 // if ($format != 'PNG') {
615 // $format = 'JPEG';
616 // }
617
618 // $size = strtolower($size);
619 // $sizes = array('s', 'm', 'l', 'xl', 'small', 'medium', 'large');
620 // // If $size is not valid, default to 'small'
621 // if (!in_array($size, $sizes)) {
622 // $size = 'small';
623 // }
624
625 // $call = 'thumbnails/' . $this->root . '/' . $this->encodePath($file);
626 // $params = array('format' => $format, 'size' => $size);
627 // $response = $this->fetch('GET', self::CONTENT_URL, $call, $params);
628
629 // return array(
630 // 'name' => basename($file),
631 // 'mime' => $this->getMimeType($response['body']),
632 // 'meta' => json_decode($response['headers']['x-dropbox-metadata']),
633 // 'data' => $response['body'],
634 // );
635 // }
636
637 /**
638 * Not used
639 * Creates and returns a copy_ref to a file
640 * This reference string can be used to copy that file to another user's
641 * Dropbox by passing it in as the from_copy_ref parameter on /fileops/copy
642 * @param $path File for which ref should be created, relative to root
643 * @return array
644 */
645 // public function copyRef($path) {
646 // $call = 'copy_ref/' . $this->root . '/' . $this->encodePath($path);
647
648 // return $this->fetch('GET', self::API_URL, $call);
649 // }
650
651 /**
652 * Not used
653 * Copies a file or folder to a new location
654 * @param string $from File or folder to be copied, relative to root
655 * @param string $to Destination path, relative to root
656 * @param null|string $fromCopyRef Must be used instead of the from_path
657 * @return object stdClass
658 */
659 // public function copy($from, $to, $fromCopyRef = null) {
660 // $call = 'fileops/copy';
661 // $params = array(
662 // 'root' => $this->root,
663 // 'from_path' => $this->normalisePath($from),
664 // 'to_path' => $this->normalisePath($to),
665 // );
666
667 // if ($fromCopyRef) {
668 // $params['from_path'] = null;
669 // $params['from_copy_ref'] = $fromCopyRef;
670 // }
671
672 // return $this->fetch('POST', self::API_URL, $call, $params);
673 // }
674
675 /**
676 * Not used
677 * Creates a folder
678 * @param string New folder to create relative to root
679 * @return object stdClass
680 */
681 // public function create($path) {
682 // $call = 'fileops/create_folder';
683 // $params = array('root' => $this->root, 'path' => $this->normalisePath($path));
684
685 // return $this->fetch('POST', self::API_URL, $call, $params);
686 // }
687
688 /**
689 * Not used
690 * Deletes a file or folder
691 * @param string $path The path to the file or folder to be deleted
692 * @return object stdClass
693 */
694 // public function delete($path) {
695 // $call = '2/files/delete';
696 // $params = array('path' => '/' . $this->normalisePath($path), 'api_v2' => true);
697 // $response = $this->fetch('POST', self::API_URL_V2, $call, $params);
698 // return $response;
699 // }
700
701 /**
702 * Not used
703 * Moves a file or folder to a new location
704 * @param string $from File or folder to be moved, relative to root
705 * @param string $to Destination path, relative to root
706 * @return object stdClass
707 */
708 // public function move($from, $to) {
709 // $call = 'fileops/move';
710 // $params = array(
711 // 'root' => $this->root,
712 // 'from_path' => $this->normalisePath($from),
713 // 'to_path' => $this->normalisePath($to),
714 // );
715
716 // return $this->fetch('POST', self::API_URL, $call, $params);
717 // }
718
719 /**
720 * Intermediate fetch function
721 * @param string $method The HTTP method
722 * @param string $url The API endpoint
723 * @param string $call The API method to call
724 * @param array $params Additional parameters
725 * @return mixed
726 */
727 private function fetch($method, $url, $call, array $params = array(), $isChunkDownload = array())
728 {
729 // Make the API call via the consumer
730 $response = $this->OAuth->fetch($method, $url, $call, $params, $isChunkDownload);
731
732 // Format the response and return
733 switch ($this->responseFormat) {
734 case 'json':
735 return json_encode($response);
736 case 'jsonp':
737 $response = json_encode($response);
738 return $this->callback . '(' . $response . ')';
739 default:
740 return $response;
741 }
742 }
743
744
745 /**
746 * Set the chunk size for chunked uploads
747 * If $chunkSize is empty, set to 4194304 bytes (4 MB)
748 * @see \Dropbox\API\chunkedUpload()
749 */
750 public function setChunkSize($chunkSize = 4194304) {
751 if (!is_int($chunkSize)) {
752 throw new Exception('Expecting chunk size to be an integer, got ' . gettype($chunkSize));
753 } elseif ($chunkSize > 157286400) {
754 throw new Exception('Chunk size must not exceed 157286400 bytes, got ' . $chunkSize);
755 } else {
756 $this->chunkSize = $chunkSize;
757 }
758 }
759
760 /**
761 * Get the mime type of downloaded file
762 * If the Fileinfo extension is not loaded, return false
763 * @param string $data File contents as a string or filename
764 * @param string $isFilename Is $data a filename?
765 * @return boolean|string Mime type and encoding of the file
766 */
767 private function getMimeType($data, $isFilename = false) {
768 if (extension_loaded('fileinfo')) {
769 $finfo = new finfo(FILEINFO_MIME);
770 if ($isFilename !== false) {
771 return @$finfo->file($data);
772 }
773
774 return $finfo->buffer($data);
775 }
776
777 return false;
778 }
779
780 /**
781 * Trim the path of forward slashes and replace
782 * consecutive forward slashes with a single slash
783 * then replace backslashes with forward slashes
784 * @param string $path The path to normalise
785 * @return string
786 */
787 private function normalisePath($path) {
788 $path = preg_replace('#/+#', '/', trim($path, '/'));
789 return $path;
790 }
791
792 /**
793 * Encode the path, then replace encoded slashes
794 * with literal forward slash characters
795 * @param string $path The path to encode
796 * @return string
797 */
798 private function encodePath($path) {
799 // in APIv1, encoding was needed because parameters were passed as part of the URL; this is no longer done in our APIv2 SDK; hence, all that we now do here is normalise.
800 return $this->normalisePath($path);
801 }
802 }
803