diff --git a/question/type/multianswer/questiontype.php b/question/type/multianswer/questiontype.php index 0c44b18a56f..9c662ab6fc0 100644 --- a/question/type/multianswer/questiontype.php +++ b/question/type/multianswer/questiontype.php @@ -110,8 +110,7 @@ class qtype_multianswer extends question_type { parent::get_question_options($question); // Get relevant data indexed by positionkey from the multianswers table. - $sequence = $DB->get_field('question_multianswer', 'sequence', - array('question' => $question->id), MUST_EXIST); + $sequence = $DB->get_field('question_multianswer', 'sequence', ['question' => $question->id]); if (empty($sequence)) { $question->options->questions = []; diff --git a/question/type/multianswer/tests/restore_test.php b/question/type/multianswer/tests/restore_test.php new file mode 100644 index 00000000000..543e8ab5a29 --- /dev/null +++ b/question/type/multianswer/tests/restore_test.php @@ -0,0 +1,97 @@ +. + +namespace qtype_multianswer; + +/** + * Unit tests for + * + * @package qtype_multianswer + * @copyright 2025 onwards Catalyst IT EU {@link https://catalyst-eu.net} + * @author Mark Johnson + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @covers \restore_qtype_multianswer_plugin + */ +final class restore_test extends \advanced_testcase { + /** + * Duplicate a quiz containing a multianswer question with no multianswer record. + */ + public function test_restore_quiz_with_edited_questions(): void { + global $CFG, $DB, $USER; + require_once($CFG->dirroot . '/backup/util/includes/backup_includes.php'); + require_once($CFG->dirroot . '/backup/util/includes/restore_includes.php'); + $this->resetAfterTest(); + $this->setAdminUser(); + + // Create a course and a user with editing teacher capabilities. + $generator = $this->getDataGenerator(); + $course1 = $generator->create_course(); + $context = \context_course::instance($course1->id); + $questiongenerator = $this->getDataGenerator()->get_plugin_generator('core_question'); + $initialcount = $DB->count_records('question'); + + // Create a question category. + $cat = $questiongenerator->create_question_category(['contextid' => $context->id]); + + // Create a quiz containing a multianswer question from the qbank. + $quiz = $this->getDataGenerator()->get_plugin_generator('mod_quiz')->create_instance(['course' => $course1->id]); + $question = $questiongenerator->create_question('multianswer', 'twosubq', ['category' => $cat->id]); + quiz_add_quiz_question($question->id, $quiz); + + // Delete the multianswer record. + $DB->delete_records('question_multianswer', ['question' => $question->id]); + + // Confirm we have created 3 additional questions (one parent, 2 children). + $this->assertEquals($initialcount + 3, $DB->count_records('question')); + + // Backup quiz. + $bc = new \backup_controller( + \backup::TYPE_1ACTIVITY, + $quiz->cmid, + \backup::FORMAT_MOODLE, + \backup::INTERACTIVE_NO, + \backup::MODE_IMPORT, + $USER->id, + ); + $backupid = $bc->get_backupid(); + $bc->execute_plan(); + $bc->destroy(); + + // Restore the backup into the same course. + $rc = new \restore_controller( + $backupid, + $course1->id, + \backup::INTERACTIVE_NO, + \backup::MODE_IMPORT, + $USER->id, + \backup::TARGET_CURRENT_ADDING, + ); + $rc->execute_precheck(); + $rc->execute_plan(); + $rc->destroy(); + + // Both quizzes should refer to the same original question. + $quizzes = get_fast_modinfo($course1->id)->get_instances_of('quiz'); + $this->assertCount(2, $quizzes); + foreach ($quizzes as $quiz) { + $structure = \mod_quiz\question\bank\qbank_helper::get_question_structure($quiz->instance, $quiz->context); + $this->assertEquals($structure[1]->questionid, $question->id); + } + + // There should be no additional questions created during the restore. + $this->assertEquals($initialcount + 3, $DB->count_records('question')); + } +}