Skip to content

Commit

Permalink
MDL-31901: Updating/moving files in FileManager
Browse files Browse the repository at this point in the history
- added new functions to the backend (repository/draftfiles_ajax.php) to allow changing of file name, location, license and author in one request
- enabled changing file properties using JS UI (lib/form/filemanager.js)
  • Loading branch information
marinaglancy committed May 21, 2012
1 parent 694beb5 commit c092681
Show file tree
Hide file tree
Showing 4 changed files with 163 additions and 69 deletions.
3 changes: 3 additions & 0 deletions lang/en/repository.php
Expand Up @@ -107,6 +107,9 @@
$string['filesaved'] = 'The file has been saved';
$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['getfile'] = 'Select this file';
$string['hidden'] = 'Hidden';
$string['choosealink'] = 'Choose a link...';
Expand Down
19 changes: 19 additions & 0 deletions lib/filestorage/stored_file.php
Expand Up @@ -196,6 +196,25 @@ public function delete_reference() {
$DB->delete_records('files_reference', array('id'=>$this->file_record->referencefileid));
}

/**
* Update some file record fields
*
* @param stdClass $dataobject
*/
public function update($dataobject) {
// TODO MDL-28666 THIS FUNCTION IS COPIED FROM UNFINISHED CODE OF MDL-28666.
global $DB;
$keys = array_keys((array)$this->file_record);
foreach ($dataobject as $field => $value) {
if (in_array($field, $keys)) {
$this->file_record->$field = $value;
} else {
throw new coding_exception("Invalid field name, $field doesn't exist in file record");
}
}
$DB->update_record('files', $this->file_record);
}

/**
* Is this a directory?
*
Expand Down
107 changes: 44 additions & 63 deletions lib/form/filemanager.js
Expand Up @@ -417,11 +417,11 @@ M.form_filemanager.init = function(Y, options) {
node.highlight(false);
node.origlist = obj.list?obj.list:null;
node.origpath = obj.path?obj.path:null;
node.origcurrentpath = node.path?node.path:'/';
node.children = [];
for(k in list) {
if (list[k].type == 'folder' && retrieved_children[list[k].filepath]) {
// if this child is a folder and has already been retrieved
retrieved_children[list[k].filepath].fileinfo = list[k];
node.children[node.children.length] = retrieved_children[list[k].filepath];
} else {
// append new file to the list
Expand Down Expand Up @@ -491,7 +491,7 @@ M.form_filemanager.init = function(Y, options) {
// save current path and filelist (in case we want to jump to other viewmode)
this.options.path = e.node.origpath;
this.options.list = e.node.origlist;
this.currentpath = e.node.origcurrentpath;
this.currentpath = e.node.path;
this.print_path();
//this.content_scrolled();
}
Expand Down Expand Up @@ -533,82 +533,64 @@ M.form_filemanager.init = function(Y, options) {
var selectnode = this.filemanager.one('.fp-select');
var fileinfo = this.selectui.fileinfo;

var newfilename = selectnode.one('.fp-saveas input').get('value');
var newfilename = Y.Lang.trim(selectnode.one('.fp-saveas input').get('value'));
var filenamechanged = (newfilename && newfilename != fileinfo.fullname);
var pathselect = selectnode.one('.fp-path select'),
pathindex = pathselect.get('selectedIndex'),
targetpath = pathselect.get("options").item(pathindex).get('value');
var filepathchanged = (targetpath != this.get_parent_folder_name(fileinfo));
var newauthor = Y.Lang.trim(selectnode.one('.fp-author input').get('value'));
var authorchanged = (newauthor != Y.Lang.trim(fileinfo.author));
var licenseselect = selectnode.one('.fp-license select'),
licenseindex = licenseselect.get('selectedIndex'),
newlicense = licenseselect.get("options").item(licenseindex).get('value');
var licensechanged = (newlicense != fileinfo.license);

if (filenamechanged && filepathchanged) {
alert('Sorry, simultaneous changing of name and path is not supported yet'); // TODO
return;
var params, action;
if (fileinfo.type == 'folder') {
if (!newfilename) {
this.print_msg(M.str.repository.entername, 'error');
return;
}
if (filenamechanged || filepathchanged) {
params = {filepath:fileinfo.filepath, newdirname:newfilename, newfilepath:targetpath};
action = 'updatedir';
}
} else {
if (!newfilename) {
this.print_msg(M.str.repository.enternewname, 'error');
return;
}
if (filenamechanged || filepathchanged || licensechanged || authorchanged) {
params = {filepath:fileinfo.filepath, filename:fileinfo.fullname,
newfilename:newfilename, newfilepath:targetpath,
newlicense:newlicense, newauthor:newauthor};
action = 'updatefile';
}
}
if (!filenamechanged && !filepathchanged) {
if (!action) {
// no changes
this.selectui.hide();
return;
}

selectnode.addClass('loading');

// RENAME
if (filenamechanged) {
var action = '';
var params = {};
if (fileinfo.type == 'folder') {
params['filepath'] = fileinfo.filepath;
params['filename'] = '.';
params['newdirname'] = newfilename;
action = 'renamedir';
} else {
params['filepath'] = fileinfo.filepath;
params['filename'] = fileinfo.fullname;
params['newfilename'] = newfilename;
action = 'rename';
}
this.request({
action: action,
scope: this,
params: params,
callback: function(id, obj, args) {
if (obj == false) {
selectnode.removeClass('loading');
args.scope.print_msg(M.str.repository.fileexists, 'error');
} else {
args.scope.selectui.hide();
args.scope.refresh(obj.filepath);
if (typeof M.core_formchangechecker != 'undefined') {
M.core_formchangechecker.set_form_changed();
}
}
}
});
}

// MOVE
if (filepathchanged) {
var params = {};
if (fileinfo.type == 'folder') {
action = 'movedir';
} else {
action = 'movefile';
}
params['filepath'] = fileinfo.filepath;
params['filename'] = fileinfo.fullname;
params['newfilepath'] = targetpath;
this.request({
action: action,
scope: this,
params: params,
callback: function(id, obj, args) {
this.request({
action: action,
scope: this,
params: params,
callback: function(id, obj, args) {
if (obj.error) {
selectnode.removeClass('loading');
args.scope.print_msg(obj.error, 'error');
} else {
args.scope.selectui.hide();
args.scope.refresh((obj && obj.filepath) ? obj.filepath : '/');
if (typeof M.core_formchangechecker != 'undefined') {
M.core_formchangechecker.set_form_changed();
}
}
});
}
}
});
},
setup_select_file: function() {
var selectnode = this.filemanager.one('.fp-select');
Expand Down Expand Up @@ -742,8 +724,7 @@ M.form_filemanager.init = function(Y, options) {
selectnode.all('.fp-path select option').each(function(el){
if (el.get('value') == foldername) {el.set('selected', true);}
});
selectnode.all('.fp-author input').set('disabled','disabled'); //TODO
selectnode.all('.fp-license select').set('disabled','disabled'); //TODO
selectnode.all('.fp-author input, .fp-license select').set('disabled',(node.type == 'folder')?'disabled':'');
// display static information about a file (when known)
var attrs = ['datemodified','datecreated','size','dimensions'];
for (var i in attrs) {
Expand Down
103 changes: 97 additions & 6 deletions repository/draftfiles_ajax.php
Expand Up @@ -76,8 +76,6 @@
$fs->create_directory($user_context->id, 'user', 'draft', $draftid, file_correct_filepath(file_correct_filepath($filepath).$newdirname));
$return = new stdClass();
$return->filepath = $filepath;
$return->tree = new stdClass();
file_get_drafarea_folders($draftid, '/', $return->tree);
echo json_encode($return);
die;

Expand Down Expand Up @@ -123,7 +121,54 @@
echo json_encode($return);
die;

case 'updatefile':
// 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]);
}
}

if (!empty($updatedata)) {
$updatedata['timemodified'] = $file->get_timemodified();
$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
$updatedata['timemodified'] = time();
}
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'))));
}
try {
$newfile = $fs->create_file_from_storedfile($updatedata, $file);
} catch (Exception $e) {
die(json_encode((object)array('error' => $e->getMessage())));
}
$file->delete();
} else {
$file->update((object)$updatedata);
}
}

die(json_encode((object)array('filepath' => $newfilepath)));

case 'rename':
// TODO deprecate this, use 'updatefile' instead
$filename = required_param('filename', PARAM_FILE);
$filepath = required_param('filepath', PARAM_PATH);
$newfilename = required_param('newfilename', PARAM_FILE);
Expand All @@ -143,8 +188,57 @@
}
die;

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);
//we must update directory and all children too
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 ($newfilepath !== $filepath && preg_match("|^$xfilepath|", $parent)) {
// we can not move folder to it's own subfolder
die(json_encode((object)array('error' => get_string('folderrecurse', 'repository'))));
}

$files = $fs->get_area_files($user_context->id, 'user', 'draft', $draftid);
$moved = array();
foreach ($files as $file) {
if (!preg_match("|^$xfilepath|", $file->get_filepath())) {
continue;
}
// move one by one
$path = preg_replace("|^$xfilepath|", $newfilepath, $file->get_filepath());
$updatedata = array('filepath' => $path, 'timemodified' => $file->get_timemodified());
if ($dirname !== $newdirname && $file->get_filepath() === $filepath) {
// this is the main directory we move/rename AND it has actually been renamed
$updatedata['timemodified'] = time();
}
$fs->create_file_from_storedfile($updatedata, $file);
$moved[] = $file;
}
foreach ($moved as $file) {
// delete all old
$file->delete();
}

$return = new stdClass();
$return->filepath = $parent;
echo json_encode($return);
die;

case 'renamedir':
case 'movedir':
// TODO deprecate this, use 'renamemovedir' instead

$filepath = required_param('filepath', PARAM_PATH);
$fs = get_file_storage();
Expand Down Expand Up @@ -195,12 +289,11 @@
} else {
$return->filepath = $newfilepath;
}
$return->tree = new stdClass();
file_get_drafarea_folders($draftid, '/', $return->tree);
echo json_encode($return);
die;

case 'movefile':
// TODO deprecate this, use 'updatefile' instead
$filename = required_param('filename', PARAM_FILE);
$filepath = required_param('filepath', PARAM_PATH);
$newfilepath = required_param('newfilepath', PARAM_PATH);
Expand Down Expand Up @@ -284,8 +377,6 @@
if ($newfile = $file->extract_to_storage($zipper, $user_context->id, 'user', 'draft', $draftid, $filepath, $USER->id)) {
$return = new stdClass();
$return->filepath = $filepath;
$return->tree = new stdClass();
file_get_drafarea_folders($draftid, '/', $return->tree);
echo json_encode($return);
} else {
echo json_encode(false);
Expand Down

0 comments on commit c092681

Please sign in to comment.