MDL-64155 core: get_recent_courses considers enrolment status
authorVictor Deniz <victor@moodle.com>
Wed, 28 Nov 2018 13:46:56 +0000 (13:46 +0000)
committerVíctor Déniz Falcón <victor@moodle.com>
Thu, 29 Nov 2018 15:37:17 +0000 (15:37 +0000)
course/lib.php
course/tests/courselib_test.php

index 9fd54f0..dbb227d 100644 (file)
@@ -4578,7 +4578,7 @@ function course_get_recent_courses(int $userid = null, int $limit = 0, int $offs
     $favservice = \core_favourites\service_factory::get_service_for_user_context($usercontext);
     list($favsql, $favparams) = $favservice->get_join_sql_by_type('core_course', 'courses', 'fav', 'ul.courseid');
 
-    $sql = "SELECT $ctxfields, $coursefields
+    $sql = "SELECT $coursefields, $ctxfields
               FROM {course} c
               JOIN {context} ctx
                    ON ctx.contextlevel = :contextlevel
@@ -4587,8 +4587,25 @@ function course_get_recent_courses(int $userid = null, int $limit = 0, int $offs
                    ON ul.courseid = c.id
             $favsql
              WHERE ul.userid = :userid
-          $orderby";
-    $params = ['userid' => $userid, 'contextlevel' => CONTEXT_COURSE] + $favparams;
+               AND c.visible = :visible
+               AND EXISTS (SELECT e.id
+                             FROM {enrol} e
+                        LEFT JOIN {user_enrolments} ue ON ue.enrolid = e.id
+                            WHERE e.courseid = c.id
+                              AND e.status = :statusenrol
+                              AND ((ue.status = :status
+                                    AND ue.userid = ul.userid
+                                    AND ue.timestart < :now1
+                                    AND (ue.timeend = 0 OR ue.timeend > :now2)
+                                   )
+                                   OR e.enrol = :guestenrol
+                                  )
+                          )
+            $orderby";
+
+    $now = round(time(), -2); // Improves db caching.
+    $params = ['userid' => $userid, 'contextlevel' => CONTEXT_COURSE, 'visible' => 1, 'status' => ENROL_USER_ACTIVE,
+               'statusenrol' => ENROL_INSTANCE_ENABLED, 'guestenrol' => 'guest', 'now1' => $now, 'now2' => $now] + $favparams;
 
     $recentcourses = $DB->get_records_sql($sql, $params, $offset, $limit);
 
index 37ca662..3d9d77a 100644 (file)
@@ -4980,4 +4980,73 @@ class core_course_courselib_testcase extends advanced_testcase {
         $this->assertEquals($course->startdate, $min[0]);
         $this->assertNull($max);
     }
+
+    /**
+     * Test the course_get_recent_courses function.
+     */
+    public function test_course_get_recent_courses() {
+
+        $this->resetAfterTest();
+        $generator = $this->getDataGenerator();
+
+        $courses = array();
+        for ($i = 1; $i < 4; $i++) {
+            $courses[]  = $generator->create_course();
+        };
+
+        $student = $generator->create_user();
+
+        foreach ($courses as $course) {
+            $generator->enrol_user($student->id, $course->id, 'student');
+        }
+
+        $this->setUser($student);
+
+        $result = course_get_recent_courses($student->id);
+
+        // No course accessed.
+        $this->assertCount(0, $result);
+
+        foreach ($courses as $course) {
+            $context = context_course::instance($course->id);
+            course_view($context);
+        }
+
+        // Every course accessed.
+        $result = course_get_recent_courses($student->id);
+        $this->assertCount(3, $result);
+
+        // Every course accessed, result limited to 2 courses.
+        $result = course_get_recent_courses($student->id, 2);
+        $this->assertCount(2, $result);
+
+        // Every course accessed, with limit and offset. Should return only the last created course ($course[2]).
+        $result = course_get_recent_courses($student->id, 3, 2);
+        $this->assertCount(1, $result);
+        $this->assertArrayHasKey($courses[2]->id, $result);
+
+        // Every course accessed, order by shortname DESC. The last create course ($course[2]) should have the greater shortname.
+        $result = course_get_recent_courses($student->id, 0, 0, 'shortname DESC');
+        $this->assertCount(3, $result);
+        $this->assertEquals($courses[2]->id, array_shift($result)->id);
+
+        $guestcourse = $generator->create_course(
+            (object)array('shortname' => 'guestcourse',
+                'enrol_guest_status_0' => ENROL_INSTANCE_ENABLED,
+                'enrol_guest_password_0' => ''));
+        $context = context_course::instance($guestcourse->id);
+        course_view($context);
+
+        // Every course accessed, even the not enrolled one.
+        $result = course_get_recent_courses($student->id);
+        $this->assertCount(4, $result);
+
+        // Suspended student.
+        $this->getDataGenerator()->enrol_user($student->id, $courses[0]->id, 'student', 'manual', 0, 0, ENROL_USER_SUSPENDED);
+
+        // The course with suspended enrolment is not returned by the function.
+        $result = course_get_recent_courses($student->id);
+        $this->assertCount(3, $result);
+        $this->assertArrayNotHasKey($courses[0]->id, $result);
+    }
 }