2009-05-20 21:16:38 +00:00
< ? php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Core file storage class definition .
*
2010-07-03 13:37:13 +00:00
* @ package core
* @ subpackage filestorage
2010-05-03 21:04:06 +00:00
* @ copyright 2008 Petr Skoda { @ link http :// skodak . org }
2009-05-21 08:25:52 +00:00
* @ license http :// www . gnu . org / copyleft / gpl . html GNU GPL v3 or later
2009-05-20 21:16:38 +00:00
*/
2008-07-31 22:15:30 +00:00
2010-07-03 13:37:13 +00:00
defined ( 'MOODLE_INTERNAL' ) || die ();
require_once ( " $CFG->libdir /filestorage/stored_file.php " );
2008-07-31 22:15:30 +00:00
2009-05-20 21:16:38 +00:00
/**
* File storage class used for low level access to stored files .
2010-05-03 21:04:06 +00:00
*
2009-05-20 21:16:38 +00:00
* Only owner of file area may use this class to access own files ,
* for example only code in mod / assignment /* may access assignment
2010-05-03 21:04:06 +00:00
* attachments . When some other part of moodle needs to access
* files of modules it has to use file_browser class instead or there
* has to be some callback API .
*
* @ copyright 2008 Petr Skoda { @ link http :// skodak . org }
* @ license http :// www . gnu . org / copyleft / gpl . html GNU GPL v3 or later
* @ since Moodle 2.0
2009-05-20 21:16:38 +00:00
*/
2008-07-31 22:15:30 +00:00
class file_storage {
2010-05-03 21:04:06 +00:00
/** @var string Directory with file contents */
2008-07-31 22:15:30 +00:00
private $filedir ;
2010-05-03 21:04:06 +00:00
/** @var string Contents of deleted files not needed any more */
2009-06-03 08:10:21 +00:00
private $trashdir ;
2010-05-20 17:13:07 +00:00
/** @var string tempdir */
private $tempdir ;
2010-05-03 21:04:06 +00:00
/** @var int Permissions for new directories */
2009-06-03 08:10:21 +00:00
private $dirpermissions ;
2010-05-03 21:04:06 +00:00
/** @var int Permissions for new files */
2009-06-03 08:10:21 +00:00
private $filepermissions ;
2010-05-03 21:04:06 +00:00
2008-07-31 22:15:30 +00:00
/**
2010-05-03 21:04:06 +00:00
* Constructor - do not use directly use @ see get_file_storage () call instead .
*
2008-07-31 22:15:30 +00:00
* @ param string $filedir full path to pool directory
2010-05-03 21:04:06 +00:00
* @ param string $trashdir temporary storage of deleted area
2010-05-20 17:13:07 +00:00
* @ param string $tempdir temporary storage of various files
2010-05-03 21:04:06 +00:00
* @ param int $dirpermissions new directory permissions
* @ param int $filepermissions new file permissions
2008-07-31 22:15:30 +00:00
*/
2010-05-20 17:13:07 +00:00
public function __construct ( $filedir , $trashdir , $tempdir , $dirpermissions , $filepermissions ) {
2009-06-03 08:10:21 +00:00
$this -> filedir = $filedir ;
$this -> trashdir = $trashdir ;
2010-05-20 17:13:07 +00:00
$this -> tempdir = $tempdir ;
2009-06-03 08:10:21 +00:00
$this -> dirpermissions = $dirpermissions ;
$this -> filepermissions = $filepermissions ;
2008-07-31 22:15:30 +00:00
// make sure the file pool directory exists
if ( ! is_dir ( $this -> filedir )) {
2009-06-03 08:10:21 +00:00
if ( ! mkdir ( $this -> filedir , $this -> dirpermissions , true )) {
2008-08-08 11:50:45 +00:00
throw new file_exception ( 'storedfilecannotcreatefiledirs' ); // permission trouble
2008-07-31 22:15:30 +00:00
}
// place warning file in file pool root
2009-06-03 08:10:21 +00:00
if ( ! file_exists ( $this -> filedir . '/warning.txt' )) {
file_put_contents ( $this -> filedir . '/warning.txt' ,
'This directory contains the content of uploaded files and is controlled by Moodle code. Do not manually move, change or rename any of the files and subdirectories here.' );
}
}
// make sure the file pool directory exists
if ( ! is_dir ( $this -> trashdir )) {
if ( ! mkdir ( $this -> trashdir , $this -> dirpermissions , true )) {
throw new file_exception ( 'storedfilecannotcreatefiledirs' ); // permission trouble
}
2008-07-31 22:15:30 +00:00
}
}
2008-08-04 13:21:38 +00:00
/**
2010-05-03 21:04:06 +00:00
* Returns location of filedir ( file pool ) .
*
* Do not use , this method is intended for stored_file instances only !!!
*
2008-09-06 10:09:33 +00:00
* @ return string pathname
2008-08-04 13:21:38 +00:00
*/
public function get_filedir () {
return $this -> filedir ;
}
2008-07-31 22:15:30 +00:00
/**
2010-05-03 21:04:06 +00:00
* Calculates sha1 hash of unique full path name information .
*
* This hash is a unique file identifier - it is used to improve
* performance and overcome db index size limits .
*
2008-07-31 22:15:30 +00:00
* @ param int $contextid
2010-07-03 13:37:13 +00:00
* @ param string $component
2008-07-31 22:15:30 +00:00
* @ param string $filearea
* @ param int $itemid
* @ param string $filepath
* @ param string $filename
2010-05-03 21:04:06 +00:00
* @ return string sha1 hash
2008-07-31 22:15:30 +00:00
*/
2010-07-03 13:37:13 +00:00
public static function get_pathname_hash ( $contextid , $component , $filearea , $itemid , $filepath , $filename ) {
return sha1 ( " / $contextid / $component / $filearea / $itemid " . $filepath . $filename );
2008-07-31 22:15:30 +00:00
}
/**
* Does this file exist ?
2010-05-03 21:04:06 +00:00
*
2008-07-31 22:15:30 +00:00
* @ param int $contextid
2010-07-03 13:37:13 +00:00
* @ param string $component
2008-07-31 22:15:30 +00:00
* @ param string $filearea
* @ param int $itemid
* @ param string $filepath
* @ param string $filename
* @ return bool
*/
2010-07-03 13:37:13 +00:00
public function file_exists ( $contextid , $component , $filearea , $itemid , $filepath , $filename ) {
2008-07-31 22:15:30 +00:00
$filepath = clean_param ( $filepath , PARAM_PATH );
$filename = clean_param ( $filename , PARAM_FILE );
if ( $filename === '' ) {
$filename = '.' ;
}
2010-07-03 13:37:13 +00:00
$pathnamehash = $this -> get_pathname_hash ( $contextid , $component , $filearea , $itemid , $filepath , $filename );
2008-07-31 22:15:30 +00:00
return $this -> file_exists_by_hash ( $pathnamehash );
}
/**
* Does this file exist ?
2010-05-03 21:04:06 +00:00
*
2008-07-31 22:15:30 +00:00
* @ param string $pathnamehash
* @ return bool
*/
public function file_exists_by_hash ( $pathnamehash ) {
global $DB ;
return $DB -> record_exists ( 'files' , array ( 'pathnamehash' => $pathnamehash ));
}
/**
2009-05-20 21:16:38 +00:00
* Fetch file using local file id .
2010-05-03 21:04:06 +00:00
*
2009-05-20 21:16:38 +00:00
* Please do not rely on file ids , it is usually easier to use
* pathname hashes instead .
2010-05-03 21:04:06 +00:00
*
2008-07-31 22:15:30 +00:00
* @ param int $fileid
2010-05-03 21:04:06 +00:00
* @ return stored_file instance if exists , false if not
2008-07-31 22:15:30 +00:00
*/
public function get_file_by_id ( $fileid ) {
global $DB ;
if ( $file_record = $DB -> get_record ( 'files' , array ( 'id' => $fileid ))) {
return new stored_file ( $this , $file_record );
} else {
return false ;
}
}
/**
* Fetch file using local file full pathname hash
2010-05-03 21:04:06 +00:00
*
2008-07-31 22:15:30 +00:00
* @ param string $pathnamehash
2010-05-03 21:04:06 +00:00
* @ return stored_file instance if exists , false if not
2008-07-31 22:15:30 +00:00
*/
public function get_file_by_hash ( $pathnamehash ) {
global $DB ;
if ( $file_record = $DB -> get_record ( 'files' , array ( 'pathnamehash' => $pathnamehash ))) {
return new stored_file ( $this , $file_record );
} else {
return false ;
}
}
/**
2010-05-03 21:04:06 +00:00
* Fetch locally stored file .
*
2008-07-31 22:15:30 +00:00
* @ param int $contextid
2010-07-03 13:37:13 +00:00
* @ param string $component
2008-07-31 22:15:30 +00:00
* @ param string $filearea
* @ param int $itemid
* @ param string $filepath
* @ param string $filename
2010-05-03 21:04:06 +00:00
* @ return stored_file instance if exists , false if not
2008-07-31 22:15:30 +00:00
*/
2010-07-03 13:37:13 +00:00
public function get_file ( $contextid , $component , $filearea , $itemid , $filepath , $filename ) {
2008-07-31 22:15:30 +00:00
$filepath = clean_param ( $filepath , PARAM_PATH );
$filename = clean_param ( $filename , PARAM_FILE );
if ( $filename === '' ) {
$filename = '.' ;
}
2010-07-03 13:37:13 +00:00
$pathnamehash = $this -> get_pathname_hash ( $contextid , $component , $filearea , $itemid , $filepath , $filename );
2008-07-31 22:15:30 +00:00
return $this -> get_file_by_hash ( $pathnamehash );
}
2010-09-12 12:29:32 +00:00
/**
* Are there any files ( or directories )
* @ param int $contextid
* @ param string $component
* @ param string $filearea
* @ param bool | int $itemid tem id or false if all items
* @ param bool $ignoredirs
* @ return bool empty
*/
public function is_area_empty ( $contextid , $component , $filearea , $itemid = false , $ignoredirs = true ) {
global $DB ;
$params = array ( 'contextid' => $contextid , 'component' => $component , 'filearea' => $filearea );
$where = " contextid = :contextid AND component = :component AND filearea = :filearea " ;
if ( $itemid !== false ) {
$params [ 'itemid' ] = $itemid ;
$where .= " AND itemid = :itemid " ;
}
if ( $ignoredirs ) {
$sql = " SELECT 'x'
FROM { files }
WHERE $where AND filename <> '.' " ;
} else {
$sql = " SELECT 'x'
FROM { files }
WHERE $where AND ( filename <> '.' OR filepath <> '/' ) " ;
}
return ! $DB -> record_exists_sql ( $sql , $params );
}
2008-07-31 22:15:30 +00:00
/**
* Returns all area files ( optionally limited by itemid )
2010-05-03 21:04:06 +00:00
*
2008-07-31 22:15:30 +00:00
* @ param int $contextid
2010-07-03 13:37:13 +00:00
* @ param string $component
2008-07-31 22:15:30 +00:00
* @ param string $filearea
* @ param int $itemid ( all files if not specified )
* @ param string $sort
* @ param bool $includedirs
2008-09-21 10:35:39 +00:00
* @ return array of stored_files indexed by pathanmehash
2008-07-31 22:15:30 +00:00
*/
2010-09-12 12:29:32 +00:00
public function get_area_files ( $contextid , $component , $filearea , $itemid = false , $sort = " sortorder, itemid, filepath, filename " , $includedirs = true ) {
2008-07-31 22:15:30 +00:00
global $DB ;
2010-07-03 13:37:13 +00:00
$conditions = array ( 'contextid' => $contextid , 'component' => $component , 'filearea' => $filearea );
2008-07-31 22:15:30 +00:00
if ( $itemid !== false ) {
$conditions [ 'itemid' ] = $itemid ;
}
$result = array ();
$file_records = $DB -> get_records ( 'files' , $conditions , $sort );
foreach ( $file_records as $file_record ) {
2008-08-29 05:32:10 +00:00
if ( ! $includedirs and $file_record -> filename === '.' ) {
2008-07-31 22:15:30 +00:00
continue ;
}
2008-09-21 10:35:39 +00:00
$result [ $file_record -> pathnamehash ] = new stored_file ( $this , $file_record );
2008-07-31 22:15:30 +00:00
}
return $result ;
}
2009-06-21 18:22:52 +00:00
/**
* Returns array based tree structure of area files
2010-05-03 21:04:06 +00:00
*
2009-06-21 18:22:52 +00:00
* @ param int $contextid
2010-07-03 13:37:13 +00:00
* @ param string $component
2009-06-21 18:22:52 +00:00
* @ param string $filearea
* @ param int $itemid
* @ return array each dir represented by dirname , subdirs , files and dirfile array elements
*/
2010-07-03 13:37:13 +00:00
public function get_area_tree ( $contextid , $component , $filearea , $itemid ) {
2009-06-21 18:22:52 +00:00
$result = array ( 'dirname' => '' , 'dirfile' => null , 'subdirs' => array (), 'files' => array ());
2010-09-18 10:33:26 +00:00
$files = $this -> get_area_files ( $contextid , $component , $filearea , $itemid , " sortorder, itemid, filepath, filename " , true );
2009-06-21 18:22:52 +00:00
// first create directory structure
foreach ( $files as $hash => $dir ) {
if ( ! $dir -> is_directory ()) {
continue ;
}
unset ( $files [ $hash ]);
if ( $dir -> get_filepath () === '/' ) {
$result [ 'dirfile' ] = $dir ;
continue ;
}
$parts = explode ( '/' , trim ( $dir -> get_filepath (), '/' ));
$pointer =& $result ;
foreach ( $parts as $part ) {
2009-07-04 18:47:56 +00:00
if ( $part === '' ) {
continue ;
}
2009-06-21 18:22:52 +00:00
if ( ! isset ( $pointer [ 'subdirs' ][ $part ])) {
$pointer [ 'subdirs' ][ $part ] = array ( 'dirname' => $part , 'dirfile' => null , 'subdirs' => array (), 'files' => array ());
}
$pointer =& $pointer [ 'subdirs' ][ $part ];
}
$pointer [ 'dirfile' ] = $dir ;
unset ( $pointer );
}
foreach ( $files as $hash => $file ) {
$parts = explode ( '/' , trim ( $file -> get_filepath (), '/' ));
$pointer =& $result ;
foreach ( $parts as $part ) {
2009-07-04 18:47:56 +00:00
if ( $part === '' ) {
continue ;
}
2009-06-21 18:22:52 +00:00
$pointer =& $pointer [ 'subdirs' ][ $part ];
}
$pointer [ 'files' ][ $file -> get_filename ()] = $file ;
unset ( $pointer );
}
return $result ;
}
2008-08-03 17:05:09 +00:00
/**
2010-05-03 21:04:06 +00:00
* Returns all files and optionally directories
*
2008-08-03 17:05:09 +00:00
* @ param int $contextid
2010-07-03 13:37:13 +00:00
* @ param string $component
2008-08-03 17:05:09 +00:00
* @ param string $filearea
* @ param int $itemid
* @ param int $filepath directory path
* @ param bool $recursive include all subdirectories
2008-08-29 05:32:10 +00:00
* @ param bool $includedirs include files and directories
2008-08-03 17:05:09 +00:00
* @ param string $sort
2008-09-21 10:35:39 +00:00
* @ return array of stored_files indexed by pathanmehash
2008-08-03 17:05:09 +00:00
*/
2010-07-03 13:37:13 +00:00
public function get_directory_files ( $contextid , $component , $filearea , $itemid , $filepath , $recursive = false , $includedirs = true , $sort = " filepath, filename " ) {
2008-08-03 17:05:09 +00:00
global $DB ;
2010-07-03 13:37:13 +00:00
if ( ! $directory = $this -> get_file ( $contextid , $component , $filearea , $itemid , $filepath , '.' )) {
2008-08-03 17:05:09 +00:00
return array ();
}
if ( $recursive ) {
2008-08-29 05:32:10 +00:00
$dirs = $includedirs ? " " : " AND filename <> '.' " ;
2008-08-03 17:05:09 +00:00
$length = textlib_get_instance () -> strlen ( $filepath );
$sql = " SELECT *
FROM { files }
2010-07-03 13:37:13 +00:00
WHERE contextid = : contextid AND component = : component AND filearea = : filearea AND itemid = : itemid
2008-10-28 15:11:10 +00:00
AND " . $DB->sql_substr ( " filepath " , 1, $length ). " = : filepath
2008-08-03 17:05:09 +00:00
AND id <> : dirid
$dirs
ORDER BY $sort " ;
2010-07-03 13:37:13 +00:00
$params = array ( 'contextid' => $contextid , 'component' => $component , 'filearea' => $filearea , 'itemid' => $itemid , 'filepath' => $filepath , 'dirid' => $directory -> get_id ());
2008-08-03 17:05:09 +00:00
$files = array ();
$dirs = array ();
$file_records = $DB -> get_records_sql ( $sql , $params );
foreach ( $file_records as $file_record ) {
if ( $file_record -> filename == '.' ) {
2008-09-21 10:35:39 +00:00
$dirs [ $file_record -> pathnamehash ] = new stored_file ( $this , $file_record );
2008-08-03 17:05:09 +00:00
} else {
2008-09-21 10:35:39 +00:00
$files [ $file_record -> pathnamehash ] = new stored_file ( $this , $file_record );
2008-08-03 17:05:09 +00:00
}
}
$result = array_merge ( $dirs , $files );
} else {
$result = array ();
2010-07-03 13:37:13 +00:00
$params = array ( 'contextid' => $contextid , 'component' => $component , 'filearea' => $filearea , 'itemid' => $itemid , 'filepath' => $filepath , 'dirid' => $directory -> get_id ());
2008-08-03 17:05:09 +00:00
$length = textlib_get_instance () -> strlen ( $filepath );
2008-08-29 05:32:10 +00:00
if ( $includedirs ) {
2008-08-03 17:05:09 +00:00
$sql = " SELECT *
FROM { files }
2010-07-03 13:37:13 +00:00
WHERE contextid = : contextid AND component = : component AND filearea = : filearea
2008-08-03 17:05:09 +00:00
AND itemid = : itemid AND filename = '.'
2008-10-28 15:11:10 +00:00
AND " . $DB->sql_substr ( " filepath " , 1, $length ). " = : filepath
2008-08-03 17:05:09 +00:00
AND id <> : dirid
ORDER BY $sort " ;
$reqlevel = substr_count ( $filepath , '/' ) + 1 ;
$file_records = $DB -> get_records_sql ( $sql , $params );
foreach ( $file_records as $file_record ) {
if ( substr_count ( $file_record -> filepath , '/' ) !== $reqlevel ) {
continue ;
}
2008-09-21 10:35:39 +00:00
$result [ $file_record -> pathnamehash ] = new stored_file ( $this , $file_record );
2008-08-03 17:05:09 +00:00
}
}
$sql = " SELECT *
FROM { files }
2010-07-03 13:37:13 +00:00
WHERE contextid = : contextid AND component = : component AND filearea = : filearea AND itemid = : itemid
2008-08-03 17:05:09 +00:00
AND filepath = : filepath AND filename <> '.'
ORDER BY $sort " ;
$file_records = $DB -> get_records_sql ( $sql , $params );
foreach ( $file_records as $file_record ) {
2008-09-21 10:35:39 +00:00
$result [ $file_record -> pathnamehash ] = new stored_file ( $this , $file_record );
2008-08-03 17:05:09 +00:00
}
}
return $result ;
}
2008-07-31 22:15:30 +00:00
/**
2010-05-03 21:04:06 +00:00
* Delete all area files ( optionally limited by itemid ) .
*
2008-07-31 22:15:30 +00:00
* @ param int $contextid
2010-07-03 13:37:13 +00:00
* @ param string $component
2008-08-27 08:23:07 +00:00
* @ param string $filearea ( all areas in context if not specified )
2008-07-31 22:15:30 +00:00
* @ param int $itemid ( all files if not specified )
2010-05-03 21:04:06 +00:00
* @ return bool success
2008-07-31 22:15:30 +00:00
*/
2010-07-03 13:37:13 +00:00
public function delete_area_files ( $contextid , $component = false , $filearea = false , $itemid = false ) {
2008-07-31 22:15:30 +00:00
global $DB ;
2008-08-27 08:23:07 +00:00
$conditions = array ( 'contextid' => $contextid );
2010-07-03 13:37:13 +00:00
if ( $component !== false ) {
$conditions [ 'component' ] = $component ;
}
2008-08-27 08:23:07 +00:00
if ( $filearea !== false ) {
$conditions [ 'filearea' ] = $filearea ;
}
2008-07-31 22:15:30 +00:00
if ( $itemid !== false ) {
$conditions [ 'itemid' ] = $itemid ;
}
$file_records = $DB -> get_records ( 'files' , $conditions );
foreach ( $file_records as $file_record ) {
$stored_file = new stored_file ( $this , $file_record );
2010-05-03 21:04:06 +00:00
$stored_file -> delete ();
2008-07-31 22:15:30 +00:00
}
2010-05-03 21:04:06 +00:00
return true ; // BC only
2008-07-31 22:15:30 +00:00
}
/**
2010-05-03 21:04:06 +00:00
* Recursively creates directory .
*
2008-07-31 22:15:30 +00:00
* @ param int $contextid
2010-07-03 13:37:13 +00:00
* @ param string $component
2008-07-31 22:15:30 +00:00
* @ param string $filearea
* @ param int $itemid
* @ param string $filepath
* @ param string $filename
* @ return bool success
*/
2010-07-03 13:37:13 +00:00
public function create_directory ( $contextid , $component , $filearea , $itemid , $filepath , $userid = null ) {
2008-07-31 22:15:30 +00:00
global $DB ;
// validate all parameters, we do not want any rubbish stored in database, right?
if ( ! is_number ( $contextid ) or $contextid < 1 ) {
2008-08-08 11:50:45 +00:00
throw new file_exception ( 'storedfileproblem' , 'Invalid contextid' );
2008-07-31 22:15:30 +00:00
}
2010-07-03 13:37:13 +00:00
if ( $component === '' or $component !== clean_param ( $component , PARAM_ALPHAEXT )) {
throw new file_exception ( 'storedfileproblem' , 'Invalid component' );
}
if ( $filearea === '' or $filearea !== clean_param ( $filearea , PARAM_ALPHAEXT )) {
2008-08-08 11:50:45 +00:00
throw new file_exception ( 'storedfileproblem' , 'Invalid filearea' );
2008-07-31 22:15:30 +00:00
}
if ( ! is_number ( $itemid ) or $itemid < 0 ) {
2008-08-08 11:50:45 +00:00
throw new file_exception ( 'storedfileproblem' , 'Invalid itemid' );
2008-07-31 22:15:30 +00:00
}
$filepath = clean_param ( $filepath , PARAM_PATH );
if ( strpos ( $filepath , '/' ) !== 0 or strrpos ( $filepath , '/' ) !== strlen ( $filepath ) - 1 ) {
// path must start and end with '/'
2008-08-08 11:50:45 +00:00
throw new file_exception ( 'storedfileproblem' , 'Invalid file path' );
2008-07-31 22:15:30 +00:00
}
2010-07-03 13:37:13 +00:00
$pathnamehash = $this -> get_pathname_hash ( $contextid , $component , $filearea , $itemid , $filepath , '.' );
2008-07-31 22:15:30 +00:00
if ( $dir_info = $this -> get_file_by_hash ( $pathnamehash )) {
return $dir_info ;
}
static $contenthash = null ;
if ( ! $contenthash ) {
2008-08-06 20:51:14 +00:00
$this -> add_string_to_pool ( '' );
2008-07-31 22:15:30 +00:00
$contenthash = sha1 ( '' );
}
$now = time ();
$dir_record = new object ();
$dir_record -> contextid = $contextid ;
2010-07-03 13:37:13 +00:00
$dir_record -> component = $component ;
2008-07-31 22:15:30 +00:00
$dir_record -> filearea = $filearea ;
$dir_record -> itemid = $itemid ;
$dir_record -> filepath = $filepath ;
$dir_record -> filename = '.' ;
$dir_record -> contenthash = $contenthash ;
$dir_record -> filesize = 0 ;
$dir_record -> timecreated = $now ;
$dir_record -> timemodified = $now ;
$dir_record -> mimetype = null ;
$dir_record -> userid = $userid ;
$dir_record -> pathnamehash = $pathnamehash ;
$DB -> insert_record ( 'files' , $dir_record );
$dir_info = $this -> get_file_by_hash ( $pathnamehash );
if ( $filepath !== '/' ) {
//recurse to parent dirs
$filepath = trim ( $filepath , '/' );
$filepath = explode ( '/' , $filepath );
array_pop ( $filepath );
$filepath = implode ( '/' , $filepath );
$filepath = ( $filepath === '' ) ? '/' : " / $filepath / " ;
2010-07-03 13:37:13 +00:00
$this -> create_directory ( $contextid , $component , $filearea , $itemid , $filepath , $userid );
2008-07-31 22:15:30 +00:00
}
return $dir_info ;
}
/**
2010-05-03 21:04:06 +00:00
* Add new local file based on existing local file .
*
2008-07-31 22:15:30 +00:00
* @ param mixed $file_record object or array describing changes
2009-10-14 08:53:50 +00:00
* @ param mixed $fileorid id or stored_file instance of the existing local file
2010-05-03 21:04:06 +00:00
* @ return stored_file instance of newly created file
2008-07-31 22:15:30 +00:00
*/
2009-10-14 08:53:50 +00:00
public function create_file_from_storedfile ( $file_record , $fileorid ) {
2010-04-06 18:34:38 +00:00
global $DB ;
2008-07-31 22:15:30 +00:00
2009-10-14 08:53:50 +00:00
if ( $fileorid instanceof stored_file ) {
$fid = $fileorid -> get_id ();
} else {
$fid = $fileorid ;
2008-08-16 21:21:23 +00:00
}
2008-09-06 21:33:07 +00:00
$file_record = ( array ) $file_record ; // we support arrays too, do not modify the submitted record!
2008-07-31 22:15:30 +00:00
unset ( $file_record [ 'id' ]);
unset ( $file_record [ 'filesize' ]);
unset ( $file_record [ 'contenthash' ]);
2008-08-16 21:21:23 +00:00
unset ( $file_record [ 'pathnamehash' ]);
2008-07-31 22:15:30 +00:00
2008-08-09 13:33:20 +00:00
if ( ! $newrecord = $DB -> get_record ( 'files' , array ( 'id' => $fid ))) {
2008-08-08 11:50:45 +00:00
throw new file_exception ( 'storedfileproblem' , 'File does not exist' );
2008-07-31 22:15:30 +00:00
}
unset ( $newrecord -> id );
foreach ( $file_record as $key => $value ) {
// validate all parameters, we do not want any rubbish stored in database, right?
if ( $key == 'contextid' and ( ! is_number ( $value ) or $value < 1 )) {
2008-08-08 11:50:45 +00:00
throw new file_exception ( 'storedfileproblem' , 'Invalid contextid' );
2008-07-31 22:15:30 +00:00
}
2010-07-03 13:37:13 +00:00
if ( $key == 'component' ) {
if ( $value === '' or $value !== clean_param ( $value , PARAM_ALPHAEXT )) {
throw new file_exception ( 'storedfileproblem' , 'Invalid component' );
}
}
2008-07-31 22:15:30 +00:00
if ( $key == 'filearea' ) {
2010-07-03 13:37:13 +00:00
if ( $value === '' or $value !== clean_param ( $value , PARAM_ALPHAEXT )) {
2008-08-08 11:50:45 +00:00
throw new file_exception ( 'storedfileproblem' , 'Invalid filearea' );
2008-07-31 22:15:30 +00:00
}
}
if ( $key == 'itemid' and ( ! is_number ( $value ) or $value < 0 )) {
2008-08-08 11:50:45 +00:00
throw new file_exception ( 'storedfileproblem' , 'Invalid itemid' );
2008-07-31 22:15:30 +00:00
}
if ( $key == 'filepath' ) {
$value = clean_param ( $value , PARAM_PATH );
2008-09-05 09:23:36 +00:00
if ( strpos ( $value , '/' ) !== 0 or strrpos ( $value , '/' ) !== strlen ( $value ) - 1 ) {
2008-07-31 22:15:30 +00:00
// path must start and end with '/'
2008-08-08 11:50:45 +00:00
throw new file_exception ( 'storedfileproblem' , 'Invalid file path' );
2008-07-31 22:15:30 +00:00
}
}
if ( $key == 'filename' ) {
$value = clean_param ( $value , PARAM_FILE );
if ( $value === '' ) {
// path must start and end with '/'
2008-08-08 11:50:45 +00:00
throw new file_exception ( 'storedfileproblem' , 'Invalid file name' );
2008-07-31 22:15:30 +00:00
}
}
$newrecord -> $key = $value ;
}
2010-07-03 13:37:13 +00:00
$newrecord -> pathnamehash = $this -> get_pathname_hash ( $newrecord -> contextid , $newrecord -> component , $newrecord -> filearea , $newrecord -> itemid , $newrecord -> filepath , $newrecord -> filename );
2008-07-31 22:15:30 +00:00
2008-09-21 10:35:39 +00:00
if ( $newrecord -> filename === '.' ) {
// special case - only this function supports directories ;-)
2010-07-03 13:37:13 +00:00
$directory = $this -> create_directory ( $newrecord -> contextid , $newrecord -> component , $newrecord -> filearea , $newrecord -> itemid , $newrecord -> filepath , $newrecord -> userid );
2008-09-21 10:35:39 +00:00
// update the existing directory with the new data
$newrecord -> id = $directory -> get_id ();
2009-06-13 16:47:05 +00:00
$DB -> update_record ( 'files' , $newrecord );
2008-09-21 10:35:39 +00:00
return new stored_file ( $this , $newrecord );
}
2008-07-31 22:15:30 +00:00
try {
$newrecord -> id = $DB -> insert_record ( 'files' , $newrecord );
2010-09-18 10:31:31 +00:00
} catch ( dml_exception $e ) {
2008-07-31 22:15:30 +00:00
$newrecord -> id = false ;
}
if ( ! $newrecord -> id ) {
2010-07-03 13:37:13 +00:00
throw new stored_file_creation_exception ( $newrecord -> contextid , $newrecord -> component , $newrecord -> filearea , $newrecord -> itemid ,
2008-09-21 10:35:39 +00:00
$newrecord -> filepath , $newrecord -> filename );
2008-07-31 22:15:30 +00:00
}
2010-07-03 13:37:13 +00:00
$this -> create_directory ( $newrecord -> contextid , $newrecord -> component , $newrecord -> filearea , $newrecord -> itemid , $newrecord -> filepath , $newrecord -> userid );
2008-07-31 22:15:30 +00:00
return new stored_file ( $this , $newrecord );
}
2008-09-06 10:09:33 +00:00
/**
2010-05-03 21:04:06 +00:00
* Add new local file .
*
2008-09-06 10:09:33 +00:00
* @ param mixed $file_record object or array describing file
* @ param string $path path to file or content of file
* @ param array $options @ see download_file_content () options
2010-05-20 17:13:07 +00:00
* @ param bool $usetempfile use temporary file for download , may prevent out of memory problems
2010-05-03 21:04:06 +00:00
* @ return stored_file instance
2008-09-06 10:09:33 +00:00
*/
2010-05-20 17:13:07 +00:00
public function create_file_from_url ( $file_record , $url , array $options = NULL , $usetempfile = false ) {
2008-09-06 21:33:07 +00:00
$file_record = ( array ) $file_record ; //do not modify the submitted record, this cast unlinks objects
2008-09-06 10:09:33 +00:00
$file_record = ( object ) $file_record ; // we support arrays too
$headers = isset ( $options [ 'headers' ]) ? $options [ 'headers' ] : null ;
$postdata = isset ( $options [ 'postdata' ]) ? $options [ 'postdata' ] : null ;
$fullresponse = isset ( $options [ 'fullresponse' ]) ? $options [ 'fullresponse' ] : false ;
$timeout = isset ( $options [ 'timeout' ]) ? $options [ 'timeout' ] : 300 ;
$connecttimeout = isset ( $options [ 'connecttimeout' ]) ? $options [ 'connecttimeout' ] : 20 ;
$skipcertverify = isset ( $options [ 'skipcertverify' ]) ? $options [ 'skipcertverify' ] : false ;
if ( ! isset ( $file_record -> filename )) {
$parts = explode ( '/' , $url );
$filename = array_pop ( $parts );
$file_record -> filename = clean_param ( $filename , PARAM_FILE );
}
2010-03-29 03:39:08 +00:00
$source = ! empty ( $file_record -> source ) ? $file_record -> source : $url ;
$file_record -> source = clean_param ( $source , PARAM_URL );
2008-09-06 10:09:33 +00:00
2010-05-20 17:13:07 +00:00
if ( $usetempfile ) {
2010-08-29 14:51:09 +00:00
check_dir_exists ( $this -> tempdir );
2010-05-20 17:13:07 +00:00
$tmpfile = tempnam ( $this -> tempdir , 'newfromurl' );
$content = download_file_content ( $url , $headers , $postdata , $fullresponse , $timeout , $connecttimeout , $skipcertverify , $tmpfile );
if ( $content === false ) {
throw new file_exception ( 'storedfileproblem' , 'Can not fetch file form URL' );
}
try {
$newfile = $this -> create_file_from_pathname ( $file_record , $tmpfile );
@ unlink ( $tmpfile );
return $newfile ;
} catch ( Exception $e ) {
@ unlink ( $tmpfile );
throw $e ;
}
} else {
$content = download_file_content ( $url , $headers , $postdata , $fullresponse , $timeout , $connecttimeout , $skipcertverify );
if ( $content === false ) {
throw new file_exception ( 'storedfileproblem' , 'Can not fetch file form URL' );
}
return $this -> create_file_from_string ( $file_record , $content );
}
2008-09-06 10:09:33 +00:00
}
2008-07-31 22:15:30 +00:00
/**
2010-05-03 21:04:06 +00:00
* Add new local file .
*
2008-07-31 22:15:30 +00:00
* @ param mixed $file_record object or array describing file
* @ param string $path path to file or content of file
2010-05-03 21:04:06 +00:00
* @ return stored_file instance
2008-07-31 22:15:30 +00:00
*/
public function create_file_from_pathname ( $file_record , $pathname ) {
2010-04-06 18:34:38 +00:00
global $DB ;
2008-07-31 22:15:30 +00:00
2008-09-06 21:33:07 +00:00
$file_record = ( array ) $file_record ; //do not modify the submitted record, this cast unlinks objects
2008-07-31 22:15:30 +00:00
$file_record = ( object ) $file_record ; // we support arrays too
// validate all parameters, we do not want any rubbish stored in database, right?
if ( ! is_number ( $file_record -> contextid ) or $file_record -> contextid < 1 ) {
2008-08-08 11:50:45 +00:00
throw new file_exception ( 'storedfileproblem' , 'Invalid contextid' );
2008-07-31 22:15:30 +00:00
}
2010-07-03 13:37:13 +00:00
if ( $file_record -> component === '' or $file_record -> component !== clean_param ( $file_record -> component , PARAM_ALPHAEXT )) {
throw new file_exception ( 'storedfileproblem' , 'Invalid component' );
}
if ( $file_record -> filearea === '' or $file_record -> filearea !== clean_param ( $file_record -> filearea , PARAM_ALPHAEXT )) {
2008-08-08 11:50:45 +00:00
throw new file_exception ( 'storedfileproblem' , 'Invalid filearea' );
2008-07-31 22:15:30 +00:00
}
if ( ! is_number ( $file_record -> itemid ) or $file_record -> itemid < 0 ) {
2008-08-08 11:50:45 +00:00
throw new file_exception ( 'storedfileproblem' , 'Invalid itemid' );
2008-07-31 22:15:30 +00:00
}
2010-05-28 07:29:11 +00:00
if ( ! empty ( $file_record -> sortorder )) {
if ( ! is_number ( $file_record -> sortorder ) or $file_record -> sortorder < 0 ) {
$file_record -> sortorder = 0 ;
}
} else {
$file_record -> sortorder = 0 ;
}
2008-07-31 22:15:30 +00:00
$file_record -> filepath = clean_param ( $file_record -> filepath , PARAM_PATH );
if ( strpos ( $file_record -> filepath , '/' ) !== 0 or strrpos ( $file_record -> filepath , '/' ) !== strlen ( $file_record -> filepath ) - 1 ) {
// path must start and end with '/'
2008-08-08 11:50:45 +00:00
throw new file_exception ( 'storedfileproblem' , 'Invalid file path' );
2008-07-31 22:15:30 +00:00
}
$file_record -> filename = clean_param ( $file_record -> filename , PARAM_FILE );
if ( $file_record -> filename === '' ) {
2008-09-05 02:57:19 +00:00
// filename must not be empty
2008-08-08 11:50:45 +00:00
throw new file_exception ( 'storedfileproblem' , 'Invalid file name' );
2008-07-31 22:15:30 +00:00
}
$now = time ();
$newrecord = new object ();
$newrecord -> contextid = $file_record -> contextid ;
2010-07-03 13:37:13 +00:00
$newrecord -> component = $file_record -> component ;
2008-07-31 22:15:30 +00:00
$newrecord -> filearea = $file_record -> filearea ;
$newrecord -> itemid = $file_record -> itemid ;
$newrecord -> filepath = $file_record -> filepath ;
$newrecord -> filename = $file_record -> filename ;
$newrecord -> timecreated = empty ( $file_record -> timecreated ) ? $now : $file_record -> timecreated ;
$newrecord -> timemodified = empty ( $file_record -> timemodified ) ? $now : $file_record -> timemodified ;
$newrecord -> mimetype = empty ( $file_record -> mimetype ) ? mimeinfo ( 'type' , $file_record -> filename ) : $file_record -> mimetype ;
$newrecord -> userid = empty ( $file_record -> userid ) ? null : $file_record -> userid ;
2010-04-06 18:34:38 +00:00
$newrecord -> source = empty ( $file_record -> source ) ? null : $file_record -> source ;
$newrecord -> author = empty ( $file_record -> author ) ? null : $file_record -> author ;
$newrecord -> license = empty ( $file_record -> license ) ? null : $file_record -> license ;
2010-05-28 07:29:11 +00:00
$newrecord -> sortorder = $file_record -> sortorder ;
2008-07-31 22:15:30 +00:00
2008-08-06 20:51:14 +00:00
list ( $newrecord -> contenthash , $newrecord -> filesize , $newfile ) = $this -> add_file_to_pool ( $pathname );
2008-07-31 22:15:30 +00:00
2010-07-03 13:37:13 +00:00
$newrecord -> pathnamehash = $this -> get_pathname_hash ( $newrecord -> contextid , $newrecord -> component , $newrecord -> filearea , $newrecord -> itemid , $newrecord -> filepath , $newrecord -> filename );
2008-07-31 22:15:30 +00:00
try {
$newrecord -> id = $DB -> insert_record ( 'files' , $newrecord );
2010-09-18 10:31:31 +00:00
} catch ( dml_exception $e ) {
2008-07-31 22:15:30 +00:00
$newrecord -> id = false ;
}
if ( ! $newrecord -> id ) {
if ( $newfile ) {
2009-07-27 12:39:13 +00:00
$this -> deleted_file_cleanup ( $newrecord -> contenthash );
2008-07-31 22:15:30 +00:00
}
2010-07-03 13:37:13 +00:00
throw new stored_file_creation_exception ( $newrecord -> contextid , $newrecord -> component , $newrecord -> filearea , $newrecord -> itemid ,
2008-07-31 22:15:30 +00:00
$newrecord -> filepath , $newrecord -> filename );
}
2010-07-03 13:37:13 +00:00
$this -> create_directory ( $newrecord -> contextid , $newrecord -> component , $newrecord -> filearea , $newrecord -> itemid , $newrecord -> filepath , $newrecord -> userid );
2008-07-31 22:15:30 +00:00
return new stored_file ( $this , $newrecord );
}
/**
2010-05-03 21:04:06 +00:00
* Add new local file .
*
2008-07-31 22:15:30 +00:00
* @ param mixed $file_record object or array describing file
* @ param string $content content of file
2010-05-03 21:04:06 +00:00
* @ return stored_file instance
2008-07-31 22:15:30 +00:00
*/
public function create_file_from_string ( $file_record , $content ) {
2010-04-06 18:34:38 +00:00
global $DB ;
2008-07-31 22:15:30 +00:00
2008-09-06 21:33:07 +00:00
$file_record = ( array ) $file_record ; //do not modify the submitted record, this cast unlinks objects
2008-07-31 22:15:30 +00:00
$file_record = ( object ) $file_record ; // we support arrays too
// validate all parameters, we do not want any rubbish stored in database, right?
if ( ! is_number ( $file_record -> contextid ) or $file_record -> contextid < 1 ) {
2008-08-08 11:50:45 +00:00
throw new file_exception ( 'storedfileproblem' , 'Invalid contextid' );
2008-07-31 22:15:30 +00:00
}
2010-07-03 13:37:13 +00:00
if ( $file_record -> component === '' or $file_record -> component !== clean_param ( $file_record -> component , PARAM_ALPHAEXT )) {
throw new file_exception ( 'storedfileproblem' , 'Invalid component' );
}
if ( $file_record -> filearea === '' or $file_record -> filearea !== clean_param ( $file_record -> filearea , PARAM_ALPHAEXT )) {
2008-08-08 11:50:45 +00:00
throw new file_exception ( 'storedfileproblem' , 'Invalid filearea' );
2008-07-31 22:15:30 +00:00
}
if ( ! is_number ( $file_record -> itemid ) or $file_record -> itemid < 0 ) {
2008-08-08 11:50:45 +00:00
throw new file_exception ( 'storedfileproblem' , 'Invalid itemid' );
2008-07-31 22:15:30 +00:00
}
2010-05-28 07:29:11 +00:00
if ( ! empty ( $file_record -> sortorder )) {
if ( ! is_number ( $file_record -> sortorder ) or $file_record -> sortorder < 0 ) {
$file_record -> sortorder = 0 ;
}
} else {
$file_record -> sortorder = 0 ;
}
2008-07-31 22:15:30 +00:00
$file_record -> filepath = clean_param ( $file_record -> filepath , PARAM_PATH );
if ( strpos ( $file_record -> filepath , '/' ) !== 0 or strrpos ( $file_record -> filepath , '/' ) !== strlen ( $file_record -> filepath ) - 1 ) {
// path must start and end with '/'
2008-08-08 11:50:45 +00:00
throw new file_exception ( 'storedfileproblem' , 'Invalid file path' );
2008-07-31 22:15:30 +00:00
}
$file_record -> filename = clean_param ( $file_record -> filename , PARAM_FILE );
if ( $file_record -> filename === '' ) {
// path must start and end with '/'
2008-08-08 11:50:45 +00:00
throw new file_exception ( 'storedfileproblem' , 'Invalid file name' );
2008-07-31 22:15:30 +00:00
}
$now = time ();
$newrecord = new object ();
$newrecord -> contextid = $file_record -> contextid ;
2010-07-03 13:37:13 +00:00
$newrecord -> component = $file_record -> component ;
2008-07-31 22:15:30 +00:00
$newrecord -> filearea = $file_record -> filearea ;
$newrecord -> itemid = $file_record -> itemid ;
$newrecord -> filepath = $file_record -> filepath ;
$newrecord -> filename = $file_record -> filename ;
$newrecord -> timecreated = empty ( $file_record -> timecreated ) ? $now : $file_record -> timecreated ;
$newrecord -> timemodified = empty ( $file_record -> timemodified ) ? $now : $file_record -> timemodified ;
$newrecord -> mimetype = empty ( $file_record -> mimetype ) ? mimeinfo ( 'type' , $file_record -> filename ) : $file_record -> mimetype ;
$newrecord -> userid = empty ( $file_record -> userid ) ? null : $file_record -> userid ;
2010-04-06 18:34:38 +00:00
$newrecord -> source = empty ( $file_record -> source ) ? null : $file_record -> source ;
$newrecord -> author = empty ( $file_record -> author ) ? null : $file_record -> author ;
$newrecord -> license = empty ( $file_record -> license ) ? null : $file_record -> license ;
2010-05-28 07:29:11 +00:00
$newrecord -> sortorder = $file_record -> sortorder ;
2010-03-29 03:39:08 +00:00
2008-08-06 20:51:14 +00:00
list ( $newrecord -> contenthash , $newrecord -> filesize , $newfile ) = $this -> add_string_to_pool ( $content );
2008-07-31 22:15:30 +00:00
2010-07-03 13:37:13 +00:00
$newrecord -> pathnamehash = $this -> get_pathname_hash ( $newrecord -> contextid , $newrecord -> component , $newrecord -> filearea , $newrecord -> itemid , $newrecord -> filepath , $newrecord -> filename );
2008-07-31 22:15:30 +00:00
try {
$newrecord -> id = $DB -> insert_record ( 'files' , $newrecord );
2010-09-18 10:31:31 +00:00
} catch ( dml_exception $e ) {
2008-07-31 22:15:30 +00:00
$newrecord -> id = false ;
}
if ( ! $newrecord -> id ) {
if ( $newfile ) {
2009-07-27 12:39:13 +00:00
$this -> deleted_file_cleanup ( $newrecord -> contenthash );
2008-07-31 22:15:30 +00:00
}
2010-07-03 13:37:13 +00:00
throw new stored_file_creation_exception ( $newrecord -> contextid , $newrecord -> component , $newrecord -> filearea , $newrecord -> itemid ,
2008-07-31 22:15:30 +00:00
$newrecord -> filepath , $newrecord -> filename );
}
2010-07-03 13:37:13 +00:00
$this -> create_directory ( $newrecord -> contextid , $newrecord -> component , $newrecord -> filearea , $newrecord -> itemid , $newrecord -> filepath , $newrecord -> userid );
2008-07-31 22:15:30 +00:00
return new stored_file ( $this , $newrecord );
}
2008-09-13 19:38:44 +00:00
/**
* Creates new image file from existing .
2010-05-03 21:04:06 +00:00
*
2008-09-13 19:38:44 +00:00
* @ param mixed $file_record object or array describing new file
* @ param mixed file id or stored file object
* @ param int $newwidth in pixels
* @ param int $newheight in pixels
* @ param bool $keepaspectratio
2010-05-03 21:04:06 +00:00
* @ param int $quality depending on image type 0 - 100 for jpeg , 0 - 9 ( 0 means no compression ) for png
* @ return stored_file instance
2008-09-13 19:38:44 +00:00
*/
2010-05-03 21:04:06 +00:00
public function convert_image ( $file_record , $fid , $newwidth = NULL , $newheight = NULL , $keepaspectratio = true , $quality = NULL ) {
2008-09-13 19:38:44 +00:00
if ( $fid instanceof stored_file ) {
$fid = $fid -> get_id ();
}
$file_record = ( array ) $file_record ; // we support arrays too, do not modify the submitted record!
if ( ! $file = $this -> get_file_by_id ( $fid )) { // make sure file really exists and we we correct data
throw new file_exception ( 'storedfileproblem' , 'File does not exist' );
}
if ( ! $imageinfo = $file -> get_imageinfo ()) {
throw new file_exception ( 'storedfileproblem' , 'File is not an image' );
}
if ( ! isset ( $file_record [ 'filename' ])) {
$file_record [ 'filename' ] == $file -> get_filename ();
}
if ( ! isset ( $file_record [ 'mimetype' ])) {
$file_record [ 'mimetype' ] = mimeinfo ( 'type' , $file_record [ 'filename' ]);
}
$width = $imageinfo [ 'width' ];
$height = $imageinfo [ 'height' ];
$mimetype = $imageinfo [ 'mimetype' ];
if ( $keepaspectratio ) {
if ( 0 >= $newwidth and 0 >= $newheight ) {
// no sizes specified
$newwidth = $width ;
$newheight = $height ;
} else if ( 0 < $newwidth and 0 < $newheight ) {
$xheight = ( $newwidth * ( $height / $width ));
if ( $xheight < $newheight ) {
$newheight = ( int ) $xheight ;
} else {
$newwidth = ( int )( $newheight * ( $width / $height ));
}
} else if ( 0 < $newwidth ) {
$newheight = ( int )( $newwidth * ( $height / $width ));
} else { //0 < $newheight
$newwidth = ( int )( $newheight * ( $width / $height ));
}
} else {
if ( 0 >= $newwidth ) {
$newwidth = $width ;
}
if ( 0 >= $newheight ) {
$newheight = $height ;
}
}
$img = imagecreatefromstring ( $file -> get_content ());
if ( $height != $newheight or $width != $newwidth ) {
$newimg = imagecreatetruecolor ( $newwidth , $newheight );
if ( ! imagecopyresized ( $newimg , $img , 0 , 0 , 0 , 0 , $newwidth , $newheight , $width , $height )) {
// weird
throw new file_exception ( 'storedfileproblem' , 'Can not resize image' );
}
imagedestroy ( $img );
$img = $newimg ;
}
ob_start ();
switch ( $file_record [ 'mimetype' ]) {
case 'image/gif' :
imagegif ( $img );
break ;
case 'image/jpeg' :
if ( is_null ( $quality )) {
imagejpeg ( $img );
} else {
imagejpeg ( $img , NULL , $quality );
}
break ;
case 'image/png' :
2008-09-16 15:56:19 +00:00
$quality = ( int ) $quality ;
2008-09-13 19:38:44 +00:00
imagepng ( $img , NULL , $quality , NULL );
break ;
default :
throw new file_exception ( 'storedfileproblem' , 'Unsupported mime type' );
}
$content = ob_get_contents ();
ob_end_clean ();
imagedestroy ( $img );
if ( ! $content ) {
throw new file_exception ( 'storedfileproblem' , 'Can not convert image' );
}
return $this -> create_file_from_string ( $file_record , $content );
}
2008-07-31 22:15:30 +00:00
/**
2010-05-03 21:04:06 +00:00
* Add file content to sha1 pool .
*
2008-07-31 22:15:30 +00:00
* @ param string $pathname path to file
2010-05-03 21:04:06 +00:00
* @ param string $contenthash sha1 hash of content if known ( performance only )
* @ return array ( contenthash , filesize , newfile )
2008-07-31 22:15:30 +00:00
*/
2010-05-03 21:04:06 +00:00
public function add_file_to_pool ( $pathname , $contenthash = NULL ) {
2008-07-31 22:15:30 +00:00
if ( ! is_readable ( $pathname )) {
2008-08-08 11:50:45 +00:00
throw new file_exception ( 'storedfilecannotread' );
2008-07-31 22:15:30 +00:00
}
if ( is_null ( $contenthash )) {
$contenthash = sha1_file ( $pathname );
}
$filesize = filesize ( $pathname );
$hashpath = $this -> path_from_hash ( $contenthash );
$hashfile = " $hashpath / $contenthash " ;
if ( file_exists ( $hashfile )) {
if ( filesize ( $hashfile ) !== $filesize ) {
throw new file_pool_content_exception ( $contenthash );
}
$newfile = false ;
} else {
2009-06-03 08:10:21 +00:00
if ( ! is_dir ( $hashpath )) {
if ( ! mkdir ( $hashpath , $this -> dirpermissions , true )) {
throw new file_exception ( 'storedfilecannotcreatefiledirs' ); // permission trouble
}
2008-07-31 22:15:30 +00:00
}
$newfile = true ;
2008-08-02 12:45:02 +00:00
if ( ! copy ( $pathname , $hashfile )) {
2008-08-08 11:50:45 +00:00
throw new file_exception ( 'storedfilecannotread' );
2008-07-31 22:15:30 +00:00
}
if ( filesize ( $hashfile ) !== $filesize ) {
@ unlink ( $hashfile );
throw new file_pool_content_exception ( $contenthash );
}
2009-06-03 08:10:21 +00:00
chmod ( $hashfile , $this -> filepermissions ); // fix permissions if needed
2008-07-31 22:15:30 +00:00
}
return array ( $contenthash , $filesize , $newfile );
}
/**
2010-05-03 21:04:06 +00:00
* Add string content to sha1 pool .
*
2008-07-31 22:15:30 +00:00
* @ param string $content file content - binary string
2010-05-03 21:04:06 +00:00
* @ return array ( contenthash , filesize , newfile )
2008-07-31 22:15:30 +00:00
*/
2008-08-06 20:51:14 +00:00
public function add_string_to_pool ( $content ) {
2008-07-31 22:15:30 +00:00
$contenthash = sha1 ( $content );
$filesize = strlen ( $content ); // binary length
$hashpath = $this -> path_from_hash ( $contenthash );
$hashfile = " $hashpath / $contenthash " ;
if ( file_exists ( $hashfile )) {
if ( filesize ( $hashfile ) !== $filesize ) {
throw new file_pool_content_exception ( $contenthash );
}
$newfile = false ;
} else {
2009-06-03 08:10:21 +00:00
if ( ! is_dir ( $hashpath )) {
if ( ! mkdir ( $hashpath , $this -> dirpermissions , true )) {
throw new file_exception ( 'storedfilecannotcreatefiledirs' ); // permission trouble
}
2008-07-31 22:15:30 +00:00
}
$newfile = true ;
2008-08-02 12:45:02 +00:00
file_put_contents ( $hashfile , $content );
2008-07-31 22:15:30 +00:00
if ( filesize ( $hashfile ) !== $filesize ) {
@ unlink ( $hashfile );
throw new file_pool_content_exception ( $contenthash );
}
2009-06-03 08:10:21 +00:00
chmod ( $hashfile , $this -> filepermissions ); // fix permissions if needed
2008-07-31 22:15:30 +00:00
}
return array ( $contenthash , $filesize , $newfile );
}
/**
2010-05-03 21:04:06 +00:00
* Return path to file with given hash .
2008-07-31 22:15:30 +00:00
*
2008-08-02 18:33:11 +00:00
* NOTE : must not be public , files in pool must not be modified
2008-07-31 22:15:30 +00:00
*
* @ param string $contenthash
* @ return string expected file location
*/
2008-08-02 18:33:11 +00:00
protected function path_from_hash ( $contenthash ) {
2008-07-31 22:15:30 +00:00
$l1 = $contenthash [ 0 ] . $contenthash [ 1 ];
$l2 = $contenthash [ 2 ] . $contenthash [ 3 ];
2010-08-25 21:45:34 +00:00
return " $this->filedir / $l1 / $l2 " ;
2008-07-31 22:15:30 +00:00
}
2009-06-03 08:10:21 +00:00
/**
2010-05-03 21:04:06 +00:00
* Return path to file with given hash .
2009-06-03 08:10:21 +00:00
*
* NOTE : must not be public , files in pool must not be modified
*
* @ param string $contenthash
* @ return string expected file location
*/
protected function trash_path_from_hash ( $contenthash ) {
$l1 = $contenthash [ 0 ] . $contenthash [ 1 ];
$l2 = $contenthash [ 2 ] . $contenthash [ 3 ];
2010-08-25 21:45:34 +00:00
return " $this->trashdir / $l1 / $l2 " ;
2009-06-03 08:10:21 +00:00
}
/**
2010-05-03 21:04:06 +00:00
* Tries to recover missing content of file from trash .
*
2009-06-03 08:10:21 +00:00
* @ param object $file_record
* @ return bool success
*/
public function try_content_recovery ( $file ) {
$contenthash = $file -> get_contenthash ();
$trashfile = $this -> trash_path_from_hash ( $contenthash ) . '/' . $contenthash ;
if ( ! is_readable ( $trashfile )) {
if ( ! is_readable ( $this -> trashdir . '/' . $contenthash )) {
return false ;
}
// nice, at least alternative trash file in trash root exists
$trashfile = $this -> trashdir . '/' . $contenthash ;
}
if ( filesize ( $trashfile ) != $file -> get_filesize () or sha1_file ( $trashfile ) != $contenthash ) {
//weird, better fail early
return false ;
}
$contentdir = $this -> path_from_hash ( $contenthash );
$contentfile = $contentdir . '/' . $contenthash ;
if ( file_exists ( $contentfile )) {
//strange, no need to recover anything
return true ;
}
if ( ! is_dir ( $contentdir )) {
if ( ! mkdir ( $contentdir , $this -> dirpermissions , true )) {
return false ;
}
}
return rename ( $trashfile , $contentfile );
}
2008-07-31 22:15:30 +00:00
/**
2010-05-03 21:04:06 +00:00
* Marks pool file as candidate for deleting .
*
* DO NOT call directly - reserved for core !!
*
2008-07-31 22:15:30 +00:00
* @ param string $contenthash
2009-06-03 08:10:21 +00:00
* @ return void
2008-07-31 22:15:30 +00:00
*/
2009-06-03 08:10:21 +00:00
public function deleted_file_cleanup ( $contenthash ) {
2008-07-31 22:15:30 +00:00
global $DB ;
2009-06-03 08:10:21 +00:00
//Note: this section is critical - in theory file could be reused at the same
// time, if this happens we can still recover the file from trash
if ( $DB -> record_exists ( 'files' , array ( 'contenthash' => $contenthash ))) {
// file content is still used
return ;
}
//move content file to trash
$contentfile = $this -> path_from_hash ( $contenthash ) . '/' . $contenthash ;
if ( ! file_exists ( $contentfile )) {
//weird, but no problem
2008-07-31 22:15:30 +00:00
return ;
}
2009-06-03 08:10:21 +00:00
$trashpath = $this -> trash_path_from_hash ( $contenthash );
$trashfile = $trashpath . '/' . $contenthash ;
if ( file_exists ( $trashfile )) {
// we already have this content in trash, no need to move it there
unlink ( $contentfile );
return ;
}
if ( ! is_dir ( $trashpath )) {
mkdir ( $trashpath , $this -> dirpermissions , true );
}
rename ( $contentfile , $trashfile );
chmod ( $trashfile , $this -> filepermissions ); // fix permissions if needed
2008-07-31 22:15:30 +00:00
}
/**
* Cron cleanup job .
2010-05-03 21:04:06 +00:00
*
* @ return void
2008-07-31 22:15:30 +00:00
*/
public function cron () {
2009-12-23 01:24:17 +00:00
global $CFG , $DB ;
2010-07-03 13:37:13 +00:00
2010-08-23 07:33:02 +00:00
// find out all stale draft areas (older than 4 days) and purge them
// those are identified by time stamp of the /. root dir
mtrace ( 'Deleting old draft files... ' , '' );
$old = time () - 60 * 60 * 24 * 4 ;
$sql = " SELECT *
FROM { files }
WHERE component = 'user' AND filearea = 'draft' AND filepath = '/' AND filename = '.'
AND timecreated < : old " ;
$rs = $DB -> get_recordset_sql ( $sql , array ( 'old' => $old ));
foreach ( $rs as $dir ) {
$this -> delete_area_files ( $dir -> contextid , $dir -> component , $dir -> filearea , $dir -> itemid );
}
2010-07-03 13:37:13 +00:00
2009-06-03 08:10:21 +00:00
// remove trash pool files once a day
// if you want to disable purging of trash put $CFG->fileslastcleanup=time(); into config.php
if ( empty ( $CFG -> fileslastcleanup ) or $CFG -> fileslastcleanup < time () - 60 * 60 * 24 ) {
require_once ( $CFG -> libdir . '/filelib.php' );
2009-12-23 01:24:17 +00:00
// Delete files that are associated with a context that no longer exists.
mtrace ( 'Cleaning up files from deleted contexts... ' , '' );
$sql = " SELECT DISTINCT f.contextid
FROM { files } f
LEFT OUTER JOIN { context } c ON f . contextid = c . id
WHERE c . id IS NULL " ;
if ( $rs = $DB -> get_recordset_sql ( $sql )) {
$fs = get_file_storage ();
foreach ( $rs as $ctx ) {
$fs -> delete_area_files ( $ctx -> contextid );
}
}
mtrace ( 'done.' );
2009-06-03 08:10:21 +00:00
mtrace ( 'Deleting trash files... ' , '' );
fulldelete ( $this -> trashdir );
set_config ( 'fileslastcleanup' , time ());
mtrace ( 'done.' );
2008-07-31 22:15:30 +00:00
}
}
}
2010-05-03 21:04:06 +00:00