mirror of
https://github.com/moodle/moodle.git
synced 2025-04-21 16:32:18 +02:00
MDL-69983 backup: Save async backups in correct area.
This commit is contained in:
parent
6628845087
commit
09a97ba0bf
@ -128,6 +128,7 @@ class core_backup_external extends external_api {
|
||||
array(
|
||||
'filename' => new external_value(PARAM_FILE, 'Backup filename', VALUE_REQUIRED, null, NULL_NOT_ALLOWED),
|
||||
'contextid' => new external_value(PARAM_INT, 'Context id', VALUE_REQUIRED, null, NULL_NOT_ALLOWED),
|
||||
'backupid' => new external_value(PARAM_ALPHANUMEXT, 'Backup id', VALUE_REQUIRED, null, NULL_NOT_ALLOWED),
|
||||
)
|
||||
);
|
||||
}
|
||||
@ -138,9 +139,10 @@ class core_backup_external extends external_api {
|
||||
*
|
||||
* @param string $filename The file name of the backup file.
|
||||
* @param int $contextid The context the backup relates to.
|
||||
* @param string $backupid The backup ID to get the backup settings.
|
||||
* @since Moodle 3.7
|
||||
*/
|
||||
public static function get_async_backup_links_backup($filename, $contextid) {
|
||||
public static function get_async_backup_links_backup($filename, $contextid, $backupid) {
|
||||
// Release session lock.
|
||||
\core\session\manager::write_close();
|
||||
|
||||
@ -149,7 +151,8 @@ class core_backup_external extends external_api {
|
||||
self::get_async_backup_links_backup_parameters(),
|
||||
array(
|
||||
'filename' => $filename,
|
||||
'contextid' => $contextid
|
||||
'contextid' => $contextid,
|
||||
'backupid' => $backupid,
|
||||
)
|
||||
);
|
||||
|
||||
@ -158,10 +161,18 @@ class core_backup_external extends external_api {
|
||||
self::validate_context($context);
|
||||
require_capability('moodle/backup:backupcourse', $context);
|
||||
|
||||
if ($cm) {
|
||||
$filearea = 'activity';
|
||||
} else {
|
||||
$filearea = 'course';
|
||||
// Backups without user info or with the anonymise functionality enabled are sent
|
||||
// to user's "user_backup" file area.
|
||||
$filearea = 'backup';
|
||||
// Get useful info to render async status in correct area.
|
||||
$bc = \backup_controller::load_controller($backupid);
|
||||
list($hasusers, $isannon) = \async_helper::get_userdata_backup_settings($bc);
|
||||
if ($hasusers && !$isannon) {
|
||||
if ($cm) {
|
||||
$filearea = 'activity';
|
||||
} else {
|
||||
$filearea = 'course';
|
||||
}
|
||||
}
|
||||
|
||||
$results = \async_helper::get_backup_file_info($filename, $filearea, $contextid);
|
||||
|
@ -87,7 +87,7 @@ class async_backup_test extends \advanced_testcase {
|
||||
set_config('buffersize', 0, 'logstore_standard');
|
||||
get_log_manager(true);
|
||||
|
||||
// Start backup process.
|
||||
// Case 1: Make a course backup without users.
|
||||
$this->setUser($teacher->id);
|
||||
|
||||
// Make the backup controller for an async backup.
|
||||
@ -132,6 +132,52 @@ class async_backup_test extends \advanced_testcase {
|
||||
'target' => 'course_backup'], '*', MUST_EXIST);
|
||||
$otherdata = json_decode($logrec->other);
|
||||
$this->assertEquals($backupid, $otherdata->backupid);
|
||||
|
||||
// Check backup was stored in correct area.
|
||||
$usercontextid = $DB->get_field('context', 'id', ['contextlevel' => CONTEXT_USER, 'instanceid' => $teacher->id]);
|
||||
$this->assertEquals(1, $DB->count_records('files', ['contextid' => $usercontextid,
|
||||
'component' => 'user', 'filearea' => 'backup', 'filename' => 'backup.mbz']));
|
||||
|
||||
// Case 2: Make a second backup with users and not anonymised.
|
||||
$this->setAdminUser();
|
||||
$bc = new backup_controller(backup::TYPE_1COURSE, $course->id, backup::FORMAT_MOODLE,
|
||||
backup::INTERACTIVE_YES, backup::MODE_ASYNC, $USER->id);
|
||||
$bc->get_plan()->get_setting('users')->set_status(\backup_setting::NOT_LOCKED);
|
||||
$bc->get_plan()->get_setting('users')->set_value(true);
|
||||
$bc->get_plan()->get_setting('anonymize')->set_value(false);
|
||||
$bc->finish_ui();
|
||||
$backupid = $bc->get_backupid();
|
||||
$bc->destroy();
|
||||
|
||||
// Create the adhoc task.
|
||||
$asynctask = new \core\task\asynchronous_backup_task();
|
||||
$asynctask->set_blocking(false);
|
||||
$asynctask->set_custom_data(['backupid' => $backupid]);
|
||||
\core\task\manager::queue_adhoc_task($asynctask);
|
||||
|
||||
// Execute adhoc task.
|
||||
$now = time();
|
||||
$task = \core\task\manager::get_next_adhoc_task($now);
|
||||
$task->execute();
|
||||
\core\task\manager::adhoc_task_complete($task);
|
||||
|
||||
$postbackuprec = $DB->get_record('backup_controllers', ['backupid' => $backupid]);
|
||||
|
||||
// Check backup was created successfully.
|
||||
$this->assertEquals(backup::STATUS_FINISHED_OK, $postbackuprec->status);
|
||||
$this->assertEquals(1.0, $postbackuprec->progress);
|
||||
$this->assertEquals($USER->id, $postbackuprec->userid);
|
||||
|
||||
// Check that the backupid was logged correctly.
|
||||
$logrec = $DB->get_record('logstore_standard_log', ['userid' => $postbackuprec->userid,
|
||||
'target' => 'course_backup'], '*', MUST_EXIST);
|
||||
$otherdata = json_decode($logrec->other);
|
||||
$this->assertEquals($backupid, $otherdata->backupid);
|
||||
|
||||
// Check backup was stored in correct area.
|
||||
$coursecontextid = $DB->get_field('context', 'id', ['contextlevel' => CONTEXT_COURSE, 'instanceid' => $course->id]);
|
||||
$this->assertEquals(1, $DB->count_records('files', ['contextid' => $coursecontextid,
|
||||
'component' => 'backup', 'filearea' => 'course', 'filename' => 'backup.mbz']));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -313,39 +313,82 @@ class async_helper {
|
||||
* Get markup for in progress async backups,
|
||||
* to use in backup table UI.
|
||||
*
|
||||
* @param \core_backup_renderer $renderer The backup renderer object.
|
||||
* @param string $filearea The filearea to get backup data for.
|
||||
* @param integer $instanceid The context id to get backup data for.
|
||||
* @return array $tabledata the rows of table data.
|
||||
*/
|
||||
public static function get_async_backups($renderer, $instanceid) {
|
||||
public static function get_async_backups($filearea, $instanceid) {
|
||||
global $DB;
|
||||
|
||||
$tabledata = array();
|
||||
$backups = [];
|
||||
|
||||
// Get relevant backup ids based on context instance id.
|
||||
$select = 'itemid = :itemid AND execution = :execution AND status < :status1 AND status > :status2 ' .
|
||||
$table = 'backup_controllers';
|
||||
$select = 'execution = :execution AND status < :status1 AND status > :status2 ' .
|
||||
'AND operation = :operation';
|
||||
$params = [
|
||||
'itemid' => $instanceid,
|
||||
'execution' => backup::EXECUTION_DELAYED,
|
||||
'status1' => backup::STATUS_FINISHED_ERR,
|
||||
'status2' => backup::STATUS_NEED_PRECHECK,
|
||||
'operation' => 'backup',
|
||||
];
|
||||
$sort = 'timecreated DESC';
|
||||
$fields = 'id, backupid, status, timecreated';
|
||||
|
||||
$backups = $DB->get_records_select('backup_controllers', $select, $params, 'timecreated DESC', 'id, backupid, timecreated');
|
||||
foreach ($backups as $backup) {
|
||||
$bc = \backup_controller::load_controller($backup->backupid); // Get the backup controller.
|
||||
$filename = $bc->get_plan()->get_setting('filename')->get_value();
|
||||
$timecreated = $backup->timecreated;
|
||||
$status = $renderer->get_status_display($bc->get_status(), $bc->get_backupid());
|
||||
$bc->destroy();
|
||||
if ($filearea == 'backup') {
|
||||
// Get relevant backup ids based on user id.
|
||||
$params['userid'] = $instanceid;
|
||||
$select = 'userid = :userid AND ' . $select;
|
||||
$records = $DB->get_records_select($table, $select, $params, $sort, $fields);
|
||||
foreach ($records as $record) {
|
||||
$bc = \backup_controller::load_controller($record->backupid);
|
||||
|
||||
$tablerow = array($filename, userdate($timecreated), '-', '-', '-', $status);
|
||||
$tabledata[] = $tablerow;
|
||||
// Get useful info to render async status in correct area.
|
||||
list($hasusers, $isannon) = self::get_userdata_backup_settings($bc);
|
||||
// Backup has users and is not anonymised -> don't show it in users backup file area.
|
||||
if ($hasusers && !$isannon) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$record->filename = $bc->get_plan()->get_setting('filename')->get_value();
|
||||
$bc->destroy();
|
||||
array_push($backups, $record);
|
||||
}
|
||||
} else {
|
||||
if ($filearea == 'course' || $filearea == 'activity') {
|
||||
// Get relevant backup ids based on context instance id.
|
||||
$params['itemid'] = $instanceid;
|
||||
$select = 'itemid = :itemid AND ' . $select;
|
||||
$records = $DB->get_records_select($table, $select, $params, $sort, $fields);
|
||||
foreach ($records as $record) {
|
||||
$bc = \backup_controller::load_controller($record->backupid);
|
||||
|
||||
// Get useful info to render async status in correct area.
|
||||
list($hasusers, $isannon) = self::get_userdata_backup_settings($bc);
|
||||
// Backup has no user or is anonymised -> don't show it in course/activity backup file area.
|
||||
if (!$hasusers || $isannon) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$record->filename = $bc->get_plan()->get_setting('filename')->get_value();
|
||||
$bc->destroy();
|
||||
array_push($backups, $record);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $tabledata;
|
||||
return $backups;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the user data settings for backups.
|
||||
*
|
||||
* @param \backup_controller $backupcontroller The backup controller object.
|
||||
* @return array Array of user data settings.
|
||||
*/
|
||||
public static function get_userdata_backup_settings(\backup_controller $backupcontroller): array {
|
||||
$hasusers = (bool)$backupcontroller->get_plan()->get_setting('users')->get_value(); // Backup has users.
|
||||
$isannon = (bool)$backupcontroller->get_plan()->get_setting('anonymize')->get_value(); // Backup is anonymised.
|
||||
return [$hasusers, $isannon];
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -331,7 +331,7 @@ abstract class backup_helper {
|
||||
// enabled are sent to user's "user_backup"
|
||||
// file area. Maintenance of such area is responsibility of
|
||||
// the user via corresponding file manager frontend
|
||||
if ($backupmode == backup::MODE_GENERAL && (!$hasusers || $isannon)) {
|
||||
if (($backupmode == backup::MODE_GENERAL || $backupmode == backup::MODE_ASYNC) && (!$hasusers || $isannon)) {
|
||||
$ctxid = context_user::instance($userid)->id;
|
||||
$component = 'user';
|
||||
$filearea = 'backup';
|
||||
|
@ -140,12 +140,11 @@ class async_helper_test extends \advanced_testcase {
|
||||
unset($bc);
|
||||
|
||||
$coursecontext = \context_course::instance($course->id);
|
||||
$renderer = $PAGE->get_renderer('core', 'backup');
|
||||
|
||||
$result = \async_helper::get_async_backups($renderer, $coursecontext->instanceid);
|
||||
$result = \async_helper::get_async_backups('course', $coursecontext->instanceid);
|
||||
|
||||
$this->assertEquals(1, count($result));
|
||||
$this->assertEquals('backup.mbz', $result[0][0]);
|
||||
$this->assertEquals('backup.mbz', $result[0]->filename);
|
||||
}
|
||||
|
||||
/**
|
||||
|
2
backup/util/ui/amd/build/async_backup.min.js
vendored
2
backup/util/ui/amd/build/async_backup.min.js
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -100,7 +100,8 @@ define(['jquery', 'core/ajax', 'core/str', 'core/notification', 'core/templates'
|
||||
methodname: 'core_backup_get_async_backup_links_backup',
|
||||
args: {
|
||||
'filename': filename,
|
||||
'contextid': contextid
|
||||
'contextid': contextid,
|
||||
'backupid': backupid
|
||||
},
|
||||
}])[0].done(function(response) {
|
||||
// We have the data now update the UI.
|
||||
|
@ -619,10 +619,10 @@ class core_backup_renderer extends plugin_renderer_base {
|
||||
* @return string
|
||||
*/
|
||||
public function render_backup_files_viewer(backup_files_viewer $viewer) {
|
||||
global $CFG;
|
||||
|
||||
$files = $viewer->files;
|
||||
|
||||
$async = async_helper::is_async_enabled();
|
||||
$async = \async_helper::is_async_enabled();
|
||||
|
||||
$tablehead = array(
|
||||
get_string('filename', 'backup'),
|
||||
@ -638,16 +638,21 @@ class core_backup_renderer extends plugin_renderer_base {
|
||||
$table->attributes['class'] = 'backup-files-table generaltable';
|
||||
$table->head = $tablehead;
|
||||
$table->width = '100%';
|
||||
$table->data = array();
|
||||
$table->data = [];
|
||||
|
||||
// First add in progress asynchronous backups.
|
||||
// Only if asynchronous backups are enabled.
|
||||
// Also only render async status in correct area. Courese OR activity (not both).
|
||||
if ($async
|
||||
&& (($viewer->filearea == 'course' && $viewer->currentcontext->contextlevel == CONTEXT_COURSE)
|
||||
|| ($viewer->filearea == 'activity' && $viewer->currentcontext->contextlevel == CONTEXT_MODULE))
|
||||
) {
|
||||
$table->data = \async_helper::get_async_backups($this, $viewer->currentcontext->instanceid);
|
||||
if ($async) {
|
||||
$tabledata = [];
|
||||
$backups = \async_helper::get_async_backups($viewer->filearea, $viewer->filecontext->instanceid);
|
||||
// For each backup get, new item name, time restore created and progress.
|
||||
foreach ($backups as $backup) {
|
||||
$status = $this->get_status_display($backup->status, $backup->backupid);
|
||||
$timecreated = $backup->timecreated;
|
||||
$tablerow = [$backup->filename, userdate($timecreated), '-', '-', '-', $status];
|
||||
$tabledata[] = $tablerow;
|
||||
}
|
||||
$table->data = $tabledata;
|
||||
}
|
||||
|
||||
// Add completed backups.
|
||||
|
Loading…
x
Reference in New Issue
Block a user