Skip to content

Commit

Permalink
MDL-72321 core: backup/restore filter condition
Browse files Browse the repository at this point in the history
  • Loading branch information
Nathan Nguyen authored and marxjohnson committed Aug 24, 2023
1 parent 83c8e7d commit 5a43635
Show file tree
Hide file tree
Showing 4 changed files with 99 additions and 12 deletions.
23 changes: 19 additions & 4 deletions backup/moodle2/restore_stepslib.php
Original file line number Diff line number Diff line change
Expand Up @@ -6191,15 +6191,30 @@ public function process_question_set_reference($data) {
$data = (object) $data;
$data->usingcontextid = $this->get_mappingid('context', $data->usingcontextid);
$data->itemid = $this->get_new_parentid('quiz_question_instance');
$filtercondition = json_decode($data->filtercondition);
if ($category = $this->get_mappingid('question_category', $filtercondition->questioncategoryid)) {
$filtercondition->questioncategoryid = $category;
$filtercondition = json_decode($data->filtercondition, true);

if (!isset($filtercondition['filter'])) {
// Pre-4.3, convert the old filtercondition format to the new format.
$filtercondition = \core_question\question_reference_manager::convert_legacy_set_reference_filter_condition(
$filtercondition);
}
$data->filtercondition = json_encode($filtercondition);

// Map category id used for category filter condition and corresponding context id.
$oldcategoryid = $filtercondition['filter']['category']['values'][0];
$newcategoryid = $this->get_mappingid('question_category', $oldcategoryid);
$filtercondition['filter']['category']['values'][0] = $newcategoryid;

if ($context = $this->get_mappingid('context', $data->questionscontextid)) {
$data->questionscontextid = $context;
}

$filtercondition['cat'] = implode(',', [
$filtercondition['filter']['category']['values'][0],
$data->questionscontextid,
]);

$data->filtercondition = json_encode($filtercondition);

$DB->insert_record('question_set_references', $data);
}
}
Expand Down
Binary file not shown.
61 changes: 61 additions & 0 deletions mod/quiz/tests/quiz_question_restore_test.php
Original file line number Diff line number Diff line change
Expand Up @@ -508,4 +508,65 @@ public function test_backup_restore_question_slots(): void {
$this->assertEquals($originalslot->maxmark, $restoredslot->maxmark);
}
}

/**
* Test pre 4.3 quiz restore for random question filter conditions.
*
* @covers \restore_question_set_reference_data_trait::process_question_set_reference
*/
public function test_pre_43_quiz_restore_for_random_question_filtercondition() {
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/moodle_42_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.
$modinfo = get_fast_modinfo($newcourseid);
$quiz = array_values($modinfo->get_instances_of('quiz'))[0];
$quizobj = \mod_quiz\quiz_settings::create($quiz->instance);
$structure = \mod_quiz\structure::create_for_quiz($quizobj);

// Count the questions in quiz qbank.
$context = \context_module::instance(get_coursemodule_from_instance("quiz", $quizobj->get_quizid(), $newcourseid)->id);
$this->assertEquals(2, $this->question_count($context->id));

// Are the correct slots returned?
$slots = $structure->get_slots();
$this->assertCount(1, $slots);

// Check that the filtercondition now matches the 4.3 structure.
foreach ($slots as $slot) {
$setreference = $DB->get_record('question_set_references',
['itemid' => $slot->id, 'component' => 'mod_quiz', 'questionarea' => 'slot']);
$filterconditions = json_decode($setreference->filtercondition, true);
$this->assertArrayHasKey('cat', $filterconditions);
$this->assertArrayHasKey('jointype', $filterconditions);
$this->assertArrayHasKey('qpage', $filterconditions);
$this->assertArrayHasKey('qperpage', $filterconditions);
$this->assertArrayHasKey('filter', $filterconditions);
$this->assertArrayHasKey('category', $filterconditions['filter']);
$this->assertArrayHasKey('qtagids', $filterconditions['filter']);
$this->assertArrayNotHasKey('questioncategoryid', $filterconditions);
$this->assertArrayNotHasKey('tags', $filterconditions);
$expectedtags = \core_tag_tag::get_by_name_bulk(1, ['foo', 'bar']);
$expectedtagids = array_values(array_map(fn($expectedtag) => $expectedtag->id, $expectedtags));
$this->assertEquals($expectedtagids, $filterconditions['filter']['qtagids']['values']);
$expectedcategory = $DB->get_record('question_categories', ['idnumber' => 'RAND']);
$this->assertEquals($expectedcategory->id, $filterconditions['filter']['category']['values'][0]);
$expectedcat = implode(',', [$expectedcategory->id, $expectedcategory->contextid]);
$this->assertEquals($expectedcat, $filterconditions['cat']);
}
}
}
27 changes: 19 additions & 8 deletions question/classes/question_reference_manager.php
Original file line number Diff line number Diff line change
Expand Up @@ -86,28 +86,39 @@ public static function questions_with_references(array $questionids): array {
* @return array Post-4.3 filter condition.
*/
public static function convert_legacy_set_reference_filter_condition(array $filtercondition): array {
if (!isset($filtercondition['filters'])) {
$filtercondition['filters'] = [];
if (!isset($filtercondition['filter'])) {
$filtercondition['filter'] = [];

// Question category filter.
if (isset($filtercondition['questioncategoryid'])) {
$filtercondition['filters']['category'] = [
'jointype' => \qbank_managecategories\category_condition::JOINTYPE_DEFAULT,
'values' => [$filtercondition['questioncategoryid']],
'includesubcategories' => $filtercondition['includingsubcategories'],
$filtercondition['filter']['category'] = [
'jointype' => \qbank_managecategories\category_condition::JOINTYPE_DEFAULT,
'values' => [$filtercondition['questioncategoryid']],
'includesubcategories' => $filtercondition['includingsubcategories'],
];
unset($filtercondition['questioncategoryid']);
unset($filtercondition['includingsubcategories']);
}

// Tag filters.
if (isset($filtercondition['tags'])) {
$filtercondition['filters']['qtagid'] = [
// Get the names of the tags in the condition. Find or create corresponding tags,
// and set their ids in the new condition.
$oldtags = array_map(fn($oldtag) => explode(',', $oldtag)[1], $filtercondition['tags']);
$newtags = \core_tag_tag::create_if_missing(1, $oldtags);
$newtagids = array_map(fn($newtag) => $newtag->id, $newtags);

$filtercondition['filter']['qtagids'] = [
'jointype' => \qbank_tagquestion\tag_condition::JOINTYPE_DEFAULT,
'values' => $filtercondition['tags']
'values' => array_values($newtagids),
];
unset($filtercondition['tags']);
}
// Add additional default properties to the filtercondition.
$filtercondition['tabname'] = 'questions';
$filtercondition['qpage'] = 0;
$filtercondition['qperpage'] = 100;
$filtercondition['jointype'] = \core\output\datafilter::JOINTYPE_ALL;
}
return $filtercondition;
}
Expand Down

0 comments on commit 5a43635

Please sign in to comment.