MDL-39177 File reference is not updated when overwriting the file
authorMarina Glancy <marina@moodle.com>
Wed, 8 May 2013 02:48:54 +0000 (12:48 +1000)
committerMarina Glancy <marina@moodle.com>
Tue, 14 May 2013 07:07:53 +0000 (17:07 +1000)
lang/en/repository.php
lib/filelib.php
lib/filestorage/stored_file.php
repository/lib.php

index f3f5fbc..be7cdc1 100644 (file)
@@ -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.';
index fb81ddd..9bf64a4 100644 (file)
@@ -828,9 +828,14 @@ function file_save_draft_area_files($draftitemid, $contextid, $component, $filea
                 $oldfile->set_timemodified($newfile->get_timemodified());
             }
 
+            if ($newfile->is_external_file() && !$allowreferences) {
+                continue;
+            }
             // Replaced file content
-            if ($oldfile->get_contenthash() != $newfile->get_contenthash() || $oldfile->get_filesize() != $newfile->get_filesize()) {
-                $oldfile->replace_content_with($newfile);
+            else if ($oldfile->get_contenthash() != $newfile->get_contenthash() ||
+                    $oldfile->get_filesize() != $newfile->get_filesize() ||
+                    $oldfile->get_referencefileid() != $newfile->get_referencefileid()) {
+                $oldfile->replace_file_with($newfile);
                 // push changes to all local files that are referencing this file
                 $fs->update_references_to_storedfile($oldfile);
             }
index fee7bfa..d78aac1 100644 (file)
@@ -210,6 +210,36 @@ 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
+     *
+     * Note that field source must be updated separately
+     *
+     * @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();
+        $this->update($filerecord);
+    }
+
     /**
      * Unlink the stored file from the referenced file
      *
index 1d89307..a1c3860 100644 (file)
@@ -2410,6 +2410,13 @@ abstract class repository {
         $user_context = get_context_instance(CONTEXT_USER, $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)) {
+                if ($tempfile->is_external_file()) {
+                    // New file is a reference. Check that existing file does not have any other files referencing to it
+                    $source = @unserialize($file->get_source());
+                    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