MDL-32867 Working with external references in filemanager
[moodle.git] / lib / filestorage / stored_file.php
CommitLineData
16a95e8f 1<?php
16a95e8f 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
18/**
8496fdac 19 * Definition of a class stored_file.
16a95e8f 20 *
d2b7803e
DC
21 * @package core_files
22 * @copyright 2008 Petr Skoda {@link http://skodak.org}
23 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
16a95e8f 24 */
25
64f93798
PS
26defined('MOODLE_INTERNAL') || die();
27
28require_once("$CFG->libdir/filestorage/stored_file.php");
67233725 29require_once("$CFG->dirroot/repository/lib.php");
172dd12c 30
31/**
8496fdac
PS
32 * Class representing local files stored in a sha1 file pool.
33 *
34 * Since Moodle 2.0 file contents are stored in sha1 pool and
35 * all other file information is stored in new "files" database table.
36 *
d2b7803e
DC
37 * @package core_files
38 * @category files
8496fdac
PS
39 * @copyright 2008 Petr Skoda {@link http://skodak.org}
40 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
41 * @since Moodle 2.0
172dd12c 42 */
43class stored_file {
8496fdac 44 /** @var file_storage file storage pool instance */
172dd12c 45 private $fs;
d2b7803e 46 /** @var stdClass record from the files table */
172dd12c 47 private $file_record;
693ef3a8
PS
48 /** @var string location of content files */
49 private $filedir;
67233725
DC
50 /** @var repository repository plugin instance */
51 public $repository;
172dd12c 52
53 /**
8496fdac
PS
54 * Constructor, this constructor should be called ONLY from the file_storage class!
55 *
56 * @param file_storage $fs file storage instance
d2b7803e
DC
57 * @param stdClass $file_record description of file
58 * @param string $filedir location of file directory with sh1 named content files
172dd12c 59 */
693ef3a8 60 public function __construct(file_storage $fs, stdClass $file_record, $filedir) {
67233725 61 global $DB, $CFG;
8496fdac
PS
62 $this->fs = $fs;
63 $this->file_record = clone($file_record); // prevent modifications
693ef3a8 64 $this->filedir = $filedir; // keep secret, do not expose!
67233725
DC
65
66 if (!empty($file_record->repositoryid)) {
67 $this->repository = repository::get_repository_by_id($file_record->repositoryid, SYSCONTEXTID);
68 if ($this->repository->supported_returntypes() & FILE_REFERENCE != FILE_REFERENCE) {
69 // Repository cannot do file reference.
70 throw new moodle_exception('error');
71 }
72 } else {
73 $this->repository = null;
74 }
75 }
76
77 /**
78 * Whether or not this is a external resource
79 *
80 * @return bool
81 */
82 public function is_external_file() {
83 return !empty($this->repository);
84 }
85
86 /**
87 * Update some file record fields
88 * NOTE: Must remain protected
89 *
90 * @param stdClass $dataobject
91 */
92 protected function update($dataobject) {
93 global $DB;
94 $keys = array_keys((array)$this->file_record);
95 foreach ($dataobject as $field => $value) {
96 if (in_array($field, $keys)) {
97 if ($field == 'contextid' and (!is_number($value) or $value < 1)) {
98 throw new file_exception('storedfileproblem', 'Invalid contextid');
99 }
100
101 if ($field == 'component') {
102 $value = clean_param($value, PARAM_COMPONENT);
103 if (empty($value)) {
104 throw new file_exception('storedfileproblem', 'Invalid component');
105 }
106 }
107
108 if ($field == 'filearea') {
109 $value = clean_param($value, PARAM_AREA);
110 if (empty($value)) {
111 throw new file_exception('storedfileproblem', 'Invalid filearea');
112 }
113 }
114
115 if ($field == 'itemid' and (!is_number($value) or $value < 0)) {
116 throw new file_exception('storedfileproblem', 'Invalid itemid');
117 }
118
119
120 if ($field == 'filepath') {
121 $value = clean_param($value, PARAM_PATH);
122 if (strpos($value, '/') !== 0 or strrpos($value, '/') !== strlen($value)-1) {
123 // path must start and end with '/'
124 throw new file_exception('storedfileproblem', 'Invalid file path');
125 }
126 }
127
128 if ($field == 'filename') {
129 $value = clean_param($value, PARAM_FILE);
130 if ($value === '') {
131 throw new file_exception('storedfileproblem', 'Invalid file name');
132 }
133 }
134
135 if ($field === 'timecreated' or $field === 'timemodified') {
136 if (!is_number($value)) {
137 throw new file_exception('storedfileproblem', 'Invalid timestamp');
138 }
139 if ($value < 0) {
140 $value = 0;
141 }
142 }
143
144 if ($field == 'referencefileid' or $field == 'referencelastsync' or $field == 'referencelifetime') {
145 $value = clean_param($value, PARAM_INT);
146 }
147
148 // adding the field
149 $this->file_record->$field = $value;
150 } else {
151 throw new coding_exception("Invalid field name, $field doesn't exist in file record");
152 }
153 }
154 $DB->update_record('files', $this->file_record);
155 }
156
157 /**
158 * Rename filename
159 *
160 * @param string $filepath file path
161 * @param string $filename file name
162 */
163 public function rename($filepath, $filename) {
164 $filerecord = new stdClass;
165 $filerecord->filepath = $filepath;
166 $filerecord->filename = $filename;
167 // populate the pathname hash
168 $filerecord->pathnamehash = $this->fs->get_pathname_hash($this->file_record->contextid, $this->file_record->component, $this->file_record->filearea, $this->file_record->itemid, $filepath, $filename);
169 $this->update($filerecord);
170 }
171
172 /**
173 * Replace the content by providing another stored_file instance
174 *
175 * @param stored_file $storedfile
176 */
177 public function replace_content_with(stored_file $storedfile) {
178 $contenthash = $storedfile->get_contenthash();
179 $this->set_contenthash($contenthash);
180 }
181
182 /**
183 * Delete file reference
184 *
185 */
186 public function delete_reference() {
187 global $DB;
188 // Remove repository info.
189 $this->repository = null;
190 unset($this->file_record->repositoryid);
191 unset($this->file_record->reference);
192 unset($this->file_record->referencelastsync);
193 unset($this->file_record->referencelifetime);
194
195 // Remove reference info from DB.
196 $DB->delete_records('files_reference', array('id'=>$this->file_record->referencefileid));
172dd12c 197 }
198
c092681b
MG
199 /**
200 * Update some file record fields
201 *
202 * @param stdClass $dataobject
203 */
204 public function update($dataobject) {
205 // TODO MDL-28666 THIS FUNCTION IS COPIED FROM UNFINISHED CODE OF MDL-28666.
206 global $DB;
207 $keys = array_keys((array)$this->file_record);
208 foreach ($dataobject as $field => $value) {
209 if (in_array($field, $keys)) {
210 $this->file_record->$field = $value;
211 } else {
212 throw new coding_exception("Invalid field name, $field doesn't exist in file record");
213 }
214 }
215 $DB->update_record('files', $this->file_record);
216 }
217
172dd12c 218 /**
219 * Is this a directory?
8496fdac
PS
220 *
221 * Directories are only emulated, internally they are stored as empty
222 * files with a "." instead of name - this means empty directory contains
223 * exactly one empty file with name dot.
224 *
225 * @return bool true means directory, false means file
172dd12c 226 */
227 public function is_directory() {
8496fdac 228 return ($this->file_record->filename === '.');
172dd12c 229 }
230
231 /**
8496fdac
PS
232 * Delete file from files table.
233 *
234 * The content of files stored in sha1 pool is reclaimed
235 * later - the occupied disk space is reclaimed much later.
236 *
237 * @return bool always true or exception if error occurred
172dd12c 238 */
239 public function delete() {
240 global $DB;
67233725
DC
241 // If other files referring to this file, we need convert them
242 if ($files = $this->fs->get_references_by_storedfile($this)) {
243 foreach ($files as $file) {
244 $this->fs->import_external_file($file);
245 }
246 }
247 // Now delete file records in DB
1aa01caf 248 $DB->delete_records('files', array('id'=>$this->file_record->id));
67233725 249 $DB->delete_records('files_reference', array('id'=>$this->file_record->referencefileid));
1aa01caf 250 // moves pool file to trash if content not needed any more
251 $this->fs->deleted_file_cleanup($this->file_record->contenthash);
8496fdac 252 return true; // BC only
172dd12c 253 }
254
255 /**
8496fdac
PS
256 * Protected - developers must not gain direct access to this function.
257 *
17d9269f 258 * NOTE: do not make this public, we must not modify or delete the pool files directly! ;-)
8496fdac
PS
259 *
260 * @return string full path to pool file with file content
172dd12c 261 **/
262 protected function get_content_file_location() {
67233725
DC
263 $this->sync_external_file();
264 // Detect is local file or not.
17d9269f 265 $contenthash = $this->file_record->contenthash;
266 $l1 = $contenthash[0].$contenthash[1];
267 $l2 = $contenthash[2].$contenthash[3];
67233725 268 $path = "$this->filedir/$l1/$l2/$contenthash";
693ef3a8 269 return "$this->filedir/$l1/$l2/$contenthash";
172dd12c 270 }
271
5035a8b4 272 /**
273 * adds this file path to a curl request (POST only)
274 *
275 * @param curl $curlrequest the curl request object
276 * @param string $key what key to use in the POST request
8496fdac 277 * @return void
5035a8b4 278 */
279 public function add_to_curl_request(&$curlrequest, $key) {
280 $curlrequest->_tmp_file_post_params[$key] = '@' . $this->get_content_file_location();
281 }
282
172dd12c 283 /**
284 * Returns file handle - read only mode, no writing allowed into pool files!
8496fdac
PS
285 *
286 * When you want to modify a file, create a new file and delete the old one.
287 *
288 * @return resource file handle
172dd12c 289 */
290 public function get_content_file_handle() {
291 $path = $this->get_content_file_location();
292 if (!is_readable($path)) {
1aa01caf 293 if (!$this->fs->try_content_recovery($this) or !is_readable($path)) {
d610cb89 294 throw new file_exception('storedfilecannotread', '', $path);
1aa01caf 295 }
172dd12c 296 }
67233725 297 return fopen($path, 'rb'); // Binary reading only!!
172dd12c 298 }
299
300 /**
8496fdac 301 * Dumps file content to page.
172dd12c 302 */
303 public function readfile() {
304 $path = $this->get_content_file_location();
305 if (!is_readable($path)) {
1aa01caf 306 if (!$this->fs->try_content_recovery($this) or !is_readable($path)) {
d610cb89 307 throw new file_exception('storedfilecannotread', '', $path);
1aa01caf 308 }
172dd12c 309 }
310 readfile($path);
311 }
312
313 /**
8496fdac
PS
314 * Returns file content as string.
315 *
172dd12c 316 * @return string content
317 */
318 public function get_content() {
319 $path = $this->get_content_file_location();
320 if (!is_readable($path)) {
1aa01caf 321 if (!$this->fs->try_content_recovery($this) or !is_readable($path)) {
d610cb89 322 throw new file_exception('storedfilecannotread', '', $path);
1aa01caf 323 }
172dd12c 324 }
325 return file_get_contents($this->get_content_file_location());
326 }
327
6c0e2d08 328 /**
8496fdac
PS
329 * Copy content of file to given pathname.
330 *
331 * @param string $pathname real path to the new file
6c0e2d08 332 * @return bool success
333 */
334 public function copy_content_to($pathname) {
335 $path = $this->get_content_file_location();
336 if (!is_readable($path)) {
1aa01caf 337 if (!$this->fs->try_content_recovery($this) or !is_readable($path)) {
d610cb89 338 throw new file_exception('storedfilecannotread', '', $path);
1aa01caf 339 }
6c0e2d08 340 }
341 return copy($path, $pathname);
342 }
343
17d9269f 344 /**
8496fdac
PS
345 * List contents of archive.
346 *
d2b7803e 347 * @param file_packer $packer file packer instance
c78a0558 348 * @return array of file infos
349 */
350 public function list_files(file_packer $packer) {
351 $archivefile = $this->get_content_file_location();
352 return $packer->list_files($archivefile);
353 }
354
355 /**
8496fdac
PS
356 * Extract file to given file path (real OS filesystem), existing files are overwritten.
357 *
d2b7803e 358 * @param file_packer $packer file packer instance
0b0bfa93 359 * @param string $pathname target directory
8496fdac 360 * @return array|bool list of processed files; false if error
17d9269f 361 */
0b0bfa93 362 public function extract_to_pathname(file_packer $packer, $pathname) {
363 $archivefile = $this->get_content_file_location();
364 return $packer->extract_to_pathname($archivefile, $pathname);
17d9269f 365 }
366
367 /**
8496fdac
PS
368 * Extract file to given file path (real OS filesystem), existing files are overwritten.
369 *
d2b7803e
DC
370 * @param file_packer $packer file packer instance
371 * @param int $contextid context ID
372 * @param string $component component
373 * @param string $filearea file area
374 * @param int $itemid item ID
375 * @param string $pathbase path base
376 * @param int $userid user ID
8496fdac 377 * @return array|bool list of processed files; false if error
17d9269f 378 */
64f93798 379 public function extract_to_storage(file_packer $packer, $contextid, $component, $filearea, $itemid, $pathbase, $userid = NULL) {
0b0bfa93 380 $archivefile = $this->get_content_file_location();
64f93798 381 return $packer->extract_to_storage($archivefile, $contextid, $component, $filearea, $itemid, $pathbase);
17d9269f 382 }
383
b1897a6d 384 /**
8496fdac
PS
385 * Add file/directory into archive.
386 *
d2b7803e 387 * @param file_archive $filearch file archive instance
c78a0558 388 * @param string $archivepath pathname in archive
b1897a6d 389 * @return bool success
390 */
0b0bfa93 391 public function archive_file(file_archive $filearch, $archivepath) {
b1897a6d 392 if ($this->is_directory()) {
0b0bfa93 393 return $filearch->add_directory($archivepath);
b1897a6d 394 } else {
395 $path = $this->get_content_file_location();
396 if (!is_readable($path)) {
397 return false;
398 }
0b0bfa93 399 return $filearch->add_file_from_pathname($archivepath, $path);
b1897a6d 400 }
401 }
402
797f19e8 403 /**
404 * Returns information about image,
405 * information is determined from the file content
d2b7803e 406 *
797f19e8 407 * @return mixed array with width, height and mimetype; false if not an image
408 */
409 public function get_imageinfo() {
410 if (!$imageinfo = getimagesize($this->get_content_file_location())) {
411 return false;
412 }
413 $image = array('width'=>$imageinfo[0], 'height'=>$imageinfo[1], 'mimetype'=>image_type_to_mime_type($imageinfo[2]));
414 if (empty($image['width']) or empty($image['height']) or empty($image['mimetype'])) {
415 // gd can not parse it, sorry
416 return false;
417 }
418 return $image;
419 }
420
421 /**
422 * Verifies the file is a valid web image - gif, png and jpeg only.
8496fdac 423 *
797f19e8 424 * It should be ok to serve this image from server without any other security workarounds.
8496fdac 425 *
797f19e8 426 * @return bool true if file ok
427 */
428 public function is_valid_image() {
429 $mimetype = $this->get_mimetype();
430 if ($mimetype !== 'image/gif' and $mimetype !== 'image/jpeg' and $mimetype !== 'image/png') {
431 return false;
432 }
433 if (!$info = $this->get_imageinfo()) {
434 return false;
435 }
436 if ($info['mimetype'] !== $mimetype) {
437 return false;
438 }
439 // ok, GD likes this image
440 return true;
441 }
442
4b6b5ce7 443 /**
8496fdac
PS
444 * Returns parent directory, creates missing parents if needed.
445 *
446 * @return stored_file
4b6b5ce7 447 */
448 public function get_parent_directory() {
449 if ($this->file_record->filepath === '/' and $this->file_record->filename === '.') {
450 //root dir does not have parent
451 return null;
452 }
453
454 if ($this->file_record->filename !== '.') {
64f93798 455 return $this->fs->create_directory($this->file_record->contextid, $this->file_record->component, $this->file_record->filearea, $this->file_record->itemid, $this->file_record->filepath);
4b6b5ce7 456 }
457
458 $filepath = $this->file_record->filepath;
459 $filepath = trim($filepath, '/');
460 $dirs = explode('/', $filepath);
461 array_pop($dirs);
462 $filepath = implode('/', $dirs);
463 $filepath = ($filepath === '') ? '/' : "/$filepath/";
464
64f93798 465 return $this->fs->create_directory($this->file_record->contextid, $this->file_record->component, $this->file_record->filearea, $this->file_record->itemid, $filepath);
4b6b5ce7 466 }
467
16a95e8f 468 /**
67233725
DC
469 * Sync external files
470 *
471 * @return bool true if file content changed, false if not
472 */
473 public function sync_external_file() {
474 global $CFG, $DB;
475 if (empty($this->file_record->referencefileid)) {
476 return false;
477 }
478 if (empty($this->file_record->referencelastsync) or ($this->file_record->referencelastsync + $this->file_record->referencelifetime < time())) {
479 require_once($CFG->dirroot.'/repository/lib.php');
480 if (repository::sync_external_file($this)) {
481 $prevcontent = $this->file_record->contenthash;
482 $sql = "SELECT f.*, r.repositoryid, r.reference
483 FROM {files} f
484 LEFT JOIN {files_reference} r
485 ON f.referencefileid = r.id
486 WHERE f.id = ?";
487 $this->file_record = $DB->get_record_sql($sql, array($this->file_record->id), MUST_EXIST);
488 return ($prevcontent !== $this->file_record->contenthash);
489 }
490 }
491 return false;
492 }
493
494 /**
495 * Returns context id of the file
8496fdac 496 *
16a95e8f 497 * @return int context id
498 */
172dd12c 499 public function get_contextid() {
500 return $this->file_record->contextid;
501 }
502
16a95e8f 503 /**
64f93798
PS
504 * Returns component name - this is the owner of the areas,
505 * nothing else is allowed to read or modify the files directly!!
506 *
507 * @return string
508 */
509 public function get_component() {
510 return $this->file_record->component;
511 }
512
513 /**
514 * Returns file area name, this divides files of one component into groups with different access control.
515 * All files in one area have the same access control.
8496fdac 516 *
16a95e8f 517 * @return string
518 */
172dd12c 519 public function get_filearea() {
520 return $this->file_record->filearea;
521 }
522
16a95e8f 523 /**
8496fdac
PS
524 * Returns returns item id of file.
525 *
16a95e8f 526 * @return int
527 */
172dd12c 528 public function get_itemid() {
529 return $this->file_record->itemid;
530 }
531
16a95e8f 532 /**
533 * Returns file path - starts and ends with /, \ are not allowed.
8496fdac 534 *
16a95e8f 535 * @return string
536 */
172dd12c 537 public function get_filepath() {
538 return $this->file_record->filepath;
539 }
540
16a95e8f 541 /**
542 * Returns file name or '.' in case of directories.
8496fdac 543 *
16a95e8f 544 * @return string
545 */
172dd12c 546 public function get_filename() {
547 return $this->file_record->filename;
548 }
549
16a95e8f 550 /**
551 * Returns id of user who created the file.
8496fdac 552 *
16a95e8f 553 * @return int
554 */
172dd12c 555 public function get_userid() {
556 return $this->file_record->userid;
557 }
558
16a95e8f 559 /**
560 * Returns the size of file in bytes.
8496fdac 561 *
16a95e8f 562 * @return int bytes
563 */
172dd12c 564 public function get_filesize() {
67233725 565 $this->sync_external_file();
172dd12c 566 return $this->file_record->filesize;
567 }
568
16a95e8f 569 /**
8496fdac
PS
570 * Returns mime type of file.
571 *
16a95e8f 572 * @return string
573 */
172dd12c 574 public function get_mimetype() {
575 return $this->file_record->mimetype;
576 }
577
16a95e8f 578 /**
8496fdac
PS
579 * Returns unix timestamp of file creation date.
580 *
16a95e8f 581 * @return int
582 */
172dd12c 583 public function get_timecreated() {
584 return $this->file_record->timecreated;
585 }
586
16a95e8f 587 /**
8496fdac
PS
588 * Returns unix timestamp of last file modification.
589 *
16a95e8f 590 * @return int
591 */
172dd12c 592 public function get_timemodified() {
67233725 593 $this->sync_external_file();
172dd12c 594 return $this->file_record->timemodified;
595 }
6c0e2d08 596
67233725
DC
597 /**
598 * set timemodified
599 *
600 * @param int $timemodified
601 */
602 public function set_timemodified($timemodified) {
603 $filerecord = new stdClass;
604 $filerecord->timemodified = $timemodified;
605 $this->update($filerecord);
606 }
607
16a95e8f 608 /**
8496fdac
PS
609 * Returns file status flag.
610 *
16a95e8f 611 * @return int 0 means file OK, anything else is a problem and file can not be used
612 */
6c0e2d08 613 public function get_status() {
614 return $this->file_record->status;
615 }
ee03a651 616
16a95e8f 617 /**
8496fdac
PS
618 * Returns file id.
619 *
16a95e8f 620 * @return int
621 */
ee03a651 622 public function get_id() {
623 return $this->file_record->id;
624 }
4284e1cc 625
16a95e8f 626 /**
8496fdac
PS
627 * Returns sha1 hash of file content.
628 *
16a95e8f 629 * @return string
630 */
4284e1cc 631 public function get_contenthash() {
67233725 632 $this->sync_external_file();
4284e1cc 633 return $this->file_record->contenthash;
634 }
6ed19c74 635
67233725
DC
636 /**
637 * Set contenthash
638 *
639 * @param string $contenthash
640 */
641 protected function set_contenthash($contenthash) {
642 // make sure the content exists in moodle file pool
643 if ($this->fs->content_exists($contenthash)) {
644 $filerecord = new stdClass;
645 $filerecord->contenthash = $contenthash;
646 $this->update($filerecord);
647 } else {
648 throw new file_exception('storedfileproblem', 'Invalid contenthash, content must be already in filepool', $contenthash);
649 }
650 }
651
16a95e8f 652 /**
64f93798 653 * Returns sha1 hash of all file path components sha1("contextid/component/filearea/itemid/dir/dir/filename.ext").
8496fdac 654 *
16a95e8f 655 * @return string
656 */
6ed19c74 657 public function get_pathnamehash() {
658 return $this->file_record->pathnamehash;
659 }
1dce6261
DC
660
661 /**
8496fdac
PS
662 * Returns the license type of the file, it is a short name referred from license table.
663 *
1dce6261
DC
664 * @return string
665 */
666 public function get_license() {
667 return $this->file_record->license;
668 }
669
67233725
DC
670 /**
671 * Set license
672 *
673 * @param string $license license
674 */
675 public function set_license($license) {
676 $filerecord = new stdClass;
677 $filerecord->license = $license;
678 $this->update($filerecord);
679 }
680
1dce6261 681 /**
8496fdac
PS
682 * Returns the author name of the file.
683 *
1dce6261
DC
684 * @return string
685 */
686 public function get_author() {
31cd5fe8 687 return $this->file_record->author;
1dce6261
DC
688 }
689
67233725
DC
690 /**
691 * Set author
692 *
693 * @param string $author
694 */
695 public function set_author($author) {
696 $filerecord = new stdClass;
697 $filerecord->author = $author;
698 $this->update($filerecord);
699 }
700
1dce6261 701 /**
8496fdac
PS
702 * Returns the source of the file, usually it is a url.
703 *
1dce6261
DC
704 * @return string
705 */
706 public function get_source() {
707 return $this->file_record->source;
708 }
8496fdac 709
67233725
DC
710 /**
711 * Set license
712 *
713 * @param string $license license
714 */
715 public function set_source($source) {
716 $filerecord = new stdClass;
717 $filerecord->source = $source;
718 $this->update($filerecord);
719 }
720
721
f79321f1
DC
722 /**
723 * Returns the sort order of file
724 *
725 * @return int
726 */
727 public function get_sortorder() {
728 return $this->file_record->sortorder;
729 }
67233725
DC
730
731 /**
732 * Set file sort order
733 *
734 * @param int $sortorder
735 * @return int
736 */
737 public function set_sortorder($sortorder) {
738 $filerecord = new stdClass;
739 $filerecord->sortorder = $sortorder;
740 $this->update($filerecord);
741 }
742
743 /**
744 * Returns repository id
745 *
746 * @return int|null
747 */
748 public function get_repository_id() {
749 if (!empty($this->repository)) {
750 return $this->repository->id;
751 } else {
752 return null;
753 }
754 }
755
756 /**
757 * get reference file id
758 * @return int
759 */
760 public function get_referencefileid() {
761 return $this->file_record->referencefileid;
762 }
763
764 /**
765 * Get reference last sync time
766 * @return int
767 */
768 public function get_referencelastsync() {
769 return $this->file_record->referencelastsync;
770 }
771
772 /**
773 * Get reference last sync time
774 * @return int
775 */
776 public function get_referencelifetime() {
777 return $this->file_record->referencelifetime;
778 }
779 /**
780 * Returns file reference
781 *
782 * @return string
783 */
784 public function get_reference() {
785 return $this->file_record->reference;
786 }
787
788 /**
789 * Get human readable file reference information
790 *
791 * @return string
792 */
793 public function get_reference_details() {
794 return $this->repository->get_reference_details($this->get_reference());
795 }
796
797 /**
798 * Send file references
799 *
800 * @param int $lifetime Number of seconds before the file should expire from caches (default 24 hours)
801 * @param int $filter 0 (default)=no filtering, 1=all files, 2=html files only
802 * @param bool $forcedownload If true (default false), forces download of file rather than view in browser/plugin
803 * @param array $options additional options affecting the file serving
804 */
805 public function send_file($lifetime, $filter, $forcedownload, $options) {
806 $this->repository->send_file($this, $lifetime, $filter, $forcedownload, $options);
807 }
f79321f1 808}