diff --git a/mod/quiz/classes/notification_helper.php b/mod/quiz/classes/notification_helper.php index 4f4982d2fd5..33ad9910ef3 100644 --- a/mod/quiz/classes/notification_helper.php +++ b/mod/quiz/classes/notification_helper.php @@ -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(); diff --git a/mod/quiz/tests/notification_helper_test.php b/mod/quiz/tests/notification_helper_test.php index 3aade56e34a..1e0e8051b6a 100644 --- a/mod/quiz/tests/notification_helper_test.php +++ b/mod/quiz/tests/notification_helper_test.php @@ -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;