Permalink
Browse files

MDL-34290 update all references after the source is changed

- When several records in {files} have the same record in {files_reference} and the synchronisation is performed, we need to update
all records in {files} so all files know if source is changed and that sync was performed;
- also when local moodle file content is changed we immediately update all files referencing to it (therefore sync of references
to the local files is unnecessary);
  • Loading branch information...
marinaglancy committed Jul 31, 2012
1 parent 2e0b5fe commit 26aaa7e8357507bea997fe09e9f5e52c90123a24
Showing with 103 additions and 28 deletions.
  1. +7 −9 lib/filelib.php
  2. +69 −0 lib/filestorage/file_storage.php
  3. +27 −19 lib/filestorage/stored_file.php
View
@@ -804,10 +804,6 @@ function file_save_draft_area_files($draftitemid, $contextid, $component, $filea
continue;
}
- // Replaced file content
- if ($oldfile->get_contenthash() != $newfile->get_contenthash()) {
- $oldfile->replace_content_with($newfile);
- }
// Updated author
if ($oldfile->get_author() != $newfile->get_author()) {
$oldfile->set_author($newfile->get_author());
@@ -827,16 +823,18 @@ 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());
- }
-
// Update file timemodified
if ($oldfile->get_timemodified() != $newfile->get_timemodified()) {
$oldfile->set_timemodified($newfile->get_timemodified());
}
+ // Replaced file content
+ if ($oldfile->get_contenthash() != $newfile->get_contenthash() || $oldfile->get_filesize() != $newfile->get_filesize()) {
+ $oldfile->replace_content_with($newfile);
+ // push changes to all local files that are referencing this file
+ $fs->update_references_to_storedfile($this);
+ }
+
// unchanged file or directory - we keep it as is
unset($newhashes[$oldhash]);
if (!$oldfile->is_directory()) {
@@ -1805,6 +1805,39 @@ public function get_references_count_by_storedfile(stored_file $storedfile) {
return $this->search_references_count(self::pack_reference($params));
}
+ /**
+ * Updates all files that are referencing this file with the new contenthash
+ * and filesize
+ *
+ * @param stored_file $storedfile
+ */
+ public function update_references_to_storedfile(stored_file $storedfile) {
+ global $CFG;
+ $params = array();
+ $params['contextid'] = $storedfile->get_contextid();
+ $params['component'] = $storedfile->get_component();
+ $params['filearea'] = $storedfile->get_filearea();
+ $params['itemid'] = $storedfile->get_itemid();
+ $params['filename'] = $storedfile->get_filename();
+ $params['filepath'] = $storedfile->get_filepath();
+ $reference = self::pack_reference($params);
+ $referencehash = sha1($reference);
+
+ $sql = "SELECT repositoryid, id FROM {files_reference}
+ WHERE referencehash = ? and reference = ?";
+ $rs = $DB->get_recordset_sql($sql, array($referencehash, $reference));
+
+ $now = time();
+ foreach ($rs as $record) {
+ require_once($CFG->dirroot.'/repository/lib.php');
+ $repo = repository::get_instance($record->repositoryid);
+ $lifetime = $repo->get_reference_file_lifetime($reference);
+ $this->update_references($record->id, $now, $lifetime,
+ $storedfile->get_contenthash(), $storedfile->get_filesize(), 0);
+ }
+ $rs->close();
+ }
+
/**
* Convert file alias to local file
*
@@ -1997,4 +2030,40 @@ private function get_referencefileid($repositoryid, $reference, $strictness) {
return $DB->get_field('files_reference', 'id',
array('repositoryid' => $repositoryid, 'referencehash' => sha1($reference)), $strictness);
}
+
+ /**
+ * Updates a reference to the external resource and all files that use it
+ *
+ * This function is called after synchronisation of an external file and updates the
+ * contenthash, filesize and status of all files that reference this external file
+ * as well as time last synchronised and sync lifetime (how long we don't need to call
+ * synchronisation for this reference).
+ *
+ * @param int $referencefileid
+ * @param int $lastsync
+ * @param int $lifetime
+ * @param string $contenthash
+ * @param int $filesize
+ * @param int $status 0 if ok or 666 if source is missing
+ */
+ public function update_references($referencefileid, $lastsync, $lifetime, $contenthash, $filesize, $status) {
+ global $DB;
+ $referencefileid = clean_param($referencefileid, PARAM_INT);
+ $lastsync = clean_param($lastsync, PARAM_INT);
+ $lifetime = clean_param($lifetime, PARAM_INT);
+ validate_param($contenthash, PARAM_TEXT, NULL_NOT_ALLOWED);
+ $filesize = clean_param($filesize, PARAM_INT);
+ $status = clean_param($status, PARAM_INT);
+ $params = array('contenthash' => $contenthash,
+ 'filesize' => $filesize,
+ 'status' => $status,
+ 'referencefileid' => $referencefileid,
+ 'lastsync' => $lastsync,
+ 'lifetime' => $lifetime);
+ $DB->execute('UPDATE {files} SET contenthash = :contenthash, filesize = :filesize,
+ status = :status, referencelastsync = :lastsync, referencelifetime = :lifetime
+ WHERE referencefileid = :referencefileid', $params);
+ $data = array('id' => $referencefileid, 'lastsync' => $lastsync, 'lifetime' => $lifetime);
+ $DB->update_record('files_reference', (object)$data);
+ }
}
@@ -195,6 +195,7 @@ public function rename($filepath, $filename) {
public function replace_content_with(stored_file $storedfile) {
$contenthash = $storedfile->get_contenthash();
$this->set_contenthash($contenthash);
+ $this->set_filesize($storedfile->get_filesize());
}
/**
@@ -877,36 +878,43 @@ public function get_reference_details() {
* We update contenthash, filesize and status in files table if changed
* and we always update lastsync in files_reference table
*
- * @param type $contenthash
- * @param type $filesize
+ * @param string $contenthash
+ * @param int $filesize
+ * @param int $status
+ * @param int $lifetime the life time of this synchronisation results
*/
- public function set_synchronized($contenthash, $filesize, $status = 0) {
+ public function set_synchronized($contenthash, $filesize, $status = 0, $lifetime = null) {
global $DB;
if (!$this->is_external_file()) {
return;
}
$now = time();
- $filerecord = new stdClass();
- if ($this->get_contenthash() !== $contenthash) {
- $filerecord->contenthash = $contenthash;
+ if ($contenthash != $this->file_record->contenthash) {
+ $oldcontenthash = $this->file_record->contenthash;
}
- if ($this->get_filesize() != $filesize) {
- $filerecord->filesize = $filesize;
+ if ($lifetime === null) {
+ $lifetime = $this->file_record->referencelifetime;
}
- if ($this->get_status() != $status) {
- $filerecord->status = $status;
- }
- $filerecord->referencelastsync = $now; // TODO MDL-33416 remove this
- if (!empty($filerecord)) {
- $this->update($filerecord);
+ // this will update all entries in {files} that have the same filereference id
+ $this->fs->update_references($this->file_record->referencefileid, $now, $lifetime, $contenthash, $filesize, $status);
+ // we don't need to call update() for this object, just set the values of changed fields
+ $this->file_record->contenthash = $contenthash;
+ $this->file_record->filesize = $filesize;
+ $this->file_record->status = $status;
+ $this->file_record->referencelastsync = $now;
+ $this->file_record->referencelifetime = $lifetime;
+ if (isset($oldcontenthash)) {
+ $this->fs->deleted_file_cleanup($oldcontenthash);
}
-
- $DB->set_field('files_reference', 'lastsync', $now, array('id'=>$this->get_referencefileid()));
- // $this->file_record->lastsync = $now; // TODO MDL-33416 uncomment or remove
}
- public function set_missingsource() {
- $this->set_synchronized($this->get_contenthash(), 0, 666);
+ /**
+ * Sets the error status for a file that could not be synchronised
+ *
+ * @param int $lifetime the life time of this synchronisation results
+ */
+ public function set_missingsource($lifetime = null) {
+ $this->set_synchronized($this->get_contenthash(), $this->get_filesize(), 666, $lifetime);
}
/**

0 comments on commit 26aaa7e

Please sign in to comment.