From 91e676ebde31bb19f902784dee7c727c673e547e Mon Sep 17 00:00:00 2001 From: Stefan Hanauska Date: Mon, 25 Aug 2025 19:52:37 +0200 Subject: [PATCH] MDL-86300 backup: Save old id of top category Co-authored-by: Paola Maneggia --- backup/moodle2/restore_stepslib.php | 2 +- backup/moodle2/tests/moodle2_test.php | 66 ++++++++++++++++++++++++++- 2 files changed, 66 insertions(+), 2 deletions(-) diff --git a/backup/moodle2/restore_stepslib.php b/backup/moodle2/restore_stepslib.php index 09b2d036fbc..c34d3490413 100644 --- a/backup/moodle2/restore_stepslib.php +++ b/backup/moodle2/restore_stepslib.php @@ -5553,7 +5553,7 @@ class restore_move_module_questions_categories extends restore_execution_step { // From 3.5 onwards, all question categories should be a child of a special category called the "top" category. $info = backup_controller_dbops::decode_backup_temp_info($modulecat->info); if ($after35 && empty($info->parent)) { - $oldtopid = $modulecat->newitemid; + $oldtopid = $modulecat->itemid; $modulecat->newitemid = $top->id; } else { $cat = new stdClass(); diff --git a/backup/moodle2/tests/moodle2_test.php b/backup/moodle2/tests/moodle2_test.php index 6b37f926058..a015c83e06a 100644 --- a/backup/moodle2/tests/moodle2_test.php +++ b/backup/moodle2/tests/moodle2_test.php @@ -1088,14 +1088,78 @@ final class moodle2_test extends \advanced_testcase { } } - // Make sure there is a single top level category in this context. + // Make sure there is a single top level category in this context and that the parents are set correctly. if ($cats) { $this->assertEquals(1, $topcategorycount[$context->id]); + $topcat = array_values($cats)[0]; + $this->assertEquals(0, $topcat->parent); + $othercat = array_values($cats)[1]; + $this->assertEquals($topcat->id, $othercat->parent); } } } } + /** + * Check that the backup/restore process correctly wires the question categories, see MDL-86300. + * @covers \restore_move_module_questions_categories::define_execution + */ + public function test_restore_question_categories_from_500(): void { + global $DB, $CFG, $USER; + + $this->resetAfterTest(true); + $this->setAdminUser(); + + // Create a course. + $generator = $this->getDataGenerator(); + $questiongenerator = $this->getDataGenerator()->get_plugin_generator('core_question'); + $course = $generator->create_course(); + + // Add a quiz with question categories. + $quiz = $generator->create_module('quiz', ['course' => $course->id]); + $quizcontext = \context_module::instance($quiz->cmid); + $questiongenerator->create_question_category(['contextid' => $quizcontext->id]); + $quizquestioncats = $DB->get_records('question_categories', ['contextid' => $quizcontext->id]); + $this->assertCount(3, $quizquestioncats); + + // Add a question bank with question categories. + $qbank = $this->getDataGenerator()->create_module('qbank', ['course' => $course->id]); + $qbankcontext = \context_module::instance($qbank->cmid); + $questiongenerator->create_question_category(['contextid' => $qbankcontext->id]); + $qbankquestioncats = $DB->get_records('question_categories', ['contextid' => $qbankcontext->id]); + $this->assertCount(3, $qbankquestioncats); + + $targetcourseid = $this->backup_and_restore($course); + + // Check the quiz and qbank question categories in the target course, in particular the parent relationship. + $modinfo = get_fast_modinfo($targetcourseid); + + $targetquizzes = $modinfo->get_instances_of('quiz'); + $this->assertCount(1, $targetquizzes); + $targetquiz = reset($targetquizzes); + $targetquizcontext = \context_module::instance($targetquiz->id); + $targetquizcats = array_values( + $DB->get_records('question_categories', ['contextid' => $targetquizcontext->id], 'parent', 'id, name, parent') + ); + $this->assertCount(3, $targetquizcats); + $quiztop = $targetquizcats[0]; + $this->assertEquals(0, $quiztop->parent); + $quiznontop = $targetquizcats[1]; + $this->assertEquals($quiztop->id, $quiznontop->parent); + + $targetqbanks = $modinfo->get_instances_of('qbank'); + $this->assertCount(1, $targetqbanks); + $targetqbankcontext = \context_module::instance(reset($targetqbanks)->id); + $targetqbankcats = array_values( + $DB->get_records('question_categories', ['contextid' => $targetqbankcontext->id], 'parent', 'id, name, parent') + ); + $this->assertCount(3, $targetqbankcats); + $qbanktop = $targetqbankcats[0]; + $this->assertEquals(0, $qbanktop->parent); + $qbanknontop = $targetqbankcats[1]; + $this->assertEquals($qbanktop->id, $qbanknontop->parent); + } + /** * Test the content bank content through a backup and restore. */