From 259bd79e2c72408a4ef6bea548e0a5f75d71dff6 Mon Sep 17 00:00:00 2001 From: Tim Hunt Date: Tue, 3 Sep 2024 17:07:58 +0200 Subject: [PATCH] MDL-77625 question restore: fix pre-parsing of questions Restore of categories and questions happens in several phases. First, the file is scanned for which questions and categories it contains, to work out if these are new questions which need to be restored, or if they already exist in the database in a place that can be used. That code had not been updated to copy with the Moodle 4.0 versionning changes, so it is updated here (while still keeping the code to cope with the old backup format.) --- backup/util/dbops/restore_dbops.class.php | 7 ++--- ...store_questions_parser_processor.class.php | 28 ++++++++++++++----- 2 files changed, 24 insertions(+), 11 deletions(-) diff --git a/backup/util/dbops/restore_dbops.class.php b/backup/util/dbops/restore_dbops.class.php index 0633fd8567c83..d587e7748ac70 100644 --- a/backup/util/dbops/restore_dbops.class.php +++ b/backup/util/dbops/restore_dbops.class.php @@ -671,8 +671,7 @@ public static function prechek_precheck_qbanks_by_level($restoreid, $courseid, $ $questions = self::restore_get_questions($restoreid, $category->id); // Collect all the questions for this category into memory so we only talk to the DB once. - $questioncache = $DB->get_records_sql_menu('SELECT q.id, - q.stamp + $questioncache = $DB->get_records_sql_menu('SELECT q.stamp, q.id FROM {question} q JOIN {question_versions} qv ON qv.questionid = q.id @@ -683,8 +682,8 @@ public static function prechek_precheck_qbanks_by_level($restoreid, $courseid, $ WHERE qc.id = ?', array($matchcat->id)); foreach ($questions as $question) { - if (isset($questioncache[$question->stamp." ".$question->version])) { - $matchqid = $questioncache[$question->stamp." ".$question->version]; + if (isset($questioncache[$question->stamp])) { + $matchqid = $questioncache[$question->stamp]; } else { $matchqid = false; } diff --git a/backup/util/helper/restore_questions_parser_processor.class.php b/backup/util/helper/restore_questions_parser_processor.class.php index 129b2f40ab67a..be3d0c28108b7 100644 --- a/backup/util/helper/restore_questions_parser_processor.class.php +++ b/backup/util/helper/restore_questions_parser_processor.class.php @@ -35,22 +35,35 @@ * TODO: Complete phpdocs */ class restore_questions_parser_processor extends grouped_parser_processor { + /** @var string XML path in the questions.xml backup file to question categories. */ + protected const CATEGORY_PATH = '/question_categories/question_category'; - protected $restoreid; - protected $lastcatid; + /** @var string XML path in the questions.xml to question elements within question_category (Moodle 4.0+). */ + protected const QUESTION_SUBPATH = + '/question_bank_entries/question_bank_entry/question_version/question_versions/questions/question'; + + /** @var string XML path in the questions.xml to question elements within question_category (before Moodle 4.0). */ + protected const LEGACY_QUESTION_SUBPATH = '/questions/question'; + + /** @var string identifies the current restore. */ + protected string $restoreid; + + /** @var int during the restore, this tracks the last category we saw. Any questions we see will be in here. */ + protected int $lastcatid; public function __construct($restoreid) { $this->restoreid = $restoreid; $this->lastcatid = 0; - parent::__construct(array()); + parent::__construct(); // Set the paths we are interested on - $this->add_path('/question_categories/question_category'); - $this->add_path('/question_categories/question_category/questions/question'); + $this->add_path(self::CATEGORY_PATH); + $this->add_path(self::CATEGORY_PATH . self::QUESTION_SUBPATH); + $this->add_path(self::CATEGORY_PATH . self::LEGACY_QUESTION_SUBPATH); } protected function dispatch_chunk($data) { // Prepare question_category record - if ($data['path'] == '/question_categories/question_category') { + if ($data['path'] == self::CATEGORY_PATH) { $info = (object)$data['tags']; $itemname = 'question_category'; $itemid = $info->id; @@ -58,7 +71,8 @@ protected function dispatch_chunk($data) { $this->lastcatid = $itemid; // Prepare question record - } else if ($data['path'] == '/question_categories/question_category/questions/question') { + } else if ($data['path'] == self::CATEGORY_PATH . self::QUESTION_SUBPATH || + $data['path'] == self::CATEGORY_PATH . self::LEGACY_QUESTION_SUBPATH) { $info = (object)$data['tags']; $itemname = 'question'; $itemid = $info->id;