diff --git a/backup/moodle2/backup_custom_fields.php b/backup/moodle2/backup_custom_fields.php index d899a65..2cc997b 100644 --- a/backup/moodle2/backup_custom_fields.php +++ b/backup/moodle2/backup_custom_fields.php @@ -95,10 +95,24 @@ class file_nested_element extends backup_nested_element { } public function fill_values($values) { + global $CFG; // Fill values parent::fill_values($values); // Do our own tasks (copy file from moodle to backup) - backup_file_manager::copy_file_moodle2backup($this->backupid, $values); + // If 'fileless' flag is set and the backup is in automatic (cron) mode, no files are copied + $fileless_flag = false; + list($dinfo, $cinfo, $sinfo) = backup_controller_dbops::get_moodle_backup_information($this->backupid); + if ($dinfo[0]->mode == backup::MODE_AUTOMATED) { + $db_config_fileless = (bool)$sinfo["fileless"]->value; + if ($db_config_fileless === true) { + $fileless_flag = $db_config_fileless; + } elseif (isset($CFG->backup_auto_fileless)) { + $fileless_flag = (bool)$CFG->backup_auto_fileless; + } + } + if ($fileless_flag === false) { + backup_file_manager::copy_file_moodle2backup($this->backupid, $values); + } } } diff --git a/backup/moodle2/backup_root_task.class.php b/backup/moodle2/backup_root_task.class.php index 73519e0..8ec9a54 100644 --- a/backup/moodle2/backup_root_task.class.php +++ b/backup/moodle2/backup_root_task.class.php @@ -71,8 +71,10 @@ class backup_root_task extends backup_task { // Define user_files (dependent of users and anonymize) $userfiles = new backup_user_files_setting('user_files', base_setting::IS_BOOLEAN, true); + $userfiles_fileless = new backup_user_files_setting('fileless', base_setting::IS_BOOLEAN, false); $userfiles->set_ui(new backup_setting_ui_checkbox($userfiles, get_string('rootsettinguserfiles', 'backup'))); $this->add_setting($userfiles); + $this->add_setting($userfiles_fileless); $users->add_dependency($userfiles); $anonymize->add_dependency($userfiles, setting_dependency::DISABLED_TRUE); diff --git a/backup/moodle2/backup_stepslib.php b/backup/moodle2/backup_stepslib.php index 269ad4b..cefee34 100644 --- a/backup/moodle2/backup_stepslib.php +++ b/backup/moodle2/backup_stepslib.php @@ -1374,9 +1374,28 @@ class backup_main_structure_step extends backup_structure_step { $info['original_course_startdate'] = $originalcourseinfo->startdate; $info['original_course_contextid'] = get_context_instance(CONTEXT_COURSE, $this->get_courseid())->id; $info['original_system_contextid'] = get_context_instance(CONTEXT_SYSTEM)->id; - + // Get more information from controller list($dinfo, $cinfo, $sinfo) = backup_controller_dbops::get_moodle_backup_information($this->get_backupid()); + + // fileless flag (only for cron update) + if ($dinfo[0]->mode == backup::MODE_AUTOMATED) { + try { + $fileless_db_setting = $this->get_setting_value('fileless'); + } catch (exception $e) { + // No 'fileless' flag in DB, we should try config file + } + if (isset($fileless_db_setting) && $fileless_db_setting === true) { + $info['fileless'] = $fileless_db_setting; + } elseif (isset($CFG->backup_auto_fileless)) { + $info['fileless'] = $CFG->backup_auto_fileless; + } else { + // No 'fileless' flag both in DB and config file, set to false + $info['fileless'] = false; + } + } else { + $info['fileless'] = false; + } // Define elements @@ -1387,7 +1406,7 @@ class backup_main_structure_step extends backup_structure_step { 'backup_release', 'backup_date', 'mnet_remoteusers', 'original_wwwroot', 'original_site_identifier_hash', 'original_course_id', 'original_course_fullname', 'original_course_shortname', 'original_course_startdate', - 'original_course_contextid', 'original_system_contextid')); + 'original_course_contextid', 'original_system_contextid', 'fileless')); $details = new backup_nested_element('details'); diff --git a/backup/util/dbops/restore_dbops.class.php b/backup/util/dbops/restore_dbops.class.php index 0b405c8..9c65f07 100644 --- a/backup/util/dbops/restore_dbops.class.php +++ b/backup/util/dbops/restore_dbops.class.php @@ -624,7 +624,7 @@ abstract class restore_dbops { * put the corresponding files in the pool */ public static function send_files_to_pool($basepath, $restoreid, $component, $filearea, $oldcontextid, $dfltuserid, $itemname = null, $olditemid = null, $forcenewcontextid = null, $skipparentitemidctxmatch = false) { - global $DB; + global $DB, $CFG; if ($forcenewcontextid) { // Some components can have "forced" new contexts (example: questions can end belonging to non-standard context mappings, @@ -679,10 +679,14 @@ abstract class restore_dbops { $params[] = $olditemid; } } - + + // check if backup is fileless + $rc_temp = restore_controller_dbops::load_controller($restoreid); + $fileless = (bool)$rc_temp->get_info()->fileless; + $fs = get_file_storage(); // Get moodle file storage - $basepath = $basepath . '/files/';// Get backup file pool base $rs = $DB->get_recordset_sql($sql, $params); + $basepath = $basepath . '/files/';// Get backup file pool base foreach ($rs as $rec) { $file = (object)unserialize(base64_decode($rec->info)); // ignore root dirs (they are created automatically) @@ -697,27 +701,60 @@ abstract class restore_dbops { $fs->create_directory($newcontextid, $component, $filearea, $rec->newitemid, $file->filepath, $file->userid); continue; } - // arrived here, file found - // Find file in backup pool - $backuppath = $basepath . backup_file_manager::get_backup_content_file_location($file->contenthash); - if (!file_exists($backuppath)) { - throw new restore_dbops_exception('file_not_found_in_pool', $file); - } - if (!$fs->file_exists($newcontextid, $component, $filearea, $rec->newitemid, $file->filepath, $file->filename)) { - $file_record = array( - 'contextid' => $newcontextid, - 'component' => $component, - 'filearea' => $filearea, - 'itemid' => $rec->newitemid, - 'filepath' => $file->filepath, - 'filename' => $file->filename, - 'timecreated' => $file->timecreated, - 'timemodified'=> $file->timemodified, - 'userid' => $file->userid, - 'author' => $file->author, - 'license' => $file->license, - 'sortorder' => $file->sortorder); - $fs->create_file_from_pathname($file_record, $backuppath); + if ($fileless === true) { + // no files in backup itself, try to restore them from data directory + // get file handler by its ID in backup XML + $existing_file = $fs->get_file_by_id($file->id); + // check if it exists in pool + if ( ! $fs->file_exists_by_hash($existing_file->get_pathnamehash())) { + throw new restore_dbops_exception('file_not_found_in_pool', $file); + } + if ( ! $fs->file_exists($newcontextid, $component, $filearea, $rec->newitemid, $file->filepath, $file->filename)) { + $now = time(); + $file_record = array( + 'contextid' => $newcontextid, + 'component' => $component, + 'filearea' => $filearea, + 'itemid' => $rec->newitemid, + 'filepath' => $file->filepath, + 'filesize' => $file->filesize, + 'contenthash' => $file->contenthash, + 'filename' => $file->filename, + 'timecreated' => $now, + 'timemodified'=> $now, + 'mimetype' => $file->mimetype, + 'userid' => $file->userid, + 'author' => $file->author, + 'status' => $file->status, + 'source' => $file->source, + 'license' => $file->license, + 'pathnamehash'=> $fs->get_pathname_hash($newcontextid, $component, $filearea, $rec->newitemid, $file->filepath, $file->filename), + 'sortorder' => $file->sortorder); + $file_record->id = $DB->insert_record('files', $file_record); + } + } else { + // arrived here, file found + // Find file in backup pool + $backuppath = $basepath . backup_file_manager::get_backup_content_file_location($file->contenthash); + if (!file_exists($backuppath)) { + throw new restore_dbops_exception('file_not_found_in_pool', $file); + } + if (!$fs->file_exists($newcontextid, $component, $filearea, $rec->newitemid, $file->filepath, $file->filename)) { + $file_record = array( + 'contextid' => $newcontextid, + 'component' => $component, + 'filearea' => $filearea, + 'itemid' => $rec->newitemid, + 'filepath' => $file->filepath, + 'filename' => $file->filename, + 'timecreated' => $file->timecreated, + 'timemodified'=> $file->timemodified, + 'userid' => $file->userid, + 'author' => $file->author, + 'license' => $file->license, + 'sortorder' => $file->sortorder); + $fs->create_file_from_pathname($file_record, $backuppath); + } } } $rs->close(); diff --git a/backup/util/helper/backup_cron_helper.class.php b/backup/util/helper/backup_cron_helper.class.php index 6044872..550824e 100644 --- a/backup/util/helper/backup_cron_helper.class.php +++ b/backup/util/helper/backup_cron_helper.class.php @@ -305,6 +305,8 @@ abstract class backup_cron_automated_helper { */ public static function launch_automated_backup($course, $starttime, $userid) { + global $CFG; + $config = get_config('backup'); $bc = new backup_controller(backup::TYPE_1COURSE, $course->id, backup::FORMAT_MOODLE, backup::INTERACTIVE_NO, backup::MODE_AUTOMATED, $userid); @@ -320,11 +322,17 @@ abstract class backup_cron_automated_helper { 'comments' => 'backup_auto_comments', 'completion_information' => 'backup_auto_userscompletion', 'logs' => 'backup_auto_logs', - 'histories' => 'backup_auto_histories' + 'histories' => 'backup_auto_histories', + 'fileless' => 'backup_auto_fileless', ); + foreach ($settings as $setting => $configsetting) { if ($bc->get_plan()->setting_exists($setting)) { - $bc->get_plan()->get_setting($setting)->set_value($config->{$configsetting}); + if (isset($config->{$configsetting})) { + $bc->get_plan()->get_setting($setting)->set_value($config->{$configsetting}); + } else { + $bc->get_plan()->get_setting($setting)->set_value(false); + } } } diff --git a/backup/util/helper/backup_general_helper.class.php b/backup/util/helper/backup_general_helper.class.php index 99db287..f232649 100644 --- a/backup/util/helper/backup_general_helper.class.php +++ b/backup/util/helper/backup_general_helper.class.php @@ -145,9 +145,10 @@ abstract class backup_general_helper extends backup_helper { $info->original_course_startdate= $infoarr['original_course_startdate']; $info->original_course_contextid= $infoarr['original_course_contextid']; $info->original_system_contextid= $infoarr['original_system_contextid']; - $info->type = $infoarr['details']['detail'][0]['type']; - $info->format = $infoarr['details']['detail'][0]['format']; - $info->mode = $infoarr['details']['detail'][0]['mode']; + $info->fileless = $infoarr['fileless']; + $info->type = $infoarr['details']['detail'][0]['type']; + $info->format = $infoarr['details']['detail'][0]['format']; + $info->mode = $infoarr['details']['detail'][0]['mode']; // Build the role mappings custom object $rolemappings = new stdclass(); $rolemappings->modified = false;