diff --git a/backup/backup.class.php b/backup/backup.class.php index ddea0891256..260058d650e 100644 --- a/backup/backup.class.php +++ b/backup/backup.class.php @@ -49,6 +49,11 @@ abstract class backup implements checksumable { const INTERACTIVE_YES = true; const INTERACTIVE_NO = false; + /** Release the session during backup/restore */ + const RELEASESESSION_YES = true; + /** Don't release the session during backup/restore */ + const RELEASESESSION_NO = false; + // Predefined modes (purposes) of the backup const MODE_GENERAL = 10; diff --git a/backup/backup.php b/backup/backup.php index cfcb3ff55f3..c68bbfa9882 100644 --- a/backup/backup.php +++ b/backup/backup.php @@ -122,7 +122,7 @@ if (!async_helper::is_async_pending($id, 'course', 'backup')) { if (!($bc = backup_ui::load_controller($backupid))) { $bc = new backup_controller($type, $id, backup::FORMAT_MOODLE, - backup::INTERACTIVE_YES, $backupmode, $USER->id); + backup::INTERACTIVE_YES, $backupmode, $USER->id, backup::RELEASESESSION_YES); // The backup id did not relate to a valid controller so we made a new controller. // Now we need to reset the backup id to match the new controller. $backupid = $bc->get_backupid(); diff --git a/backup/controller/backup_controller.class.php b/backup/controller/backup_controller.class.php index 52793b24d68..c2c7fdd3dfc 100644 --- a/backup/controller/backup_controller.class.php +++ b/backup/controller/backup_controller.class.php @@ -79,8 +79,9 @@ class backup_controller extends base_controller { * @param bool $interactive Whether this backup will require user interaction; backup::INTERACTIVE_YES or INTERACTIVE_NO * @param int $mode One of backup::MODE_GENERAL, MODE_IMPORT, MODE_SAMESITE, MODE_HUB, MODE_AUTOMATED * @param int $userid The id of the user making the backup + * @param bool $releasesession Should release the session? backup::RELEASESESSION_YES or backup::RELEASESESSION_NO */ - public function __construct($type, $id, $format, $interactive, $mode, $userid){ + public function __construct($type, $id, $format, $interactive, $mode, $userid, $releasesession = backup::RELEASESESSION_NO) { $this->type = $type; $this->id = $id; $this->courseid = backup_controller_dbops::get_courseid_from_type_id($this->type, $this->id); @@ -88,6 +89,7 @@ class backup_controller extends base_controller { $this->interactive = $interactive; $this->mode = $mode; $this->userid = $userid; + $this->releasesession = $releasesession; // Apply some defaults $this->operation = backup::OPERATION_BACKUP; @@ -359,6 +361,11 @@ class backup_controller extends base_controller { core_php_time_limit::raise(1 * 60 * 60); // 1 hour for 1 course initially granted raise_memory_limit(MEMORY_EXTRA); + // Release the session so other tabs in the same session are not blocked. + if ($this->get_releasesession() === backup::RELEASESESSION_YES) { + \core\session\manager::write_close(); + } + // If the controller has decided that we can include files, then check the setting, otherwise do not include files. if ($this->get_include_files()) { $this->set_include_files((bool) $this->get_plan()->get_setting('files')->get_value()); diff --git a/backup/controller/base_controller.class.php b/backup/controller/base_controller.class.php index 09987965e5f..32aa06cc5b4 100644 --- a/backup/controller/base_controller.class.php +++ b/backup/controller/base_controller.class.php @@ -33,6 +33,9 @@ abstract class base_controller extends backup implements loggable { */ protected $logger; + /** @var bool Whether this backup should release the session. */ + protected $releasesession = backup::RELEASESESSION_NO; + /** * Gets the progress reporter, which can be used to report progress within * the backup or restore process. @@ -82,4 +85,14 @@ abstract class base_controller extends backup implements loggable { public function log($message, $level, $a = null, $depth = null, $display = false) { backup_helper::log($message, $level, $a, $depth, $display, $this->logger); } + + /** + * Returns the set value of releasesession. + * This is used to indicate if the session should be closed during the backup/restore. + * + * @return bool Indicates whether the session should be released. + */ + public function get_releasesession() { + return $this->releasesession; + } } diff --git a/backup/controller/restore_controller.class.php b/backup/controller/restore_controller.class.php index 1f63e577cc3..cf37e552dc5 100644 --- a/backup/controller/restore_controller.class.php +++ b/backup/controller/restore_controller.class.php @@ -79,15 +79,17 @@ class restore_controller extends base_controller { * @param int $userid * @param int $target backup::TARGET_[ NEW_COURSE | CURRENT_ADDING | CURRENT_DELETING | EXISTING_ADDING | EXISTING_DELETING ] * @param \core\progress\base $progress Optional progress monitor + * @param bool $releasesession Should release the session? backup::RELEASESESSION_YES or backup::RELEASESESSION_NO */ public function __construct($tempdir, $courseid, $interactive, $mode, $userid, $target, - \core\progress\base $progress = null) { + \core\progress\base $progress = null, $releasesession = backup::RELEASESESSION_NO) { $this->tempdir = $tempdir; $this->courseid = $courseid; $this->interactive = $interactive; $this->mode = $mode; $this->userid = $userid; $this->target = $target; + $this->releasesession = $releasesession; // Apply some defaults $this->type = ''; @@ -357,6 +359,11 @@ class restore_controller extends base_controller { core_php_time_limit::raise(1 * 60 * 60); // 1 hour for 1 course initially granted raise_memory_limit(MEMORY_EXTRA); + // Release the session so other tabs in the same session are not blocked. + if ($this->get_releasesession() === backup::RELEASESESSION_YES) { + \core\session\manager::write_close(); + } + // Do course cleanup precheck, if required. This was originally in restore_ui. Moved to handle async backup/restore. if ($this->get_target() == backup::TARGET_CURRENT_DELETING || $this->get_target() == backup::TARGET_EXISTING_DELETING) { $options = array(); diff --git a/backup/restore.php b/backup/restore.php index 750a3988380..a6b7d76280a 100644 --- a/backup/restore.php +++ b/backup/restore.php @@ -91,7 +91,7 @@ if ($stage & restore_ui::STAGE_CONFIRM + restore_ui::STAGE_DESTINATION) { $restore = restore_ui::engage_independent_stage($stage/2, $contextid); if ($restore->process()) { $rc = new restore_controller($restore->get_filepath(), $restore->get_course_id(), backup::INTERACTIVE_YES, - $backupmode, $USER->id, $restore->get_target()); + $backupmode, $USER->id, $restore->get_target(), null, backup::RELEASESESSION_YES); } } if ($rc) {