Skip to content

Commit

Permalink
MDL-39177 Discard file origin when moving/renaming a file in filemanager
Browse files Browse the repository at this point in the history
Created one function that handles file update to be used from both JS and nonJS filepicker
  • Loading branch information
marinaglancy authored and stronk7 committed May 22, 2013
1 parent d262212 commit 6c43ee5
Show file tree
Hide file tree
Showing 4 changed files with 115 additions and 91 deletions.
2 changes: 1 addition & 1 deletion lang/en/repository.php
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@
$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['help'] = 'Help';
Expand Down
89 changes: 16 additions & 73 deletions repository/draftfiles_ajax.php
Original file line number Diff line number Diff line change
Expand Up @@ -125,90 +125,33 @@
// 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)));
}
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());
try {
repository::update_draftfile($draftid, $filepath, '.', array('filepath' => $newfilepath));
} catch (moodle_exception $e) {
die(json_encode((object)array('error' => $e->getMessage())));
}

$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);
Expand Down
19 changes: 2 additions & 17 deletions repository/draftfiles_manager.php
Original file line number Diff line number Diff line change
Expand Up @@ -122,14 +122,7 @@
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);
Expand Down Expand Up @@ -194,15 +187,7 @@

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);
Expand Down
96 changes: 96 additions & 0 deletions repository/lib.php
Original file line number Diff line number Diff line change
Expand Up @@ -2574,6 +2574,102 @@ public static function overwrite_existing_draftfile($itemid, $filepath, $filenam
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
*
Expand Down

0 comments on commit 6c43ee5

Please sign in to comment.