diff --git a/lib/filebrowser/file_info.php b/lib/filebrowser/file_info.php index e53640b3076..2771e04040f 100644 --- a/lib/filebrowser/file_info.php +++ b/lib/filebrowser/file_info.php @@ -303,15 +303,11 @@ abstract class file_info { /** * Copy content of this file to local storage, overriding current file if needed. * - * @param int $contextid context ID - * @param string $component component - * @param string $filearea file area - * @param int $itemid item ID - * @param string $filepath file path - * @param string $filename file name - * @return boolean success + * @param array|stdClass $filerecord contains contextid, component, filearea, + * itemid, filepath, filename and optionally other attributes of the new file + * @return bool success */ - public function copy_to_storage($contextid, $component, $filearea, $itemid, $filepath, $filename) { + public function copy_to_storage($filerecord) { return false; } diff --git a/lib/filebrowser/file_info_stored.php b/lib/filebrowser/file_info_stored.php index 2f3ea57211a..6eb760ff42b 100644 --- a/lib/filebrowser/file_info_stored.php +++ b/lib/filebrowser/file_info_stored.php @@ -519,25 +519,21 @@ class file_info_stored extends file_info { /** * Copy content of this file to local storage, overriding current file if needed. * - * @param int $contextid context ID - * @param string $component file component - * @param string $filearea file area - * @param int $itemid item ID - * @param string $filepath file path - * @param string $filename file name + * @param array|stdClass $filerecord contains contextid, component, filearea, + * itemid, filepath, filename and optionally other attributes of the new file * @return bool success */ - public function copy_to_storage($contextid, $component, $filearea, $itemid, $filepath, $filename) { + public function copy_to_storage($filerecord) { if (!$this->is_readable() or $this->is_directory()) { return false; } + $filerecord = (array)$filerecord; $fs = get_file_storage(); - if ($existing = $fs->get_file($contextid, $component, $filearea, $itemid, $filepath, $filename)) { + if ($existing = $fs->get_file($filerecord['contextid'], $filerecord['component'], $filerecord['filearea'], $filerecord['itemid'], $filerecord['filepath'], $filerecord['filename'])) { $existing->delete(); } - $file_record = array('contextid'=>$contextid, 'component'=>$component, 'filearea'=>$filearea, 'itemid'=>$itemid, 'filepath'=>$filepath, 'filename'=>$filename); - $fs->create_file_from_storedfile($file_record, $this->lf); + $fs->create_file_from_storedfile($filerecord, $this->lf); return true; } diff --git a/repository/lib.php b/repository/lib.php index 3abca8d9a75..5f72bafe676 100644 --- a/repository/lib.php +++ b/repository/lib.php @@ -648,13 +648,14 @@ abstract class repository { * This function is used to copy a moodle file to draft area * * @param string $encoded The metainfo of file, it is base64 encoded php serialized data - * @param int $draftitemid itemid - * @param string $new_filepath the new path in draft area - * @param string $new_filename The intended name of file + * @param stdClass|array $filerecord contains itemid, filepath, filename and optionally other + * attributes of the new file + * @param int $maxbytes maximum allowed size of file, -1 if unlimited. If size of file exceeds + * the limit, the file_exception is thrown. * @return array The information of file */ - public function copy_to_area($encoded, $draftitemid, $new_filepath, $new_filename) { - global $USER, $DB; + public function copy_to_area($encoded, $filerecord, $maxbytes = -1) { + global $USER; $fs = get_file_storage(); $browser = get_file_browser(); @@ -662,9 +663,17 @@ abstract class repository { throw new coding_exception('Only repository used to browse moodle files can use repository::copy_to_area()'); } - $params = unserialize(base64_decode($encoded)); - $user_context = get_context_instance(CONTEXT_USER, $USER->id); + $user_context = context_user::instance($USER->id); + + $filerecord = (array)$filerecord; + // make sure the new file will be created in user draft area + $filerecord['component'] = 'user'; + $filerecord['filearea'] = 'draft'; + $filerecord['contextid'] = $user_context->id; + $draftitemid = $filerecord['itemid']; + $new_filepath = $filerecord['filepath']; + $new_filename = $filerecord['filename']; $contextid = clean_param($params['contextid'], PARAM_INT); $fileitemid = clean_param($params['itemid'], PARAM_INT); @@ -676,11 +685,15 @@ abstract class repository { $context = get_context_instance_by_id($contextid); // the file needs to copied to draft area $file_info = $browser->get_file_info($context, $component, $filearea, $fileitemid, $filepath, $filename); + if ($maxbytes !== -1 && $file_info->get_filesize() > $maxbytes) { + throw new file_exception('maxbytes'); + } if (repository::draftfile_exists($draftitemid, $new_filepath, $new_filename)) { // create new file $unused_filename = repository::get_unused_filename($draftitemid, $new_filepath, $new_filename); - $file_info->copy_to_storage($user_context->id, 'user', 'draft', $draftitemid, $new_filepath, $unused_filename); + $filerecord['filename'] = $unused_filename; + $file_info->copy_to_storage($filerecord); $event = array(); $event['event'] = 'fileexists'; $event['newfile'] = new stdClass; @@ -690,12 +703,13 @@ abstract class repository { $event['existingfile'] = new stdClass; $event['existingfile']->filepath = $new_filepath; $event['existingfile']->filename = $new_filename; - $event['existingfile']->url = moodle_url::make_draftfile_url($draftitemid, $filepath, $filename)->out();; + $event['existingfile']->url = moodle_url::make_draftfile_url($draftitemid, $new_filepath, $new_filename)->out();; return $event; } else { - $file_info->copy_to_storage($user_context->id, 'user', 'draft', $draftitemid, $new_filepath, $new_filename); + $file_info->copy_to_storage($filerecord); $info = array(); $info['itemid'] = $draftitemid; + $info['file'] = $new_filename; $info['title'] = $new_filename; $info['contextid'] = $user_context->id; $info['url'] = moodle_url::make_draftfile_url($draftitemid, $new_filepath, $new_filename)->out();; @@ -1464,6 +1478,7 @@ abstract class repository { * @return int file size in bytes */ public function get_file_size($source) { + // TODO MDL-33297 remove this function completely? $browser = get_file_browser(); $params = unserialize(base64_decode($source)); $contextid = clean_param($params['contextid'], PARAM_INT); diff --git a/repository/recent/lib.php b/repository/recent/lib.php index a491015235e..2c1acf23579 100644 --- a/repository/recent/lib.php +++ b/repository/recent/lib.php @@ -180,19 +180,28 @@ class repository_recent extends repository { /** * This function overwrite the default implement to copying file using file_storage * - * @global object $USER - * @global object $DB * @param string $encoded The information of file, it is base64 encoded php serialized data - * @param string $draftitemid itemid - * @param string $new_filename The intended name of file - * @param string $new_filepath the new path in draft area + * @param stdClass|array $filerecord contains itemid, filepath, filename and optionally other + * attributes of the new file + * @param int $maxbytes maximum allowed size of file, -1 if unlimited. If size of file exceeds + * the limit, the file_exception is thrown. * @return array The information of file */ - public function copy_to_area($encoded, $draftitemid, $new_filepath, $new_filename) { - global $USER, $DB; + public function copy_to_area($encoded, $filerecord, $maxbytes = -1) { + global $USER; $user_context = get_context_instance(CONTEXT_USER, $USER->id); + $filerecord = (array)$filerecord; + // make sure the new file will be created in user draft area + $filerecord['component'] = 'user'; // make sure + $filerecord['filearea'] = 'draft'; // make sure + $filerecord['contextid'] = $user_context->id; + $filerecord['sortorder'] = 0; + $draftitemid = $filerecord['itemid']; + $new_filepath = $filerecord['filepath']; + $new_filename = $filerecord['filename']; + $fs = get_file_storage(); $params = unserialize(base64_decode($encoded)); @@ -211,21 +220,23 @@ class repository_recent extends repository { // // To get 'recent' plugin working, we need to use lower level file_stoarge class to bypass the // capability check, we will use a better workaround to improve it. + // TODO MDL-33297 apply here if ($stored_file = $fs->get_file($contextid, $component, $filearea, $fileitemid, $filepath, $filename)) { // verify user id if ($USER->id != $stored_file->get_userid()) { throw new moodle_exception('errornotyourfile', 'repository'); } - $file_record = array('contextid'=>$user_context->id, 'component'=>'user', 'filearea'=>'draft', - 'itemid'=>$draftitemid, 'filepath'=>$new_filepath, 'filename'=>$new_filename, 'sortorder'=>0); + if ($maxbytes !== -1 && $stored_file->get_filesize() > $maxbytes) { + throw new file_exception('maxbytes'); + } // test if file already exists if (repository::draftfile_exists($draftitemid, $new_filepath, $new_filename)) { // create new file $unused_filename = repository::get_unused_filename($draftitemid, $new_filepath, $new_filename); - $file_record['filename'] = $unused_filename; + $filerecord['filename'] = $unused_filename; // create a tmp file - $fs->create_file_from_storedfile($file_record, $stored_file); + $fs->create_file_from_storedfile($filerecord, $stored_file); $event = array(); $event['event'] = 'fileexists'; $event['newfile'] = new stdClass; @@ -238,9 +249,10 @@ class repository_recent extends repository { $event['existingfile']->url = moodle_url::make_draftfile_url($draftitemid, $new_filepath, $new_filename)->out();; return $event; } else { - $fs->create_file_from_storedfile($file_record, $stored_file); + $fs->create_file_from_storedfile($filerecord, $stored_file); $info = array(); $info['title'] = $new_filename; + $info['file'] = $new_filename; $info['itemid'] = $draftitemid; $info['filesize'] = $stored_file->get_filesize(); $info['url'] = moodle_url::make_draftfile_url($draftitemid, $new_filepath, $new_filename)->out();; diff --git a/repository/repository_ajax.php b/repository/repository_ajax.php index aa1e434d36e..cb7dea85908 100644 --- a/repository/repository_ajax.php +++ b/repository/repository_ajax.php @@ -209,30 +209,6 @@ switch ($action) { die; } else { $fs = get_file_storage(); - // Some repository plugins are hosting moodle internal files, we cannot use get_file - // method, so we use copy_to_area method - // (local, user, coursefiles, recent) - if ($repo->has_moodle_files() && !$usefilereference) { - // check filesize against max allowed size - $filesize = $repo->get_file_size($source); - if (empty($filesize)) { - $filesize = 0; - } - if (($maxbytes !== -1) && ($filesize > $maxbytes)) { - throw new file_exception('maxbytes'); - } - // If the moodle file is an alias to a file in external repository - // we copy this alias instead of create alias to alias - // {@link repository::copy_to_area()}. - $fileinfo = $repo->copy_to_area($source, $itemid, $saveas_path, $saveas_filename); - - if (!isset($fileinfo['event'])) { - $fileinfo['file'] = $fileinfo['title']; - } - - echo json_encode($fileinfo); - die; - } // Prepare file record. $record = new stdClass(); @@ -240,21 +216,9 @@ switch ($action) { $record->filename = $saveas_filename; $record->component = 'user'; $record->filearea = 'draft'; - if (!is_numeric($itemid)) { - $record->itemid = 0; - } else { - $record->itemid = $itemid; - } - if (!empty($file['license'])) { - $record->license = $file['license']; - } else { - $record->license = $license; - } - if (!empty($file['author'])) { - $record->author = $file['author']; - } else { - $record->author = $author; - } + $record->itemid = $itemid; + $record->license = $license; + $record->author = $author; if ($record->filepath !== '/') { $record->filepath = trim($record->filepath, '/'); @@ -263,10 +227,9 @@ switch ($action) { $usercontext = get_context_instance(CONTEXT_USER, $USER->id); $now = time(); $record->contextid = $usercontext->id; - $record->timecreated = $now; + $record->timecreated = $now; $record->timemodified = $now; - $record->userid = $USER->id; - + $record->userid = $USER->id; if ($usefilereference) { $reference = $repo->get_file_reference($source); @@ -307,6 +270,16 @@ switch ($action) { ); echo json_encode($info); die; + } else if ($repo->has_moodle_files()) { + // Some repository plugins (local, user, coursefiles, recent) are hosting moodle + // internal files, we cannot use get_file method, so we use copy_to_area method + + // If the moodle file is an alias we copy this alias, otherwise we copy the file + // {@link repository::copy_to_area()}. + $fileinfo = $repo->copy_to_area($source, $record, $maxbytes); + + echo json_encode($fileinfo); + die; } else { // Download file to moodle. $downloadedfile = $repo->get_file($source, $saveas_filename);