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