Merge branch 'wip-mdl-30121-m22' of git://github.com/rajeshtaneja/moodle into MOODLE_...
[moodle.git] / lib / filestorage / stored_file.php
blob212179c1a356300b2dd0d10813445efe80fdd19c
1 <?php
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.
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/>.
19 /**
20 * Definition of a class stored_file.
22 * @package core
23 * @subpackage filestorage
24 * @copyright 2008 Petr Skoda {@link http://skodak.org}
25 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
28 defined('MOODLE_INTERNAL') || die();
30 require_once("$CFG->libdir/filestorage/stored_file.php");
32 /**
33 * Class representing local files stored in a sha1 file pool.
35 * Since Moodle 2.0 file contents are stored in sha1 pool and
36 * all other file information is stored in new "files" database table.
38 * @copyright 2008 Petr Skoda {@link http://skodak.org}
39 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
40 * @since Moodle 2.0
42 class stored_file {
43 /** @var file_storage file storage pool instance */
44 private $fs;
45 /** @var object record from the files table */
46 private $file_record;
47 /** @var string location of content files */
48 private $filedir;
50 /**
51 * Constructor, this constructor should be called ONLY from the file_storage class!
53 * @param file_storage $fs file storage instance
54 * @param object $file_record description of file
55 * @param string $filepool location of file directory with sh1 named content files
57 public function __construct(file_storage $fs, stdClass $file_record, $filedir) {
58 $this->fs = $fs;
59 $this->file_record = clone($file_record); // prevent modifications
60 $this->filedir = $filedir; // keep secret, do not expose!
63 /**
64 * Is this a directory?
66 * Directories are only emulated, internally they are stored as empty
67 * files with a "." instead of name - this means empty directory contains
68 * exactly one empty file with name dot.
70 * @return bool true means directory, false means file
72 public function is_directory() {
73 return ($this->file_record->filename === '.');
76 /**
77 * Delete file from files table.
79 * The content of files stored in sha1 pool is reclaimed
80 * later - the occupied disk space is reclaimed much later.
82 * @return bool always true or exception if error occurred
84 public function delete() {
85 global $DB;
86 $DB->delete_records('files', array('id'=>$this->file_record->id));
87 // moves pool file to trash if content not needed any more
88 $this->fs->deleted_file_cleanup($this->file_record->contenthash);
89 return true; // BC only
92 /**
93 * Protected - developers must not gain direct access to this function.
95 * NOTE: do not make this public, we must not modify or delete the pool files directly! ;-)
97 * @return string full path to pool file with file content
98 **/
99 protected function get_content_file_location() {
100 $contenthash = $this->file_record->contenthash;
101 $l1 = $contenthash[0].$contenthash[1];
102 $l2 = $contenthash[2].$contenthash[3];
103 return "$this->filedir/$l1/$l2/$contenthash";
107 * adds this file path to a curl request (POST only)
109 * @param curl $curlrequest the curl request object
110 * @param string $key what key to use in the POST request
111 * @return void
113 public function add_to_curl_request(&$curlrequest, $key) {
114 $curlrequest->_tmp_file_post_params[$key] = '@' . $this->get_content_file_location();
118 * Returns file handle - read only mode, no writing allowed into pool files!
120 * When you want to modify a file, create a new file and delete the old one.
122 * @return resource file handle
124 public function get_content_file_handle() {
125 $path = $this->get_content_file_location();
126 if (!is_readable($path)) {
127 if (!$this->fs->try_content_recovery($this) or !is_readable($path)) {
128 throw new file_exception('storedfilecannotread', '', $path);
131 return fopen($path, 'rb'); //binary reading only!!
135 * Dumps file content to page.
137 * @return void
139 public function readfile() {
140 $path = $this->get_content_file_location();
141 if (!is_readable($path)) {
142 if (!$this->fs->try_content_recovery($this) or !is_readable($path)) {
143 throw new file_exception('storedfilecannotread', '', $path);
146 readfile($path);
150 * Returns file content as string.
152 * @return string content
154 public function get_content() {
155 $path = $this->get_content_file_location();
156 if (!is_readable($path)) {
157 if (!$this->fs->try_content_recovery($this) or !is_readable($path)) {
158 throw new file_exception('storedfilecannotread', '', $path);
161 return file_get_contents($this->get_content_file_location());
165 * Copy content of file to given pathname.
167 * @param string $pathname real path to the new file
168 * @return bool success
170 public function copy_content_to($pathname) {
171 $path = $this->get_content_file_location();
172 if (!is_readable($path)) {
173 if (!$this->fs->try_content_recovery($this) or !is_readable($path)) {
174 throw new file_exception('storedfilecannotread', '', $path);
177 return copy($path, $pathname);
181 * List contents of archive.
183 * @param file_packer $file_packer
184 * @return array of file infos
186 public function list_files(file_packer $packer) {
187 $archivefile = $this->get_content_file_location();
188 return $packer->list_files($archivefile);
192 * Extract file to given file path (real OS filesystem), existing files are overwritten.
194 * @param file_packer $file_packer
195 * @param string $pathname target directory
196 * @return array|bool list of processed files; false if error
198 public function extract_to_pathname(file_packer $packer, $pathname) {
199 $archivefile = $this->get_content_file_location();
200 return $packer->extract_to_pathname($archivefile, $pathname);
204 * Extract file to given file path (real OS filesystem), existing files are overwritten.
206 * @param file_packer $file_packer
207 * @param int $contextid
208 * @param string $component
209 * @param string $filearea
210 * @param int $itemid
211 * @param string $pathbase
212 * @param int $userid
213 * @return array|bool list of processed files; false if error
215 public function extract_to_storage(file_packer $packer, $contextid, $component, $filearea, $itemid, $pathbase, $userid = NULL) {
216 $archivefile = $this->get_content_file_location();
217 return $packer->extract_to_storage($archivefile, $contextid, $component, $filearea, $itemid, $pathbase);
221 * Add file/directory into archive.
223 * @param file_archive $filearch
224 * @param string $archivepath pathname in archive
225 * @return bool success
227 public function archive_file(file_archive $filearch, $archivepath) {
228 if ($this->is_directory()) {
229 return $filearch->add_directory($archivepath);
230 } else {
231 $path = $this->get_content_file_location();
232 if (!is_readable($path)) {
233 return false;
235 return $filearch->add_file_from_pathname($archivepath, $path);
240 * Returns information about image,
241 * information is determined from the file content
242 * @return mixed array with width, height and mimetype; false if not an image
244 public function get_imageinfo() {
245 if (!$imageinfo = getimagesize($this->get_content_file_location())) {
246 return false;
248 $image = array('width'=>$imageinfo[0], 'height'=>$imageinfo[1], 'mimetype'=>image_type_to_mime_type($imageinfo[2]));
249 if (empty($image['width']) or empty($image['height']) or empty($image['mimetype'])) {
250 // gd can not parse it, sorry
251 return false;
253 return $image;
257 * Verifies the file is a valid web image - gif, png and jpeg only.
259 * It should be ok to serve this image from server without any other security workarounds.
261 * @return bool true if file ok
263 public function is_valid_image() {
264 $mimetype = $this->get_mimetype();
265 if ($mimetype !== 'image/gif' and $mimetype !== 'image/jpeg' and $mimetype !== 'image/png') {
266 return false;
268 if (!$info = $this->get_imageinfo()) {
269 return false;
271 if ($info['mimetype'] !== $mimetype) {
272 return false;
274 // ok, GD likes this image
275 return true;
279 * Returns parent directory, creates missing parents if needed.
281 * @return stored_file
283 public function get_parent_directory() {
284 if ($this->file_record->filepath === '/' and $this->file_record->filename === '.') {
285 //root dir does not have parent
286 return null;
289 if ($this->file_record->filename !== '.') {
290 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);
293 $filepath = $this->file_record->filepath;
294 $filepath = trim($filepath, '/');
295 $dirs = explode('/', $filepath);
296 array_pop($dirs);
297 $filepath = implode('/', $dirs);
298 $filepath = ($filepath === '') ? '/' : "/$filepath/";
300 return $this->fs->create_directory($this->file_record->contextid, $this->file_record->component, $this->file_record->filearea, $this->file_record->itemid, $filepath);
304 * Returns context id of the file-
306 * @return int context id
308 public function get_contextid() {
309 return $this->file_record->contextid;
313 * Returns component name - this is the owner of the areas,
314 * nothing else is allowed to read or modify the files directly!!
316 * @return string
318 public function get_component() {
319 return $this->file_record->component;
323 * Returns file area name, this divides files of one component into groups with different access control.
324 * All files in one area have the same access control.
326 * @return string
328 public function get_filearea() {
329 return $this->file_record->filearea;
333 * Returns returns item id of file.
335 * @return int
337 public function get_itemid() {
338 return $this->file_record->itemid;
342 * Returns file path - starts and ends with /, \ are not allowed.
344 * @return string
346 public function get_filepath() {
347 return $this->file_record->filepath;
351 * Returns file name or '.' in case of directories.
353 * @return string
355 public function get_filename() {
356 return $this->file_record->filename;
360 * Returns id of user who created the file.
362 * @return int
364 public function get_userid() {
365 return $this->file_record->userid;
369 * Returns the size of file in bytes.
371 * @return int bytes
373 public function get_filesize() {
374 return $this->file_record->filesize;
378 * Returns mime type of file.
380 * @return string
382 public function get_mimetype() {
383 return $this->file_record->mimetype;
387 * Returns unix timestamp of file creation date.
389 * @return int
391 public function get_timecreated() {
392 return $this->file_record->timecreated;
396 * Returns unix timestamp of last file modification.
398 * @return int
400 public function get_timemodified() {
401 return $this->file_record->timemodified;
405 * Returns file status flag.
407 * @return int 0 means file OK, anything else is a problem and file can not be used
409 public function get_status() {
410 return $this->file_record->status;
414 * Returns file id.
416 * @return int
418 public function get_id() {
419 return $this->file_record->id;
423 * Returns sha1 hash of file content.
425 * @return string
427 public function get_contenthash() {
428 return $this->file_record->contenthash;
432 * Returns sha1 hash of all file path components sha1("contextid/component/filearea/itemid/dir/dir/filename.ext").
434 * @return string
436 public function get_pathnamehash() {
437 return $this->file_record->pathnamehash;
441 * Returns the license type of the file, it is a short name referred from license table.
443 * @return string
445 public function get_license() {
446 return $this->file_record->license;
450 * Returns the author name of the file.
452 * @return string
454 public function get_author() {
455 return $this->file_record->author;
459 * Returns the source of the file, usually it is a url.
461 * @return string
463 public function get_source() {
464 return $this->file_record->source;
468 * Returns the sort order of file
470 * @return int
472 public function get_sortorder() {
473 return $this->file_record->sortorder;