MDL-75696 quiz: Fix restoring pre-4.0 quizzes with random questions
Restoring multiple quizzes from a pre-4.0 backup was broken when the quizzes shared a random question. This is because after the first quiz created a set reference in place of the random question, it deleted the question record so it was not there for the second quiz to use. This change tracks the IDs of random questions so they can be deleted at the end.
This commit is contained in:
@@ -40,6 +40,11 @@ class restore_quiz_activity_structure_step extends restore_questions_activity_st
|
||||
*/
|
||||
protected $legacyshufflequestionsoption = false;
|
||||
|
||||
/**
|
||||
* @var array Track old question ids that need to be removed at the end of the restore.
|
||||
*/
|
||||
protected $oldquestionids = [];
|
||||
|
||||
protected function define_structure() {
|
||||
|
||||
$paths = array();
|
||||
@@ -342,8 +347,7 @@ class restore_quiz_activity_structure_step extends restore_questions_activity_st
|
||||
$filtercondition->includingsubcategories = $data->includingsubcategories ?? false;
|
||||
$questionsetreference->filtercondition = json_encode($filtercondition);
|
||||
$DB->insert_record('question_set_references', $questionsetreference);
|
||||
// Cleanup leftover random qtype data from question table.
|
||||
question_delete_question($question->questionid);
|
||||
$this->oldquestionids[$question->questionid] = 1;
|
||||
} else {
|
||||
// Reference data.
|
||||
$questionreference = new \stdClass();
|
||||
@@ -604,4 +608,12 @@ class restore_quiz_activity_structure_step extends restore_questions_activity_st
|
||||
'shufflequestions' => $this->legacyshufflequestionsoption));
|
||||
}
|
||||
}
|
||||
|
||||
protected function after_restore() {
|
||||
parent::after_restore();
|
||||
// Delete old random questions that have been converted to set references.
|
||||
foreach (array_keys($this->oldquestionids) as $oldquestionid) {
|
||||
question_delete_question($oldquestionid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Binary file not shown.
@@ -380,6 +380,59 @@ class quiz_question_restore_test extends \advanced_testcase {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Test pre 4.0 quiz restore for random question used on multiple quizzes.
|
||||
*
|
||||
* @covers ::process_quiz_question_legacy_instance
|
||||
*/
|
||||
public function test_pre_4_quiz_restore_shared_random_question() {
|
||||
global $USER, $DB;
|
||||
$this->resetAfterTest();
|
||||
|
||||
$backupid = 'abc';
|
||||
$backuppath = make_backup_temp_directory($backupid);
|
||||
get_file_packer('application/vnd.moodle.backup')->extract_to_pathname(
|
||||
__DIR__ . "/fixtures/pre-40-shared-random-question.mbz", $backuppath);
|
||||
|
||||
// Do the restore to new course with default settings.
|
||||
$categoryid = $DB->get_field_sql("SELECT MIN(id) FROM {course_categories}");
|
||||
$newcourseid = \restore_dbops::create_new_course('Test fullname', 'Test shortname', $categoryid);
|
||||
$rc = new \restore_controller($backupid, $newcourseid, \backup::INTERACTIVE_NO, \backup::MODE_GENERAL, $USER->id,
|
||||
\backup::TARGET_NEW_COURSE);
|
||||
|
||||
$this->assertTrue($rc->execute_precheck());
|
||||
$rc->execute_plan();
|
||||
$rc->destroy();
|
||||
|
||||
// Get the information about the resulting course and check that it is set up correctly.
|
||||
// Each quiz should contain an instance of the random question.
|
||||
$modinfo = get_fast_modinfo($newcourseid);
|
||||
$quizzes = $modinfo->get_instances_of('quiz');
|
||||
$this->assertCount(2, $quizzes);
|
||||
foreach ($quizzes as $quiz) {
|
||||
$quizobj = \quiz::create($quiz->instance);
|
||||
$structure = structure::create_for_quiz($quizobj);
|
||||
|
||||
// Are the correct slots returned?
|
||||
$slots = $structure->get_slots();
|
||||
$this->assertCount(1, $slots);
|
||||
|
||||
$quizobj->preload_questions();
|
||||
$quizobj->load_questions();
|
||||
$questions = $quizobj->get_questions();
|
||||
$this->assertCount(1, $questions);
|
||||
}
|
||||
|
||||
// Count the questions for course question bank.
|
||||
// We should have a single question, the random question should have been deleted after the restore.
|
||||
$this->assertEquals(1, $this->question_count(\context_course::instance($newcourseid)->id));
|
||||
$this->assertEquals(1, $this->question_count(\context_course::instance($newcourseid)->id,
|
||||
"AND q.qtype <> 'random'"));
|
||||
|
||||
// Count the questions in quiz qbank.
|
||||
$this->assertEquals(0, $this->question_count($quizobj->get_context()->id));
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure that question slots are correctly backed up and restored with all properties.
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user