Merge branch 'wip-MDL-39177-m24' of git://github.com/marinaglancy/moodle into MOODLE_24_STABLE
This commit is contained in:
@@ -97,6 +97,7 @@ $string['enter'] = 'Enter';
|
||||
$string['entername'] = 'Please enter folder name';
|
||||
$string['enternewname'] = 'Please enter the new file name';
|
||||
$string['error'] = 'An unknown error occurred!';
|
||||
$string['errordoublereference'] = 'Unable to overwrite file with a shortcut/alias because shortcuts to this file already exist.';
|
||||
$string['errornotyourfile'] = 'You cannot pick file which is not added by your';
|
||||
$string['erroruniquename'] = 'Repository instance name should be unique';
|
||||
$string['errorpostmaxsize'] = 'The uploaded file may exceed the post_max_size directive in php.ini.';
|
||||
@@ -115,7 +116,7 @@ $string['filepicker'] = 'File picker';
|
||||
$string['filesizenull'] = 'File size cannot be determined';
|
||||
$string['folderexists'] = 'Folder name already being used, please use another name';
|
||||
$string['foldernotfound'] = 'Folder not found';
|
||||
$string['folderrecurse'] = 'Folder can not be moved to it\s own subfolder';
|
||||
$string['folderrecurse'] = 'Folder can not be moved to it\'s own subfolder';
|
||||
$string['getfile'] = 'Select this file';
|
||||
$string['hidden'] = 'Hidden';
|
||||
$string['choosealink'] = 'Choose a link...';
|
||||
|
||||
+63
-69
@@ -713,6 +713,9 @@ function file_get_submitted_draft_itemid($elname) {
|
||||
/**
|
||||
* Restore the original source field from draft files
|
||||
*
|
||||
* Do not use this function because it makes field files.source inconsistent
|
||||
* for draft area files. This function will be deprecated in 2.6
|
||||
*
|
||||
* @param stored_file $storedfile This only works with draft files
|
||||
* @return stored_file
|
||||
*/
|
||||
@@ -783,58 +786,37 @@ function file_save_draft_area_files($draftitemid, $contextid, $component, $filea
|
||||
$draftfiles = $fs->get_area_files($usercontext->id, 'user', 'draft', $draftitemid, 'id');
|
||||
$oldfiles = $fs->get_area_files($contextid, $component, $filearea, $itemid, 'id');
|
||||
|
||||
if (count($draftfiles) < 2) {
|
||||
// means there are no files - one file means root dir only ;-)
|
||||
$fs->delete_area_files($contextid, $component, $filearea, $itemid);
|
||||
|
||||
} else if (count($oldfiles) < 2) {
|
||||
$filecount = 0;
|
||||
// there were no files before - one file means root dir only ;-)
|
||||
foreach ($draftfiles as $file) {
|
||||
$file_record = array('contextid'=>$contextid, 'component'=>$component, 'filearea'=>$filearea, 'itemid'=>$itemid);
|
||||
if (!$options['subdirs']) {
|
||||
if ($file->get_filepath() !== '/' or $file->is_directory()) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if ($options['maxbytes'] and $options['maxbytes'] < $file->get_filesize()) {
|
||||
// oversized file - should not get here at all
|
||||
continue;
|
||||
}
|
||||
if ($options['maxfiles'] != -1 and $options['maxfiles'] <= $filecount) {
|
||||
// more files - should not get here at all
|
||||
break;
|
||||
}
|
||||
if (!$file->is_directory()) {
|
||||
$filecount++;
|
||||
}
|
||||
|
||||
if ($file->is_external_file()) {
|
||||
if (!$allowreferences) {
|
||||
continue;
|
||||
}
|
||||
$repoid = $file->get_repository_id();
|
||||
if (!empty($repoid)) {
|
||||
$file_record['repositoryid'] = $repoid;
|
||||
$file_record['reference'] = $file->get_reference();
|
||||
}
|
||||
}
|
||||
file_restore_source_field_from_draft_file($file);
|
||||
|
||||
$fs->create_file_from_storedfile($file_record, $file);
|
||||
}
|
||||
|
||||
} else {
|
||||
// One file in filearea means it is empty (it has only top-level directory '.').
|
||||
if (count($draftfiles) > 1 || count($oldfiles) > 1) {
|
||||
// we have to merge old and new files - we want to keep file ids for files that were not changed
|
||||
// we change time modified for all new and changed files, we keep time created as is
|
||||
|
||||
$newhashes = array();
|
||||
$filecount = 0;
|
||||
foreach ($draftfiles as $file) {
|
||||
if (!$options['subdirs'] && ($file->get_filepath() !== '/' or $file->is_directory())) {
|
||||
continue;
|
||||
}
|
||||
if (!$allowreferences && $file->is_external_file()) {
|
||||
continue;
|
||||
}
|
||||
if (!$file->is_directory()) {
|
||||
if ($options['maxbytes'] and $options['maxbytes'] < $file->get_filesize()) {
|
||||
// oversized file - should not get here at all
|
||||
continue;
|
||||
}
|
||||
if ($options['maxfiles'] != -1 and $options['maxfiles'] <= $filecount) {
|
||||
// more files - should not get here at all
|
||||
continue;
|
||||
}
|
||||
$filecount++;
|
||||
}
|
||||
$newhash = $fs->get_pathname_hash($contextid, $component, $filearea, $itemid, $file->get_filepath(), $file->get_filename());
|
||||
file_restore_source_field_from_draft_file($file);
|
||||
$newhashes[$newhash] = $file;
|
||||
}
|
||||
$filecount = 0;
|
||||
|
||||
// Loop through oldfiles and decide which we need to delete and which to update.
|
||||
// After this cycle the array $newhashes will only contain the files that need to be added.
|
||||
foreach ($oldfiles as $oldfile) {
|
||||
$oldhash = $oldfile->get_pathnamehash();
|
||||
if (!isset($newhashes[$oldhash])) {
|
||||
@@ -844,6 +826,25 @@ function file_save_draft_area_files($draftitemid, $contextid, $component, $filea
|
||||
}
|
||||
|
||||
$newfile = $newhashes[$oldhash];
|
||||
// Now we know that we have $oldfile and $newfile for the same path.
|
||||
// Let's check if we can update this file or we need to delete and create.
|
||||
if ($newfile->is_directory()) {
|
||||
// Directories are always ok to just update.
|
||||
} else if (($source = @unserialize($newfile->get_source())) && isset($source->original)) {
|
||||
// File has the 'original' - we need to update the file (it may even have not been changed at all).
|
||||
$original = file_storage::unpack_reference($source->original);
|
||||
if ($original['filename'] !== $oldfile->get_filename() || $original['filepath'] !== $oldfile->get_filepath()) {
|
||||
// Very odd, original points to another file. Delete and create file.
|
||||
$oldfile->delete();
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
// The same file name but absence of 'original' means that file was deteled and uploaded again.
|
||||
// By deleting and creating new file we properly manage all existing references.
|
||||
$oldfile->delete();
|
||||
continue;
|
||||
}
|
||||
|
||||
// status changed, we delete old file, and create a new one
|
||||
if ($oldfile->get_status() != $newfile->get_status()) {
|
||||
// file was changed, use updated with new timemodified data
|
||||
@@ -862,8 +863,14 @@ function file_save_draft_area_files($draftitemid, $contextid, $component, $filea
|
||||
}
|
||||
|
||||
// Updated file source
|
||||
if ($oldfile->get_source() != $newfile->get_source()) {
|
||||
$oldfile->set_source($newfile->get_source());
|
||||
// Field files.source for draftarea files contains serialised object with source and original information.
|
||||
// We only store the source part of it for non-draft file area.
|
||||
$newsource = $newfile->get_source();
|
||||
if ($source = @unserialize($newfile->get_source())) {
|
||||
$newsource = $source->source;
|
||||
}
|
||||
if ($oldfile->get_source() !== $newsource) {
|
||||
$oldfile->set_source($newsource);
|
||||
}
|
||||
|
||||
// Updated sort order
|
||||
@@ -877,44 +884,31 @@ function file_save_draft_area_files($draftitemid, $contextid, $component, $filea
|
||||
}
|
||||
|
||||
// Replaced file content
|
||||
if ($oldfile->get_contenthash() != $newfile->get_contenthash() || $oldfile->get_filesize() != $newfile->get_filesize()) {
|
||||
$oldfile->replace_content_with($newfile);
|
||||
if (!$oldfile->is_directory() &&
|
||||
($oldfile->get_contenthash() != $newfile->get_contenthash() ||
|
||||
$oldfile->get_filesize() != $newfile->get_filesize() ||
|
||||
$oldfile->get_referencefileid() != $newfile->get_referencefileid() ||
|
||||
$oldfile->get_userid() != $newfile->get_userid())) {
|
||||
$oldfile->replace_file_with($newfile);
|
||||
// push changes to all local files that are referencing this file
|
||||
$fs->update_references_to_storedfile($oldfile);
|
||||
}
|
||||
|
||||
// unchanged file or directory - we keep it as is
|
||||
unset($newhashes[$oldhash]);
|
||||
if (!$oldfile->is_directory()) {
|
||||
$filecount++;
|
||||
}
|
||||
}
|
||||
|
||||
// Add fresh file or the file which has changed status
|
||||
// the size and subdirectory tests are extra safety only, the UI should prevent it
|
||||
foreach ($newhashes as $file) {
|
||||
$file_record = array('contextid'=>$contextid, 'component'=>$component, 'filearea'=>$filearea, 'itemid'=>$itemid, 'timemodified'=>time());
|
||||
if (!$options['subdirs']) {
|
||||
if ($file->get_filepath() !== '/' or $file->is_directory()) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if ($options['maxbytes'] and $options['maxbytes'] < $file->get_filesize()) {
|
||||
// oversized file - should not get here at all
|
||||
continue;
|
||||
}
|
||||
if ($options['maxfiles'] != -1 and $options['maxfiles'] <= $filecount) {
|
||||
// more files - should not get here at all
|
||||
break;
|
||||
}
|
||||
if (!$file->is_directory()) {
|
||||
$filecount++;
|
||||
if ($source = @unserialize($file->get_source())) {
|
||||
// Field files.source for draftarea files contains serialised object with source and original information.
|
||||
// We only store the source part of it for non-draft file area.
|
||||
$file_record['source'] = $source->source;
|
||||
}
|
||||
|
||||
if ($file->is_external_file()) {
|
||||
if (!$allowreferences) {
|
||||
continue;
|
||||
}
|
||||
$repoid = $file->get_repository_id();
|
||||
if (!empty($repoid)) {
|
||||
$file_record['repositoryid'] = $repoid;
|
||||
|
||||
@@ -210,6 +210,40 @@ class stored_file {
|
||||
$this->set_filesize($storedfile->get_filesize());
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces the fields that might have changed when file was overriden in filepicker:
|
||||
* reference, contenthash, filesize, userid
|
||||
*
|
||||
* Note that field 'source' must be updated separately because
|
||||
* it has different format for draft and non-draft areas and
|
||||
* this function will usually be used to replace non-draft area
|
||||
* file with draft area file.
|
||||
*
|
||||
* @param stored_file $newfile
|
||||
* @throws coding_exception
|
||||
*/
|
||||
public function replace_file_with(stored_file $newfile) {
|
||||
if ($newfile->get_referencefileid() &&
|
||||
$this->fs->get_references_count_by_storedfile($this)) {
|
||||
// The new file is a reference.
|
||||
// The current file has other local files referencing to it.
|
||||
// Double reference is not allowed.
|
||||
throw new moodle_exception('errordoublereference', 'repository');
|
||||
}
|
||||
|
||||
$filerecord = new stdClass;
|
||||
$contenthash = $newfile->get_contenthash();
|
||||
if ($this->fs->content_exists($contenthash)) {
|
||||
$filerecord->contenthash = $contenthash;
|
||||
} else {
|
||||
throw new file_exception('storedfileproblem', 'Invalid contenthash, content must be already in filepool', $contenthash);
|
||||
}
|
||||
$filerecord->filesize = $newfile->get_filesize();
|
||||
$filerecord->referencefileid = $newfile->get_referencefileid();
|
||||
$filerecord->userid = $newfile->get_userid();
|
||||
$this->update($filerecord);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unlink the stored file from the referenced file
|
||||
*
|
||||
|
||||
@@ -125,90 +125,33 @@ switch ($action) {
|
||||
// Allows to Rename file, move it to another directory, change it's license and author information in one request
|
||||
$filename = required_param('filename', PARAM_FILE);
|
||||
$filepath = required_param('filepath', PARAM_PATH);
|
||||
|
||||
$fs = get_file_storage();
|
||||
if (!($file = $fs->get_file($user_context->id, 'user', 'draft', $draftid, $filepath, $filename))) {
|
||||
die(json_encode((object)array('error' => get_string('filenotfound', 'error'))));
|
||||
}
|
||||
|
||||
$updatedata = array();
|
||||
$updatedata['filename'] = $newfilename = optional_param('newfilename', $file->get_filename(), PARAM_FILE);
|
||||
$updatedata['filepath'] = $newfilepath = optional_param('newfilepath', $file->get_filepath(), PARAM_PATH);
|
||||
$updatedata['license'] = optional_param('newlicense', $file->get_license(), PARAM_TEXT);
|
||||
$updatedata['author'] = optional_param('newauthor', $file->get_author(), PARAM_TEXT);
|
||||
foreach ($updatedata as $key => $value) {
|
||||
if (''.$value === ''.$file->{'get_'.$key}()) {
|
||||
unset($updatedata[$key]);
|
||||
}
|
||||
$updatedata['filename'] = optional_param('newfilename', $filename, PARAM_FILE);
|
||||
$updatedata['filepath'] = $newfilepath = optional_param('newfilepath', $filepath, PARAM_PATH);
|
||||
if (($v = optional_param('newlicense', false, PARAM_TEXT)) !== false) {
|
||||
$updatedata['license'] = $v;
|
||||
}
|
||||
|
||||
if (!empty($updatedata)) {
|
||||
if (array_key_exists('filename', $updatedata) || array_key_exists('filepath', $updatedata)) {
|
||||
// check that target file name does not exist
|
||||
if ($fs->file_exists($user_context->id, 'user', 'draft', $draftid, $newfilepath, $newfilename)) {
|
||||
die(json_encode((object)array('error' => get_string('fileexists', 'repository'))));
|
||||
}
|
||||
$file->rename($newfilepath, $newfilename);
|
||||
}
|
||||
if (array_key_exists('license', $updatedata)) {
|
||||
$file->set_license($updatedata['license']);
|
||||
}
|
||||
if (array_key_exists('author', $updatedata)) {
|
||||
$file->set_author($updatedata['author']);
|
||||
}
|
||||
$changes = array_diff(array_keys($updatedata), array('filepath'));
|
||||
if (!empty($changes)) {
|
||||
// any change except for the moving to another folder alters 'Date modified' of the file
|
||||
$file->set_timemodified(time());
|
||||
}
|
||||
if (($v = optional_param('newauthor', false, PARAM_TEXT)) !== false) {
|
||||
$updatedata['author'] = $v;
|
||||
}
|
||||
try {
|
||||
repository::update_draftfile($draftid, $filepath, $filename, $updatedata);
|
||||
} catch (moodle_exception $e) {
|
||||
die(json_encode((object)array('error' => $e->getMessage())));
|
||||
}
|
||||
|
||||
die(json_encode((object)array('filepath' => $newfilepath)));
|
||||
|
||||
case 'updatedir':
|
||||
$filepath = required_param('filepath', PARAM_PATH);
|
||||
$fs = get_file_storage();
|
||||
if (!$dir = $fs->get_file($user_context->id, 'user', 'draft', $draftid, $filepath, '.')) {
|
||||
die(json_encode((object)array('error' => get_string('foldernotfound', 'repository'))));
|
||||
}
|
||||
$parts = explode('/', trim($dir->get_filepath(), '/'));
|
||||
$dirname = end($parts);
|
||||
$newdirname = required_param('newdirname', PARAM_FILE);
|
||||
$parent = required_param('newfilepath', PARAM_PATH);
|
||||
$newfilepath = clean_param($parent . '/' . $newdirname . '/', PARAM_PATH);
|
||||
if ($newfilepath == $filepath) {
|
||||
// no action required
|
||||
die(json_encode((object)array('filepath' => $parent)));
|
||||
try {
|
||||
repository::update_draftfile($draftid, $filepath, '.', array('filepath' => $newfilepath));
|
||||
} catch (moodle_exception $e) {
|
||||
die(json_encode((object)array('error' => $e->getMessage())));
|
||||
}
|
||||
if ($fs->get_directory_files($user_context->id, 'user', 'draft', $draftid, $newfilepath, true)) {
|
||||
//bad luck, we can not rename if something already exists there
|
||||
die(json_encode((object)array('error' => get_string('folderexists', 'repository'))));
|
||||
}
|
||||
$xfilepath = preg_quote($filepath, '|');
|
||||
if (preg_match("|^$xfilepath|", $parent)) {
|
||||
// we can not move folder to it's own subfolder
|
||||
die(json_encode((object)array('error' => get_string('folderrecurse', 'repository'))));
|
||||
}
|
||||
|
||||
//we must update directory and all children too
|
||||
$files = $fs->get_area_files($user_context->id, 'user', 'draft', $draftid);
|
||||
foreach ($files as $file) {
|
||||
if (!preg_match("|^$xfilepath|", $file->get_filepath())) {
|
||||
continue;
|
||||
}
|
||||
// move one by one
|
||||
$path = preg_replace("|^$xfilepath|", $newfilepath, $file->get_filepath());
|
||||
if ($dirname !== $newdirname && $file->get_filepath() === $filepath && $file->get_filename() === '.') {
|
||||
// this is the main directory we move/rename AND it has actually been renamed
|
||||
$file->set_timemodified(time());
|
||||
}
|
||||
$file->rename($path, $file->get_filename());
|
||||
}
|
||||
|
||||
$return = new stdClass();
|
||||
$return->filepath = $parent;
|
||||
echo json_encode($return);
|
||||
die;
|
||||
die(json_encode((object)array('filepath' => $parent)));
|
||||
|
||||
case 'zip':
|
||||
$filepath = required_param('filepath', PARAM_PATH);
|
||||
@@ -274,14 +217,47 @@ switch ($action) {
|
||||
|
||||
$file = $fs->get_file($user_context->id, 'user', 'draft', $draftid, $filepath, $filename);
|
||||
|
||||
if ($newfile = $file->extract_to_storage($zipper, $user_context->id, 'user', 'draft', $draftid, $filepath, $USER->id)) {
|
||||
// Find unused name for directory to extract the archive.
|
||||
$temppath = $filepath. pathinfo($filename, PATHINFO_FILENAME). '/';
|
||||
if ($fs->file_exists($user_context->id, 'user', 'draft', $draftid, $temppath, '.')) {
|
||||
for ($i=0; $i<1000; $i++) {
|
||||
if (!$fs->file_exists($user_context->id, 'user', 'draft', $draftid, rtrim($temppath, '/'). " ($i)/", '.')) {
|
||||
$temppath = rtrim($temppath, '/'). " ($i)/";
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Extract archive and move all files from $temppath to $filepath
|
||||
if ($file->extract_to_storage($zipper, $user_context->id, 'user', 'draft', $draftid, $temppath, $USER->id) !== false) {
|
||||
$extractedfiles = $fs->get_directory_files($user_context->id, 'user', 'draft', $draftid, $temppath, true);
|
||||
$xtemppath = preg_quote($temppath, '|');
|
||||
foreach ($extractedfiles as $file) {
|
||||
$realpath = preg_replace('|^'.$xtemppath.'|', $filepath, $file->get_filepath());
|
||||
if (!$file->is_directory()) {
|
||||
// Set the source to the extracted file to indicate that it came from archive.
|
||||
$file->set_source(serialize((object)array('source' => $filepath)));
|
||||
}
|
||||
if (!$fs->file_exists($user_context->id, 'user', 'draft', $draftid, $realpath, $file->get_filename())) {
|
||||
// File or directory did not exist, just move it.
|
||||
$file->rename($realpath, $file->get_filename());
|
||||
} else if (!$file->is_directory()) {
|
||||
// File already existed, overwrite it (nothing to do with existing directories).
|
||||
repository::overwrite_existing_draftfile($draftid, $realpath, $file->get_filename(), $file->get_filepath(), $file->get_filename());
|
||||
}
|
||||
}
|
||||
$return = new stdClass();
|
||||
$return->filepath = $filepath;
|
||||
echo json_encode($return);
|
||||
} else {
|
||||
echo json_encode(false);
|
||||
$return = false;
|
||||
}
|
||||
die;
|
||||
// Remove remaining temporary directories.
|
||||
foreach ($fs->get_directory_files($user_context->id, 'user', 'draft', $draftid, $temppath, true, true, 'filepath desc, filename desc') as $file) {
|
||||
$file->delete();
|
||||
}
|
||||
if ($file = $fs->get_file($user_context->id, 'user', 'draft', $draftid, $temppath, '.')) {
|
||||
$file->delete();
|
||||
}
|
||||
die(json_encode($return));
|
||||
|
||||
case 'getoriginal':
|
||||
$filename = required_param('filename', PARAM_FILE);
|
||||
|
||||
@@ -122,14 +122,7 @@ case 'renameform':
|
||||
break;
|
||||
|
||||
case 'rename':
|
||||
|
||||
if ($fs->file_exists($user_context->id, 'user', 'draft', $itemid, $draftpath, $newfilename)) {
|
||||
print_error('fileexists');
|
||||
} else if ($file = $fs->get_file($user_context->id, 'user', 'draft', $itemid, $draftpath, $filename)) {
|
||||
$newfile = $fs->create_file_from_storedfile(array('filename'=>$newfilename), $file);
|
||||
$file->delete();
|
||||
}
|
||||
|
||||
repository::update_draftfile($itemid, $draftpath, $filename, array('filename' => $newfilename));
|
||||
$home_url->param('action', 'browse');
|
||||
$home_url->param('draftpath', $draftpath);
|
||||
redirect($home_url);
|
||||
@@ -194,15 +187,7 @@ case 'unzip':
|
||||
|
||||
case 'movefile':
|
||||
if (!empty($targetpath)) {
|
||||
if ($fs->file_exists($user_context->id, 'user', 'draft', $itemid, $targetpath, $filename)) {
|
||||
print_error('cannotmovefile');
|
||||
} else if ($file = $fs->get_file($user_context->id, 'user', 'draft', $itemid, $draftpath, $filename)) {
|
||||
$newfile = $fs->create_file_from_storedfile(array('filepath'=>$targetpath), $file);
|
||||
$file->delete();
|
||||
} else {
|
||||
var_dump('cannot find file');
|
||||
die;
|
||||
}
|
||||
repository::update_draftfile($itemid, $draftpath, $filename, array('filepath' => $targetpath));
|
||||
$home_url->param('action', 'browse');
|
||||
$home_url->param('draftpath', $targetpath);
|
||||
redirect($home_url);
|
||||
|
||||
@@ -662,18 +662,16 @@ M.core_filepicker.init = function(Y, options) {
|
||||
'repository_id': this.active_repo.id,
|
||||
'callback': function(id, o, args) {
|
||||
scope.hide();
|
||||
// editor needs to update url
|
||||
// filemanager do nothing
|
||||
if (scope.options.editor_target && scope.options.env == 'editor') {
|
||||
// editor needs to update url
|
||||
scope.options.editor_target.value = data.existingfile.url;
|
||||
scope.options.editor_target.onchange();
|
||||
} else if (scope.options.env === 'filepicker') {
|
||||
var fileinfo = {'client_id':scope.options.client_id,
|
||||
'url':data.existingfile.url,
|
||||
'file':data.existingfile.filename};
|
||||
var formcallback_scope = scope.options.magicscope ? scope.options.magicscope : scope;
|
||||
scope.options.formcallback.apply(formcallback_scope, [fileinfo]);
|
||||
}
|
||||
var fileinfo = {'client_id':scope.options.client_id,
|
||||
'url':data.existingfile.url,
|
||||
'file':data.existingfile.filename};
|
||||
var formcallback_scope = scope.options.magicscope ? scope.options.magicscope : scope;
|
||||
scope.options.formcallback.apply(formcallback_scope, [fileinfo]);
|
||||
}
|
||||
}, true);
|
||||
}
|
||||
|
||||
@@ -2416,10 +2416,26 @@ abstract class repository {
|
||||
$user_context = context_user::instance($USER->id);
|
||||
if ($file = $fs->get_file($user_context->id, 'user', 'draft', $itemid, $filepath, $filename)) {
|
||||
if ($tempfile = $fs->get_file($user_context->id, 'user', 'draft', $itemid, $newfilepath, $newfilename)) {
|
||||
// Remember original file source field.
|
||||
$source = @unserialize($file->get_source());
|
||||
if ($tempfile->is_external_file()) {
|
||||
// New file is a reference. Check that existing file does not have any other files referencing to it
|
||||
if (isset($source->original) && $fs->search_references_count($source->original)) {
|
||||
return (object)array('error' => get_string('errordoublereference', 'repository'));
|
||||
}
|
||||
}
|
||||
// delete existing file to release filename
|
||||
$file->delete();
|
||||
// create new file
|
||||
$newfile = $fs->create_file_from_storedfile(array('filepath'=>$filepath, 'filename'=>$filename), $tempfile);
|
||||
// Preserve original file location (stored in source field) for handling references
|
||||
if (isset($source->original)) {
|
||||
if (!($newfilesource = @unserialize($newfile->get_source()))) {
|
||||
$newfilesource = new stdClass();
|
||||
}
|
||||
$newfilesource->original = $source->original;
|
||||
$newfile->set_source(serialize($newfilesource));
|
||||
}
|
||||
// remove temp file
|
||||
$tempfile->delete();
|
||||
return true;
|
||||
@@ -2428,6 +2444,102 @@ abstract class repository {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates a file in draft filearea.
|
||||
*
|
||||
* This function can only update fields filepath, filename, author, license.
|
||||
* If anything (except filepath) is updated, timemodified is set to current time.
|
||||
* If filename or filepath is updated the file unconnects from it's origin
|
||||
* and therefore all references to it will be converted to copies when
|
||||
* filearea is saved.
|
||||
*
|
||||
* @param int $draftid
|
||||
* @param string $filepath path to the directory containing the file, or full path in case of directory
|
||||
* @param string $filename name of the file, or '.' in case of directory
|
||||
* @param array $updatedata array of fields to change (only filename, filepath, license and/or author can be updated)
|
||||
* @throws moodle_exception if for any reason file can not be updated (file does not exist, target already exists, etc.)
|
||||
*/
|
||||
public static function update_draftfile($draftid, $filepath, $filename, $updatedata) {
|
||||
global $USER;
|
||||
$fs = get_file_storage();
|
||||
$usercontext = context_user::instance($USER->id);
|
||||
// make sure filename and filepath are present in $updatedata
|
||||
$updatedata = $updatedata + array('filepath' => $filepath, 'filename' => $filename);
|
||||
$filemodified = false;
|
||||
if (!$file = $fs->get_file($usercontext->id, 'user', 'draft', $draftid, $filepath, $filename)) {
|
||||
if ($filename === '.') {
|
||||
throw new moodle_exception('foldernotfound', 'repository');
|
||||
} else {
|
||||
throw new moodle_exception('filenotfound', 'error');
|
||||
}
|
||||
}
|
||||
if (!$file->is_directory()) {
|
||||
// This is a file
|
||||
if ($updatedata['filepath'] !== $filepath || $updatedata['filename'] !== $filename) {
|
||||
// Rename/move file: check that target file name does not exist.
|
||||
if ($fs->file_exists($usercontext->id, 'user', 'draft', $draftid, $updatedata['filepath'], $updatedata['filename'])) {
|
||||
throw new moodle_exception('fileexists', 'repository');
|
||||
}
|
||||
if (($filesource = @unserialize($file->get_source())) && isset($filesource->original)) {
|
||||
unset($filesource->original);
|
||||
$file->set_source(serialize($filesource));
|
||||
}
|
||||
$file->rename($updatedata['filepath'], $updatedata['filename']);
|
||||
// timemodified is updated only when file is renamed and not updated when file is moved.
|
||||
$filemodified = $filemodified || ($updatedata['filename'] !== $filename);
|
||||
}
|
||||
if (array_key_exists('license', $updatedata) && $updatedata['license'] !== $file->get_license()) {
|
||||
// Update license and timemodified.
|
||||
$file->set_license($updatedata['license']);
|
||||
$filemodified = true;
|
||||
}
|
||||
if (array_key_exists('author', $updatedata) && $updatedata['author'] !== $file->get_author()) {
|
||||
// Update author and timemodified.
|
||||
$file->set_author($updatedata['author']);
|
||||
$filemodified = true;
|
||||
}
|
||||
// Update timemodified:
|
||||
if ($filemodified) {
|
||||
$file->set_timemodified(time());
|
||||
}
|
||||
} else {
|
||||
// This is a directory - only filepath can be updated for a directory (it was moved).
|
||||
if ($updatedata['filepath'] === $filepath) {
|
||||
// nothing to update
|
||||
return;
|
||||
}
|
||||
if ($fs->file_exists($usercontext->id, 'user', 'draft', $draftid, $updatedata['filepath'], '.')) {
|
||||
// bad luck, we can not rename if something already exists there
|
||||
throw new moodle_exception('folderexists', 'repository');
|
||||
}
|
||||
$xfilepath = preg_quote($filepath, '|');
|
||||
if (preg_match("|^$xfilepath|", $updatedata['filepath'])) {
|
||||
// we can not move folder to it's own subfolder
|
||||
throw new moodle_exception('folderrecurse', 'repository');
|
||||
}
|
||||
|
||||
// If directory changed the name, update timemodified.
|
||||
$filemodified = (basename(rtrim($file->get_filepath(), '/')) !== basename(rtrim($updatedata['filepath'], '/')));
|
||||
|
||||
// Now update directory and all children.
|
||||
$files = $fs->get_area_files($usercontext->id, 'user', 'draft', $draftid);
|
||||
foreach ($files as $f) {
|
||||
if (preg_match("|^$xfilepath|", $f->get_filepath())) {
|
||||
$path = preg_replace("|^$xfilepath|", $updatedata['filepath'], $f->get_filepath());
|
||||
if (($filesource = @unserialize($f->get_source())) && isset($filesource->original)) {
|
||||
// unset original so the references are not shown any more
|
||||
unset($filesource->original);
|
||||
$f->set_source(serialize($filesource));
|
||||
}
|
||||
$f->rename($path, $f->get_filename());
|
||||
if ($filemodified && $f->get_filepath() === $updatedata['filepath'] && $f->get_filename() === $filename) {
|
||||
$f->set_timemodified(time());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a temp file from draft area
|
||||
*
|
||||
|
||||
@@ -201,13 +201,14 @@ class repository_upload extends repository {
|
||||
$record->userid = $USER->id;
|
||||
|
||||
if (repository::draftfile_exists($record->itemid, $record->filepath, $record->filename)) {
|
||||
$existingfilename = $record->filename;
|
||||
$unused_filename = repository::get_unused_filename($record->itemid, $record->filepath, $record->filename);
|
||||
$record->filename = $unused_filename;
|
||||
$stored_file = $fs->create_file_from_pathname($record, $_FILES[$elname]['tmp_name']);
|
||||
if ($overwriteexisting) {
|
||||
repository::delete_tempfile_from_draft($record->itemid, $record->filepath, $record->filename);
|
||||
repository::overwrite_existing_draftfile($record->itemid, $record->filepath, $existingfilename, $record->filepath, $record->filename);
|
||||
$record->filename = $existingfilename;
|
||||
} else {
|
||||
$existingfilename = $record->filename;
|
||||
$unused_filename = repository::get_unused_filename($record->itemid, $record->filepath, $record->filename);
|
||||
$record->filename = $unused_filename;
|
||||
$stored_file = $fs->create_file_from_pathname($record, $_FILES[$elname]['tmp_name']);
|
||||
$event = array();
|
||||
$event['event'] = 'fileexists';
|
||||
$event['newfile'] = new stdClass;
|
||||
@@ -221,10 +222,10 @@ class repository_upload extends repository {
|
||||
$event['existingfile']->url = moodle_url::make_draftfile_url($record->itemid, $record->filepath, $existingfilename)->out(false);
|
||||
return $event;
|
||||
}
|
||||
} else {
|
||||
$stored_file = $fs->create_file_from_pathname($record, $_FILES[$elname]['tmp_name']);
|
||||
}
|
||||
|
||||
$stored_file = $fs->create_file_from_pathname($record, $_FILES[$elname]['tmp_name']);
|
||||
|
||||
return array(
|
||||
'url'=>moodle_url::make_draftfile_url($record->itemid, $record->filepath, $record->filename)->out(false),
|
||||
'id'=>$record->itemid,
|
||||
|
||||
Reference in New Issue
Block a user