diff --git a/blocks/recentlyaccesseditems/classes/helper.php b/blocks/recentlyaccesseditems/classes/helper.php index e7e204f4e6f..b7d2b72af6f 100644 --- a/blocks/recentlyaccesseditems/classes/helper.php +++ b/blocks/recentlyaccesseditems/classes/helper.php @@ -68,6 +68,9 @@ class helper { // Group by courses to reduce get_fast_modinfo requests. foreach ($courses as $key => $items) { $modinfo = get_fast_modinfo($key); + if (!can_access_course($modinfo->get_course(), null, '', true)) { + continue; + } foreach ($items as $key => $item) { // Exclude not visible items. if (!$modinfo->cms[$item->cmid]->uservisible) { diff --git a/blocks/recentlyaccesseditems/version.php b/blocks/recentlyaccesseditems/version.php index e820334a5b1..1b52c622ed0 100644 --- a/blocks/recentlyaccesseditems/version.php +++ b/blocks/recentlyaccesseditems/version.php @@ -22,6 +22,6 @@ */ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2018120300; // The current plugin version (Date: YYYYMMDDXX). +$plugin->version = 2018120301; // The current plugin version (Date: YYYYMMDDXX). $plugin->requires = 2018112800; // Requires this Moodle version. $plugin->component = 'block_recentlyaccesseditems'; // Full name of the plugin (used for diagnostics). diff --git a/course/lib.php b/course/lib.php index a409cf1965e..dbb227dc6df 100644 --- a/course/lib.php +++ b/course/lib.php @@ -4572,21 +4572,40 @@ function course_get_recent_courses(int $userid = null, int $limit = 0, int $offs $coursefields = 'c.' .join(',', $basefields); - $sql = "SELECT $ctxfields, $coursefields + // Ask the favourites service to give us the join SQL for favourited courses, + // so we can include favourite information in the query. + $usercontext = \context_user::instance($userid); + $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 $coursefields, $ctxfields FROM {course} c JOIN {context} ctx ON ctx.contextlevel = :contextlevel AND ctx.instanceid = c.id JOIN {user_lastaccess} ul ON ul.courseid = c.id - LEFT JOIN {favourite} f - ON f.component = 'core_course' - AND f.itemtype = 'courses' - AND f.userid = ul.userid - AND f.itemid = ul.courseid + $favsql WHERE ul.userid = :userid - $orderby"; - $params = ['userid' => $userid, 'contextlevel' => CONTEXT_COURSE]; + 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); diff --git a/course/tests/courselib_test.php b/course/tests/courselib_test.php index 37ca6629042..3d9d77ac87e 100644 --- a/course/tests/courselib_test.php +++ b/course/tests/courselib_test.php @@ -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); + } }