// there were no files before - one file means root dir only ;-)
foreach ($draftfiles as $file) {
$file_record = array('contextid'=>$contextid, 'component'=>$component, 'filearea'=>$filearea, 'itemid'=>$itemid);
+ if ($source = @unserialize($file->get_source())) {
+ // Field files.source for draftarea files contains serialised object with source and original information.
+ $file_record['source'] = $source->source;
+ }
if (!$options['subdirs']) {
if ($file->get_filepath() !== '/' or $file->is_directory()) {
continue;
$file_record['reference'] = $file->get_reference();
}
}
- file_restore_source_field_from_draft_file($file);
$fs->create_file_from_storedfile($file_record, $file);
}
$newhashes = array();
foreach ($draftfiles as $file) {
$newhash = $fs->get_pathname_hash($contextid, $component, $filearea, $itemid, $file->get_filepath(), $file->get_filename());
- file_restore_source_field_from_draft_file($file);
$newhashes[$newhash] = $file;
}
$filecount = 0;
}
$newfile = $newhashes[$oldhash];
+ // Now we know that we have $oldfile and $newfile for the same path.
+ // Let's check if we can update this file or we need to delete and create.
+ if ($newfile->is_directory()) {
+ // Directories are always ok to just update.
+ } else if (($source = @unserialize($newfile->get_source())) && isset($source->original)) {
+ // File has the 'original' - we need to update the file (it may even have not been changed at all).
+ $original = file_storage::unpack_reference($source->original);
+ if ($original['filename'] !== $oldfile->get_filename() || $original['filepath'] !== $oldfile->get_filepath()) {
+ // Very odd, original points to another file. Delete and create file.
+ $oldfile->delete();
+ continue;
+ }
+ } else {
+ // The same file name but absence of 'original' means that file was deteled and uploaded again.
+ // By deleting and creating new file we properly manage all existing references.
+ $oldfile->delete();
+ continue;
+ }
+
// status changed, we delete old file, and create a new one
if ($oldfile->get_status() != $newfile->get_status()) {
// file was changed, use updated with new timemodified data
}
// Updated file source
- if ($oldfile->get_source() != $newfile->get_source()) {
- $oldfile->set_source($newfile->get_source());
+ $newsource = $newfile->get_source();
+ if ($source = @unserialize($newfile->get_source())) {
+ $newsource = $source->source;
+ }
+ if ($oldfile->get_source() !== $newsource) {
+ $oldfile->set_source($newsource);
}
// Updated sort order
continue;
}
// Replaced file content
- else if ($oldfile->get_contenthash() != $newfile->get_contenthash() ||
+ if (!$oldfile->is_directory() &&
+ ($oldfile->get_contenthash() != $newfile->get_contenthash() ||
$oldfile->get_filesize() != $newfile->get_filesize() ||
- $oldfile->get_referencefileid() != $newfile->get_referencefileid()) {
+ $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);
// the size and subdirectory tests are extra safety only, the UI should prevent it
foreach ($newhashes as $file) {
$file_record = array('contextid'=>$contextid, 'component'=>$component, 'filearea'=>$filearea, 'itemid'=>$itemid, 'timemodified'=>time());
+ if ($source = @unserialize($file->get_source())) {
+ // Field files.source for draftarea files contains serialised object with source and original information.
+ $file_record['source'] = $source->source;
+ }
if (!$options['subdirs']) {
if ($file->get_filepath() !== '/' or $file->is_directory()) {
continue;