Merge branch 'MDL-83784_404' of https://github.com/cwarwicker/moodle into MOODLE_404_STABLE

This commit is contained in:
Sara Arjona
2025-02-19 12:00:29 +01:00
9 changed files with 112 additions and 3 deletions
@@ -1067,6 +1067,13 @@ class edit_renderer extends \plugin_renderer_base {
$temp->questiontext = '';
$temp->name = $structure->describe_random_slot($slot->id);
$instancename = quiz_question_tostring($temp);
if (strpos($instancename, structure::MISSING_QUESTION_CATEGORY_PLACEHOLDER) !== false) {
$label = html_writer::span(
get_string('missingcategory', 'mod_quiz'),
'badge bg-danger text-white h-50'
);
$instancename = str_replace(structure::MISSING_QUESTION_CATEGORY_PLACEHOLDER, $label, $instancename);
}
$configuretitle = get_string('configurerandomquestion', 'quiz');
$qtype = \question_bank::get_qtype($question->qtype, false);
+13
View File
@@ -42,6 +42,12 @@ use stdClass;
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class structure {
/**
* Placeholder string used when a question category is missing.
*/
const MISSING_QUESTION_CATEGORY_PLACEHOLDER = 'missing_question_category';
/** @var quiz_settings the quiz this is the structure of. */
protected $quizobj = null;
@@ -1759,6 +1765,13 @@ class structure {
// Now, put the data required for each slot into $this->randomslotcategories and $this->randomslottags.
foreach ($randomcategoriesandtags as $slotid => $catandtags) {
$qcategoryid = $catandtags['cat']['values'];
// If the category does not exist, replace with a temporary placeholder.
if (!array_key_exists($qcategoryid, $categories)) {
$this->randomslotcategories[$slotid] = self::MISSING_QUESTION_CATEGORY_PLACEHOLDER;
continue;
}
$qcategory = $categories[$qcategoryid];
$includesubcategories = $catandtags['cat']['includesubcategories'];
$this->randomslotcategories[$slotid] = $this->get_used_category_description($qcategory, $includesubcategories);
+5 -3
View File
@@ -23,6 +23,7 @@
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
use core_question\local\bank\filter_condition_manager;
use core_question\question_reference_manager;
use mod_quiz\quiz_settings;
use mod_quiz\question\bank\random_question_view;
@@ -58,6 +59,7 @@ $setreference = $DB->get_record('question_set_references',
['itemid' => $slot->id, 'component' => 'mod_quiz', 'questionarea' => 'slot']);
$filterconditions = json_decode($setreference->filtercondition, true);
$filterconditions = question_reference_manager::convert_legacy_set_reference_filter_condition($filterconditions);
$filterconditions = filter_condition_manager::filter_invalid_values($filterconditions);
$params = $filterconditions;
$params['cmid'] = $cm->id;
@@ -132,9 +134,10 @@ if ($mform->is_cancelled()) {
redirect($returnurl);
}
$PAGE->set_title('Random question');
$heading = get_string('randomediting', 'mod_quiz');
$PAGE->set_title($heading);
$PAGE->set_heading($COURSE->fullname);
$PAGE->navbar->add('Random question');
$PAGE->navbar->add($heading);
// Custom View.
$questionbank = new random_question_view($contexts, $thispageurl, $course, $cm, $params, $extraparams);
@@ -151,7 +154,6 @@ $PAGE->requires->js_call_amd('mod_quiz/update_random_question_filter_condition',
// Display a heading, question editing form.
echo $OUTPUT->header();
$heading = get_string('randomediting', 'mod_quiz');
echo $OUTPUT->heading_with_help($heading, 'randomquestion', 'mod_quiz');
echo $updateform;
echo $OUTPUT->footer();
+1
View File
@@ -555,6 +555,7 @@ $string['maxmarks_help'] = 'The maximum mark available for each question.';
$string['min'] = 'Min';
$string['minutes'] = 'Minutes';
$string['missingcategory'] = 'Missing question category';
$string['missingcorrectanswer'] = 'Correct answer must be specified';
$string['missingitemtypename'] = 'Missing name';
$string['missingquestion'] = 'This question no longer seems to exist';
@@ -71,3 +71,18 @@ Feature: Moving a question to another category should not affect random question
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 (Used category new) based on filter condition" on quiz page "1"
@javascript
Scenario: A random question with an invalid category should still be editable
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 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 (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 "Delete" "link" in the "Used category" "list_item"
And I press "Save in category"
And I am on the "Quiz 1" "mod_quiz > Edit" page logged in as "teacher1"
Then I should not see "Random (Used category) based on filter condition" on quiz page "1"
And I should see "Missing question category" on quiz page "1"
@@ -336,4 +336,35 @@ class category_condition extends condition {
public function is_required(): bool {
return true;
}
#[\Override]
public function filter_invalid_values(array $filterconditions): array {
global $DB;
$defaultcatid = explode(',', $filterconditions['cat'])[0];
[$insql, $inparams] = $DB->get_in_or_equal($filterconditions['filter']['category']['values']);
$categories = $DB->get_records_select('question_categories', "id {$insql}",
$inparams, null, 'id');
$categoryids = array_keys($categories);
foreach ($filterconditions['filter']['category']['values'] as $key => $catid) {
// Check that the category still exists, and if not, remove it from the conditions.
if (!in_array($catid, $categoryids)) {
unset($filterconditions['filter']['category']['values'][$key]);
}
}
// If we now don't have any valid categories, use the default loaded from the page.
if (count($filterconditions['filter']['category']['values']) === 0) {
$filterconditions['filter']['category']['values'] = [$defaultcatid];
}
return $filterconditions;
}
}
+15
View File
@@ -200,6 +200,21 @@ abstract class condition {
];
}
/**
* Method to be overridden in condition classes to filter out anything invalid from the filterconditions array.
*
* This can be applied anywhere where the $filterconditions array exists, to let condition plugins remove elements
* from the array, based on their own internal logic/validation. For example, this is used on the
* /mod/quiz/editrandom.php page to filter out question categories which no longer exist, which previously
* broke the editrandom page.
*
* @param array $filterconditions
* @return array
*/
public function filter_invalid_values(array $filterconditions): array {
return $filterconditions;
}
/**
* Given an array of filters, pick the entry that matches the condition key and return it.
*
@@ -117,4 +117,24 @@ class filter_condition_manager {
}
return $filters;
}
/**
* Filter out invalid values from the filterconditions array,
*
* @param array $filterconditions
* @return array
* @throws \dml_exception
*/
public static function filter_invalid_values(array $filterconditions): array {
$classes = self::get_condition_classes();
foreach ($classes as $class) {
$condition = new $class();
$filterconditions = $condition->filter_invalid_values($filterconditions);
}
return $filterconditions;
}
}
+5
View File
@@ -1,5 +1,10 @@
This files describes API changes for code that uses the question API.
=== 4.4.7 ===
* Question bank Condition classes can now implement a function called
"filter_invalid_values($filterconditions)" to remove anything from the
filterconditions array which is invalid or should not be there.
=== 4.4 ===
* The following previously deprecated methods have been removed and can no longer be used:
- `submit_tags_form`