MDL-18011 - removing reference to loancalc block from core
[moodle.git] / lib / file / stored_file.php
CommitLineData
16a95e8f 1<?php
2
3// This file is part of Moodle - http://moodle.org/
4//
5// Moodle is free software: you can redistribute it and/or modify
6// it under the terms of the GNU General Public License as published by
7// the Free Software Foundation, either version 3 of the License, or
8// (at your option) any later version.
9//
10// Moodle is distributed in the hope that it will be useful,
11// but WITHOUT ANY WARRANTY; without even the implied warranty of
12// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13// GNU General Public License for more details.
14//
15// You should have received a copy of the GNU General Public License
16// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
17
18
19/**
8496fdac 20 * Definition of a class stored_file.
16a95e8f 21 *
64a19b38 22 * @package moodlecore
23 * @subpackage file-storage
8496fdac 24 * @copyright 2008 Petr Skoda {@link http://skodak.org}
64a19b38 25 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
16a95e8f 26 */
27
28require_once("$CFG->libdir/file/stored_file.php");
172dd12c 29
30/**
8496fdac
PS
31 * Class representing local files stored in a sha1 file pool.
32 *
33 * Since Moodle 2.0 file contents are stored in sha1 pool and
34 * all other file information is stored in new "files" database table.
35 *
36 * @copyright 2008 Petr Skoda {@link http://skodak.org}
37 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
38 * @since Moodle 2.0
172dd12c 39 */
40class stored_file {
8496fdac 41 /** @var file_storage file storage pool instance */
172dd12c 42 private $fs;
8496fdac 43 /** @var object record from the files table */
172dd12c 44 private $file_record;
45
46 /**
8496fdac
PS
47 * Constructor, this constructor should be called ONLY from the file_storage class!
48 *
49 * @param file_storage $fs file storage instance
172dd12c 50 * @param object $file_record description of file
51 */
8496fdac
PS
52 public function __construct(file_storage $fs, stdClass $file_record) {
53 $this->fs = $fs;
54 $this->file_record = clone($file_record); // prevent modifications
172dd12c 55 }
56
57 /**
58 * Is this a directory?
8496fdac
PS
59 *
60 * Directories are only emulated, internally they are stored as empty
61 * files with a "." instead of name - this means empty directory contains
62 * exactly one empty file with name dot.
63 *
64 * @return bool true means directory, false means file
172dd12c 65 */
66 public function is_directory() {
8496fdac 67 return ($this->file_record->filename === '.');
172dd12c 68 }
69
70 /**
8496fdac
PS
71 * Delete file from files table.
72 *
73 * The content of files stored in sha1 pool is reclaimed
74 * later - the occupied disk space is reclaimed much later.
75 *
76 * @return bool always true or exception if error occurred
172dd12c 77 */
78 public function delete() {
79 global $DB;
1aa01caf 80 $DB->delete_records('files', array('id'=>$this->file_record->id));
81 // moves pool file to trash if content not needed any more
82 $this->fs->deleted_file_cleanup($this->file_record->contenthash);
8496fdac 83 return true; // BC only
172dd12c 84 }
85
86 /**
8496fdac
PS
87 * Protected - developers must not gain direct access to this function.
88 *
17d9269f 89 * NOTE: do not make this public, we must not modify or delete the pool files directly! ;-)
8496fdac
PS
90 *
91 * @return string full path to pool file with file content
172dd12c 92 **/
93 protected function get_content_file_location() {
744b64ff 94 $filedir = $this->fs->get_filedir();
17d9269f 95 $contenthash = $this->file_record->contenthash;
96 $l1 = $contenthash[0].$contenthash[1];
97 $l2 = $contenthash[2].$contenthash[3];
98 $l3 = $contenthash[4].$contenthash[5];
99 return "$filedir/$l1/$l2/$l3/$contenthash";
172dd12c 100 }
101
5035a8b4 102 /**
103 * adds this file path to a curl request (POST only)
104 *
105 * @param curl $curlrequest the curl request object
106 * @param string $key what key to use in the POST request
8496fdac 107 * @return void
5035a8b4 108 */
109 public function add_to_curl_request(&$curlrequest, $key) {
110 $curlrequest->_tmp_file_post_params[$key] = '@' . $this->get_content_file_location();
111 }
112
172dd12c 113 /**
114 * Returns file handle - read only mode, no writing allowed into pool files!
8496fdac
PS
115 *
116 * When you want to modify a file, create a new file and delete the old one.
117 *
118 * @return resource file handle
172dd12c 119 */
120 public function get_content_file_handle() {
121 $path = $this->get_content_file_location();
122 if (!is_readable($path)) {
1aa01caf 123 if (!$this->fs->try_content_recovery($this) or !is_readable($path)) {
124 throw new file_exception('storedfilecannotread');
125 }
172dd12c 126 }
127 return fopen($path, 'rb'); //binary reading only!!
128 }
129
130 /**
8496fdac
PS
131 * Dumps file content to page.
132 *
133 * @return void
172dd12c 134 */
135 public function readfile() {
136 $path = $this->get_content_file_location();
137 if (!is_readable($path)) {
1aa01caf 138 if (!$this->fs->try_content_recovery($this) or !is_readable($path)) {
139 throw new file_exception('storedfilecannotread');
140 }
172dd12c 141 }
142 readfile($path);
143 }
144
145 /**
8496fdac
PS
146 * Returns file content as string.
147 *
172dd12c 148 * @return string content
149 */
150 public function get_content() {
151 $path = $this->get_content_file_location();
152 if (!is_readable($path)) {
1aa01caf 153 if (!$this->fs->try_content_recovery($this) or !is_readable($path)) {
154 throw new file_exception('storedfilecannotread');
155 }
172dd12c 156 }
157 return file_get_contents($this->get_content_file_location());
158 }
159
6c0e2d08 160 /**
8496fdac
PS
161 * Copy content of file to given pathname.
162 *
163 * @param string $pathname real path to the new file
6c0e2d08 164 * @return bool success
165 */
166 public function copy_content_to($pathname) {
167 $path = $this->get_content_file_location();
168 if (!is_readable($path)) {
1aa01caf 169 if (!$this->fs->try_content_recovery($this) or !is_readable($path)) {
170 throw new file_exception('storedfilecannotread');
171 }
6c0e2d08 172 }
173 return copy($path, $pathname);
174 }
175
17d9269f 176 /**
8496fdac
PS
177 * List contents of archive.
178 *
179 * @param file_packer $file_packer
c78a0558 180 * @return array of file infos
181 */
182 public function list_files(file_packer $packer) {
183 $archivefile = $this->get_content_file_location();
184 return $packer->list_files($archivefile);
185 }
186
187 /**
8496fdac
PS
188 * Extract file to given file path (real OS filesystem), existing files are overwritten.
189 *
190 * @param file_packer $file_packer
0b0bfa93 191 * @param string $pathname target directory
8496fdac 192 * @return array|bool list of processed files; false if error
17d9269f 193 */
0b0bfa93 194 public function extract_to_pathname(file_packer $packer, $pathname) {
195 $archivefile = $this->get_content_file_location();
196 return $packer->extract_to_pathname($archivefile, $pathname);
17d9269f 197 }
198
199 /**
8496fdac
PS
200 * Extract file to given file path (real OS filesystem), existing files are overwritten.
201 *
202 * @param file_packer $file_packer
17d9269f 203 * @param int $contextid
204 * @param string $filearea
205 * @param int $itemid
206 * @param string $pathbase
207 * @param int $userid
8496fdac 208 * @return array|bool list of processed files; false if error
17d9269f 209 */
8496fdac 210 public function extract_to_storage(file_packer $packer, $contextid, $filearea, $itemid, $pathbase, $userid = NULL) {
0b0bfa93 211 $archivefile = $this->get_content_file_location();
212 return $packer->extract_to_storage($archivefile, $contextid, $filearea, $itemid, $pathbase);
17d9269f 213 }
214
b1897a6d 215 /**
8496fdac
PS
216 * Add file/directory into archive.
217 *
218 * @param file_archive $filearch
c78a0558 219 * @param string $archivepath pathname in archive
b1897a6d 220 * @return bool success
221 */
0b0bfa93 222 public function archive_file(file_archive $filearch, $archivepath) {
b1897a6d 223 if ($this->is_directory()) {
0b0bfa93 224 return $filearch->add_directory($archivepath);
b1897a6d 225 } else {
226 $path = $this->get_content_file_location();
227 if (!is_readable($path)) {
228 return false;
229 }
0b0bfa93 230 return $filearch->add_file_from_pathname($archivepath, $path);
b1897a6d 231 }
232 }
233
797f19e8 234 /**
235 * Returns information about image,
236 * information is determined from the file content
237 * @return mixed array with width, height and mimetype; false if not an image
238 */
239 public function get_imageinfo() {
240 if (!$imageinfo = getimagesize($this->get_content_file_location())) {
241 return false;
242 }
243 $image = array('width'=>$imageinfo[0], 'height'=>$imageinfo[1], 'mimetype'=>image_type_to_mime_type($imageinfo[2]));
244 if (empty($image['width']) or empty($image['height']) or empty($image['mimetype'])) {
245 // gd can not parse it, sorry
246 return false;
247 }
248 return $image;
249 }
250
251 /**
252 * Verifies the file is a valid web image - gif, png and jpeg only.
8496fdac 253 *
797f19e8 254 * It should be ok to serve this image from server without any other security workarounds.
8496fdac 255 *
797f19e8 256 * @return bool true if file ok
257 */
258 public function is_valid_image() {
259 $mimetype = $this->get_mimetype();
260 if ($mimetype !== 'image/gif' and $mimetype !== 'image/jpeg' and $mimetype !== 'image/png') {
261 return false;
262 }
263 if (!$info = $this->get_imageinfo()) {
264 return false;
265 }
266 if ($info['mimetype'] !== $mimetype) {
267 return false;
268 }
269 // ok, GD likes this image
270 return true;
271 }
272
4b6b5ce7 273 /**
8496fdac
PS
274 * Returns parent directory, creates missing parents if needed.
275 *
276 * @return stored_file
4b6b5ce7 277 */
278 public function get_parent_directory() {
279 if ($this->file_record->filepath === '/' and $this->file_record->filename === '.') {
280 //root dir does not have parent
281 return null;
282 }
283
284 if ($this->file_record->filename !== '.') {
285 return $this->fs->create_directory($this->file_record->contextid, $this->file_record->filearea, $this->file_record->itemid, $this->file_record->filepath);
286 }
287
288 $filepath = $this->file_record->filepath;
289 $filepath = trim($filepath, '/');
290 $dirs = explode('/', $filepath);
291 array_pop($dirs);
292 $filepath = implode('/', $dirs);
293 $filepath = ($filepath === '') ? '/' : "/$filepath/";
294
295 return $this->fs->create_directory($this->file_record->contextid, $this->file_record->filearea, $this->file_record->itemid, $filepath);
296 }
297
16a95e8f 298 /**
8496fdac
PS
299 * Returns context id of the file-
300 *
16a95e8f 301 * @return int context id
302 */
172dd12c 303 public function get_contextid() {
304 return $this->file_record->contextid;
305 }
306
16a95e8f 307 /**
308 * Returns file area name, the areas do not have to be unique,
8496fdac
PS
309 * but usually have form component_typeofarea such as forum_attachments.
310 *
16a95e8f 311 * @return string
312 */
172dd12c 313 public function get_filearea() {
314 return $this->file_record->filearea;
315 }
316
16a95e8f 317 /**
8496fdac
PS
318 * Returns returns item id of file.
319 *
16a95e8f 320 * @return int
321 */
172dd12c 322 public function get_itemid() {
323 return $this->file_record->itemid;
324 }
325
16a95e8f 326 /**
327 * Returns file path - starts and ends with /, \ are not allowed.
8496fdac 328 *
16a95e8f 329 * @return string
330 */
172dd12c 331 public function get_filepath() {
332 return $this->file_record->filepath;
333 }
334
16a95e8f 335 /**
336 * Returns file name or '.' in case of directories.
8496fdac 337 *
16a95e8f 338 * @return string
339 */
172dd12c 340 public function get_filename() {
341 return $this->file_record->filename;
342 }
343
16a95e8f 344 /**
345 * Returns id of user who created the file.
8496fdac 346 *
16a95e8f 347 * @return int
348 */
172dd12c 349 public function get_userid() {
350 return $this->file_record->userid;
351 }
352
16a95e8f 353 /**
354 * Returns the size of file in bytes.
8496fdac 355 *
16a95e8f 356 * @return int bytes
357 */
172dd12c 358 public function get_filesize() {
359 return $this->file_record->filesize;
360 }
361
16a95e8f 362 /**
8496fdac
PS
363 * Returns mime type of file.
364 *
16a95e8f 365 * @return string
366 */
172dd12c 367 public function get_mimetype() {
368 return $this->file_record->mimetype;
369 }
370
16a95e8f 371 /**
8496fdac
PS
372 * Returns unix timestamp of file creation date.
373 *
16a95e8f 374 * @return int
375 */
172dd12c 376 public function get_timecreated() {
377 return $this->file_record->timecreated;
378 }
379
16a95e8f 380 /**
8496fdac
PS
381 * Returns unix timestamp of last file modification.
382 *
16a95e8f 383 * @return int
384 */
172dd12c 385 public function get_timemodified() {
386 return $this->file_record->timemodified;
387 }
6c0e2d08 388
16a95e8f 389 /**
8496fdac
PS
390 * Returns file status flag.
391 *
16a95e8f 392 * @return int 0 means file OK, anything else is a problem and file can not be used
393 */
6c0e2d08 394 public function get_status() {
395 return $this->file_record->status;
396 }
ee03a651 397
16a95e8f 398 /**
8496fdac
PS
399 * Returns file id.
400 *
16a95e8f 401 * @return int
402 */
ee03a651 403 public function get_id() {
404 return $this->file_record->id;
405 }
4284e1cc 406
16a95e8f 407 /**
8496fdac
PS
408 * Returns sha1 hash of file content.
409 *
16a95e8f 410 * @return string
411 */
4284e1cc 412 public function get_contenthash() {
413 return $this->file_record->contenthash;
414 }
6ed19c74 415
16a95e8f 416 /**
8496fdac
PS
417 * Returns sha1 hash of all file path components sha1("contextid/filearea/itemid/dir/dir/filename.ext").
418 *
16a95e8f 419 * @return string
420 */
6ed19c74 421 public function get_pathnamehash() {
422 return $this->file_record->pathnamehash;
423 }
1dce6261
DC
424
425 /**
8496fdac
PS
426 * Returns the license type of the file, it is a short name referred from license table.
427 *
1dce6261
DC
428 * @return string
429 */
430 public function get_license() {
431 return $this->file_record->license;
432 }
433
434 /**
8496fdac
PS
435 * Returns the author name of the file.
436 *
1dce6261
DC
437 * @return string
438 */
439 public function get_author() {
440 return $this->file_record->license;
441 }
442
443 /**
8496fdac
PS
444 * Returns the source of the file, usually it is a url.
445 *
1dce6261
DC
446 * @return string
447 */
448 public function get_source() {
449 return $this->file_record->source;
450 }
8496fdac 451
f79321f1
DC
452 /**
453 * Returns the sort order of file
454 *
455 * @return int
456 */
457 public function get_sortorder() {
458 return $this->file_record->sortorder;
459 }
460}