This commit is contained in:
Ilya Tregubov 2024-09-18 15:30:40 +08:00
commit fb54a5a3f5
7 changed files with 145 additions and 19 deletions

View File

@ -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;
@ -1067,7 +1066,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');

View File

@ -69,6 +69,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.
*
@ -1701,4 +1707,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(int $slotid): string {
$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(): void {
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(): void {
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);
}
}
}
}

View File

@ -849,6 +849,9 @@ $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.';

View File

@ -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"

View File

@ -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

View File

@ -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"

View File

@ -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 open the action menu in "Used category" "list_item"
And I choose "Edit" in the open action menu
@ -72,4 +72,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"