diff --git a/lang/en/error.php b/lang/en/error.php index 371cf469fd3..b40859b4e18 100644 --- a/lang/en/error.php +++ b/lang/en/error.php @@ -324,6 +324,7 @@ $string['invalidsection'] = 'Course module record contains invalid section'; $string['invalidsesskey'] = 'Incorrect sesskey submitted, form not accepted!'; $string['invalidshortname'] = 'That\'s an invalid short course name'; $string['invalidstatedetected'] = 'Something has gone wrong: {$a}. This should never normally happen.'; +$string['invalidsourcefield'] = 'Draft file\'s source field is invalid'; $string['invalidurl'] = 'Invalid URL'; $string['invaliduser'] = 'Invalid user'; $string['invaliduserid'] = 'Invalid user id'; diff --git a/lib/filelib.php b/lib/filelib.php index 11cba0fac86..8d8faf4db96 100644 --- a/lib/filelib.php +++ b/lib/filelib.php @@ -375,7 +375,7 @@ function file_prepare_draft_area(&$draftitemid, $contextid, $component, $fileare continue; } $draftfile = $fs->create_file_from_storedfile($file_record, $file); - // XXX: This is a hack for file manager + // XXX: This is a hack for file manager (MDL-28666) // File manager needs to know the original file information before copying // to draft area, so we append these information in mdl_files.source field // {@link file_storage::search_references()} @@ -679,9 +679,13 @@ function file_get_submitted_draft_itemid($elname) { */ function file_restore_source_field_from_draft_file($storedfile) { $source = unserialize($storedfile->get_source()); - if (!empty($source) && is_object($source)) { - $restoredsource = $source->source; - $storedfile->set_source($restoredsource); + if (!empty($source)) { + if (is_object($source)) { + $restoredsource = $source->source; + $storedfile->set_source($restoredsource); + } else { + throw new moodle_exception('invalidsourcefield', 'error'); + } } return $storedfile; } @@ -813,6 +817,11 @@ function file_save_draft_area_files($draftitemid, $contextid, $component, $filea $oldfile->set_sortorder($newfile->get_sortorder()); } + // Update file size + if ($oldfile->get_filesize() != $newfile->get_filesize()) { + $oldfile->set_filesize($newfile->get_filesize()); + } + // unchanged file or directory - we keep it as is unset($newhashes[$oldhash]); if (!$oldfile->is_directory()) { diff --git a/lib/filestorage/stored_file.php b/lib/filestorage/stored_file.php index f20a528700b..5141c61caa2 100644 --- a/lib/filestorage/stored_file.php +++ b/lib/filestorage/stored_file.php @@ -191,15 +191,27 @@ class stored_file { */ public function delete_reference() { global $DB; + // Remove repository info. $this->repository = null; + + // Remove reference info from DB. + $DB->delete_records('files_reference', array('id'=>$this->file_record->referencefileid)); + + // Must refresh $this->file_record form DB + $filerecord = $DB->get_record('files', array('id'=>$this->get_id())); + // Update DB + $filerecord->referencelastsync = null; + $filerecord->referencelifetime = null; + $filerecord->referencefileid = null; + $this->update($filerecord); + + // unset object variable unset($this->file_record->repositoryid); unset($this->file_record->reference); unset($this->file_record->referencelastsync); unset($this->file_record->referencelifetime); - - // Remove reference info from DB. - $DB->delete_records('files_reference', array('id'=>$this->file_record->referencefileid)); + unset($this->file_record->referencefileid); } /** @@ -560,6 +572,17 @@ class stored_file { return $this->file_record->filesize; } + /** + * Returns the size of file in bytes. + * + * @param int $filesize bytes + */ + public function set_filesize($filesize) { + $filerecord = new stdClass; + $filerecord->filesize = $filesize; + $this->update($filerecord); + } + /** * Returns mime type of file. * diff --git a/lib/filestorage/tests/file_storage_test.php b/lib/filestorage/tests/file_storage_test.php index 9685e3f401a..5f70959c17d 100644 --- a/lib/filestorage/tests/file_storage_test.php +++ b/lib/filestorage/tests/file_storage_test.php @@ -109,15 +109,17 @@ class filestoragelib_testcase extends advanced_testcase { $contenthash = $originalfile->get_contenthash(); $newpath = '/test/'; $newname = 'newtest.txt'; - // try break it - $this->setExpectedException('file_exception'); - // this shall throw exception - $originalfile->rename($filepath, $filename); + // this should work $originalfile->rename($newpath, $newname); $file = $fs->get_file($syscontext->id, $component, $filearea, $itemid, $newpath, $newname); $this->assertInstanceOf('stored_file', $file); $this->assertEquals($contenthash, $file->get_contenthash()); + + // try break it + $this->setExpectedException('file_exception'); + // this shall throw exception + $originalfile->rename($newpath, $newname); } /** diff --git a/lib/tests/filelib_test.php b/lib/tests/filelib_test.php index 9a419de243a..ee743e8055e 100644 --- a/lib/tests/filelib_test.php +++ b/lib/tests/filelib_test.php @@ -195,4 +195,78 @@ class filelib_testcase extends advanced_testcase { $this->assertEquals($license, $file->get_license()); $this->assertEquals($newsourcefield, $file->get_source()); } + + /** + * Testing deleting original files + * + * @copyright 2012 Dongsheng Cai {@link http://dongsheng.org} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + public function test_delete_original_file_from_draft() { + global $USER, $DB; + + $this->resetAfterTest(true); + + $generator = $this->getDataGenerator(); + $user = $generator->create_user(); + $usercontext = context_user::instance($user->id); + $USER = $DB->get_record('user', array('id'=>$user->id)); + + $repositorypluginname = 'user'; + + $args = array(); + $args['type'] = $repositorypluginname; + $repos = repository::get_instances($args); + $userrepository = reset($repos); + $this->assertInstanceOf('repository', $userrepository); + + $fs = get_file_storage(); + $syscontext = context_system::instance(); + + $filecontent = 'User file content'; + + // create a user private file + $userfilerecord = new stdClass; + $userfilerecord->contextid = $usercontext->id; + $userfilerecord->component = 'user'; + $userfilerecord->filearea = 'private'; + $userfilerecord->itemid = 0; + $userfilerecord->filepath = '/'; + $userfilerecord->filename = 'userfile.txt'; + $userfilerecord->source = 'test'; + $userfile = $fs->create_file_from_string($userfilerecord, $filecontent); + $userfileref = $fs->pack_reference($userfilerecord); + $contenthash = $userfile->get_contenthash(); + + $filerecord = array( + 'contextid' => $syscontext->id, + 'component' => 'core', + 'filearea' => 'phpunit', + 'itemid' => 0, + 'filepath' => '/', + 'filename' => 'test.txt', + ); + // create a file reference + $fileref = $fs->create_file_from_reference($filerecord, $userrepository->id, $userfileref); + $this->assertInstanceOf('stored_file', $fileref); + $this->assertEquals($userrepository->id, $fileref->repository->id); + $this->assertEquals($userfile->get_contenthash(), $fileref->get_contenthash()); + $this->assertEquals($userfile->get_filesize(), $fileref->get_filesize()); + $this->assertRegExp('#' . $userfile->get_filename(). '$#', $fileref->get_reference_details()); + + $draftitemid = 0; + file_prepare_draft_area($draftitemid, $usercontext->id, 'user', 'private', 0); + $draftfiles = $fs->get_area_files($usercontext->id, 'user', 'draft', $draftitemid); + $this->assertEquals(2, count($draftfiles)); + $draftfile = $fs->get_file($usercontext->id, 'user', 'draft', $draftitemid, $userfilerecord->filepath, $userfilerecord->filename); + $draftfile->delete(); + // Save changed file + file_save_draft_area_files($draftitemid, $usercontext->id, 'user', 'private', 0); + + // The file reference should be a regular moodle file now + $fileref = $fs->get_file($syscontext->id, 'core', 'phpunit', 0, '/', 'test.txt'); + $this->assertEquals(false, $fileref->is_external_file()); + $this->assertEquals($contenthash, $fileref->get_contenthash()); + $this->assertEquals($filecontent, $fileref->get_content()); + } } diff --git a/repository/coursefiles/lib.php b/repository/coursefiles/lib.php index 06d75f689da..64fb1a0c60a 100644 --- a/repository/coursefiles/lib.php +++ b/repository/coursefiles/lib.php @@ -279,6 +279,17 @@ class repository_coursefiles extends repository { return $coursename . ': ' . $params['filepath'] . $params['filename']; } + /** + * Return reference file life time + * + * @param string $ref + * @return int + */ + public function get_reference_file_lifetime($ref) { + // this should be realtime + return 0; + } + /** * Repository method to serve file * diff --git a/repository/googledocs/lib.php b/repository/googledocs/lib.php index 833eee953b5..36648bdb81e 100644 --- a/repository/googledocs/lib.php +++ b/repository/googledocs/lib.php @@ -19,7 +19,7 @@ * * @since 2.0 * @package repository_googledocs - * @copyright 2010 Dongsheng Cai {@link http://dongsheng.org} + * @copyright 2009 Dan Poltawski * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ require_once($CFG->dirroot . '/repository/lib.php'); diff --git a/repository/lib.php b/repository/lib.php index 9cea0f8eb39..20849b0eef5 100644 --- a/repository/lib.php +++ b/repository/lib.php @@ -1066,6 +1066,7 @@ abstract class repository { * @param array $options additional options affecting the file serving */ public function send_file($storedfile, $lifetime=86400 , $filter=0, $forcedownload=false, array $options = null) { + throw new coding_exception("Repository plugin must implement send_file() method."); } /** diff --git a/repository/picasa/lib.php b/repository/picasa/lib.php index c1cbc3ef8cb..6a83ca08238 100644 --- a/repository/picasa/lib.php +++ b/repository/picasa/lib.php @@ -19,7 +19,7 @@ * * @since 2.0 * @package repository_picasa - * @copyright 2010 Dongsheng Cai {@link http://dongsheng.org} + * @copyright 2009 Dan Poltawski * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ require_once($CFG->dirroot . '/repository/lib.php'); diff --git a/repository/user/lib.php b/repository/user/lib.php index 80dc94b6667..9d0537a8a27 100644 --- a/repository/user/lib.php +++ b/repository/user/lib.php @@ -225,6 +225,17 @@ class repository_user extends repository { return $this->get_name() . ': ' . $params['filepath'] . $params['filename']; } + /** + * Return reference file life time + * + * @param string $ref + * @return int + */ + public function get_reference_file_lifetime($ref) { + // this should be realtime + return 0; + } + /** * Repository method to serve file *