From 47fb08fc6d82bab3e4c8299596c7b7be7eee4177 Mon Sep 17 00:00:00 2001 From: Mark Johnson Date: Tue, 3 Jun 2025 14:08:54 +0100 Subject: [PATCH] MDL-85166 question: Update move_question_set_references This backports the applicable part of MDL-85210 to 4.5. move_question_set_references expected the set reference to use the old filter format. This change converts the filter to the new format if required, before updating the category and context ids. --- lib/questionlib.php | 19 +++--- lib/tests/questionlib_test.php | 102 +++++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+), 9 deletions(-) diff --git a/lib/questionlib.php b/lib/questionlib.php index e59d5e37383..f4833c302e4 100644 --- a/lib/questionlib.php +++ b/lib/questionlib.php @@ -782,16 +782,17 @@ function move_question_set_references(int $oldcategoryid, int $newcatgoryid, if ($delete || $oldcontextid !== $newcontextid) { $setreferences = $DB->get_recordset('question_set_references', ['questionscontextid' => $oldcontextid]); foreach ($setreferences as $setreference) { - $filter = json_decode($setreference->filtercondition); - if (isset($filter->questioncategoryid)) { - if ((int)$filter->questioncategoryid === $oldcategoryid) { - $setreference->questionscontextid = $newcontextid; - if ($oldcategoryid !== $newcatgoryid) { - $filter->questioncategoryid = $newcatgoryid; - $setreference->filtercondition = json_encode($filter); - } - $DB->update_record('question_set_references', $setreference); + $filter = json_decode($setreference->filtercondition, true); + if (isset($filter['questioncategoryid'])) { + $filter = question_reference_manager::convert_legacy_set_reference_filter_condition($filter); + } + if ((int)$filter['filter']['category']['values'][0] === $oldcategoryid) { + $setreference->questionscontextid = $newcontextid; + if ($oldcategoryid !== $newcatgoryid) { + $filter['filter']['category']['values'][0] = $newcatgoryid; + $setreference->filtercondition = json_encode($filter); } + $DB->update_record('question_set_references', $setreference); } } $setreferences->close(); diff --git a/lib/tests/questionlib_test.php b/lib/tests/questionlib_test.php index 270c7bf75f0..ec3a1001a44 100644 --- a/lib/tests/questionlib_test.php +++ b/lib/tests/questionlib_test.php @@ -16,6 +16,8 @@ namespace core; +use core_question\local\bank\question_bank_helper; +use mod_quiz\quiz_settings; use question_bank; defined('MOODLE_INTERNAL') || die(); @@ -2437,4 +2439,104 @@ final class questionlib_test extends \advanced_testcase { $this->assertEquals(2, $nextversion); } + /** + * Update the context for a set reference, keeping the original category. + * + * @covers ::move_question_set_references() + */ + public function test_move_question_set_references_context(): void { + $this->setAdminUser(); + $sitecontext = \context_system::instance(); + $topcategory = question_get_top_category($sitecontext->id, true); + $randomcategory = self::getDataGenerator()->get_plugin_generator('core_question')->create_question_category( + ['parent' => $topcategory->id], + ); + // Create a course with a quiz containing a random question from the system context. + $randomcourse = self::getDataGenerator()->create_course(['shortname' => 'Random']); + $coursecontext = \context_course::instance($randomcourse->id); + $randomquiz = self::getDataGenerator()->get_plugin_generator('mod_quiz')->create_instance( + [ + 'course' => $randomcourse->id, + 'grade' => 100.0, + 'sumgrades' => 2, + 'layout' => '1,0', + ], + ); + + $randomquizsettings = quiz_settings::create($randomquiz->id); + $structure = $randomquizsettings->get_structure(); + + $filtercondition = [ + 'filter' => [ + 'category' => [ + 'jointype' => \core_question\local\bank\condition::JOINTYPE_DEFAULT, + 'values' => [$randomcategory->id], + 'filteroptions' => ['includesubcategories' => true], + ], + ], + ]; + $structure->add_random_questions(1, 1, $filtercondition); + $structure = $randomquizsettings->get_structure(); + $randomquestion = $structure->get_question_in_slot(1); + + $this->assertEquals($randomquestion->contextid, $sitecontext->id); + $this->assertEquals($randomquestion->filtercondition['filter']['category']['values'][0], $randomcategory->id); + + move_question_set_references($randomcategory->id, $randomcategory->id, $sitecontext->id, $coursecontext->id); + + $structure = $randomquizsettings->get_structure(); + $randomquestion = $structure->get_question_in_slot(1); + + $this->assertEquals($randomquestion->contextid, $coursecontext->id); + $this->assertEquals($randomquestion->filtercondition['filter']['category']['values'][0], $randomcategory->id); + } + + /** + * Update the context and category for a set reference. + * + * @covers ::move_question_set_references() + */ + public function test_move_question_set_references_category(): void { + $this->setAdminUser(); + $sitecontext = \context_system::instance(); + $sitetopcategory = question_get_top_category($sitecontext->id, true); + // Create a course with a quiz containing a random question from the system context. + $randomcourse = self::getDataGenerator()->create_course(['shortname' => 'Random']); + $coursecontext = \context_course::instance($randomcourse->id); + $coursetopcategory = question_get_top_category($coursecontext->id, true); + $randomquiz = self::getDataGenerator()->get_plugin_generator('mod_quiz')->create_instance( + [ + 'course' => $randomcourse->id, + 'grade' => 100.0, + 'sumgrades' => 2, + 'layout' => '1,0', + ], + ); + $randomquizsettings = quiz_settings::create($randomquiz->id); + + $structure = $randomquizsettings->get_structure(); + $filtercondition = [ + 'filter' => [ + 'category' => [ + 'jointype' => \core_question\local\bank\condition::JOINTYPE_DEFAULT, + 'values' => [$sitetopcategory->id], + 'filteroptions' => ['includesubcategories' => true], + ], + ], + ]; + $structure->add_random_questions(1, 1, $filtercondition); + $structure = $randomquizsettings->get_structure(); + $randomquestion = $structure->get_question_in_slot(1); + + $this->assertEquals($randomquestion->contextid, $sitecontext->id); + $this->assertEquals($randomquestion->filtercondition['filter']['category']['values'][0], $sitetopcategory->id); + + move_question_set_references($sitetopcategory->id, $coursetopcategory->id, $sitecontext->id, $coursecontext->id); + + $structure = $randomquizsettings->get_structure(); + $randomquestion = $structure->get_question_in_slot(1); + + $this->assertEquals($randomquestion->contextid, $coursecontext->id); + $this->assertEquals($randomquestion->filtercondition['filter']['category']['values'][0], $coursetopcategory->id); + } }