diff --git a/mod/quiz/classes/output/edit_renderer.php b/mod/quiz/classes/output/edit_renderer.php index 21a8d6c9c33..9ddd5e93e0d 100644 --- a/mod/quiz/classes/output/edit_renderer.php +++ b/mod/quiz/classes/output/edit_renderer.php @@ -25,7 +25,6 @@ namespace mod_quiz\output; use core_question\local\bank\question_version_status; -use mod_quiz\question\bank\qbank_helper; use \mod_quiz\structure; use \html_writer; use qbank_previewquestion\question_preview_options; @@ -1066,7 +1065,7 @@ class edit_renderer extends \plugin_renderer_base { $temp = clone($question); $temp->questiontext = ''; - $temp->name = qbank_helper::describe_random_question($slot); + $temp->name = $structure->describe_random_slot($slot->id); $instancename = quiz_question_tostring($temp); $configuretitle = get_string('configurerandomquestion', 'quiz'); diff --git a/mod/quiz/classes/structure.php b/mod/quiz/classes/structure.php index cd451d5ffa7..777ceb4c470 100644 --- a/mod/quiz/classes/structure.php +++ b/mod/quiz/classes/structure.php @@ -68,6 +68,12 @@ class structure { /** @var bool caches the results of can_add_random_question. */ protected $canaddrandom = null; + /** @var array the slotids => question categories array for all slots containing a random question. */ + protected $randomslotcategories = null; + + /** @var array the slotids => question tags array for all slots containing a random question. */ + protected $randomslottags = null; + /** * Create an instance of this class representing an empty quiz. * @@ -1650,4 +1656,122 @@ class structure { $randomslot->insert($addonpage); } } + + /** + * Get a human-readable description of a random slot. + * + * @param int $slotid id of slot. + * @return string that can be used to display the random slot. + */ + public function describe_random_slot($slotid) { + $this->ensure_random_slot_info_loaded(); + + if (!isset($this->randomslotcategories[$slotid])) { + throw new coding_exception('Called describe_random_slot on slot id ' . + $slotid . ' which is not a random slot.'); + } + + // Build the random question name with categories and tags information and return. + $a = new stdClass(); + $a->category = $this->randomslotcategories[$slotid]; + $stringid = 'randomqnamecat'; + + if (!empty($this->randomslottags[$slotid])) { + $a->tags = $this->randomslottags[$slotid]; + $stringid = 'randomqnamecattags'; + } + + return shorten_text(get_string($stringid, 'quiz', $a), 255); + } + + /** + * Ensure that {@see load_random_slot_info()} has been called, so the data is available. + */ + protected function ensure_random_slot_info_loaded() { + if ($this->randomslotcategories == null) { + $this->load_random_slot_info(); + } + } + + /** + * Load information about the question categories and tags for all random slots, + */ + protected function load_random_slot_info() { + global $DB; + + // Find the random slots. + $allslots = $this->get_slots(); + foreach ($allslots as $key => $slot) { + if ($slot->qtype != 'random') { + unset($allslots[$key]); + } + } + if (empty($allslots)) { + // No random slots. Nothing to do. + $this->randomslotcategories = []; + $this->randomslottags = []; + return; + } + + // Loop over all random slots to build arrays of the data we will need. + $tagids = []; + $questioncategoriesids = []; + $randomcategoriesandtags = []; // An associative array of slotid => ['cat' => catid, 'tag' => [tagid, tagid, ...]]. + foreach ($allslots as $slotid => $slot) { + foreach ($slot->filtercondition as $name => $value) { + if ($name !== 'filter') { + continue; + } + + // Parse the filter condition. + foreach ($value as $filteroption => $filtervalue) { + if ($filteroption === 'category') { + $randomcategoriesandtags[$slotid]['cat'] = $filtervalue['values']; + $questioncategoriesids[] = $filtervalue['values'][0]; + } + + if ($filteroption === 'qtagids') { + foreach ($filtervalue as $qtagidsoption => $qtagidsvalue) { + if ($qtagidsoption !== 'values') { + continue; + } + foreach ($qtagidsvalue as $qtagidsvaluevalue) { + $randomcategoriesandtags[$slotid]['tag'][] = $qtagidsvaluevalue; + $tagids[] = $qtagidsvaluevalue; + } + } + } + } + } + } + + // Get names for all tags into a tagid => name array. + $tags = \core_tag_tag::get_bulk($tagids, 'id, rawname'); + $tagnames = array_map(fn($tag) => $tag->get_display_name(), $tags); + + // Get names for all question categories. + $categories = $DB->get_records_list('question_categories', 'id', $questioncategoriesids, + 'id', 'id, name, contextid, parent'); + $categorynames = []; + foreach ($categories as $id => $category) { + if ($category->name === 'top') { + $categoryname = $DB->get_field('question_categories', 'name', ['parent' => $id]); + } else { + $categoryname = $category->name; + } + $categorynames[$id] = $categoryname; + } + + // Now, put the data required for each slot into $this->randomslotcategories and $this->randomslottags. + foreach ($randomcategoriesandtags as $slotid => $catandtags) { + $this->randomslotcategories[$slotid] = $categorynames[$catandtags['cat'][0]]; + if (isset($catandtags['tag'])) { + $slottagnames = []; + foreach ($catandtags['tag'] as $tagid) { + $slottagnames[] = $tagnames[$tagid]; + } + $this->randomslottags[$slotid] = implode(', ', $slottagnames); + } + } + } } diff --git a/mod/quiz/lang/en/quiz.php b/mod/quiz/lang/en/quiz.php index fe28e8f8ca7..03b8e724221 100644 --- a/mod/quiz/lang/en/quiz.php +++ b/mod/quiz/lang/en/quiz.php @@ -844,6 +844,8 @@ $string['randomfromunavailabletag'] = '{$a} (unavailable)'; $string['randomnumber'] = 'Number of random questions'; $string['randomnosubcat'] = 'Questions from this category only, not its subcategories.'; $string['randomqname'] = 'Random question based on filter condition'; +$string['randomqnamecat'] = 'Random ({$a->category}) based on filter condition'; +$string['randomqnamecattags'] = 'Random ({$a->category}) based on filter condition with tags: {$a->tags}';$string['randomquestion'] = 'Random question'; $string['randomqnametags'] = 'Random question based on filter condition with tags: {$a}'; $string['randomquestion'] = 'Random question'; $string['randomquestion_help'] = 'A random question is a way of inserting a randomly-chosen question from a specified category or by a specified tag into an activity.'; diff --git a/mod/quiz/tests/behat/editing_add_random.feature b/mod/quiz/tests/behat/editing_add_random.feature index 7dc16b6dcb4..79e2a7a169d 100644 --- a/mod/quiz/tests/behat/editing_add_random.feature +++ b/mod/quiz/tests/behat/editing_add_random.feature @@ -77,8 +77,8 @@ Feature: Adding random questions to a quiz based on category and tags And I apply question bank filter "Tag" with value "foo" And I select "1" from the "randomcount" singleselect And I press "Add random question" - And I should see "Random question based on filter condition with tags: foo" on quiz page "1" - When I click on "Configure question" "link" in the "Random question based on filter condition with tags: foo" "list_item" + And I should see "Random (Questions Category 1) based on filter condition with tags: foo" on quiz page "1" + When I click on "Configure question" "link" in the "Random (Questions Category 1) based on filter condition with tags: foo" "list_item" Then I should see "Questions Category 1" And I should see "foo" And I should see "question 1 name" @@ -115,6 +115,6 @@ Feature: Adding random questions to a quiz based on category and tags | Name | New Random category | | Parent category | Default for Quiz 1 | And I press "Create category and add random question" - And I should see "Random question based on filter condition" on quiz page "1" - And I click on "Configure question" "link" in the "Random question based on filter condition" "list_item" + And I should see "Random (New Random category) based on filter condition" on quiz page "1" + And I click on "Configure question" "link" in the "Random (New Random category) based on filter condition" "list_item" Then I should see "New Random category" diff --git a/mod/quiz/tests/behat/editing_edit_random.feature b/mod/quiz/tests/behat/editing_edit_random.feature index df05f8344a6..827463f7ac0 100644 --- a/mod/quiz/tests/behat/editing_edit_random.feature +++ b/mod/quiz/tests/behat/editing_edit_random.feature @@ -45,10 +45,10 @@ Feature: Editing random questions already in a quiz based on category and tags And I apply question bank filter "Tag" with value "hard" And I press "Add random question" And I follow "Add page break" - When I click on "Configure question" "link" in the "Random question based on filter condition with tags: easy" "list_item" + When I click on "Configure question" "link" in the "Random (Questions Category 1) based on filter condition with tags: easy" "list_item" And I apply question bank filter "Tag" with value "essay" And I press "Update filter conditions" - Then I should see "Random question based on filter condition with tags: essay" on quiz page "1" - And I should see "Random question based on filter condition with tags: hard" on quiz page "2" - And I click on "Configure question" "link" in the "Random question based on filter condition with tags: hard" "list_item" + Then I should see "Random (Questions Category 1) based on filter condition with tags: essay" on quiz page "1" + And I should see "Random (Questions Category 1) based on filter condition with tags: essay, hard" on quiz page "2" + And I click on "Configure question" "link" in the "Random (Questions Category 1) based on filter condition with tags: hard" "list_item" And "hard" "autocomplete_selection" should be visible diff --git a/mod/quiz/tests/behat/editing_remove_multiple_questions.feature b/mod/quiz/tests/behat/editing_remove_multiple_questions.feature index 47df9df9d63..7a87eafc1f4 100644 --- a/mod/quiz/tests/behat/editing_remove_multiple_questions.feature +++ b/mod/quiz/tests/behat/editing_remove_multiple_questions.feature @@ -261,9 +261,9 @@ Feature: Edit quiz page - remove multiple questions And I click on "selectquestion-2" "checkbox" And I click on "Delete selected" "button" And I click on "Yes" "button" in the "Confirm" "dialogue" - Then I should see "Random question based on filter condition" on quiz page "1" - And I should not see "Random question based on filter condition" on quiz page "2" - And I should not see "Random question based on filter condition" on quiz page "3" + Then I should see "Random (Test questions) based on filter condition" on quiz page "1" + And I should not see "Random (Test questions) based on filter condition" on quiz page "2" + And I should not see "Random (Test questions) based on filter condition" on quiz page "3" And I should see "Total of marks: 1.00" And I should see "Questions: 1" diff --git a/mod/quiz/tests/behat/random_question.feature b/mod/quiz/tests/behat/random_question.feature index 15a7e047b68..f6f53f1f120 100644 --- a/mod/quiz/tests/behat/random_question.feature +++ b/mod/quiz/tests/behat/random_question.feature @@ -35,8 +35,8 @@ Feature: Moving a question to another category should not affect random question And I follow "a random question" And I apply question bank filter "Category" with value "Used category" And I press "Add random question" - And I should see "Random question based on filter condition" on quiz page "1" - And I click on "Configure question" "link" in the "Random question based on filter condition" "list_item" + And I should see "Random (Used category) based on filter condition" on quiz page "1" + And I click on "Configure question" "link" in the "Random (Used category) based on filter condition" "list_item" And I should see "Used category" And I am on "Course 1" course homepage And I navigate to "Question bank" in current page administration @@ -49,8 +49,8 @@ Feature: Moving a question to another category should not affect random question Then I should see "Test question to be moved" And I should see "Subcategory (1)" And I am on the "Quiz 1" "mod_quiz > Edit" page - And I should see "Random question based on filter condition" on quiz page "1" - And I click on "Configure question" "link" in the "Random question based on filter condition" "list_item" + And I should see "Random (Used category) based on filter condition" on quiz page "1" + And I click on "Configure question" "link" in the "Random (Used category) based on filter condition" "list_item" And I should see "Used category" @javascript @@ -60,7 +60,7 @@ Feature: Moving a question to another category should not affect random question And I follow "a random question" And I apply question bank filter "Category" with value "Used category" And I press "Add random question" - And I should see "Random question based on filter condition" on quiz page "1" + And I should see "Random (Used category) based on filter condition" on quiz page "1" And I am on the "Course 1" "core_question > course question categories" page And I click on "Edit this category" "link" in the "Used category" "list_item" And I set the following fields to these values: @@ -70,4 +70,4 @@ Feature: Moving a question to another category should not affect random question Then I should see "Used category new" And I should see "I was edited" in the "Used category new" "list_item" And I am on the "Quiz 1" "mod_quiz > Edit" page - And I should see "Random question based on filter condition" on quiz page "1" + And I should see "Random (Used category new) based on filter condition" on quiz page "1"