PageRenderTime 32ms CodeModel.GetById 1ms RepoModel.GetById 0ms app.codeStats 0ms

/repository/dropbox/lib.php

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