MDL-52051 oauth: expires_in is optional
[moodle.git] / repository / dropbox / lib.php
CommitLineData
3e123368 1<?php
3e123368
DC
2// This file is part of Moodle - http://moodle.org/
3//
4// Moodle is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8//
9// Moodle is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12// GNU General Public License for more details.
13//
14// You should have received a copy of the GNU General Public License
15// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
16
17/**
e35194be
DC
18 * This plugin is used to access user's dropbox files
19 *
5bcfd504 20 * @since Moodle 2.0
67233725 21 * @package repository_dropbox
75dd40b2 22 * @copyright 2012 Marina Glancy
67233725 23 * @copyright 2010 Dongsheng Cai {@link http://dongsheng.org}
d078f6d3 24 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
3e123368 25 */
67233725 26require_once($CFG->dirroot . '/repository/lib.php');
1fcf0ca8 27require_once(__DIR__.'/locallib.php');
e35194be 28
75dd40b2
MG
29/**
30 * Repository to access Dropbox files
31 *
32 * @package repository_dropbox
33 * @copyright 2010 Dongsheng Cai
34 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
35 */
e35194be 36class repository_dropbox extends repository {
67233725 37 /** @var dropbox the instance of dropbox client */
e35194be 38 private $dropbox;
67233725 39 /** @var array files */
e35194be 40 public $files;
67233725 41 /** @var bool flag of login status */
e35194be 42 public $logged=false;
75dd40b2
MG
43 /** @var int maximum size of file to cache in moodle filepool */
44 public $cachelimit=null;
e35194be 45
67233725
DC
46 /** @var int cached file ttl */
47 private $cachedfilettl = null;
48
e35194be
DC
49 /**
50 * Constructor of dropbox plugin
67233725 51 *
e35194be 52 * @param int $repositoryid
67233725 53 * @param stdClass $context
e35194be
DC
54 * @param array $options
55 */
56 public function __construct($repositoryid, $context = SYSCONTEXTID, $options = array()) {
67233725 57 global $CFG;
e35194be
DC
58 $options['page'] = optional_param('p', 1, PARAM_INT);
59 parent::__construct($repositoryid, $context, $options);
60
61 $this->setting = 'dropbox_';
62
63 $this->dropbox_key = $this->get_option('dropbox_key');
64 $this->dropbox_secret = $this->get_option('dropbox_secret');
65
67233725
DC
66 // one day
67 $this->cachedfilettl = 60 * 60 * 24;
68
69 if (isset($options['access_key'])) {
70 $this->access_key = $options['access_key'];
71 } else {
72 $this->access_key = get_user_preferences($this->setting.'_access_key', '');
73 }
74 if (isset($options['access_secret'])) {
75 $this->access_secret = $options['access_secret'];
76 } else {
77 $this->access_secret = get_user_preferences($this->setting.'_access_secret', '');
78 }
e35194be
DC
79
80 if (!empty($this->access_key) && !empty($this->access_secret)) {
81 $this->logged = true;
82 }
83
67233725 84 $callbackurl = new moodle_url($CFG->wwwroot.'/repository/repository_callback.php', array(
e35194be
DC
85 'callback'=>'yes',
86 'repo_id'=>$repositoryid
87 ));
88
89 $args = array(
90 'oauth_consumer_key'=>$this->dropbox_key,
91 'oauth_consumer_secret'=>$this->dropbox_secret,
67233725 92 'oauth_callback' => $callbackurl->out(false),
926a3512 93 'api_root' => 'https://api.dropbox.com/1/oauth',
e35194be
DC
94 );
95
96 $this->dropbox = new dropbox($args);
97 }
98
67233725
DC
99 /**
100 * Set access key
101 *
102 * @param string $access_key
103 */
104 public function set_access_key($access_key) {
105 $this->access_key = $access_key;
106 }
107
108 /**
109 * Set access secret
110 *
111 * @param string $access_secret
112 */
113 public function set_access_secret($access_secret) {
114 $this->access_secret = $access_secret;
115 }
116
117
e35194be
DC
118 /**
119 * Check if moodle has got access token and secret
67233725 120 *
e35194be
DC
121 * @return bool
122 */
123 public function check_login() {
124 return !empty($this->logged);
125 }
126
127 /**
128 * Generate dropbox login url
67233725 129 *
e35194be
DC
130 * @return array
131 */
132 public function print_login() {
133 $result = $this->dropbox->request_token();
134 set_user_preference($this->setting.'_request_secret', $result['oauth_token_secret']);
135 $url = $result['authorize_url'];
136 if ($this->options['ajax']) {
137 $ret = array();
6bdfef5d 138 $popup_btn = new stdClass();
e35194be
DC
139 $popup_btn->type = 'popup';
140 $popup_btn->url = $url;
141 $ret['login'] = array($popup_btn);
142 return $ret;
143 } else {
4b05a49b 144 echo '<a target="_blank" href="'.$url.'">'.get_string('login', 'repository').'</a>';
e35194be
DC
145 }
146 }
147
148 /**
149 * Request access token
67233725 150 *
e35194be
DC
151 * @return array
152 */
153 public function callback() {
154 $token = optional_param('oauth_token', '', PARAM_TEXT);
155 $secret = get_user_preferences($this->setting.'_request_secret', '');
156 $access_token = $this->dropbox->get_access_token($token, $secret);
157 set_user_preference($this->setting.'_access_key', $access_token['oauth_token']);
158 set_user_preference($this->setting.'_access_secret', $access_token['oauth_token_secret']);
159 }
160
161 /**
162 * Get dropbox files
67233725 163 *
e35194be
DC
164 * @param string $path
165 * @param int $page
166 * @return array
167 */
168 public function get_listing($path = '', $page = '1') {
169 global $OUTPUT;
170 if (empty($path) || $path=='/') {
171 $path = '/';
172 } else {
173 $path = file_correct_filepath($path);
174 }
ab603b24 175 $encoded_path = str_replace("%2F", "/", rawurlencode($path));
e35194be
DC
176
177 $list = array();
178 $list['list'] = array();
75dd40b2 179 $list['manage'] = 'https://www.dropbox.com/home';
32368e99
DC
180 $list['dynload'] = true;
181 $list['nosearch'] = true;
a3433213
RW
182 $list['logouturl'] = 'https://www.dropbox.com/logout';
183 $list['message'] = get_string('logoutdesc', 'repository_dropbox');
ab603b24 184 // process breadcrumb trail
e35194be 185 $list['path'] = array(
0e61528d 186 array('name'=>get_string('dropbox', 'repository_dropbox'), 'path'=>'/')
e35194be 187 );
32368e99 188
ab603b24 189 $result = $this->dropbox->get_listing($encoded_path, $this->access_key, $this->access_secret);
0e61528d 190
32368e99
DC
191 if (!is_object($result) || empty($result)) {
192 return $list;
193 }
194 if (empty($result->path)) {
195 $current_path = '/';
196 } else {
197 $current_path = file_correct_filepath($result->path);
198 }
199
e35194be
DC
200 $trail = '';
201 if (!empty($path)) {
202 $parts = explode('/', $path);
203 if (count($parts) > 1) {
204 foreach ($parts as $part) {
205 if (!empty($part)) {
206 $trail .= ('/'.$part);
207 $list['path'][] = array('name'=>$part, 'path'=>$trail);
208 }
209 }
210 } else {
211 $list['path'][] = array('name'=>$path, 'path'=>$path);
212 }
213 }
e35194be 214
810aea11
DC
215 if (!empty($result->error)) {
216 // reset access key
217 set_user_preference($this->setting.'_access_key', '');
218 set_user_preference($this->setting.'_access_secret', '');
219 throw new repository_exception('repositoryerror', 'repository', '', $result->error);
220 }
221 if (empty($result->contents) or !is_array($result->contents)) {
32368e99
DC
222 return $list;
223 }
810aea11 224 $files = $result->contents;
f4fe646b
MG
225 $dirslist = array();
226 $fileslist = array();
e35194be
DC
227 foreach ($files as $file) {
228 if ($file->is_dir) {
f4fe646b 229 $dirslist[] = array(
e35194be
DC
230 'title' => substr($file->path, strpos($file->path, $current_path)+strlen($current_path)),
231 'path' => file_correct_filepath($file->path),
f4fe646b
MG
232 'date' => strtotime($file->modified),
233 'thumbnail' => $OUTPUT->pix_url(file_folder_icon(64))->out(false),
234 'thumbnail_height' => 64,
235 'thumbnail_width' => 64,
e35194be
DC
236 'children' => array(),
237 );
238 } else {
f4fe646b
MG
239 $thumbnail = null;
240 if ($file->thumb_exists) {
241 $thumburl = new moodle_url('/repository/dropbox/thumbnail.php',
242 array('repo_id' => $this->id,
243 'ctx_id' => $this->context->id,
244 'source' => $file->path,
245 'rev' => $file->rev // include revision to avoid cache problems
246 ));
247 $thumbnail = $thumburl->out(false);
248 }
249 $fileslist[] = array(
e35194be
DC
250 'title' => substr($file->path, strpos($file->path, $current_path)+strlen($current_path)),
251 'source' => $file->path,
f4fe646b
MG
252 'size' => $file->bytes,
253 'date' => strtotime($file->modified),
254 'thumbnail' => $OUTPUT->pix_url(file_extension_icon($file->path, 64))->out(false),
255 'realthumbnail' => $thumbnail,
256 'thumbnail_height' => 64,
257 'thumbnail_width' => 64,
e35194be
DC
258 );
259 }
260 }
f4fe646b
MG
261 $fileslist = array_filter($fileslist, array($this, 'filter'));
262 $list['list'] = array_merge($dirslist, array_values($fileslist));
e35194be
DC
263 return $list;
264 }
f4fe646b
MG
265
266 /**
267 * Displays a thumbnail for current user's dropbox file
268 *
269 * @param string $string
270 */
271 public function send_thumbnail($source) {
c1b3ac43 272 global $CFG;
f4fe646b
MG
273 $saveas = $this->prepare_file('');
274 try {
275 $access_key = get_user_preferences($this->setting.'_access_key', '');
276 $access_secret = get_user_preferences($this->setting.'_access_secret', '');
277 $this->dropbox->set_access_token($access_key, $access_secret);
c1b3ac43 278 $this->dropbox->get_thumbnail($source, $saveas, $CFG->repositorysyncimagetimeout);
f4fe646b
MG
279 $content = file_get_contents($saveas);
280 unlink($saveas);
281 // set 30 days lifetime for the image. If the image is changed in dropbox it will have
282 // different revision number and URL will be different. It is completely safe
283 // to cache thumbnail in the browser for a long time
284 send_file($content, basename($source), 30*24*60*60, 0, true);
285 } catch (Exception $e) {}
286 }
287
e35194be
DC
288 /**
289 * Logout from dropbox
290 * @return array
291 */
292 public function logout() {
293 set_user_preference($this->setting.'_access_key', '');
294 set_user_preference($this->setting.'_access_secret', '');
295 $this->access_key = '';
296 $this->access_secret = '';
297 return $this->print_login();
298 }
299
300 /**
301 * Set dropbox option
302 * @param array $options
303 * @return mixed
304 */
305 public function set_option($options = array()) {
306 if (!empty($options['dropbox_key'])) {
307 set_config('dropbox_key', trim($options['dropbox_key']), 'dropbox');
308 }
309 if (!empty($options['dropbox_secret'])) {
310 set_config('dropbox_secret', trim($options['dropbox_secret']), 'dropbox');
311 }
75dd40b2
MG
312 if (!empty($options['dropbox_cachelimit'])) {
313 $this->cachelimit = (int)trim($options['dropbox_cachelimit']);
314 set_config('dropbox_cachelimit', $this->cachelimit, 'dropbox');
315 }
e35194be
DC
316 unset($options['dropbox_key']);
317 unset($options['dropbox_secret']);
75dd40b2 318 unset($options['dropbox_cachelimit']);
e35194be
DC
319 $ret = parent::set_option($options);
320 return $ret;
321 }
322
323 /**
324 * Get dropbox options
325 * @param string $config
326 * @return mixed
327 */
328 public function get_option($config = '') {
329 if ($config==='dropbox_key') {
330 return trim(get_config('dropbox', 'dropbox_key'));
331 } elseif ($config==='dropbox_secret') {
332 return trim(get_config('dropbox', 'dropbox_secret'));
75dd40b2
MG
333 } elseif ($config==='dropbox_cachelimit') {
334 return $this->max_cache_bytes();
e35194be 335 } else {
75dd40b2 336 $options = parent::get_option();
e35194be
DC
337 $options['dropbox_key'] = trim(get_config('dropbox', 'dropbox_key'));
338 $options['dropbox_secret'] = trim(get_config('dropbox', 'dropbox_secret'));
75dd40b2 339 $options['dropbox_cachelimit'] = $this->max_cache_bytes();
e35194be 340 }
e35194be
DC
341 return $options;
342 }
343
75dd40b2
MG
344 /**
345 * Fixes references in DB that contains user credentials
346 *
347 * @param string $reference contents of DB field files_reference.reference
348 */
349 public function fix_old_style_reference($reference) {
c1b3ac43 350 global $CFG;
75dd40b2
MG
351 $ref = unserialize($reference);
352 if (!isset($ref->url)) {
353 $this->dropbox->set_access_token($ref->access_key, $ref->access_secret);
c1b3ac43 354 $ref->url = $this->dropbox->get_file_share_link($ref->path, $CFG->repositorygetfiletimeout);
75dd40b2
MG
355 if (!$ref->url) {
356 // some error occurred, do not fix reference for now
357 return $reference;
358 }
359 }
360 unset($ref->access_key);
361 unset($ref->access_secret);
362 $newreference = serialize($ref);
363 if ($newreference !== $reference) {
364 // we need to update references in the database
365 global $DB;
366 $params = array(
367 'newreference' => $newreference,
368 'newhash' => sha1($newreference),
369 'reference' => $reference,
370 'hash' => sha1($reference),
371 'repoid' => $this->id
372 );
373 $refid = $DB->get_field_sql('SELECT id FROM {files_reference}
374 WHERE reference = :reference AND referencehash = :hash
375 AND repositoryid = :repoid', $params);
376 if (!$refid) {
377 return $newreference;
378 }
379 $existingrefid = $DB->get_field_sql('SELECT id FROM {files_reference}
380 WHERE reference = :newreference AND referencehash = :newhash
381 AND repositoryid = :repoid', $params);
382 if ($existingrefid) {
383 // the same reference already exists, we unlink all files from it,
384 // link them to the current reference and remove the old one
385 $DB->execute('UPDATE {files} SET referencefileid = :refid
386 WHERE referencefileid = :existingrefid',
387 array('refid' => $refid, 'existingrefid' => $existingrefid));
388 $DB->delete_records('files_reference', array('id' => $existingrefid));
389 }
390 // update the reference
391 $params['refid'] = $refid;
392 $DB->execute('UPDATE {files_reference}
393 SET reference = :newreference, referencehash = :newhash
394 WHERE id = :refid', $params);
395 }
396 return $newreference;
397 }
398
399 /**
400 * Converts a URL received from dropbox API function 'shares' into URL that
401 * can be used to download/access file directly
402 *
403 * @param string $sharedurl
404 * @return string
405 */
406 private function get_file_download_link($sharedurl) {
407 return preg_replace('|^(\w*://)www(.dropbox.com)|','\1dl\2',$sharedurl);
408 }
409
e35194be 410 /**
59cb7598 411 * Downloads a file from external repository and saves it in temp dir
e35194be 412 *
59cb7598
MG
413 * @throws moodle_exception when file could not be downloaded
414 *
75dd40b2
MG
415 * @param string $reference the content of files.reference field or result of
416 * function {@link repository_dropbox::get_file_reference()}
417 * @param string $saveas filename (without path) to save the downloaded file in the
59cb7598
MG
418 * temporary directory, if omitted or file already exists the new filename will be generated
419 * @return array with elements:
420 * path: internal location of the file
421 * url: URL to the source (from parameters)
e35194be 422 */
59cb7598 423 public function get_file($reference, $saveas = '') {
c1b3ac43 424 global $CFG;
75dd40b2 425 $ref = unserialize($reference);
991aa8ab 426 $saveas = $this->prepare_file($saveas);
75dd40b2
MG
427 if (isset($ref->access_key) && isset($ref->access_secret) && isset($ref->path)) {
428 $this->dropbox->set_access_token($ref->access_key, $ref->access_secret);
c1b3ac43 429 return $this->dropbox->get_file($ref->path, $saveas, $CFG->repositorygetfiletimeout);
75dd40b2
MG
430 } else if (isset($ref->url)) {
431 $c = new curl;
432 $url = $this->get_file_download_link($ref->url);
c1b3ac43 433 $result = $c->download_one($url, null, array('filepath' => $saveas, 'timeout' => $CFG->repositorygetfiletimeout, 'followlocation' => true));
75dd40b2
MG
434 $info = $c->get_info();
435 if ($result !== true || !isset($info['http_code']) || $info['http_code'] != 200) {
436 throw new moodle_exception('errorwhiledownload', 'repository', '', $result);
437 }
438 return array('path'=>$saveas, 'url'=>$url);
439 }
440 throw new moodle_exception('cannotdownload', 'repository');
e35194be
DC
441 }
442 /**
443 * Add Plugin settings input to Moodle form
67233725 444 *
75dd40b2
MG
445 * @param moodleform $mform Moodle form (passed by reference)
446 * @param string $classname repository class name
e35194be 447 */
68a7c9a6 448 public static function type_config_form($mform, $classname = 'repository') {
e35194be 449 global $CFG;
a5adfa26 450 parent::type_config_form($mform);
e35194be
DC
451 $key = get_config('dropbox', 'dropbox_key');
452 $secret = get_config('dropbox', 'dropbox_secret');
453
454 if (empty($key)) {
455 $key = '';
456 }
457 if (empty($secret)) {
458 $secret = '';
459 }
460
461 $strrequired = get_string('required');
462
463 $mform->addElement('text', 'dropbox_key', get_string('apikey', 'repository_dropbox'), array('value'=>$key,'size' => '40'));
63745aef 464 $mform->setType('dropbox_key', PARAM_RAW_TRIMMED);
e35194be
DC
465 $mform->addElement('text', 'dropbox_secret', get_string('secret', 'repository_dropbox'), array('value'=>$secret,'size' => '40'));
466
467 $mform->addRule('dropbox_key', $strrequired, 'required', null, 'client');
468 $mform->addRule('dropbox_secret', $strrequired, 'required', null, 'client');
63745aef 469 $mform->setType('dropbox_secret', PARAM_RAW_TRIMMED);
e35194be
DC
470 $str_getkey = get_string('instruction', 'repository_dropbox');
471 $mform->addElement('static', null, '', $str_getkey);
75dd40b2
MG
472
473 $mform->addElement('text', 'dropbox_cachelimit', get_string('cachelimit', 'repository_dropbox'), array('size' => '40'));
7e3f70be
DP
474 $mform->addRule('dropbox_cachelimit', null, 'numeric', null, 'client');
475 $mform->setType('dropbox_cachelimit', PARAM_INT);
75dd40b2
MG
476 $mform->addElement('static', 'dropbox_cachelimit_info', '', get_string('cachelimit_info', 'repository_dropbox'));
477 }
478
e35194be
DC
479 /**
480 * Option names of dropbox plugin
67233725 481 *
e35194be
DC
482 * @return array
483 */
484 public static function get_type_option_names() {
75dd40b2 485 return array('dropbox_key', 'dropbox_secret', 'pluginname', 'dropbox_cachelimit');
e35194be
DC
486 }
487
488 /**
489 * Dropbox plugin supports all kinds of files
67233725 490 *
e35194be
DC
491 * @return array
492 */
493 public function supported_filetypes() {
494 return '*';
495 }
3e123368 496
e35194be
DC
497 /**
498 * User cannot use the external link to dropbox
67233725 499 *
e35194be
DC
500 * @return int
501 */
502 public function supported_returntypes() {
75dd40b2
MG
503 return FILE_INTERNAL | FILE_REFERENCE | FILE_EXTERNAL;
504 }
505
506 /**
507 * Return file URL for external link
508 *
509 * @param string $reference the result of get_file_reference()
510 * @return string
511 */
512 public function get_link($reference) {
c1b3ac43 513 global $CFG;
75dd40b2 514 $ref = unserialize($reference);
006bbbdf
MG
515 if (!isset($ref->url)) {
516 $this->dropbox->set_access_token($ref->access_key, $ref->access_secret);
c1b3ac43 517 $ref->url = $this->dropbox->get_file_share_link($ref->path, $CFG->repositorygetfiletimeout);
006bbbdf 518 }
75dd40b2 519 return $this->get_file_download_link($ref->url);
67233725
DC
520 }
521
522 /**
523 * Prepare file reference information
524 *
525 * @param string $source
526 * @return string file referece
527 */
528 public function get_file_reference($source) {
c1b3ac43 529 global $USER, $CFG;
67233725
DC
530 $reference = new stdClass;
531 $reference->path = $source;
59cb7598
MG
532 $reference->userid = $USER->id;
533 $reference->username = fullname($USER);
75dd40b2
MG
534 $reference->access_key = get_user_preferences($this->setting.'_access_key', '');
535 $reference->access_secret = get_user_preferences($this->setting.'_access_secret', '');
536
537 // by API we don't know if we need this reference to just download a file from dropbox
538 // into moodle filepool or create a reference. Since we need to create a shared link
539 // only in case of reference we analyze the script parameter
540 $usefilereference = optional_param('usefilereference', false, PARAM_BOOL);
541 if ($usefilereference) {
542 $this->dropbox->set_access_token($reference->access_key, $reference->access_secret);
c1b3ac43 543 $url = $this->dropbox->get_file_share_link($source, $CFG->repositorygetfiletimeout);
75dd40b2
MG
544 if ($url) {
545 unset($reference->access_key);
546 unset($reference->access_secret);
547 $reference->url = $url;
548 }
549 }
67233725
DC
550 return serialize($reference);
551 }
552
5e5923ea 553 public function sync_reference(stored_file $file) {
c3df05a9
RT
554 global $CFG;
555
5e5923ea
MG
556 if ($file->get_referencelastsync() + DAYSECS > time()) {
557 // Synchronise not more often than once a day.
558 return false;
559 }
560 $ref = unserialize($file->get_reference());
75dd40b2
MG
561 if (!isset($ref->url)) {
562 // this is an old-style reference in DB. We need to fix it
5e5923ea 563 $ref = unserialize($this->fix_old_style_reference($file->get_reference()));
75dd40b2
MG
564 }
565 if (!isset($ref->url)) {
5e5923ea 566 return false;
0b2bfbd1 567 }
75dd40b2
MG
568 $c = new curl;
569 $url = $this->get_file_download_link($ref->url);
570 if (file_extension_in_typegroup($ref->path, 'web_image')) {
571 $saveas = $this->prepare_file('');
572 try {
c1b3ac43 573 $result = $c->download_one($url, array(), array('filepath' => $saveas, 'timeout' => $CFG->repositorysyncimagetimeout, 'followlocation' => true));
75dd40b2
MG
574 $info = $c->get_info();
575 if ($result === true && isset($info['http_code']) && $info['http_code'] == 200) {
5e5923ea
MG
576 $fs = get_file_storage();
577 list($contenthash, $filesize, $newfile) = $fs->add_file_to_pool($saveas);
578 $file->set_synchronized($contenthash, $filesize);
579 return true;
75dd40b2
MG
580 }
581 } catch (Exception $e) {}
59cb7598 582 }
c1b3ac43 583 $c->get($url, null, array('timeout' => $CFG->repositorysyncimagetimeout, 'followlocation' => true, 'nobody' => true));
75dd40b2
MG
584 $info = $c->get_info();
585 if (isset($info['http_code']) && $info['http_code'] == 200 &&
586 array_key_exists('download_content_length', $info) &&
587 $info['download_content_length'] >= 0) {
5e5923ea
MG
588 $filesize = (int)$info['download_content_length'];
589 $file->set_synchronized(null, $filesize);
590 return true;
75dd40b2 591 }
5e5923ea
MG
592 $file->set_missingsource();
593 return true;
75dd40b2 594 }
67233725
DC
595
596 /**
75dd40b2
MG
597 * Cache file from external repository by reference
598 *
599 * Dropbox repository regularly caches all external files that are smaller than
600 * {@link repository_dropbox::max_cache_bytes()}
67233725
DC
601 *
602 * @param string $reference this reference is generated by
603 * repository::get_file_reference()
604 * @param stored_file $storedfile created file reference
605 */
606 public function cache_file_by_reference($reference, $storedfile) {
75dd40b2
MG
607 try {
608 $this->import_external_file_contents($storedfile, $this->max_cache_bytes());
609 } catch (Exception $e) {}
67233725
DC
610 }
611
612 /**
613 * Return human readable reference information
614 * {@link stored_file::get_reference()}
615 *
616 * @param string $reference
0b2bfbd1
MG
617 * @param int $filestatus status of the file, 0 - ok, 666 - source missing
618 * @return string
67233725 619 */
0b2bfbd1 620 public function get_reference_details($reference, $filestatus = 0) {
59cb7598 621 global $USER;
67233725 622 $ref = unserialize($reference);
75dd40b2 623 $detailsprefix = $this->get_name();
59cb7598 624 if (isset($ref->userid) && $ref->userid != $USER->id && isset($ref->username)) {
75dd40b2 625 $detailsprefix .= ' ('.$ref->username.')';
59cb7598 626 }
75dd40b2 627 $details = $detailsprefix;
0b2bfbd1 628 if (isset($ref->path)) {
75dd40b2 629 $details .= ': '. $ref->path;
0b2bfbd1
MG
630 }
631 if (isset($ref->path) && !$filestatus) {
632 // Indicate this is from dropbox with path
633 return $details;
634 } else {
75dd40b2
MG
635 if (isset($ref->url)) {
636 $details = $detailsprefix. ': '. $ref->url;
637 }
0b2bfbd1
MG
638 return get_string('lostsource', 'repository', $details);
639 }
67233725
DC
640 }
641
d6453211
DC
642 /**
643 * Return the source information
644 *
59cb7598
MG
645 * @param string $source
646 * @return string
d6453211 647 */
59cb7598
MG
648 public function get_file_source_info($source) {
649 global $USER;
650 return 'Dropbox ('.fullname($USER).'): ' . $source;
d6453211
DC
651 }
652
75dd40b2
MG
653 /**
654 * Returns the maximum size of the Dropbox files to cache in moodle
655 *
5e5923ea 656 * Note that {@link repository_dropbox::sync_reference()} will try to cache images even
75dd40b2
MG
657 * when they are bigger in order to generate thumbnails. However there is
658 * a small timeout for downloading images for synchronisation and it will
659 * probably fail if the image is too big.
660 *
661 * @return int
662 */
663 public function max_cache_bytes() {
664 if ($this->cachelimit === null) {
665 $this->cachelimit = (int)get_config('dropbox', 'dropbox_cachelimit');
666 }
667 return $this->cachelimit;
668 }
669
67233725 670 /**
0b2bfbd1
MG
671 * Repository method to serve the referenced file
672 *
673 * This method is ivoked from {@link send_stored_file()}.
674 * Dropbox repository first caches the file by reading it into temporary folder and then
675 * serves from there.
67233725 676 *
0b2bfbd1 677 * @param stored_file $storedfile the file that contains the reference
0c431257 678 * @param int $lifetime Number of seconds before the file should expire from caches (null means $CFG->filelifetime)
67233725
DC
679 * @param int $filter 0 (default)=no filtering, 1=all files, 2=html files only
680 * @param bool $forcedownload If true (default false), forces download of file rather than view in browser/plugin
681 * @param array $options additional options affecting the file serving
682 */
0c431257 683 public function send_file($storedfile, $lifetime=null , $filter=0, $forcedownload=false, array $options = null) {
75dd40b2
MG
684 $ref = unserialize($storedfile->get_reference());
685 if ($storedfile->get_filesize() > $this->max_cache_bytes()) {
686 header('Location: '.$this->get_file_download_link($ref->url));
687 die;
688 }
689 try {
690 $this->import_external_file_contents($storedfile, $this->max_cache_bytes());
691 if (!is_array($options)) {
692 $options = array();
0b2bfbd1 693 }
75dd40b2
MG
694 $options['sendcachedexternalfile'] = true;
695 send_stored_file($storedfile, $lifetime, $filter, $forcedownload, $options);
696 } catch (moodle_exception $e) {
697 // redirect to Dropbox, it will show the error.
698 // We redirect to Dropbox shared link, not to download link here!
699 header('Location: '.$ref->url);
700 die;
67233725 701 }
67233725
DC
702 }
703
75dd40b2
MG
704 /**
705 * Caches all references to Dropbox files in moodle filepool
706 *
707 * Invoked by {@link repository_dropbox_cron()}. Only files smaller than
708 * {@link repository_dropbox::max_cache_bytes()} and only files which
709 * synchronisation timeout have not expired are cached.
710 */
67233725
DC
711 public function cron() {
712 $fs = get_file_storage();
713 $files = $fs->get_external_files($this->id);
714 foreach ($files as $file) {
75dd40b2
MG
715 try {
716 // This call will cache all files that are smaller than max_cache_bytes()
717 // and synchronise file size of all others
718 $this->import_external_file_contents($file, $this->max_cache_bytes());
719 } catch (moodle_exception $e) {}
67233725
DC
720 }
721 }
722}
723
724/**
725 * Dropbox plugin cron task
726 */
727function repository_dropbox_cron() {
728 $instances = repository::get_instances(array('type'=>'dropbox'));
729 foreach ($instances as $instance) {
730 $instance->cron();
3e123368
DC
731 }
732}