MDL-58518 calendar: ignore events from courses user not enrolled in
authorRyan Wyllie <ryan@moodle.com>
Mon, 1 May 2017 07:56:34 +0000 (07:56 +0000)
committerRyan Wyllie <ryan@moodle.com>
Tue, 2 May 2017 02:53:25 +0000 (02:53 +0000)
calendar/classes/local/event/container.php
calendar/tests/container_test.php

index bb88a5c..083b19c 100644 (file)
@@ -147,7 +147,16 @@ class container {
                     $cm = $instances[$dbrow->modulename][$dbrow->instance];
 
                     // If the module is not visible to the current user, we should ignore it.
-                    if (!$cm->uservisible) {
+                    // We have to check enrolment here as well because the uservisible check
+                    // looks for the "view" capability however some activities (such as Lesson)
+                    // 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));
+                    if (!$cm->uservisible || !$canseecourse) {
                         return true;
                     }
 
index 8f4f5a7..f162238 100644 (file)
@@ -233,6 +233,58 @@ class core_calendar_container_testcase extends advanced_testcase {
         $this->assertNull($factory->create_instance($event));
     }
 
+    /**
+     * Test that the event factory only returns an event if the logged in user
+     * is enrolled in the course.
+     */
+    public function test_event_factory_unenrolled_user() {
+        $user = $this->getDataGenerator()->create_user();
+        // Create the course we will be using.
+        $course = $this->getDataGenerator()->create_course();
+
+        // Add the assignment.
+        $generator = $this->getDataGenerator()->get_plugin_generator('mod_lesson');
+        $lesson = $generator->create_instance(array('course' => $course->id));
+
+        // Create a user override event for the lesson.
+        $event = new \stdClass();
+        $event->name = 'An event';
+        $event->description = 'Event description';
+        $event->format = FORMAT_HTML;
+        $event->eventtype = 'close';
+        $event->userid = $user->id;
+        $event->modulename = 'lesson';
+        $event->instance = $lesson->id;
+        $event->courseid = $course->id;
+        $event->groupid = 0;
+        $event->timestart = time();
+        $event->timesort = time();
+        $event->timemodified = time();
+        $event->timeduration = 0;
+        $event->subscriptionid = null;
+        $event->repeatid = 0;
+        $legacyevent = $this->create_event($event);
+
+        // Update the id of the event that was created.
+        $event->id = $legacyevent->id;
+
+        // Set the logged in user to the one we created.
+        $this->setUser($user);
+
+        // Create the factory we are going to be testing the behaviour of.
+        $factory = \core_calendar\local\event\container::get_event_factory();
+
+        // The result should be null since the user is not enrolled in the
+        // course the event is for.
+        $this->assertNull($factory->create_instance($event));
+
+        // Now enrol the user in the course.
+        $this->getDataGenerator()->enrol_user($user->id, $course->id);
+
+        // Check that we get the correct instance.
+        $this->assertInstanceOf(event_interface::class, $factory->create_instance($event));
+    }
+
     /**
      * Test getting the event mapper.
      */