MDL-84327 mod_quiz: Add availability conditions in quiz notification

Only users meeting availability conditions (time, group, etc.) in a quiz,
will receive the message for quiz opens soon notifications
This commit is contained in:
raortegar
2025-02-20 16:33:05 +01:00
parent 3c848c4dce
commit ceeaa53d84
2 changed files with 56 additions and 1 deletions
+8 -1
View File
@@ -44,11 +44,14 @@ class notification_helper {
$sql = "SELECT DISTINCT q.id
FROM {quiz} q
JOIN {course} c ON q.course = c.id
JOIN {course_modules} cm ON q.id = cm.instance
JOIN {modules} m ON cm.module = m.id AND m.name = :modulename
LEFT JOIN {quiz_overrides} qo ON q.id = qo.quiz
WHERE (q.timeopen < :futuretime OR qo.timeopen < :qo_futuretime)
AND (q.timeopen > :timenow OR qo.timeopen > :qo_timenow)";
AND (q.timeopen > :timenow OR qo.timeopen > :qo_timenow)
AND cm.visible = 1
AND c.visible = 1";
$params = [
'timenow' => $timenow,
@@ -79,6 +82,10 @@ class notification_helper {
userfields: 'u.id, u.firstname',
);
// Filter a list of users who meet the availability conditions.
$info = new \core_availability\info_module($quizobj->get_cm());
$users = $info->filter_user_list($users);
// Check for any override dates.
$overrides = $quizobj->get_override_manager()->get_all_overrides();
@@ -78,6 +78,7 @@ final class notification_helper_test extends \advanced_testcase {
* Test getting users within a quiz that are within our date range.
*/
public function test_get_users_within_quiz(): void {
global $DB;
$this->resetAfterTest();
$generator = $this->getDataGenerator();
$helper = \core\di::get(notification_helper::class);
@@ -148,6 +149,32 @@ final class notification_helper_test extends \advanced_testcase {
// User5 should not be in the returned users because they are a teacher.
$this->assertArrayNotHasKey($user5->id, $users);
// Let's add some availability conditions.
$availability =
[
'op' => '&',
'showc' => [true],
'c' => [
[
'type' => 'group',
'id' => (int)$group->id,
],
],
];
$cm = get_coursemodule_from_instance('quiz', $quiz->id, $course->id);
$DB->set_field('course_modules', 'availability', json_encode($availability), ['id' => $cm->id]);
// Rebuild course cache to apply changes.
rebuild_course_cache($course->id, true);
// Get the users after availability conditions of the given quiz.
$users = notification_helper::get_users_within_quiz($quiz->id);
// Returns only users matching availability conditions who are in the specified group.
$this->assertCount(2, $users);
ksort($users);
$this->assertEquals([$user2->id, $user3->id], array_keys($users));
}
/**
@@ -220,6 +247,27 @@ final class notification_helper_test extends \advanced_testcase {
// Clear sink.
$sink->clear();
// Let's modify the 'timeopen' one more time and change the visibility.
$cm = get_coursemodule_from_instance('quiz', $quiz->id, $course->id);
$DB->set_field('course_modules', 'visible', 0, ['id' => $cm->id]);
$updatedata = new \stdClass();
$updatedata->id = $quiz->id;
$updatedata->timeopen = $timeopen + DAYSECS;
$DB->update_record('quiz', $updatedata);
// Run the tasks again.
$this->run_notification_helper_tasks();
// There should not be a new notification because the quiz is not visible.
$this->assertCount(0, $sink->get_messages_by_component('mod_quiz'));
// Set back the visibility.
$DB->set_field('course_modules', 'visible', 1, ['id' => $cm->id]);
// Clear sink.
$sink->clear();
// Let's modify the 'timeopen' one more time.
$updatedata = new \stdClass();
$updatedata->id = $quiz->id;