diff --git a/calendar/classes/local/event/container.php b/calendar/classes/local/event/container.php index 9ac8cbf3432..70c2cb7b4bc 100644 --- a/calendar/classes/local/event/container.php +++ b/calendar/classes/local/event/container.php @@ -137,10 +137,15 @@ class container { // have that capability set on the "Authenticated User" role rather than // on "Student" role, which means uservisible returns true even when the user // is no longer enrolled in the course. - $modulecontext = \context_module::instance($cm->id); - // A user with the 'moodle/course:view' capability is able to see courses - // that they are not a participant in. - $canseecourse = (has_capability('moodle/course:view', $modulecontext) || is_enrolled($modulecontext)); + // So, with the following we are checking - + // 1) Only process modules if $cm->uservisible is true. + // 2) Only process modules for courses a user has the capability to view OR they are enrolled in. + // 3) Only process modules for courses that are visible OR if the course is not visible, the user + // has the capability to view hidden courses. + $coursecontext = \context_course::instance($dbrow->courseid); + $canseecourse = has_capability('moodle/course:view', $coursecontext) || is_enrolled($coursecontext); + $canseecourse = $canseecourse && + ($cm->get_course()->visible || has_capability('moodle/course:viewhiddencourses', $coursecontext)); if (!$cm->uservisible || !$canseecourse) { return true; } diff --git a/calendar/tests/container_test.php b/calendar/tests/container_test.php index 3f08efbee43..ba1eb6ccca7 100644 --- a/calendar/tests/container_test.php +++ b/calendar/tests/container_test.php @@ -183,6 +183,63 @@ class core_calendar_container_testcase extends advanced_testcase { $this->assertNull($event); } + /** + * Test that the event factory deals with invisible courses as an admin. + * + * @dataProvider get_event_factory_testcases() + * @param \stdClass $dbrow Row from the "database". + */ + public function test_event_factory_when_course_visibility_is_toggled_as_admin($dbrow) { + $legacyevent = $this->create_event($dbrow); + $factory = \core_calendar\local\event\container::get_event_factory(); + + // Create a hidden course with an assignment. + $course = $this->getDataGenerator()->create_course(['visible' => 0]); + $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign'); + $moduleinstance = $generator->create_instance(['course' => $course->id]); + + $dbrow->id = $legacyevent->id; + $dbrow->courseid = $course->id; + $dbrow->instance = $moduleinstance->id; + $dbrow->modulename = 'assign'; + $event = $factory->create_instance($dbrow); + + // Module is still visible to admins even if the course is invisible. + $this->assertInstanceOf(event_interface::class, $event); + } + + /** + * Test that the event factory deals with invisible courses as a student. + * + * @dataProvider get_event_factory_testcases() + * @param \stdClass $dbrow Row from the "database". + */ + public function test_event_factory_when_course_visibility_is_toggled_as_student($dbrow) { + $legacyevent = $this->create_event($dbrow); + $factory = \core_calendar\local\event\container::get_event_factory(); + + // Create a hidden course with an assignment. + $course = $this->getDataGenerator()->create_course(['visible' => 0]); + $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign'); + $moduleinstance = $generator->create_instance(['course' => $course->id]); + + // Enrol a student into this course. + $student = $this->getDataGenerator()->create_user(); + $this->getDataGenerator()->enrol_user($student->id, $course->id); + + // Set the user to the student. + $this->setUser($student); + + $dbrow->id = $legacyevent->id; + $dbrow->courseid = $course->id; + $dbrow->instance = $moduleinstance->id; + $dbrow->modulename = 'assign'; + $event = $factory->create_instance($dbrow); + + // Module is invisible to students if the course is invisible. + $this->assertNull($event); + } + /** * Test that the event factory deals with completion related events properly. */