PageRenderTime 27ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/repository/dropbox/lib.php

https://bitbucket.org/kudutest1/moodlegit
PHP | 728 lines | 439 code | 50 blank | 239 comment | 70 complexity | 15dada2cebb9a855b1b70bd36cbda4b6 MD5 | raw file
  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. /**
  507. * Returns information about file in this repository by reference
  508. * {@link repository::get_file_reference()}
  509. * {@link repository::get_file()}
  510. *
  511. * Returns null if file not found or is not readable
  512. *
  513. * @param stdClass $reference file reference db record
  514. * @return null|stdClass that has 'filepath' property
  515. */
  516. public function get_file_by_reference($reference) {
  517. global $USER;
  518. $ref = unserialize($reference->reference);
  519. if (!isset($ref->url)) {
  520. // this is an old-style reference in DB. We need to fix it
  521. $ref = unserialize($this->fix_old_style_reference($reference->reference));
  522. }
  523. if (!isset($ref->url)) {
  524. return null;
  525. }
  526. $c = new curl;
  527. $url = $this->get_file_download_link($ref->url);
  528. if (file_extension_in_typegroup($ref->path, 'web_image')) {
  529. $saveas = $this->prepare_file('');
  530. try {
  531. $result = $c->download_one($url, array(), array('filepath' => $saveas, 'timeout' => self::SYNCIMAGE_TIMEOUT, 'followlocation' => true));
  532. $info = $c->get_info();
  533. if ($result === true && isset($info['http_code']) && $info['http_code'] == 200) {
  534. return (object)array('filepath' => $saveas);
  535. }
  536. } catch (Exception $e) {}
  537. }
  538. $c->get($url, null, array('timeout' => self::SYNCIMAGE_TIMEOUT, 'followlocation' => true, 'nobody' => true));
  539. $info = $c->get_info();
  540. if (isset($info['http_code']) && $info['http_code'] == 200 &&
  541. array_key_exists('download_content_length', $info) &&
  542. $info['download_content_length'] >= 0) {
  543. return (object)array('filesize' => (int)$info['download_content_length']);
  544. }
  545. return null;
  546. }
  547. /**
  548. * Cache file from external repository by reference
  549. *
  550. * Dropbox repository regularly caches all external files that are smaller than
  551. * {@link repository_dropbox::max_cache_bytes()}
  552. *
  553. * @param string $reference this reference is generated by
  554. * repository::get_file_reference()
  555. * @param stored_file $storedfile created file reference
  556. */
  557. public function cache_file_by_reference($reference, $storedfile) {
  558. try {
  559. $this->import_external_file_contents($storedfile, $this->max_cache_bytes());
  560. } catch (Exception $e) {}
  561. }
  562. /**
  563. * Return human readable reference information
  564. * {@link stored_file::get_reference()}
  565. *
  566. * @param string $reference
  567. * @param int $filestatus status of the file, 0 - ok, 666 - source missing
  568. * @return string
  569. */
  570. public function get_reference_details($reference, $filestatus = 0) {
  571. global $USER;
  572. $ref = unserialize($reference);
  573. $detailsprefix = $this->get_name();
  574. if (isset($ref->userid) && $ref->userid != $USER->id && isset($ref->username)) {
  575. $detailsprefix .= ' ('.$ref->username.')';
  576. }
  577. $details = $detailsprefix;
  578. if (isset($ref->path)) {
  579. $details .= ': '. $ref->path;
  580. }
  581. if (isset($ref->path) && !$filestatus) {
  582. // Indicate this is from dropbox with path
  583. return $details;
  584. } else {
  585. if (isset($ref->url)) {
  586. $details = $detailsprefix. ': '. $ref->url;
  587. }
  588. return get_string('lostsource', 'repository', $details);
  589. }
  590. }
  591. /**
  592. * Return the source information
  593. *
  594. * @param string $source
  595. * @return string
  596. */
  597. public function get_file_source_info($source) {
  598. global $USER;
  599. return 'Dropbox ('.fullname($USER).'): ' . $source;
  600. }
  601. /**
  602. * Returns the maximum size of the Dropbox files to cache in moodle
  603. *
  604. * Note that {@link repository_dropbox::get_file_by_reference()} called by
  605. * {@link repository::sync_external_file()} will try to cache images even
  606. * when they are bigger in order to generate thumbnails. However there is
  607. * a small timeout for downloading images for synchronisation and it will
  608. * probably fail if the image is too big.
  609. *
  610. * @return int
  611. */
  612. public function max_cache_bytes() {
  613. if ($this->cachelimit === null) {
  614. $this->cachelimit = (int)get_config('dropbox', 'dropbox_cachelimit');
  615. }
  616. return $this->cachelimit;
  617. }
  618. /**
  619. * Repository method to serve the referenced file
  620. *
  621. * This method is ivoked from {@link send_stored_file()}.
  622. * Dropbox repository first caches the file by reading it into temporary folder and then
  623. * serves from there.
  624. *
  625. * @param stored_file $storedfile the file that contains the reference
  626. * @param int $lifetime Number of seconds before the file should expire from caches (default 24 hours)
  627. * @param int $filter 0 (default)=no filtering, 1=all files, 2=html files only
  628. * @param bool $forcedownload If true (default false), forces download of file rather than view in browser/plugin
  629. * @param array $options additional options affecting the file serving
  630. */
  631. public function send_file($storedfile, $lifetime=86400 , $filter=0, $forcedownload=false, array $options = null) {
  632. $ref = unserialize($storedfile->get_reference());
  633. if ($storedfile->get_filesize() > $this->max_cache_bytes()) {
  634. header('Location: '.$this->get_file_download_link($ref->url));
  635. die;
  636. }
  637. try {
  638. $this->import_external_file_contents($storedfile, $this->max_cache_bytes());
  639. if (!is_array($options)) {
  640. $options = array();
  641. }
  642. $options['sendcachedexternalfile'] = true;
  643. send_stored_file($storedfile, $lifetime, $filter, $forcedownload, $options);
  644. } catch (moodle_exception $e) {
  645. // redirect to Dropbox, it will show the error.
  646. // We redirect to Dropbox shared link, not to download link here!
  647. header('Location: '.$ref->url);
  648. die;
  649. }
  650. }
  651. /**
  652. * Caches all references to Dropbox files in moodle filepool
  653. *
  654. * Invoked by {@link repository_dropbox_cron()}. Only files smaller than
  655. * {@link repository_dropbox::max_cache_bytes()} and only files which
  656. * synchronisation timeout have not expired are cached.
  657. */
  658. public function cron() {
  659. $fs = get_file_storage();
  660. $files = $fs->get_external_files($this->id);
  661. foreach ($files as $file) {
  662. try {
  663. // This call will cache all files that are smaller than max_cache_bytes()
  664. // and synchronise file size of all others
  665. $this->import_external_file_contents($file, $this->max_cache_bytes());
  666. } catch (moodle_exception $e) {}
  667. }
  668. }
  669. }
  670. /**
  671. * Dropbox plugin cron task
  672. */
  673. function repository_dropbox_cron() {
  674. $instances = repository::get_instances(array('type'=>'dropbox'));
  675. foreach ($instances as $instance) {
  676. $instance->cron();
  677. }
  678. }