Merge branch 'MDL-32471-thumbnails' of git://github.com/mudrd8mz/moodle
This commit is contained in:
+3
-2
@@ -28,9 +28,10 @@
|
||||
* @param string $filearea file area
|
||||
* @param array $args extra arguments
|
||||
* @param bool $forcedownload whether or not force download
|
||||
* @param array $options additional options affecting the file serving
|
||||
* @return bool
|
||||
*/
|
||||
function block_html_pluginfile($course, $birecord_or_cm, $context, $filearea, $args, $forcedownload) {
|
||||
function block_html_pluginfile($course, $birecord_or_cm, $context, $filearea, $args, $forcedownload, array $options=array()) {
|
||||
global $SCRIPT;
|
||||
|
||||
if ($context->contextlevel != CONTEXT_BLOCK) {
|
||||
@@ -64,7 +65,7 @@ function block_html_pluginfile($course, $birecord_or_cm, $context, $filearea, $a
|
||||
}
|
||||
|
||||
session_get_instance()->write_close();
|
||||
send_stored_file($file, 60*60, 0, $forcedownload);
|
||||
send_stored_file($file, 60*60, 0, $forcedownload, $options);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,6 +1,12 @@
|
||||
This files describes API changes in /blocks/* - activity modules,
|
||||
information provided here is intended especially for developers.
|
||||
|
||||
=== 2.3 ===
|
||||
|
||||
required changes in code:
|
||||
* block_xxx_pluginfile() is now given the 7th parameter (hopefully the last one) that
|
||||
contains additional options for the file serving. The array should be re-passed
|
||||
to send_stored_file().
|
||||
|
||||
=== 2.0 ===
|
||||
|
||||
|
||||
+71
-36
@@ -1950,6 +1950,14 @@ function send_file($path, $filename, $lifetime = 'default' , $filter=0, $pathiss
|
||||
* Handles the sending of file data to the user's browser, including support for
|
||||
* byteranges etc.
|
||||
*
|
||||
* The $options parameter supports the following keys:
|
||||
* (string|null) preview - send the preview of the file (e.g. "thumb" for a thumbnail)
|
||||
* (string|null) filename - overrides the implicit filename
|
||||
* (bool) dontdie - return control to caller afterwards. this is not recommended and only used for cleanup tasks.
|
||||
* if this is passed as true, ignore_user_abort is called. if you don't want your processing to continue on cancel,
|
||||
* you must detect this case when control is returned using connection_aborted. Please not that session is closed
|
||||
* and should not be reopened.
|
||||
*
|
||||
* @category files
|
||||
* @global stdClass $CFG
|
||||
* @global stdClass $COURSE
|
||||
@@ -1958,16 +1966,41 @@ function send_file($path, $filename, $lifetime = 'default' , $filter=0, $pathiss
|
||||
* @param int $lifetime Number of seconds before the file should expire from caches (default 24 hours)
|
||||
* @param int $filter 0 (default)=no filtering, 1=all files, 2=html files only
|
||||
* @param bool $forcedownload If true (default false), forces download of file rather than view in browser/plugin
|
||||
* @param string $filename Override filename
|
||||
* @param bool $dontdie - return control to caller afterwards. this is not recommended and only used for cleanup tasks.
|
||||
* if this is passed as true, ignore_user_abort is called. if you don't want your processing to continue on cancel,
|
||||
* you must detect this case when control is returned using connection_aborted. Please not that session is closed
|
||||
* and should not be reopened.
|
||||
* @return null script execution stopped unless $dontdie is true
|
||||
* @param array $options additional options affecting the file serving
|
||||
* @return null script execution stopped unless $options['dontdie'] is true
|
||||
*/
|
||||
function send_stored_file($stored_file, $lifetime=86400 , $filter=0, $forcedownload=false, $filename=null, $dontdie=false) {
|
||||
function send_stored_file($stored_file, $lifetime=86400 , $filter=0, $forcedownload=false, array $options=array()) {
|
||||
global $CFG, $COURSE, $SESSION;
|
||||
|
||||
if (empty($options['filename'])) {
|
||||
$filename = null;
|
||||
} else {
|
||||
$filename = $options['filename'];
|
||||
}
|
||||
|
||||
if (empty($options['dontdie'])) {
|
||||
$dontdie = false;
|
||||
} else {
|
||||
$dontdie = true;
|
||||
}
|
||||
|
||||
if (!empty($options['preview'])) {
|
||||
// replace the file with its preview
|
||||
$fs = get_file_storage();
|
||||
$stored_file = $fs->get_file_preview($stored_file, $options['preview']);
|
||||
if (!$stored_file) {
|
||||
// unable to create a preview of the file
|
||||
send_header_404();
|
||||
die();
|
||||
} else {
|
||||
// preview images have fixed cache lifetime and they ignore forced download
|
||||
// (they are generated by GD and therefore they are considered reasonably safe).
|
||||
$lifetime = DAYSECS;
|
||||
$filter = 0;
|
||||
$forcedownload = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!$stored_file or $stored_file->is_directory()) {
|
||||
// nothing to serve
|
||||
if ($dontdie) {
|
||||
@@ -3211,9 +3244,10 @@ class filetype_parser {
|
||||
*
|
||||
* @param string $relativepath
|
||||
* @param bool $forcedownload
|
||||
* @param null|string $preview the preview mode, defaults to serving the original file
|
||||
* @todo MDL-31088 file serving improments
|
||||
*/
|
||||
function file_pluginfile($relativepath, $forcedownload) {
|
||||
function file_pluginfile($relativepath, $forcedownload, $preview = null) {
|
||||
global $DB, $CFG, $USER;
|
||||
// relative path must start with '/'
|
||||
if (!$relativepath) {
|
||||
@@ -3289,7 +3323,7 @@ function file_pluginfile($relativepath, $forcedownload) {
|
||||
send_file_not_found();
|
||||
}
|
||||
|
||||
send_stored_file($file, 10*60, 0, true); // download MUST be forced - security!
|
||||
send_stored_file($file, 10*60, 0, true, array('preview' => $preview)); // download MUST be forced - security!
|
||||
|
||||
// ========================================================================================================================
|
||||
} else if ($component === 'grade') {
|
||||
@@ -3306,7 +3340,7 @@ function file_pluginfile($relativepath, $forcedownload) {
|
||||
}
|
||||
|
||||
session_get_instance()->write_close(); // unlock session during fileserving
|
||||
send_stored_file($file, 60*60, 0, $forcedownload);
|
||||
send_stored_file($file, 60*60, 0, $forcedownload, array('preview' => $preview));
|
||||
|
||||
} else if ($filearea === 'feedback' and $context->contextlevel == CONTEXT_COURSE) {
|
||||
//TODO: nobody implemented this yet in grade edit form!!
|
||||
@@ -3323,7 +3357,7 @@ function file_pluginfile($relativepath, $forcedownload) {
|
||||
}
|
||||
|
||||
session_get_instance()->write_close(); // unlock session during fileserving
|
||||
send_stored_file($file, 60*60, 0, $forcedownload);
|
||||
send_stored_file($file, 60*60, 0, $forcedownload, array('preview' => $preview));
|
||||
} else {
|
||||
send_file_not_found();
|
||||
}
|
||||
@@ -3344,7 +3378,7 @@ function file_pluginfile($relativepath, $forcedownload) {
|
||||
}
|
||||
|
||||
session_get_instance()->write_close(); // unlock session during fileserving
|
||||
send_stored_file($file, 60*60, 0, true);
|
||||
send_stored_file($file, 60*60, 0, true, array('preview' => $preview));
|
||||
|
||||
} else {
|
||||
send_file_not_found();
|
||||
@@ -3376,7 +3410,7 @@ function file_pluginfile($relativepath, $forcedownload) {
|
||||
}
|
||||
|
||||
session_get_instance()->write_close(); // unlock session during fileserving
|
||||
send_stored_file($file, 60*60, 0, $forcedownload);
|
||||
send_stored_file($file, 60*60, 0, $forcedownload, array('preview' => $preview));
|
||||
|
||||
} else if ($filearea === 'event_description' and $context->contextlevel == CONTEXT_USER) {
|
||||
|
||||
@@ -3404,7 +3438,7 @@ function file_pluginfile($relativepath, $forcedownload) {
|
||||
}
|
||||
|
||||
session_get_instance()->write_close(); // unlock session during fileserving
|
||||
send_stored_file($file, 60*60, 0, $forcedownload);
|
||||
send_stored_file($file, 60*60, 0, $forcedownload, array('preview' => $preview));
|
||||
|
||||
} else if ($filearea === 'event_description' and $context->contextlevel == CONTEXT_COURSE) {
|
||||
|
||||
@@ -3451,7 +3485,7 @@ function file_pluginfile($relativepath, $forcedownload) {
|
||||
}
|
||||
|
||||
session_get_instance()->write_close(); // unlock session during fileserving
|
||||
send_stored_file($file, 60*60, 0, $forcedownload);
|
||||
send_stored_file($file, 60*60, 0, $forcedownload, array('preview' => $preview));
|
||||
|
||||
} else {
|
||||
send_file_not_found();
|
||||
@@ -3488,7 +3522,7 @@ function file_pluginfile($relativepath, $forcedownload) {
|
||||
$theme = theme_config::load($themename);
|
||||
redirect($theme->pix_url('u/'.$filename, 'moodle'));
|
||||
}
|
||||
send_stored_file($file, 60*60*24); // enable long caching, there are many images on each page
|
||||
send_stored_file($file, 60*60*24, 0, false, array('preview' => $preview)); // enable long caching, there are many images on each page
|
||||
|
||||
} else if ($filearea === 'private' and $context->contextlevel == CONTEXT_USER) {
|
||||
require_login();
|
||||
@@ -3508,7 +3542,7 @@ function file_pluginfile($relativepath, $forcedownload) {
|
||||
}
|
||||
|
||||
session_get_instance()->write_close(); // unlock session during fileserving
|
||||
send_stored_file($file, 0, 0, true); // must force download - security!
|
||||
send_stored_file($file, 0, 0, true, array('preview' => $preview)); // must force download - security!
|
||||
|
||||
} else if ($filearea === 'profile' and $context->contextlevel == CONTEXT_USER) {
|
||||
|
||||
@@ -3555,7 +3589,7 @@ function file_pluginfile($relativepath, $forcedownload) {
|
||||
}
|
||||
|
||||
session_get_instance()->write_close(); // unlock session during fileserving
|
||||
send_stored_file($file, 0, 0, true); // must force download - security!
|
||||
send_stored_file($file, 0, 0, true, array('preview' => $preview)); // must force download - security!
|
||||
|
||||
} else if ($filearea === 'profile' and $context->contextlevel == CONTEXT_COURSE) {
|
||||
$userid = (int)array_shift($args);
|
||||
@@ -3593,7 +3627,7 @@ function file_pluginfile($relativepath, $forcedownload) {
|
||||
}
|
||||
|
||||
session_get_instance()->write_close(); // unlock session during fileserving
|
||||
send_stored_file($file, 0, 0, true); // must force download - security!
|
||||
send_stored_file($file, 0, 0, true, array('preview' => $preview)); // must force download - security!
|
||||
|
||||
} else if ($filearea === 'backup' and $context->contextlevel == CONTEXT_USER) {
|
||||
require_login();
|
||||
@@ -3614,7 +3648,7 @@ function file_pluginfile($relativepath, $forcedownload) {
|
||||
}
|
||||
|
||||
session_get_instance()->write_close(); // unlock session during fileserving
|
||||
send_stored_file($file, 0, 0, true); // must force download - security!
|
||||
send_stored_file($file, 0, 0, true, array('preview' => $preview)); // must force download - security!
|
||||
|
||||
} else {
|
||||
send_file_not_found();
|
||||
@@ -3639,7 +3673,7 @@ function file_pluginfile($relativepath, $forcedownload) {
|
||||
}
|
||||
|
||||
session_get_instance()->write_close(); // unlock session during fileserving
|
||||
send_stored_file($file, 60*60, 0, $forcedownload);
|
||||
send_stored_file($file, 60*60, 0, $forcedownload, array('preview' => $preview));
|
||||
} else {
|
||||
send_file_not_found();
|
||||
}
|
||||
@@ -3662,7 +3696,7 @@ function file_pluginfile($relativepath, $forcedownload) {
|
||||
}
|
||||
|
||||
session_get_instance()->write_close(); // unlock session during fileserving
|
||||
send_stored_file($file, 60*60, 0, $forcedownload);
|
||||
send_stored_file($file, 60*60, 0, $forcedownload, array('preview' => $preview));
|
||||
|
||||
} else if ($filearea === 'section') {
|
||||
if ($CFG->forcelogin) {
|
||||
@@ -3691,7 +3725,7 @@ function file_pluginfile($relativepath, $forcedownload) {
|
||||
}
|
||||
|
||||
session_get_instance()->write_close(); // unlock session during fileserving
|
||||
send_stored_file($file, 60*60, 0, $forcedownload);
|
||||
send_stored_file($file, 60*60, 0, $forcedownload, array('preview' => $preview));
|
||||
|
||||
} else {
|
||||
send_file_not_found();
|
||||
@@ -3723,7 +3757,7 @@ function file_pluginfile($relativepath, $forcedownload) {
|
||||
}
|
||||
|
||||
session_get_instance()->write_close(); // unlock session during fileserving
|
||||
send_stored_file($file, 60*60, 0, $forcedownload);
|
||||
send_stored_file($file, 60*60, 0, $forcedownload, array('preview' => $preview));
|
||||
|
||||
} else if ($filearea === 'icon') {
|
||||
$filename = array_pop($args);
|
||||
@@ -3738,7 +3772,7 @@ function file_pluginfile($relativepath, $forcedownload) {
|
||||
}
|
||||
|
||||
session_get_instance()->write_close(); // unlock session during fileserving
|
||||
send_stored_file($file, 60*60);
|
||||
send_stored_file($file, 60*60, 0, false, array('preview' => $preview));
|
||||
|
||||
} else {
|
||||
send_file_not_found();
|
||||
@@ -3763,7 +3797,7 @@ function file_pluginfile($relativepath, $forcedownload) {
|
||||
}
|
||||
|
||||
session_get_instance()->write_close(); // unlock session during fileserving
|
||||
send_stored_file($file, 60*60, 0, $forcedownload);
|
||||
send_stored_file($file, 60*60, 0, $forcedownload, array('preview' => $preview));
|
||||
|
||||
} else {
|
||||
send_file_not_found();
|
||||
@@ -3782,7 +3816,7 @@ function file_pluginfile($relativepath, $forcedownload) {
|
||||
}
|
||||
|
||||
session_get_instance()->write_close(); // unlock session during fileserving
|
||||
send_stored_file($file, 0, 0, $forcedownload);
|
||||
send_stored_file($file, 0, 0, $forcedownload, array('preview' => $preview));
|
||||
|
||||
} else if ($filearea === 'section' and $context->contextlevel == CONTEXT_COURSE) {
|
||||
require_login($course);
|
||||
@@ -3797,7 +3831,7 @@ function file_pluginfile($relativepath, $forcedownload) {
|
||||
}
|
||||
|
||||
session_get_instance()->write_close();
|
||||
send_stored_file($file, 60*60, 0, $forcedownload);
|
||||
send_stored_file($file, 60*60, 0, $forcedownload, array('preview' => $preview));
|
||||
|
||||
} else if ($filearea === 'activity' and $context->contextlevel == CONTEXT_MODULE) {
|
||||
require_login($course, false, $cm);
|
||||
@@ -3810,7 +3844,7 @@ function file_pluginfile($relativepath, $forcedownload) {
|
||||
}
|
||||
|
||||
session_get_instance()->write_close();
|
||||
send_stored_file($file, 60*60, 0, $forcedownload);
|
||||
send_stored_file($file, 60*60, 0, $forcedownload, array('preview' => $preview));
|
||||
|
||||
} else if ($filearea === 'automated' and $context->contextlevel == CONTEXT_COURSE) {
|
||||
// Backup files that were generated by the automated backup systems.
|
||||
@@ -3825,7 +3859,7 @@ function file_pluginfile($relativepath, $forcedownload) {
|
||||
}
|
||||
|
||||
session_get_instance()->write_close(); // unlock session during fileserving
|
||||
send_stored_file($file, 0, 0, $forcedownload);
|
||||
send_stored_file($file, 0, 0, $forcedownload, array('preview' => $preview));
|
||||
|
||||
} else {
|
||||
send_file_not_found();
|
||||
@@ -3871,7 +3905,7 @@ function file_pluginfile($relativepath, $forcedownload) {
|
||||
}
|
||||
|
||||
session_get_instance()->write_close(); // unlock session during fileserving
|
||||
send_stored_file($file, 60*60, 0, $forcedownload);
|
||||
send_stored_file($file, 60*60, 0, $forcedownload, array('preview' => $preview));
|
||||
}
|
||||
|
||||
// ========================================================================================================================
|
||||
@@ -3905,17 +3939,17 @@ function file_pluginfile($relativepath, $forcedownload) {
|
||||
$lifetime = isset($CFG->filelifetime) ? $CFG->filelifetime : 86400;
|
||||
|
||||
// finally send the file
|
||||
send_stored_file($file, $lifetime, 0);
|
||||
send_stored_file($file, $lifetime, 0, false, array('preview' => $preview));
|
||||
}
|
||||
|
||||
$filefunction = $component.'_pluginfile';
|
||||
$filefunctionold = $modname.'_pluginfile';
|
||||
if (function_exists($filefunction)) {
|
||||
// if the function exists, it must send the file and terminate. Whatever it returns leads to "not found"
|
||||
$filefunction($course, $cm, $context, $filearea, $args, $forcedownload);
|
||||
$filefunction($course, $cm, $context, $filearea, $args, $forcedownload, array('preview' => $preview));
|
||||
} else if (function_exists($filefunctionold)) {
|
||||
// if the function exists, it must send the file and terminate. Whatever it returns leads to "not found"
|
||||
$filefunctionold($course, $cm, $context, $filearea, $args, $forcedownload);
|
||||
$filefunctionold($course, $cm, $context, $filearea, $args, $forcedownload, array('preview' => $preview));
|
||||
}
|
||||
|
||||
send_file_not_found();
|
||||
@@ -3942,11 +3976,12 @@ function file_pluginfile($relativepath, $forcedownload) {
|
||||
$filefunction = $component.'_pluginfile';
|
||||
if (function_exists($filefunction)) {
|
||||
// if the function exists, it must send the file and terminate. Whatever it returns leads to "not found"
|
||||
$filefunction($course, $birecord, $context, $filearea, $args, $forcedownload);
|
||||
$filefunction($course, $birecord, $context, $filearea, $args, $forcedownload, array('preview' => $preview));
|
||||
}
|
||||
|
||||
send_file_not_found();
|
||||
|
||||
// ========================================================================================================================
|
||||
} else if (strpos($component, '_') === false) {
|
||||
// all core subsystems have to be specified above, no more guessing here!
|
||||
send_file_not_found();
|
||||
@@ -3962,7 +3997,7 @@ function file_pluginfile($relativepath, $forcedownload) {
|
||||
$filefunction = $component.'_pluginfile';
|
||||
if (function_exists($filefunction)) {
|
||||
// if the function exists, it must send the file and terminate. Whatever it returns leads to "not found"
|
||||
$filefunction($course, $cm, $context, $filearea, $args, $forcedownload);
|
||||
$filefunction($course, $cm, $context, $filearea, $args, $forcedownload, array('preview' => $preview));
|
||||
}
|
||||
|
||||
send_file_not_found();
|
||||
|
||||
@@ -152,6 +152,113 @@ class file_storage {
|
||||
return new stored_file($this, $file_record, $this->filedir);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an image file that represent the given stored file as a preview
|
||||
*
|
||||
* At the moment, only GIF, JPEG and PNG files are supported to have previews. In the
|
||||
* future, the support for other mimetypes can be added, too (eg. generate an image
|
||||
* preview of PDF, text documents etc).
|
||||
*
|
||||
* @param stored_file $file the file we want to preview
|
||||
* @param string $mode preview mode, eg. 'thumb'
|
||||
* @return stored_file|bool false if unable to create the preview, stored file otherwise
|
||||
*/
|
||||
public function get_file_preview(stored_file $file, $mode) {
|
||||
|
||||
$context = context_system::instance();
|
||||
$path = '/' . trim($mode, '/') . '/';
|
||||
$preview = $this->get_file($context->id, 'core', 'preview', 0, $path, $file->get_contenthash());
|
||||
|
||||
if (!$preview) {
|
||||
$preview = $this->create_file_preview($file, $mode);
|
||||
if (!$preview) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return $preview;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a preview image for the stored file
|
||||
*
|
||||
* @param stored_file $file the file we want to preview
|
||||
* @param string $mode preview mode, eg. 'thumb'
|
||||
* @return stored_file|bool the newly created preview file or false
|
||||
*/
|
||||
protected function create_file_preview(stored_file $file, $mode) {
|
||||
|
||||
$mimetype = $file->get_mimetype();
|
||||
|
||||
if ($mimetype === 'image/gif' or $mimetype === 'image/jpeg' or $mimetype === 'image/png') {
|
||||
// make a preview of the image
|
||||
$data = $this->create_imagefile_preview($file, $mode);
|
||||
|
||||
} else {
|
||||
// unable to create the preview of this mimetype yet
|
||||
return false;
|
||||
}
|
||||
|
||||
if (empty($data)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// getimagesizefromstring() is available from PHP 5.4 but we need to support
|
||||
// lower versions, so...
|
||||
$tmproot = make_temp_directory('thumbnails');
|
||||
$tmpfilepath = $tmproot.'/'.$file->get_contenthash().'_'.$mode;
|
||||
file_put_contents($tmpfilepath, $data);
|
||||
$imageinfo = getimagesize($tmpfilepath);
|
||||
unlink($tmpfilepath);
|
||||
|
||||
$context = context_system::instance();
|
||||
|
||||
$record = array(
|
||||
'contextid' => $context->id,
|
||||
'component' => 'core',
|
||||
'filearea' => 'preview',
|
||||
'itemid' => 0,
|
||||
'filepath' => '/' . trim($mode, '/') . '/',
|
||||
'filename' => $file->get_contenthash(),
|
||||
);
|
||||
|
||||
if ($imageinfo) {
|
||||
$record['mimetype'] = $imageinfo['mime'];
|
||||
}
|
||||
|
||||
return $this->create_file_from_string($record, $data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a preview for the stored image file
|
||||
*
|
||||
* @param stored_file $file the image we want to preview
|
||||
* @param string $mode preview mode, eg. 'thumb'
|
||||
* @return string|bool false if a problem occurs, the thumbnail image data otherwise
|
||||
*/
|
||||
protected function create_imagefile_preview(stored_file $file, $mode) {
|
||||
global $CFG;
|
||||
require_once($CFG->libdir.'/gdlib.php');
|
||||
|
||||
$tmproot = make_temp_directory('thumbnails');
|
||||
$tmpfilepath = $tmproot.'/'.$file->get_contenthash();
|
||||
$file->copy_content_to($tmpfilepath);
|
||||
|
||||
if ($mode === 'tinyicon') {
|
||||
$data = generate_image_thumbnail($tmpfilepath, 16, 16);
|
||||
|
||||
} else if ($mode === 'thumb') {
|
||||
$data = generate_image_thumbnail($tmpfilepath, 90, 90);
|
||||
|
||||
} else {
|
||||
throw new file_exception('storedfileproblem', 'Invalid preview mode requested');
|
||||
}
|
||||
|
||||
unlink($tmpfilepath);
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch file using local file id.
|
||||
*
|
||||
@@ -1306,6 +1413,25 @@ class file_storage {
|
||||
$rs->close();
|
||||
mtrace('done.');
|
||||
|
||||
// remove orphaned preview files (that is files in the core preview filearea without
|
||||
// the existing original file)
|
||||
mtrace('Deleting orphaned preview files... ', '');
|
||||
$sql = "SELECT p.*
|
||||
FROM {files} p
|
||||
LEFT JOIN {files} o ON (p.filename = o.contenthash)
|
||||
WHERE p.contextid = ? AND p.component = 'core' AND p.filearea = 'preview' AND p.itemid = 0
|
||||
AND o.id IS NULL";
|
||||
$syscontext = context_system::instance();
|
||||
$rs = $DB->get_recordset_sql($sql, array($syscontext->id));
|
||||
foreach ($rs as $orphan) {
|
||||
$file = $this->get_file_instance($orphan);
|
||||
if (!$file->is_directory()) {
|
||||
$file->delete();
|
||||
}
|
||||
}
|
||||
$rs->close();
|
||||
mtrace('done.');
|
||||
|
||||
// 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) {
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
<?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/>.
|
||||
|
||||
/**
|
||||
* Unit tests for /lib/filestorage/file_storage.php
|
||||
*
|
||||
* @package core
|
||||
* @category test
|
||||
* @copyright 2012 David Mudrak <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
global $CFG;
|
||||
require_once($CFG->libdir . '/filelib.php');
|
||||
|
||||
class filestoragelib_testcase extends advanced_testcase {
|
||||
|
||||
/**
|
||||
* Local files can be added to the filepool
|
||||
*/
|
||||
public function test_create_file_from_pathname() {
|
||||
global $CFG;
|
||||
|
||||
$this->resetAfterTest(false);
|
||||
|
||||
$filepath = $CFG->dirroot.'/lib/filestorage/tests/fixtures/testimage.jpg';
|
||||
$syscontext = context_system::instance();
|
||||
$filerecord = array(
|
||||
'contextid' => $syscontext->id,
|
||||
'component' => 'core',
|
||||
'filearea' => 'unittest',
|
||||
'itemid' => 0,
|
||||
'filepath' => '/images/',
|
||||
'filename' => 'testimage.jpg',
|
||||
);
|
||||
|
||||
$fs = get_file_storage();
|
||||
$fs->create_file_from_pathname($filerecord, $filepath);
|
||||
|
||||
$this->assertTrue($fs->file_exists($syscontext->id, 'core', 'unittest', 0, '/images/', 'testimage.jpg'));
|
||||
|
||||
return $fs->get_file($syscontext->id, 'core', 'unittest', 0, '/images/', 'testimage.jpg');
|
||||
}
|
||||
|
||||
/**
|
||||
* Local images can be added to the filepool and their preview can be obtained
|
||||
*
|
||||
* @depends test_create_file_from_pathname
|
||||
*/
|
||||
public function test_get_file_preview(stored_file $file) {
|
||||
global $CFG;
|
||||
|
||||
$this->resetAfterTest(true);
|
||||
$fs = get_file_storage();
|
||||
|
||||
$previewtinyicon = $fs->get_file_preview($file, 'tinyicon');
|
||||
$this->assertInstanceOf('stored_file', $previewtinyicon);
|
||||
$this->assertEquals('6b9864ae1536a8eeef54e097319175a8be12f07c', $previewtinyicon->get_filename());
|
||||
|
||||
$previewtinyicon = $fs->get_file_preview($file, 'thumb');
|
||||
$this->assertInstanceOf('stored_file', $previewtinyicon);
|
||||
$this->assertEquals('6b9864ae1536a8eeef54e097319175a8be12f07c', $previewtinyicon->get_filename());
|
||||
}
|
||||
}
|
||||
BIN
Binary file not shown.
|
After Width: | Height: | Size: 28 KiB |
+139
-53
@@ -27,61 +27,62 @@
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
/**
|
||||
* Copies a rectangular portion of the source image to another rectangle in the destination image
|
||||
*
|
||||
* long description
|
||||
* @global object
|
||||
* @param object $dst_img
|
||||
* @param object $src_img
|
||||
* @param int $dst_x
|
||||
* @param int $dst_y
|
||||
* @param int $src_x
|
||||
* @param int $src_y
|
||||
* @param int $dst_w
|
||||
* @param int $dst_h
|
||||
* @param int $src_w
|
||||
* @param int $src_h
|
||||
* @return bool
|
||||
* @todo Finish documenting this function
|
||||
* This function calls imagecopyresampled() if it is available and GD version is 2 at least.
|
||||
* Otherwise it reimplements the same behaviour. See the PHP manual page for more info.
|
||||
*
|
||||
* @link http://php.net/manual/en/function.imagecopyresampled.php
|
||||
* @param resource $dst_img the destination GD image resource
|
||||
* @param resource $src_img the source GD image resource
|
||||
* @param int $dst_x vthe X coordinate of the upper left corner in the destination image
|
||||
* @param int $dst_y the Y coordinate of the upper left corner in the destination image
|
||||
* @param int $src_x the X coordinate of the upper left corner in the source image
|
||||
* @param int $src_y the Y coordinate of the upper left corner in the source image
|
||||
* @param int $dst_w the width of the destination rectangle
|
||||
* @param int $dst_h the height of the destination rectangle
|
||||
* @param int $src_w the width of the source rectangle
|
||||
* @param int $src_h the height of the source rectangle
|
||||
* @return bool tru on success, false otherwise
|
||||
*/
|
||||
function ImageCopyBicubic($dst_img, $src_img, $dst_x, $dst_y, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h) {
|
||||
|
||||
function imagecopybicubic($dst_img, $src_img, $dst_x, $dst_y, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h) {
|
||||
global $CFG;
|
||||
|
||||
if (function_exists('ImageCopyResampled') and $CFG->gdversion >= 2) {
|
||||
return ImageCopyResampled($dst_img, $src_img, $dst_x, $dst_y, $src_x, $src_y,
|
||||
if (function_exists('imagecopyresampled') and $CFG->gdversion >= 2) {
|
||||
return imagecopyresampled($dst_img, $src_img, $dst_x, $dst_y, $src_x, $src_y,
|
||||
$dst_w, $dst_h, $src_w, $src_h);
|
||||
}
|
||||
|
||||
$totalcolors = imagecolorstotal($src_img);
|
||||
for ($i=0; $i<$totalcolors; $i++) {
|
||||
if ($colors = ImageColorsForIndex($src_img, $i)) {
|
||||
ImageColorAllocate($dst_img, $colors['red'], $colors['green'], $colors['blue']);
|
||||
if ($colors = imagecolorsforindex($src_img, $i)) {
|
||||
imagecolorallocate($dst_img, $colors['red'], $colors['green'], $colors['blue']);
|
||||
}
|
||||
}
|
||||
|
||||
$scaleX = ($src_w - 1) / $dst_w;
|
||||
$scaleY = ($src_h - 1) / $dst_h;
|
||||
$scalex = ($src_w - 1) / $dst_w;
|
||||
$scaley = ($src_h - 1) / $dst_h;
|
||||
|
||||
$scaleX2 = $scaleX / 2.0;
|
||||
$scaleY2 = $scaleY / 2.0;
|
||||
$scalex2 = $scalex / 2.0;
|
||||
$scaley2 = $scaley / 2.0;
|
||||
|
||||
for ($j = 0; $j < $dst_h; $j++) {
|
||||
$sY = $j * $scaleY;
|
||||
$sy = $j * $scaley;
|
||||
|
||||
for ($i = 0; $i < $dst_w; $i++) {
|
||||
$sX = $i * $scaleX;
|
||||
$sx = $i * $scalex;
|
||||
|
||||
$c1 = ImageColorsForIndex($src_img,ImageColorAt($src_img,(int)$sX,(int)$sY+$scaleY2));
|
||||
$c2 = ImageColorsForIndex($src_img,ImageColorAt($src_img,(int)$sX,(int)$sY));
|
||||
$c3 = ImageColorsForIndex($src_img,ImageColorAt($src_img,(int)$sX+$scaleX2,(int)$sY+$scaleY2));
|
||||
$c4 = ImageColorsForIndex($src_img,ImageColorAt($src_img,(int)$sX+$scaleX2,(int)$sY));
|
||||
$c1 = imagecolorsforindex($src_img, imagecolorat($src_img, (int)$sx, (int)$sy + $scaley2));
|
||||
$c2 = imagecolorsforindex($src_img, imagecolorat($src_img, (int)$sx, (int)$sy));
|
||||
$c3 = imagecolorsforindex($src_img, imagecolorat($src_img, (int)$sx + $scalex2, (int)$sy + $scaley2));
|
||||
$c4 = imagecolorsforindex($src_img, imagecolorat($src_img, (int)$sx + $scalex2, (int)$sy));
|
||||
|
||||
$red = (int) (($c1['red'] + $c2['red'] + $c3['red'] + $c4['red']) / 4);
|
||||
$green = (int) (($c1['green'] + $c2['green'] + $c3['green'] + $c4['green']) / 4);
|
||||
$blue = (int) (($c1['blue'] + $c2['blue'] + $c3['blue'] + $c4['blue']) / 4);
|
||||
|
||||
$color = ImageColorClosest ($dst_img, $red, $green, $blue);
|
||||
ImageSetPixel ($dst_img, $i + $dst_x, $j + $dst_y, $color);
|
||||
$color = imagecolorclosest($dst_img, $red, $green, $blue);
|
||||
imagesetpixel($dst_img, $i + $dst_x, $j + $dst_y, $color);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -106,7 +107,7 @@ function process_new_icon($context, $component, $filearea, $itemid, $originalfil
|
||||
return false;
|
||||
}
|
||||
|
||||
$imageinfo = GetImageSize($originalfile);
|
||||
$imageinfo = getimagesize($originalfile);
|
||||
|
||||
if (empty($imageinfo)) {
|
||||
return false;
|
||||
@@ -119,24 +120,24 @@ function process_new_icon($context, $component, $filearea, $itemid, $originalfil
|
||||
|
||||
switch ($image->type) {
|
||||
case IMAGETYPE_GIF:
|
||||
if (function_exists('ImageCreateFromGIF')) {
|
||||
$im = ImageCreateFromGIF($originalfile);
|
||||
if (function_exists('imagecreatefromgif')) {
|
||||
$im = imagecreatefromgif($originalfile);
|
||||
} else {
|
||||
debugging('GIF not supported on this server');
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case IMAGETYPE_JPEG:
|
||||
if (function_exists('ImageCreateFromJPEG')) {
|
||||
$im = ImageCreateFromJPEG($originalfile);
|
||||
if (function_exists('imagecreatefromjpeg')) {
|
||||
$im = imagecreatefromjpeg($originalfile);
|
||||
} else {
|
||||
debugging('JPEG not supported on this server');
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case IMAGETYPE_PNG:
|
||||
if (function_exists('ImageCreateFromPNG')) {
|
||||
$im = ImageCreateFromPNG($originalfile);
|
||||
if (function_exists('imagecreatefrompng')) {
|
||||
$im = imagecreatefrompng($originalfile);
|
||||
} else {
|
||||
debugging('PNG not supported on this server');
|
||||
return false;
|
||||
@@ -146,13 +147,13 @@ function process_new_icon($context, $component, $filearea, $itemid, $originalfil
|
||||
return false;
|
||||
}
|
||||
|
||||
if (function_exists('ImagePng')) {
|
||||
$imagefnc = 'ImagePng';
|
||||
if (function_exists('imagepng')) {
|
||||
$imagefnc = 'imagepng';
|
||||
$imageext = '.png';
|
||||
$filters = PNG_NO_FILTER;
|
||||
$quality = 1;
|
||||
} else if (function_exists('ImageJpeg')) {
|
||||
$imagefnc = 'ImageJpeg';
|
||||
} else if (function_exists('imagejpeg')) {
|
||||
$imagefnc = 'imagejpeg';
|
||||
$imageext = '.jpg';
|
||||
$filters = null; // not used
|
||||
$quality = 90;
|
||||
@@ -161,10 +162,10 @@ function process_new_icon($context, $component, $filearea, $itemid, $originalfil
|
||||
return false;
|
||||
}
|
||||
|
||||
if (function_exists('ImageCreateTrueColor') and $CFG->gdversion >= 2) {
|
||||
$im1 = ImageCreateTrueColor(100,100);
|
||||
$im2 = ImageCreateTrueColor(35,35);
|
||||
if ($image->type == IMAGETYPE_PNG and $imagefnc === 'ImagePng') {
|
||||
if (function_exists('imagecreatetruecolor') and $CFG->gdversion >= 2) {
|
||||
$im1 = imagecreatetruecolor(100, 100);
|
||||
$im2 = imagecreatetruecolor(35, 35);
|
||||
if ($image->type == IMAGETYPE_PNG and $imagefnc === 'imagepng') {
|
||||
imagealphablending($im1, false);
|
||||
$color = imagecolorallocatealpha($im1, 0, 0, 0, 127);
|
||||
imagefill($im1, 0, 0, $color);
|
||||
@@ -175,8 +176,8 @@ function process_new_icon($context, $component, $filearea, $itemid, $originalfil
|
||||
imagesavealpha($im2, true);
|
||||
}
|
||||
} else {
|
||||
$im1 = ImageCreate(100,100);
|
||||
$im2 = ImageCreate(35,35);
|
||||
$im1 = imagecreate(100, 100);
|
||||
$im2 = imagecreate(35, 35);
|
||||
}
|
||||
|
||||
$cx = $image->width / 2;
|
||||
@@ -188,8 +189,8 @@ function process_new_icon($context, $component, $filearea, $itemid, $originalfil
|
||||
$half = floor($image->height / 2.0);
|
||||
}
|
||||
|
||||
ImageCopyBicubic($im1, $im, 0, 0, $cx-$half, $cy-$half, 100, 100, $half*2, $half*2);
|
||||
ImageCopyBicubic($im2, $im, 0, 0, $cx-$half, $cy-$half, 35, 35, $half*2, $half*2);
|
||||
imagecopybicubic($im1, $im, 0, 0, $cx - $half, $cy - $half, 100, 100, $half * 2, $half * 2);
|
||||
imagecopybicubic($im2, $im, 0, 0, $cx - $half, $cy - $half, 35, 35, $half * 2, $half * 2);
|
||||
|
||||
$fs = get_file_storage();
|
||||
|
||||
@@ -202,7 +203,7 @@ function process_new_icon($context, $component, $filearea, $itemid, $originalfil
|
||||
return false;
|
||||
}
|
||||
$data = ob_get_clean();
|
||||
ImageDestroy($im1);
|
||||
imagedestroy($im1);
|
||||
$icon['filename'] = 'f1'.$imageext;
|
||||
$fs->delete_area_files($context->id, $component, $filearea, $itemid);
|
||||
$fs->create_file_from_string($icon, $data);
|
||||
@@ -214,10 +215,95 @@ function process_new_icon($context, $component, $filearea, $itemid, $originalfil
|
||||
return false;
|
||||
}
|
||||
$data = ob_get_clean();
|
||||
ImageDestroy($im2);
|
||||
imagedestroy($im2);
|
||||
$icon['filename'] = 'f2'.$imageext;
|
||||
$fs->create_file_from_string($icon, $data);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a thumbnail for the given image
|
||||
*
|
||||
* If the GD library has at least version 2 and PNG support is available, the returned data
|
||||
* is the content of a transparent PNG file containing the thumbnail. Otherwise, the function
|
||||
* returns contents of a JPEG file with black background containing the thumbnail.
|
||||
*
|
||||
* @param string $filepath the full path to the original image file
|
||||
* @param int $width the width of the requested thumbnail
|
||||
* @param int $height the height of the requested thumbnail
|
||||
* @return string|bool false if a problem occurs, the thumbnail image data otherwise
|
||||
*/
|
||||
function generate_image_thumbnail($filepath, $width, $height) {
|
||||
global $CFG;
|
||||
|
||||
if (empty($CFG->gdversion) or empty($filepath) or empty($width) or empty($height)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$imageinfo = getimagesize($filepath);
|
||||
|
||||
if (empty($imageinfo)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$originalwidth = $imageinfo[0];
|
||||
$originalheight = $imageinfo[1];
|
||||
|
||||
if (empty($originalwidth) or empty($originalheight)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$original = imagecreatefromstring(file_get_contents($filepath));
|
||||
|
||||
if (function_exists('imagepng')) {
|
||||
$imagefnc = 'imagepng';
|
||||
$filters = PNG_NO_FILTER;
|
||||
$quality = 1;
|
||||
} else if (function_exists('imagejpeg')) {
|
||||
$imagefnc = 'imagejpeg';
|
||||
$filters = null;
|
||||
$quality = 90;
|
||||
} else {
|
||||
debugging('Neither JPEG nor PNG are supported at this server, please fix the system configuration.');
|
||||
return false;
|
||||
}
|
||||
|
||||
if (function_exists('imagecreatetruecolor') and $CFG->gdversion >= 2) {
|
||||
$thumbnail = imagecreatetruecolor($width, $height);
|
||||
if ($imagefnc === 'imagepng') {
|
||||
imagealphablending($thumbnail, false);
|
||||
imagefill($thumbnail, 0, 0, imagecolorallocatealpha($thumbnail, 0, 0, 0, 127));
|
||||
imagesavealpha($thumbnail, true);
|
||||
}
|
||||
} else {
|
||||
$thumbnail = imagecreate($width, $height);
|
||||
}
|
||||
|
||||
$ratio = min($width / $originalwidth, $height / $originalheight);
|
||||
|
||||
if ($ratio < 1) {
|
||||
$targetwidth = floor($originalwidth * $ratio);
|
||||
$targetheight = floor($originalheight * $ratio);
|
||||
} else {
|
||||
// do not enlarge the original file if it is smaller than the requested thumbnail size
|
||||
$targetwidth = $originalwidth;
|
||||
$targetheight = $originalheight;
|
||||
}
|
||||
|
||||
$dstx = floor(($width - $targetwidth) / 2);
|
||||
$dsty = floor(($height - $targetheight) / 2);
|
||||
|
||||
imagecopybicubic($thumbnail, $original, $dstx, $dsty, 0, 0, $targetwidth, $targetheight, $originalwidth, $originalheight);
|
||||
|
||||
ob_start();
|
||||
if (!$imagefnc($thumbnail, null, $quality, $filters)) {
|
||||
ob_end_clean();
|
||||
return false;
|
||||
}
|
||||
$data = ob_get_clean();
|
||||
imagedestroy($original);
|
||||
imagedestroy($thumbnail);
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
@@ -822,8 +822,8 @@ abstract class portfolio_plugin_pull_base extends portfolio_plugin_base {
|
||||
if (!($file instanceof stored_file)) {
|
||||
throw new portfolio_export_exception($this->get('exporter'), 'filenotfound', 'portfolio');
|
||||
}
|
||||
// the last 'true' on the end of this means don't die(); afterwards, so we can clean up.
|
||||
send_stored_file($file, 0, 0, true, null, true);
|
||||
// don't die(); afterwards, so we can clean up.
|
||||
send_stored_file($file, 0, 0, true, array('dontdie' => true));
|
||||
$this->get('exporter')->log_transfer();
|
||||
}
|
||||
|
||||
|
||||
+11
-8
@@ -1719,8 +1719,9 @@ function question_rewrite_questiontext_preview_urls($questiontext, $contextid,
|
||||
* @param int $questionid the question id
|
||||
* @param array $args the remaining file arguments (file path).
|
||||
* @param bool $forcedownload whether the user must be forced to download the file.
|
||||
* @param array $options additional options affecting the file serving
|
||||
*/
|
||||
function question_send_questiontext_file($questionid, $args, $forcedownload) {
|
||||
function question_send_questiontext_file($questionid, $args, $forcedownload, $options) {
|
||||
global $DB;
|
||||
|
||||
$question = $DB->get_record_sql('
|
||||
@@ -1735,7 +1736,7 @@ function question_send_questiontext_file($questionid, $args, $forcedownload) {
|
||||
send_file_not_found();
|
||||
}
|
||||
|
||||
send_stored_file($file, 0, 0, $forcedownload);
|
||||
send_stored_file($file, 0, 0, $forcedownload, $options);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1759,8 +1760,9 @@ function question_send_questiontext_file($questionid, $args, $forcedownload) {
|
||||
* @param string $filearea the name of the file area.
|
||||
* @param array $args the remaining bits of the file path.
|
||||
* @param bool $forcedownload whether the user must be forced to download the file.
|
||||
* @param array $options additional options affecting the file serving
|
||||
*/
|
||||
function question_pluginfile($course, $context, $component, $filearea, $args, $forcedownload) {
|
||||
function question_pluginfile($course, $context, $component, $filearea, $args, $forcedownload, array $options=array()) {
|
||||
global $DB, $CFG;
|
||||
|
||||
if ($filearea === 'questiontext_preview') {
|
||||
@@ -1768,7 +1770,7 @@ function question_pluginfile($course, $context, $component, $filearea, $args, $f
|
||||
$questionid = array_shift($args);
|
||||
|
||||
component_callback($component, 'questiontext_preview_pluginfile', array(
|
||||
$context, $questionid, $args, $forcedownload));
|
||||
$context, $questionid, $args, $forcedownload, $options));
|
||||
|
||||
send_file_not_found();
|
||||
}
|
||||
@@ -1841,7 +1843,7 @@ function question_pluginfile($course, $context, $component, $filearea, $args, $f
|
||||
if ($module === 'core_question_preview') {
|
||||
require_once($CFG->dirroot . '/question/previewlib.php');
|
||||
return question_preview_question_pluginfile($course, $context,
|
||||
$component, $filearea, $qubaid, $slot, $args, $forcedownload);
|
||||
$component, $filearea, $qubaid, $slot, $args, $forcedownload, $options);
|
||||
|
||||
} else {
|
||||
$dir = get_component_directory($module);
|
||||
@@ -1856,7 +1858,7 @@ function question_pluginfile($course, $context, $component, $filearea, $args, $f
|
||||
}
|
||||
|
||||
$filefunction($course, $context, $component, $filearea, $qubaid, $slot,
|
||||
$args, $forcedownload);
|
||||
$args, $forcedownload, $options);
|
||||
|
||||
send_file_not_found();
|
||||
}
|
||||
@@ -1871,8 +1873,9 @@ function question_pluginfile($course, $context, $component, $filearea, $args, $f
|
||||
* @param int $questionid the question id
|
||||
* @param array $args remaining file args
|
||||
* @param bool $forcedownload
|
||||
* @param array $options additional options affecting the file serving
|
||||
*/
|
||||
function core_question_questiontext_preview_pluginfile($context, $questionid, $args, $forcedownload) {
|
||||
function core_question_questiontext_preview_pluginfile($context, $questionid, $args, $forcedownload, array $options=array()) {
|
||||
global $DB;
|
||||
|
||||
// Verify that contextid matches the question.
|
||||
@@ -1889,7 +1892,7 @@ function core_question_questiontext_preview_pluginfile($context, $questionid, $a
|
||||
|
||||
question_require_capability_on($question, 'use');
|
||||
|
||||
question_send_questiontext_file($questionid, $args, $forcedownload);
|
||||
question_send_questiontext_file($questionid, $args, $forcedownload, $options);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -11,6 +11,9 @@ Note:
|
||||
* DDL and DML methods which were deprecated in 2.0 have now been removed, they will no longer produce
|
||||
debug messages and will produce fatal errors
|
||||
|
||||
API changes:
|
||||
* send_stored_file() has changed its interface
|
||||
|
||||
=== 2.2 ===
|
||||
|
||||
removed unused libraries:
|
||||
|
||||
@@ -1979,11 +1979,15 @@ class assignment_base {
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a file
|
||||
*
|
||||
* @param string $filearea
|
||||
* @param array $args
|
||||
* @param bool $forcedownload whether or not force download
|
||||
* @param array $options additional options affecting the file serving
|
||||
* @return bool
|
||||
*/
|
||||
function send_file($filearea, $args) {
|
||||
function send_file($filearea, $args, $forcedownload, array $options=array()) {
|
||||
debugging('plugin does not implement file sending', DEBUG_DEVELOPER);
|
||||
return false;
|
||||
}
|
||||
@@ -3087,9 +3091,10 @@ function assignment_get_participants($assignmentid) {
|
||||
* @param string $filearea file area
|
||||
* @param array $args extra arguments
|
||||
* @param bool $forcedownload whether or not force download
|
||||
* @param array $options additional options affecting the file serving
|
||||
* @return bool false if file not found, does not return if found - just send the file
|
||||
*/
|
||||
function assignment_pluginfile($course, $cm, $context, $filearea, $args, $forcedownload) {
|
||||
function assignment_pluginfile($course, $cm, $context, $filearea, $args, $forcedownload, array $options=array()) {
|
||||
global $CFG, $DB;
|
||||
|
||||
if ($context->contextlevel != CONTEXT_MODULE) {
|
||||
@@ -3106,7 +3111,7 @@ function assignment_pluginfile($course, $cm, $context, $filearea, $args, $forced
|
||||
$assignmentclass = 'assignment_'.$assignment->assignmenttype;
|
||||
$assignmentinstance = new $assignmentclass($cm->id, $assignment, $cm, $course);
|
||||
|
||||
return $assignmentinstance->send_file($filearea, $args);
|
||||
return $assignmentinstance->send_file($filearea, $args, $forcedownload, $options);
|
||||
}
|
||||
/**
|
||||
* Checks if a scale is being used by an assignment
|
||||
|
||||
@@ -375,7 +375,7 @@ class assignment_online extends assignment_base {
|
||||
}
|
||||
}
|
||||
|
||||
public function send_file($filearea, $args) {
|
||||
public function send_file($filearea, $args, $forcedownload, array $options=array()) {
|
||||
global $USER;
|
||||
require_capability('mod/assignment:view', $this->context);
|
||||
|
||||
@@ -391,7 +391,8 @@ class assignment_online extends assignment_base {
|
||||
}
|
||||
|
||||
session_get_instance()->write_close(); // unlock session during fileserving
|
||||
send_stored_file($file, 60*60, 0, true);
|
||||
|
||||
send_stored_file($file, 60*60, 0, true, $options);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
This file describes changes in the assignment type API and DB structures.
|
||||
Information provided here is intended especially for developers.
|
||||
|
||||
=== 2.3 ===
|
||||
|
||||
API changes:
|
||||
* send_file() methods now accept $forcedownload and $options parameters
|
||||
@@ -614,7 +614,7 @@ class assignment_upload extends assignment_base {
|
||||
die;
|
||||
}
|
||||
|
||||
function send_file($filearea, $args) {
|
||||
function send_file($filearea, $args, $forcedownload, array $options=array()) {
|
||||
global $CFG, $DB, $USER;
|
||||
require_once($CFG->libdir.'/filelib.php');
|
||||
|
||||
@@ -638,7 +638,8 @@ class assignment_upload extends assignment_base {
|
||||
if (!$file = $fs->get_file_by_hash(sha1($fullpath)) or $file->is_directory()) {
|
||||
return false;
|
||||
}
|
||||
send_stored_file($file, 0, 0, true); // download MUST be forced - security!
|
||||
|
||||
send_stored_file($file, 0, 0, true, $options); // download MUST be forced - security!
|
||||
|
||||
} else if ($filearea === 'response') {
|
||||
$submissionid = (int)array_shift($args);
|
||||
@@ -658,7 +659,7 @@ class assignment_upload extends assignment_base {
|
||||
if (!$file = $fs->get_file_by_hash(sha1($fullpath)) or $file->is_directory()) {
|
||||
return false;
|
||||
}
|
||||
send_stored_file($file, 0, 0, true);
|
||||
send_stored_file($file, 0, 0, true, $options);
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
@@ -300,7 +300,7 @@ class assignment_uploadsingle extends assignment_base {
|
||||
return true;
|
||||
}
|
||||
|
||||
function send_file($filearea, $args) {
|
||||
function send_file($filearea, $args, $forcedownload, array $options=array()) {
|
||||
global $CFG, $DB, $USER;
|
||||
require_once($CFG->libdir.'/filelib.php');
|
||||
|
||||
@@ -329,7 +329,7 @@ class assignment_uploadsingle extends assignment_base {
|
||||
return false;
|
||||
}
|
||||
|
||||
send_stored_file($file, 0, 0, true); // download MUST be forced - security!
|
||||
send_stored_file($file, 0, 0, true, $options); // download MUST be forced - security!
|
||||
}
|
||||
|
||||
function extend_settings_navigation($node) {
|
||||
|
||||
+3
-2
@@ -2963,9 +2963,10 @@ function mod_data_get_file_info($browser, $areas, $course, $cm, $context, $filea
|
||||
* @param string $filearea file area
|
||||
* @param array $args extra arguments
|
||||
* @param bool $forcedownload whether or not force download
|
||||
* @param array $options additional options affecting the file serving
|
||||
* @return bool false if file not found, does not return if found - justsend the file
|
||||
*/
|
||||
function data_pluginfile($course, $cm, $context, $filearea, $args, $forcedownload) {
|
||||
function data_pluginfile($course, $cm, $context, $filearea, $args, $forcedownload, array $options=array()) {
|
||||
global $CFG, $DB;
|
||||
|
||||
if ($context->contextlevel != CONTEXT_MODULE) {
|
||||
@@ -3028,7 +3029,7 @@ function data_pluginfile($course, $cm, $context, $filearea, $args, $forcedownloa
|
||||
}
|
||||
|
||||
// finally send the file
|
||||
send_stored_file($file, 0, 0, true); // download MUST be forced - security!
|
||||
send_stored_file($file, 0, 0, true, $options); // download MUST be forced - security!
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
@@ -182,9 +182,10 @@ function feedback_update_instance($feedback) {
|
||||
* @param string $filearea file area
|
||||
* @param array $args extra arguments
|
||||
* @param bool $forcedownload whether or not force download
|
||||
* @param array $options additional options affecting the file serving
|
||||
* @return bool false if file not found, does not return if found - justsend the file
|
||||
*/
|
||||
function feedback_pluginfile($course, $cm, $context, $filearea, $args, $forcedownload) {
|
||||
function feedback_pluginfile($course, $cm, $context, $filearea, $args, $forcedownload, array $options=array()) {
|
||||
global $CFG, $DB;
|
||||
|
||||
if ($filearea === 'item' or $filearea === 'template') {
|
||||
@@ -273,7 +274,7 @@ function feedback_pluginfile($course, $cm, $context, $filearea, $args, $forcedow
|
||||
}
|
||||
|
||||
// finally send the file
|
||||
send_stored_file($file, 0, 0, true); // download MUST be forced - security!
|
||||
send_stored_file($file, 0, 0, true, $options); // download MUST be forced - security!
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
+3
-2
@@ -293,9 +293,10 @@ function folder_get_file_info($browser, $areas, $course, $cm, $context, $fileare
|
||||
* @param string $filearea file area
|
||||
* @param array $args extra arguments
|
||||
* @param bool $forcedownload whether or not force download
|
||||
* @param array $options additional options affecting the file serving
|
||||
* @return bool false if file not found, does not return if found - just send the file
|
||||
*/
|
||||
function folder_pluginfile($course, $cm, $context, $filearea, $args, $forcedownload) {
|
||||
function folder_pluginfile($course, $cm, $context, $filearea, $args, $forcedownload, array $options=array()) {
|
||||
global $CFG, $DB;
|
||||
|
||||
if ($context->contextlevel != CONTEXT_MODULE) {
|
||||
@@ -323,7 +324,7 @@ function folder_pluginfile($course, $cm, $context, $filearea, $args, $forcedownl
|
||||
|
||||
// finally send the file
|
||||
// for folder module, we force download file all the time
|
||||
send_stored_file($file, 86400, 0, true);
|
||||
send_stored_file($file, 86400, 0, true, $options);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+3
-3
@@ -4108,9 +4108,10 @@ function forum_get_file_info($browser, $areas, $course, $cm, $context, $filearea
|
||||
* @param string $filearea file area
|
||||
* @param array $args extra arguments
|
||||
* @param bool $forcedownload whether or not force download
|
||||
* @param array $options additional options affecting the file serving
|
||||
* @return bool false if file not found, does not return if found - justsend the file
|
||||
*/
|
||||
function forum_pluginfile($course, $cm, $context, $filearea, $args, $forcedownload) {
|
||||
function forum_pluginfile($course, $cm, $context, $filearea, $args, $forcedownload, array $options=array()) {
|
||||
global $CFG, $DB;
|
||||
|
||||
if ($context->contextlevel != CONTEXT_MODULE) {
|
||||
@@ -4162,9 +4163,8 @@ function forum_pluginfile($course, $cm, $context, $filearea, $args, $forcedownlo
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// finally send the file
|
||||
send_stored_file($file, 0, 0, true); // download MUST be forced - security!
|
||||
send_stored_file($file, 0, 0, true, $options); // download MUST be forced - security!
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1538,9 +1538,10 @@ function mod_glossary_get_file_info($browser, $areas, $course, $cm, $context, $f
|
||||
* @param string $filearea file area
|
||||
* @param array $args extra arguments
|
||||
* @param bool $forcedownload whether or not force download
|
||||
* @param array $options additional options affecting the file serving
|
||||
* @return bool false if file not found, does not return if found - justsend the file
|
||||
*/
|
||||
function glossary_pluginfile($course, $cm, $context, $filearea, $args, $forcedownload) {
|
||||
function glossary_pluginfile($course, $cm, $context, $filearea, $args, $forcedownload, array $options=array()) {
|
||||
global $CFG, $DB;
|
||||
|
||||
if ($context->contextlevel != CONTEXT_MODULE) {
|
||||
@@ -1590,7 +1591,7 @@ function glossary_pluginfile($course, $cm, $context, $filearea, $args, $forcedow
|
||||
}
|
||||
|
||||
// finally send the file
|
||||
send_stored_file($file, 0, 0, true); // download MUST be forced - security!
|
||||
send_stored_file($file, 0, 0, true, $options); // download MUST be forced - security!
|
||||
|
||||
} else if ($filearea === 'export') {
|
||||
require_login($course, false, $cm);
|
||||
|
||||
+4
-3
@@ -337,9 +337,10 @@ function imscp_get_file_info($browser, $areas, $course, $cm, $context, $filearea
|
||||
* @param string $filearea file area
|
||||
* @param array $args extra arguments
|
||||
* @param bool $forcedownload whether or not force download
|
||||
* @param array $options additional options affecting the file serving
|
||||
* @return bool false if file not found, does not return if found - justsend the file
|
||||
*/
|
||||
function imscp_pluginfile($course, $cm, $context, $filearea, $args, $forcedownload) {
|
||||
function imscp_pluginfile($course, $cm, $context, $filearea, $args, $forcedownload, array $options=array()) {
|
||||
global $CFG, $DB;
|
||||
|
||||
if ($context->contextlevel != CONTEXT_MODULE) {
|
||||
@@ -367,7 +368,7 @@ function imscp_pluginfile($course, $cm, $context, $filearea, $args, $forcedownlo
|
||||
}
|
||||
|
||||
// finally send the file
|
||||
send_stored_file($file, 86400, 0, $forcedownload);
|
||||
send_stored_file($file, 86400, 0, $forcedownload, $options);
|
||||
|
||||
} else if ($filearea === 'backup') {
|
||||
if (!has_capability('moodle/course:managefiles', $context)) {
|
||||
@@ -383,7 +384,7 @@ function imscp_pluginfile($course, $cm, $context, $filearea, $args, $forcedownlo
|
||||
}
|
||||
|
||||
// finally send the file
|
||||
send_stored_file($file, 86400, 0, $forcedownload);
|
||||
send_stored_file($file, 86400, 0, $forcedownload, $options);
|
||||
|
||||
} else {
|
||||
return false;
|
||||
|
||||
+3
-2
@@ -876,9 +876,10 @@ function lesson_get_import_export_formats($type) {
|
||||
* @param string $filearea file area
|
||||
* @param array $args extra arguments
|
||||
* @param bool $forcedownload whether or not force download
|
||||
* @param array $options additional options affecting the file serving
|
||||
* @return bool false if file not found, does not return if found - justsend the file
|
||||
*/
|
||||
function lesson_pluginfile($course, $cm, $context, $filearea, $args, $forcedownload) {
|
||||
function lesson_pluginfile($course, $cm, $context, $filearea, $args, $forcedownload, array $options=array()) {
|
||||
global $CFG, $DB;
|
||||
|
||||
if ($context->contextlevel != CONTEXT_MODULE) {
|
||||
@@ -917,7 +918,7 @@ function lesson_pluginfile($course, $cm, $context, $filearea, $args, $forcedownl
|
||||
}
|
||||
|
||||
// finally send the file
|
||||
send_stored_file($file, 0, 0, $forcedownload); // download MUST be forced - security!
|
||||
send_stored_file($file, 0, 0, $forcedownload, $options); // download MUST be forced - security!
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+3
-2
@@ -360,9 +360,10 @@ function page_get_file_info($browser, $areas, $course, $cm, $context, $filearea,
|
||||
* @param string $filearea file area
|
||||
* @param array $args extra arguments
|
||||
* @param bool $forcedownload whether or not force download
|
||||
* @param array $options additional options affecting the file serving
|
||||
* @return bool false if file not found, does not return if found - just send the file
|
||||
*/
|
||||
function page_pluginfile($course, $cm, $context, $filearea, $args, $forcedownload) {
|
||||
function page_pluginfile($course, $cm, $context, $filearea, $args, $forcedownload, array $options=array()) {
|
||||
global $CFG, $DB;
|
||||
require_once("$CFG->libdir/resourcelib.php");
|
||||
|
||||
@@ -418,7 +419,7 @@ function page_pluginfile($course, $cm, $context, $filearea, $args, $forcedownloa
|
||||
}
|
||||
|
||||
// finally send the file
|
||||
send_stored_file($file, 86400, 0, $forcedownload);
|
||||
send_stored_file($file, 86400, 0, $forcedownload, $options);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+6
-4
@@ -1655,9 +1655,10 @@ function quiz_extend_settings_navigation($settings, $quiznode) {
|
||||
* @param string $filearea file area
|
||||
* @param array $args extra arguments
|
||||
* @param bool $forcedownload whether or not force download
|
||||
* @param array $options additional options affecting the file serving
|
||||
* @return bool false if file not found, does not return if found - justsend the file
|
||||
*/
|
||||
function quiz_pluginfile($course, $cm, $context, $filearea, $args, $forcedownload) {
|
||||
function quiz_pluginfile($course, $cm, $context, $filearea, $args, $forcedownload, array $options=array()) {
|
||||
global $CFG, $DB;
|
||||
|
||||
if ($context->contextlevel != CONTEXT_MODULE) {
|
||||
@@ -1687,7 +1688,7 @@ function quiz_pluginfile($course, $cm, $context, $filearea, $args, $forcedownloa
|
||||
if (!$file = $fs->get_file_by_hash(sha1($fullpath)) or $file->is_directory()) {
|
||||
return false;
|
||||
}
|
||||
send_stored_file($file, 0, 0, true);
|
||||
send_stored_file($file, 0, 0, true, $options);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1704,10 +1705,11 @@ function quiz_pluginfile($course, $cm, $context, $filearea, $args, $forcedownloa
|
||||
* @param int $slot the id of a question in this quiz attempt.
|
||||
* @param array $args the remaining bits of the file path.
|
||||
* @param bool $forcedownload whether the user must be forced to download the file.
|
||||
* @param array $options additional options affecting the file serving
|
||||
* @return bool false if file not found, does not return if found - justsend the file
|
||||
*/
|
||||
function mod_quiz_question_pluginfile($course, $context, $component,
|
||||
$filearea, $qubaid, $slot, $args, $forcedownload) {
|
||||
$filearea, $qubaid, $slot, $args, $forcedownload, array $options=array()) {
|
||||
global $CFG;
|
||||
require_once($CFG->dirroot . '/mod/quiz/locallib.php');
|
||||
|
||||
@@ -1739,7 +1741,7 @@ function mod_quiz_question_pluginfile($course, $context, $component,
|
||||
send_file_not_found();
|
||||
}
|
||||
|
||||
send_stored_file($file, 0, 0, $forcedownload);
|
||||
send_stored_file($file, 0, 0, $forcedownload, $options);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -35,8 +35,9 @@ defined('MOODLE_INTERNAL') || die();
|
||||
* @param int $questionid the question id
|
||||
* @param array $args remaining file args
|
||||
* @param bool $forcedownload
|
||||
* @param array $options additional options affecting the file serving
|
||||
*/
|
||||
function quiz_statistics_questiontext_preview_pluginfile($context, $questionid, $args, $forcedownload) {
|
||||
function quiz_statistics_questiontext_preview_pluginfile($context, $questionid, $args, $forcedownload, array $options=array()) {
|
||||
global $CFG;
|
||||
require_once($CFG->dirroot . '/mod/quiz/locallib.php');
|
||||
|
||||
@@ -47,7 +48,7 @@ function quiz_statistics_questiontext_preview_pluginfile($context, $questionid,
|
||||
// validate questionid, becuase of the complexity of random quetsions.
|
||||
require_capability('quiz/statistics:view', $context);
|
||||
|
||||
question_send_questiontext_file($questionid, $args, $forcedownload);
|
||||
question_send_questiontext_file($questionid, $args, $forcedownload, $options);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -382,9 +382,10 @@ function resource_get_file_info($browser, $areas, $course, $cm, $context, $filea
|
||||
* @param string $filearea file area
|
||||
* @param array $args extra arguments
|
||||
* @param bool $forcedownload whether or not force download
|
||||
* @param array $options additional options affecting the file serving
|
||||
* @return bool false if file not found, does not return if found - just send the file
|
||||
*/
|
||||
function resource_pluginfile($course, $cm, $context, $filearea, $args, $forcedownload) {
|
||||
function resource_pluginfile($course, $cm, $context, $filearea, $args, $forcedownload, array $options=array()) {
|
||||
global $CFG, $DB;
|
||||
require_once("$CFG->libdir/resourcelib.php");
|
||||
|
||||
@@ -443,7 +444,7 @@ function resource_pluginfile($course, $cm, $context, $filearea, $args, $forcedow
|
||||
}
|
||||
|
||||
// finally send the file
|
||||
send_stored_file($file, 86400, $filter, $forcedownload);
|
||||
send_stored_file($file, 86400, $filter, $forcedownload, $options);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+3
-2
@@ -927,9 +927,10 @@ function scorm_get_file_info($browser, $areas, $course, $cm, $context, $filearea
|
||||
* @param string $filearea file area
|
||||
* @param array $args extra arguments
|
||||
* @param bool $forcedownload whether or not force download
|
||||
* @param array $options additional options affecting the file serving
|
||||
* @return bool false if file not found, does not return if found - just send the file
|
||||
*/
|
||||
function scorm_pluginfile($course, $cm, $context, $filearea, $args, $forcedownload) {
|
||||
function scorm_pluginfile($course, $cm, $context, $filearea, $args, $forcedownload, array $options=array()) {
|
||||
global $CFG;
|
||||
|
||||
if ($context->contextlevel != CONTEXT_MODULE) {
|
||||
@@ -968,7 +969,7 @@ function scorm_pluginfile($course, $cm, $context, $filearea, $args, $forcedownlo
|
||||
}
|
||||
|
||||
// finally send the file
|
||||
send_stored_file($file, $lifetime, 0, false);
|
||||
send_stored_file($file, $lifetime, 0, false, $options);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -7,6 +7,9 @@ information provided here is intended especially for developers.
|
||||
required changes in code:
|
||||
* define the capability mod/xxx:addinstance (and the corresponding lang string)
|
||||
(unless your mod is a MOD_ARCHETYPE_SYSTEM).
|
||||
* xxx_pluginfile() is now given the 7th parameter (hopefully the last one) that
|
||||
contains additional options for the file serving. The array should be re-passed
|
||||
to send_stored_file().
|
||||
|
||||
|
||||
=== 2.2 ===
|
||||
|
||||
+4
-2
@@ -445,8 +445,10 @@ function wiki_scale_used_anywhere($scaleid) {
|
||||
* @param string $filearea file area
|
||||
* @param array $args extra arguments
|
||||
* @param bool $forcedownload whether or not force download
|
||||
* @param array $options additional options affecting the file serving
|
||||
* @return bool false if the file was not found, just send the file otherwise and do not return anything
|
||||
*/
|
||||
function wiki_pluginfile($course, $cm, $context, $filearea, $args, $forcedownload) {
|
||||
function wiki_pluginfile($course, $cm, $context, $filearea, $args, $forcedownload, array $options=array()) {
|
||||
global $CFG;
|
||||
|
||||
if ($context->contextlevel != CONTEXT_MODULE) {
|
||||
@@ -477,7 +479,7 @@ function wiki_pluginfile($course, $cm, $context, $filearea, $args, $forcedownloa
|
||||
|
||||
$lifetime = isset($CFG->filelifetime) ? $CFG->filelifetime : 86400;
|
||||
|
||||
send_stored_file($file, $lifetime, 0);
|
||||
send_stored_file($file, $lifetime, 0, $options);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -38,9 +38,10 @@ require_once($CFG->libdir . '/gradelib.php'); // to handle float vs de
|
||||
* @param string $filearea file area
|
||||
* @param array $args extra arguments
|
||||
* @param bool $forcedownload whether or not force download
|
||||
* @param array $options additional options affecting the file serving
|
||||
* @return bool
|
||||
*/
|
||||
function workshopform_accumulative_pluginfile($course, $cm, $context, $filearea, array $args, $forcedownload) {
|
||||
function workshopform_accumulative_pluginfile($course, $cm, $context, $filearea, array $args, $forcedownload, array $options=array()) {
|
||||
global $DB;
|
||||
|
||||
if ($context->contextlevel != CONTEXT_MODULE) {
|
||||
@@ -72,7 +73,7 @@ function workshopform_accumulative_pluginfile($course, $cm, $context, $filearea,
|
||||
}
|
||||
|
||||
// finally send the file
|
||||
send_stored_file($file);
|
||||
send_stored_file($file, 0, 0, $forcedownload, $options);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -38,9 +38,10 @@ require_once($CFG->libdir . '/gradelib.php'); // to handle float vs de
|
||||
* @param string $filearea file area
|
||||
* @param array $args extra arguments
|
||||
* @param bool $forcedownload whether or not force download
|
||||
* @param array $options additional options affecting the file serving
|
||||
* @return bool
|
||||
*/
|
||||
function workshopform_comments_pluginfile($course, $cm, $context, $filearea, array $args, $forcedownload) {
|
||||
function workshopform_comments_pluginfile($course, $cm, $context, $filearea, array $args, $forcedownload, array $options=array()) {
|
||||
global $DB;
|
||||
|
||||
if ($context->contextlevel != CONTEXT_MODULE) {
|
||||
@@ -72,7 +73,7 @@ function workshopform_comments_pluginfile($course, $cm, $context, $filearea, arr
|
||||
}
|
||||
|
||||
// finally send the file
|
||||
send_stored_file($file);
|
||||
send_stored_file($file, 0, 0, $forcedownload, $options);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -38,9 +38,10 @@ require_once($CFG->libdir . '/gradelib.php'); // to handle float vs de
|
||||
* @param string $filearea file area
|
||||
* @param array $args extra arguments
|
||||
* @param bool $forcedownload whether or not force download
|
||||
* @param array $options additional options affecting the file serving
|
||||
* @return bool
|
||||
*/
|
||||
function workshopform_numerrors_pluginfile($course, $cm, $context, $filearea, array $args, $forcedownload) {
|
||||
function workshopform_numerrors_pluginfile($course, $cm, $context, $filearea, array $args, $forcedownload, array $options=array()) {
|
||||
global $DB;
|
||||
|
||||
if ($context->contextlevel != CONTEXT_MODULE) {
|
||||
@@ -72,7 +73,7 @@ function workshopform_numerrors_pluginfile($course, $cm, $context, $filearea, ar
|
||||
}
|
||||
|
||||
// finally send the file
|
||||
send_stored_file($file);
|
||||
send_stored_file($file, 0, 0, $forcedownload, $options);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -38,9 +38,10 @@ require_once($CFG->libdir . '/gradelib.php'); // to handle float vs de
|
||||
* @param string $filearea file area
|
||||
* @param array $args extra arguments
|
||||
* @param bool $forcedownload whether or not force download
|
||||
* @param array $options additional options affecting the file serving
|
||||
* @return bool
|
||||
*/
|
||||
function workshopform_rubric_pluginfile($course, $cm, $context, $filearea, array $args, $forcedownload) {
|
||||
function workshopform_rubric_pluginfile($course, $cm, $context, $filearea, array $args, $forcedownload, array $options=array()) {
|
||||
global $DB;
|
||||
|
||||
if ($context->contextlevel != CONTEXT_MODULE) {
|
||||
@@ -72,7 +73,7 @@ function workshopform_rubric_pluginfile($course, $cm, $context, $filearea, array
|
||||
}
|
||||
|
||||
// finally send the file
|
||||
send_stored_file($file);
|
||||
send_stored_file($file, 0, 0, $forcedownload, $options);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+13
-12
@@ -1221,15 +1221,16 @@ function workshop_get_file_areas($course, $cm, $context) {
|
||||
* @package mod_workshop
|
||||
* @category files
|
||||
*
|
||||
* @param stdClass $course
|
||||
* @param stdClass $cm
|
||||
* @param stdClass $context
|
||||
* @param string $filearea
|
||||
* @param array $args
|
||||
* @param bool $forcedownload
|
||||
* @return void this should never return to the caller
|
||||
* @param stdClass $course the course object
|
||||
* @param stdClass $cm the course module object
|
||||
* @param stdClass $context the workshop's context
|
||||
* @param string $filearea the name of the file area
|
||||
* @param array $args extra arguments (itemid, path)
|
||||
* @param bool $forcedownload whether or not force download
|
||||
* @param array $options additional options affecting the file serving
|
||||
* @return bool false if the file not found, just send the file otherwise and do not return anything
|
||||
*/
|
||||
function workshop_pluginfile($course, $cm, $context, $filearea, array $args, $forcedownload) {
|
||||
function workshop_pluginfile($course, $cm, $context, $filearea, array $args, $forcedownload, array $options=array()) {
|
||||
global $DB, $CFG;
|
||||
|
||||
if ($context->contextlevel != CONTEXT_MODULE) {
|
||||
@@ -1246,7 +1247,7 @@ function workshop_pluginfile($course, $cm, $context, $filearea, array $args, $fo
|
||||
|
||||
array_shift($args); // we do not use itemids here
|
||||
$relativepath = implode('/', $args);
|
||||
$fullpath = "/$context->id/mod_workshop/$filearea/0/$relativepath"; // beware, slashes are not used here!
|
||||
$fullpath = "/$context->id/mod_workshop/$filearea/0/$relativepath";
|
||||
|
||||
$fs = get_file_storage();
|
||||
if (!$file = $fs->get_file_by_hash(sha1($fullpath)) or $file->is_directory()) {
|
||||
@@ -1256,7 +1257,7 @@ function workshop_pluginfile($course, $cm, $context, $filearea, array $args, $fo
|
||||
$lifetime = isset($CFG->filelifetime) ? $CFG->filelifetime : 86400;
|
||||
|
||||
// finally send the file
|
||||
send_stored_file($file, $lifetime, 0);
|
||||
send_stored_file($file, $lifetime, 0, $forcedownload, $options);
|
||||
}
|
||||
|
||||
if ($filearea === 'instructreviewers') {
|
||||
@@ -1277,7 +1278,7 @@ function workshop_pluginfile($course, $cm, $context, $filearea, array $args, $fo
|
||||
$lifetime = isset($CFG->filelifetime) ? $CFG->filelifetime : 86400;
|
||||
|
||||
// finally send the file
|
||||
send_stored_file($file, $lifetime, 0);
|
||||
send_stored_file($file, $lifetime, 0, $forcedownload, $options);
|
||||
|
||||
} else if ($filearea === 'submission_content' or $filearea === 'submission_attachment') {
|
||||
$itemid = (int)array_shift($args);
|
||||
@@ -1296,7 +1297,7 @@ function workshop_pluginfile($course, $cm, $context, $filearea, array $args, $fo
|
||||
}
|
||||
// finally send the file
|
||||
// these files are uploaded by students - forcing download for security reasons
|
||||
send_stored_file($file, 0, 0, true);
|
||||
send_stored_file($file, 0, 0, true, $options);
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
@@ -29,6 +29,9 @@
|
||||
<directory suffix="_test.php">lib/ajax/tests</directory>
|
||||
<directory suffix="_test.php">lib/form/tests</directory>
|
||||
</testsuite>
|
||||
<testsuite name="core_files">
|
||||
<directory suffix="_test.php">lib/filestorage/tests</directory>
|
||||
</testsuite>
|
||||
<testsuite name="core_grade">
|
||||
<directory suffix="_test.php">lib/grade/tests</directory>
|
||||
<directory suffix="_test.php">grade/tests</directory>
|
||||
|
||||
+2
-1
@@ -33,5 +33,6 @@ require_once('lib/filelib.php');
|
||||
|
||||
$relativepath = get_file_argument();
|
||||
$forcedownload = optional_param('forcedownload', 0, PARAM_BOOL);
|
||||
$preview = optional_param('preview', null, PARAM_ALPHANUM);
|
||||
|
||||
file_pluginfile($relativepath, $forcedownload);
|
||||
file_pluginfile($relativepath, $forcedownload, $preview);
|
||||
|
||||
@@ -224,10 +224,11 @@ class question_preview_options extends question_display_options {
|
||||
* @param int $slot the relevant slot within the usage.
|
||||
* @param array $args the remaining bits of the file path.
|
||||
* @param bool $forcedownload whether the user must be forced to download the file.
|
||||
* @param array $options additional options affecting the file serving
|
||||
* @return bool false if file not found, does not return if found - justsend the file
|
||||
*/
|
||||
function question_preview_question_pluginfile($course, $context, $component,
|
||||
$filearea, $qubaid, $slot, $args, $forcedownload) {
|
||||
$filearea, $qubaid, $slot, $args, $forcedownload, $options) {
|
||||
global $USER, $DB, $CFG;
|
||||
|
||||
$quba = question_engine::load_questions_usage_by_activity($qubaid);
|
||||
@@ -255,7 +256,7 @@ function question_preview_question_pluginfile($course, $context, $component,
|
||||
send_file_not_found();
|
||||
}
|
||||
|
||||
send_stored_file($file, 0, 0, $forcedownload);
|
||||
send_stored_file($file, 0, 0, $forcedownload, $options);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -38,10 +38,11 @@ defined('MOODLE_INTERNAL') || die();
|
||||
* @param string $filearea file area
|
||||
* @param array $args extra arguments
|
||||
* @param bool $forcedownload whether or not force download
|
||||
* @param array $options additional options affecting the file serving
|
||||
* @return bool
|
||||
*/
|
||||
function qtype_calculated_pluginfile($course, $cm, $context, $filearea, $args, $forcedownload) {
|
||||
function qtype_calculated_pluginfile($course, $cm, $context, $filearea, $args, $forcedownload, array $options=array()) {
|
||||
global $CFG;
|
||||
require_once($CFG->libdir . '/questionlib.php');
|
||||
question_pluginfile($course, $context, 'qtype_calculated', $filearea, $args, $forcedownload);
|
||||
question_pluginfile($course, $context, 'qtype_calculated', $filearea, $args, $forcedownload, $options);
|
||||
}
|
||||
|
||||
@@ -38,12 +38,13 @@ defined('MOODLE_INTERNAL') || die();
|
||||
* @param string $filearea file area
|
||||
* @param array $args extra arguments
|
||||
* @param bool $forcedownload whether or not force download
|
||||
* @param array $options additional options affecting the file serving
|
||||
* @return bool
|
||||
*/
|
||||
function qtype_calculatedmulti_pluginfile($course, $cm, $context, $filearea, $args,
|
||||
$forcedownload) {
|
||||
$forcedownload, array $options=array()) {
|
||||
global $DB, $CFG;
|
||||
require_once($CFG->libdir . '/questionlib.php');
|
||||
question_pluginfile($course, $context, 'qtype_calculatedmulti', $filearea, $args,
|
||||
$forcedownload);
|
||||
$forcedownload, $options);
|
||||
}
|
||||
|
||||
@@ -39,12 +39,13 @@ defined('MOODLE_INTERNAL') || die();
|
||||
* @param string $filearea
|
||||
* @param array $args
|
||||
* @param bool $forcedownload
|
||||
* @param array $options additional options affecting the file serving
|
||||
* @return bool
|
||||
*/
|
||||
function qtype_calculatedsimple_pluginfile($course, $cm, $context, $filearea,
|
||||
$args, $forcedownload) {
|
||||
$args, $forcedownload, array $options=array()) {
|
||||
global $CFG;
|
||||
require_once($CFG->libdir . '/questionlib.php');
|
||||
question_pluginfile($course, $context, 'qtype_calculatedsimple', $filearea,
|
||||
$args, $forcedownload);
|
||||
$args, $forcedownload, $options);
|
||||
}
|
||||
|
||||
@@ -38,10 +38,11 @@ defined('MOODLE_INTERNAL') || die();
|
||||
* @param string $filearea file area
|
||||
* @param array $args extra arguments
|
||||
* @param bool $forcedownload whether or not force download
|
||||
* @param array $options additional options affecting the file serving
|
||||
* @return bool
|
||||
*/
|
||||
function qtype_essay_pluginfile($course, $cm, $context, $filearea, $args, $forcedownload) {
|
||||
function qtype_essay_pluginfile($course, $cm, $context, $filearea, $args, $forcedownload, array $options=array()) {
|
||||
global $CFG;
|
||||
require_once($CFG->libdir . '/questionlib.php');
|
||||
question_pluginfile($course, $context, 'qtype_essay', $filearea, $args, $forcedownload);
|
||||
question_pluginfile($course, $context, 'qtype_essay', $filearea, $args, $forcedownload, $options);
|
||||
}
|
||||
|
||||
@@ -37,10 +37,11 @@ defined('MOODLE_INTERNAL') || die();
|
||||
* @param string $filearea file area
|
||||
* @param array $args extra arguments
|
||||
* @param bool $forcedownload whether or not force download
|
||||
* @param array $options additional options affecting the file serving
|
||||
* @return bool
|
||||
*/
|
||||
function qtype_match_pluginfile($course, $cm, $context, $filearea, $args, $forcedownload) {
|
||||
function qtype_match_pluginfile($course, $cm, $context, $filearea, $args, $forcedownload, array $options=array()) {
|
||||
global $DB, $CFG;
|
||||
require_once($CFG->libdir . '/questionlib.php');
|
||||
question_pluginfile($course, $context, 'qtype_match', $filearea, $args, $forcedownload);
|
||||
question_pluginfile($course, $context, 'qtype_match', $filearea, $args, $forcedownload, $options);
|
||||
}
|
||||
|
||||
@@ -38,10 +38,11 @@ defined('MOODLE_INTERNAL') || die();
|
||||
* @param string $filearea file area
|
||||
* @param array $args extra arguments
|
||||
* @param bool $forcedownload whether or not force download
|
||||
* @param array $options additional options affecting the file serving
|
||||
* @return bool
|
||||
*/
|
||||
function qtype_multichoice_pluginfile($course, $cm, $context, $filearea, $args, $forcedownload) {
|
||||
function qtype_multichoice_pluginfile($course, $cm, $context, $filearea, $args, $forcedownload, array $options=array()) {
|
||||
global $CFG;
|
||||
require_once($CFG->libdir . '/questionlib.php');
|
||||
question_pluginfile($course, $context, 'qtype_multichoice', $filearea, $args, $forcedownload);
|
||||
question_pluginfile($course, $context, 'qtype_multichoice', $filearea, $args, $forcedownload, $options);
|
||||
}
|
||||
|
||||
@@ -38,10 +38,11 @@ defined('MOODLE_INTERNAL') || die();
|
||||
* @param string $filearea file area
|
||||
* @param array $args extra arguments
|
||||
* @param bool $forcedownload whether or not force download
|
||||
* @param array $options additional options affecting the file serving
|
||||
* @return bool
|
||||
*/
|
||||
function qtype_numerical_pluginfile($course, $cm, $context, $filearea, $args, $forcedownload) {
|
||||
function qtype_numerical_pluginfile($course, $cm, $context, $filearea, $args, $forcedownload, array $options=array()) {
|
||||
global $CFG;
|
||||
require_once($CFG->libdir . '/questionlib.php');
|
||||
question_pluginfile($course, $context, 'qtype_numerical', $filearea, $args, $forcedownload);
|
||||
question_pluginfile($course, $context, 'qtype_numerical', $filearea, $args, $forcedownload, $options);
|
||||
}
|
||||
|
||||
@@ -37,10 +37,11 @@ defined('MOODLE_INTERNAL') || die();
|
||||
* @param string $filearea file area
|
||||
* @param array $args extra arguments
|
||||
* @param bool $forcedownload whether or not force download
|
||||
* @param array $options additional options affecting the file serving
|
||||
* @return bool
|
||||
*/
|
||||
function qtype_shortanswer_pluginfile($course, $cm, $context, $filearea, $args, $forcedownload) {
|
||||
function qtype_shortanswer_pluginfile($course, $cm, $context, $filearea, $args, $forcedownload, array $options=array()) {
|
||||
global $DB, $CFG;
|
||||
require_once($CFG->libdir . '/questionlib.php');
|
||||
question_pluginfile($course, $context, 'qtype_shortanswer', $filearea, $args, $forcedownload);
|
||||
question_pluginfile($course, $context, 'qtype_shortanswer', $filearea, $args, $forcedownload, $options);
|
||||
}
|
||||
|
||||
@@ -37,10 +37,11 @@ defined('MOODLE_INTERNAL') || die();
|
||||
* @param string $filearea file area
|
||||
* @param array $args extra arguments
|
||||
* @param bool $forcedownload whether or not force download
|
||||
* @param array $options additional options affecting the file serving
|
||||
* @return bool
|
||||
*/
|
||||
function qtype_truefalse_pluginfile($course, $cm, $context, $filearea, $args, $forcedownload) {
|
||||
function qtype_truefalse_pluginfile($course, $cm, $context, $filearea, $args, $forcedownload, array $options=array()) {
|
||||
global $CFG;
|
||||
require_once($CFG->libdir . '/questionlib.php');
|
||||
question_pluginfile($course, $context, 'qtype_truefalse', $filearea, $args, $forcedownload);
|
||||
question_pluginfile($course, $context, 'qtype_truefalse', $filearea, $args, $forcedownload, $options);
|
||||
}
|
||||
|
||||
@@ -7,6 +7,9 @@ This files describes API changes for question type plugins.
|
||||
import and export, then you will probably get PHP strict syntax notices in developer
|
||||
debug mode until you change the method signature to include qformat_xml $format.
|
||||
That is, you need to specify the argument type.
|
||||
* qtype_xxx_pluginfile() is now given the 7th parameter (hopefully the last
|
||||
one) that contains additional options for the file serving. The array should
|
||||
be re-passed to question_pluginfile() as is.
|
||||
|
||||
|
||||
=== 2.2 ===
|
||||
|
||||
Reference in New Issue
Block a user