Skip to content

Commit

Permalink
Merge branch 'MDL-83264-403-1' of https://github.com/mihailges/moodle
Browse files Browse the repository at this point in the history
…into MOODLE_403_STABLE
  • Loading branch information
junpataleta committed Oct 1, 2024
2 parents d56e90c + f2f64d4 commit 0138b52
Show file tree
Hide file tree
Showing 3 changed files with 210 additions and 14 deletions.
67 changes: 54 additions & 13 deletions mod/quiz/classes/structure.php
Original file line number Diff line number Diff line change
Expand Up @@ -1494,7 +1494,9 @@ protected function load_random_slot_info(): void {
// 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, ...]].
// An associative array of slotid. Example structure:
// ['cat' => [values => catid, 'includesubcategories' => true, 'tag' => [tagid, tagid, ...]].
$randomcategoriesandtags = [];
foreach ($allslots as $slotid => $slot) {
foreach ($slot->filtercondition as $name => $value) {
if ($name !== 'filter') {
Expand All @@ -1504,8 +1506,9 @@ protected function load_random_slot_info(): void {
// Parse the filter condition.
foreach ($value as $filteroption => $filtervalue) {
if ($filteroption === 'category') {
$randomcategoriesandtags[$slotid]['cat'] = $filtervalue['values'];
$questioncategoriesids[] = $filtervalue['values'][0];
$randomcategoriesandtags[$slotid]['cat']['values'] = $questioncategoriesids[] = $filtervalue['values'][0];
$randomcategoriesandtags[$slotid]['cat']['includesubcategories'] =
$filtervalue['filteroptions']['includesubcategories'] ?? false;
}

if ($filteroption === 'qtagids') {
Expand All @@ -1530,19 +1533,13 @@ protected function load_random_slot_info(): void {
// 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]];
$qcategoryid = $catandtags['cat']['values'];
$qcategory = $categories[$qcategoryid];
$includesubcategories = $catandtags['cat']['includesubcategories'];
$this->randomslotcategories[$slotid] = $this->get_used_category_description($qcategory, $includesubcategories);
if (isset($catandtags['tag'])) {
$slottagnames = [];
foreach ($catandtags['tag'] as $tagid) {
Expand All @@ -1552,4 +1549,48 @@ protected function load_random_slot_info(): void {
}
}
}

/**
* Returns a description of the used question category, taking into account the context and whether subcategories are
* included.
*
* @param stdClass $qcategory The question category object containing category details.
* @param bool $includesubcategories Whether subcategories are included.
* @return string The generated description based on the used category.
* @throws coding_exception If the context level is unsupported.
*/
private function get_used_category_description(stdClass $qcategory, bool $includesubcategories): string {
if ($qcategory->name === 'top') { // This is a "top" question category.
if (!$includesubcategories) {
// Question categories labeled as "top" cannot directly contain questions. If the subcategories that may
// hold questions are excluded, the generated random questions will be invalid. Thus, return a description
// that informs the user about the issues associated with these types of generated random questions.
return get_string('randomfaultynosubcat', 'mod_quiz');
}

$context = \context::instance_by_id($qcategory->contextid);

switch ($context->contextlevel) {
case CONTEXT_MODULE:
return get_string('randommodulewithsubcat', 'mod_quiz');

case CONTEXT_COURSE:
return get_string('randomcoursewithsubcat', 'mod_quiz');

case CONTEXT_COURSECAT:
$contextname = shorten_text($context->get_context_name(false), 100);
return get_string('randomcoursecatwithsubcat', 'mod_quiz', $contextname);

case CONTEXT_SYSTEM:
return get_string('randomsystemwithsubcat', 'mod_quiz');

default:
throw new coding_exception('Unsupported context.');
}
}
// Otherwise, return the description of the used standard question category, also indicating whether subcategories
// are included.
return $includesubcategories ? get_string('randomcatwithsubcat', 'mod_quiz', $qcategory->name) :
$qcategory->name;
}
}
6 changes: 6 additions & 0 deletions mod/quiz/lang/en/quiz.php
Original file line number Diff line number Diff line change
Expand Up @@ -804,11 +804,16 @@
$string['quiztimer'] = 'Quiz Timer';
$string['quizwillopen'] = 'This quiz will open {$a}';
$string['random'] = 'Random question';
$string['randomcatwithsubcat'] = '{$a} and subcategories';
$string['randomcoursecatwithsubcat'] = 'Any category inside course category {$a}';
$string['randomcoursewithsubcat'] = 'Any category in this course';
$string['randomcreate'] = 'Create random questions';
$string['randomediting'] = 'Editing a random question';
$string['randomfaultynosubcat'] = 'Faulty question';
$string['randomfromcategory'] = 'Random question from category:';
$string['randomfromexistingcategory'] = 'Random question from an existing category';
$string['randomfromunavailabletag'] = '{$a} (unavailable)';
$string['randommodulewithsubcat'] = 'Any category of this quiz';
$string['randomnumber'] = 'Number of random questions';
$string['randomnosubcat'] = 'Questions from this category only, not its subcategories.';
$string['randomqname'] = 'Random question based on filter condition';
Expand All @@ -823,6 +828,7 @@
The "random" questions will be selected from the questions that have all these tags.';
$string['randomquestionusinganewcategory'] = 'Random question using a new category';
$string['randomsystemwithsubcat'] = 'Any system-level category';
$string['randomwithsubcat'] = 'Questions from this category and its subcategories.';
$string['readytosend'] = 'You are about to send your whole quiz to be graded. Are you sure you want to continue?';
$string['reattemptquiz'] = 'Re-attempt quiz';
Expand Down
151 changes: 150 additions & 1 deletion mod/quiz/tests/behat/editing_add_random.feature
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ Feature: Adding random questions to a quiz based on category and tags

Scenario: A random question can be added to the quiz
Given I am on the "Quiz 1" "mod_quiz > Edit" page logged in as "teacher1"
When I open the "last" add to quiz menu
And I open the "last" add to quiz menu
And I follow "a random question"
And I apply question bank filter "Tag" with value "foo"
And I select "1" from the "randomcount" singleselect
Expand All @@ -83,6 +83,155 @@ Feature: Adding random questions to a quiz based on category and tags
And I should see "foo"
And I should see "question 1 name"
And I should see "\"listen\" & \"answer\""
# Include subcategories.
And I navigate to "Questions" in current page administration
And I open the "Page 1" add to quiz menu
And I follow "a random question"
And I set the field "Also show questions from subcategories" to "1"
And I click on "Apply filters" "button"
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 (Questions Category 1 and subcategories) based on filter condition with tags: foo" on quiz page "1"
And I click on "Configure question" "link" in the "Random (Questions Category 1 and subcategories) based on filter condition with tags: foo" "list_item"
And I should see "Questions Category 1"
And I should see "foo"
And I should see "question 1 name"
And I should see "\"listen\" & \"answer\""
And I should see "question 3 name"

Scenario: A random question from the course's top category can be added to the quiz
Given I am on the "Quiz 1" "mod_quiz > Edit" page logged in as "teacher1"
And I open the "last" add to quiz menu
And I follow "a random question"
And I apply question bank filter "Category" with value "Top for Course 1"
And I set the field "Also show questions from subcategories" to "1"
And I click on "Apply filters" "button"
And I apply question bank filter "Tag" with value "foo"
And I select "1" from the "randomcount" singleselect
When I press "Add random question"
Then I should see "Random (Any category in this course) based on filter condition with tags: foo" on quiz page "1"
And I click on "Configure question" "link" in the "Random (Any category in this course) based on filter condition with tags: foo" "list_item"
And I should see "Top for Course 1"
And I should see "foo"
And I should see "question 1 name"
And I should see "\"listen\" & \"answer\""

Scenario: A random question from the quiz's top category can be added to the quiz
Given the following "question categories" exist:
| contextlevel | reference | name |
| Activity module | quiz1 | Quiz 1 category |
And the following "questions" exist:
| questioncategory | qtype | name | user | questiontext |
| Quiz 1 category | essay | quiz 1 question 1 name | teacher1 | Quiz 1 question 1 text |
| Quiz 1 category | essay | quiz 1 question 2 name | teacher1 | Quiz 1 question 2 text |
And the following "core_question > Tags" exist:
| question | tag |
| quiz 1 question 1 name | foo |
And I am on the "Quiz 1" "mod_quiz > Edit" page logged in as "teacher1"
And I open the "last" add to quiz menu
And I follow "a random question"
And I apply question bank filter "Category" with value "Top for Quiz 1"
And I set the field "Also show questions from subcategories" to "1"
And I click on "Apply filters" "button"
And I apply question bank filter "Tag" with value "foo"
And I select "1" from the "randomcount" singleselect
When I press "Add random question"
Then I should see "Random (Any category of this quiz) based on filter condition with tags: foo" on quiz page "1"
And I click on "Configure question" "link" in the "Random (Any category of this quiz) based on filter condition with tags: foo" "list_item"
And I should see "Top for Quiz 1"
And I should see "foo"
And I should see "quiz 1 question 1 name"
And I should not see "quiz 1 question 2 name"

Scenario: A random question from the course category's top category can be added to the quiz.
Given the following "system role assigns" exist:
| user | role | contextlevel |
| teacher1 | editingteacher | Category |
And the following "categories" exist:
| name | category | idnumber |
| Category 1 | 0 | CAT1 |
And the following "question categories" exist:
| contextlevel | reference | name |
| Category | CAT1 | Default for Category 1 |
And I am on the "Course 1" "core_question > course question bank" page logged in as "teacher1"
# Create a question in the 'Default for Category 1' category.
And I press "Create a new question ..."
And I set the field "item_qtype_essay" to "1"
And I click on "Add" "button" in the "Choose a question type to add" "dialogue"
And I set the field "Category" to "Default for Category 1"
And I set the field "Question name" to "default for category 1 question 1 name"
And I set the field "Question text" to "Default for Category 1 question 1 text"
And I press "id_submitbutton"
# Create a second question in the 'Default for Category 1' category.
And I press "Create a new question ..."
And I set the field "item_qtype_essay" to "1"
And I click on "Add" "button" in the "Choose a question type to add" "dialogue"
And I set the field "Category" to "Default for Category 1"
And I set the field "Question name" to "default for category 1 question 2 name"
And I set the field "Question text" to "Default for Category 1 question 2 text"
And I press "id_submitbutton"
# Add a tag to the second question.
And I choose "Manage tags" action for "default for category 1 question 2 name" in the question bank
And I set the field "Tags" to "bar"
And I click on "Save changes" "button" in the "Question tags" "dialogue"
And I am on the "Quiz 1" "mod_quiz > Edit" page logged in as "teacher1"
And I open the "last" add to quiz menu
And I follow "a random question"
And I apply question bank filter "Category" with value "Top for Category 1"
And I set the field "Also show questions from subcategories" to "1"
And I click on "Apply filters" "button"
And I apply question bank filter "Tag" with value "bar"
And I select "1" from the "randomcount" singleselect
When I press "Add random question"
Then I should see "Random (Any category inside course category Category 1) based on filter condition with tags: bar" on quiz page "1"
And I click on "Configure question" "link" in the "Random (Any category inside course category Category 1) based on filter condition with tags: bar" "list_item"
And I should see "Top for Category 1"
And I should see "bar"
And I should see "default for category 1 question 2 name"
And I should not see "default for category 1 question 1 name"

Scenario: A random question from the system's top category can be added to the quiz
Given the following "system role assigns" exist:
| user | role | contextlevel |
| teacher1 | editingteacher | System |
And the following "question categories" exist:
| contextlevel | reference | name |
| System | | System category |
And the following "questions" exist:
| questioncategory | qtype | name | user | questiontext |
| System category | essay | system question 1 name | admin | System question 1 text |
| System category | essay | system question 2 name | admin | System question 2 text |
And the following "core_question > Tags" exist:
| question | tag |
| system question 1 name | foo |
And I am on the "Quiz 1" "mod_quiz > Edit" page logged in as "admin"
And I open the "last" add to quiz menu
And I follow "a random question"
And I apply question bank filter "Category" with value "Top for System"
And I set the field "Also show questions from subcategories" to "1"
And I click on "Apply filters" "button"
And I apply question bank filter "Tag" with value "foo"
And I select "1" from the "randomcount" singleselect
When I press "Add random question"
Then I should see "Random (Any system-level category) based on filter condition with tags: foo" on quiz page "1"
And I click on "Configure question" "link" in the "Random (Any system-level category) based on filter condition with tags: foo" "list_item"
And I should see "Top for System"
And I should see "foo"
And I should see "system question 1 name"
And I should not see "system question 2 name"

Scenario: A random question from a top category, excluding subcategories, shows an indicator of being faulty
Given I am on the "Quiz 1" "mod_quiz > Edit" page logged in as "teacher1"
And I open the "last" add to quiz menu
And I follow "a random question"
And I apply question bank filter "Category" with value "Top for Course 1"
And I set the field "Also show questions from subcategories" to "0"
And I click on "Apply filters" "button"
And I apply question bank filter "Tag" with value "foo"
And I select "1" from the "randomcount" singleselect
When I press "Add random question"
Then I should see "Random (Faulty question) based on filter condition" on quiz page "1"

Scenario: After closing and reopening the modal, it still works
When I am on the "Quiz 1" "mod_quiz > Edit" page logged in as teacher1
Expand Down

0 comments on commit 0138b52

Please sign in to comment.