MDL-66144 course: add function to calculate user course dates

This commit is contained in:
Ryan Wyllie
2019-07-17 15:52:51 +08:00
parent f7e108438f
commit 00a66396c7
5 changed files with 1466 additions and 1 deletions
+151
View File
@@ -4666,3 +4666,154 @@ function course_get_recent_courses(int $userid = null, int $limit = 0, int $offs
return $recentcourses;
}
/**
* Calculate the course start date and offset for the given user ids.
*
* If the course is a fixed date course then the course start date will be returned.
* If the course is a relative date course then the course date will be calculated and
* and offset provided.
*
* The dates are returned as an array with the index being the user id. The array
* contains the start date and start offset values for the user.
*
* If the user is not enrolled in the course then the course start date will be returned.
*
* If we have a course which starts on 1563244000 and 2 users, id 123 and 456, where the
* former is enrolled in the course at 1563244693 and the latter is not enrolled then the
* return value would look like:
* [
* '123' => [
* 'start' => 1563244693,
* 'startoffset' => 693
* ],
* '456' => [
* 'start' => 1563244000,
* 'startoffset' => 0
* ]
* ]
*
* @param stdClass $course The course to fetch dates for.
* @param array $userids The list of user ids to get dates for.
* @return array
*/
function course_get_course_dates_for_user_ids(stdClass $course, array $userids): array {
if (empty($course->relativedatesmode)) {
// This course isn't set to relative dates so we can early return with the course
// start date.
return array_reduce($userids, function($carry, $userid) use ($course) {
$carry[$userid] = [
'start' => $course->startdate,
'startoffset' => 0
];
return $carry;
}, []);
}
// We're dealing with a relative dates course now so we need to calculate some dates.
$cache = cache::make('core', 'course_user_dates');
$dates = [];
$uncacheduserids = [];
// Try fetching the values from the cache so that we don't need to do a DB request.
foreach ($userids as $userid) {
$cachekey = "{$course->id}_{$userid}";
$cachedvalue = $cache->get($cachekey);
if ($cachedvalue === false) {
// Looks like we haven't seen this user for this course before so we'll have
// to fetch it.
$uncacheduserids[] = $userid;
} else {
[$start, $startoffset] = $cachedvalue;
$dates[$userid] = [
'start' => $start,
'startoffset' => $startoffset
];
}
}
if (!empty($uncacheduserids)) {
// Load the enrolments for any users we haven't seen yet. Set the "onlyactive" param
// to false because it filters out users with enrolment start times in the future which
// we don't want.
$enrolments = enrol_get_course_users($course->id, false, $uncacheduserids);
foreach ($uncacheduserids as $userid) {
// Find the user enrolment that has the earliest start date.
$enrolment = array_reduce(array_values($enrolments), function($carry, $enrolment) use ($userid) {
// Only consider enrolments for this user if the user enrolment is active and the
// enrolment method is enabled.
if (
$enrolment->uestatus == ENROL_USER_ACTIVE &&
$enrolment->estatus == ENROL_INSTANCE_ENABLED &&
$enrolment->id == $userid
) {
if (is_null($carry)) {
// Haven't found an enrolment yet for this user so use the one we just found.
$carry = $enrolment;
} else {
// We've already found an enrolment for this user so let's use which ever one
// has the earliest start time.
$carry = $carry->uetimestart < $enrolment->uetimestart ? $carry : $enrolment;
}
}
return $carry;
}, null);
if ($enrolment) {
// The course is in relative dates mode so we calculate the student's start
// date based on their enrolment start date.
$start = $course->startdate > $enrolment->uetimestart ? $course->startdate : $enrolment->uetimestart;
$startoffset = $start - $course->startdate;
} else {
// The user is not enrolled in the course so default back to the course start date.
$start = $course->startdate;
$startoffset = 0;
}
$dates[$userid] = [
'start' => $start,
'startoffset' => $startoffset
];
$cachekey = "{$course->id}_{$userid}";
$cache->set($cachekey, [$start, $startoffset]);
}
}
return $dates;
}
/**
* Calculate the course start date and offset for the given user id.
*
* If the course is a fixed date course then the course start date will be returned.
* If the course is a relative date course then the course date will be calculated and
* and offset provided.
*
* The return array contains the start date and start offset values for the user.
*
* If the user is not enrolled in the course then the course start date will be returned.
*
* If we have a course which starts on 1563244000. If a user's enrolment starts on 1563244693
* then the return would be:
* [
* 'start' => 1563244693,
* 'startoffset' => 693
* ]
*
* If the use was not enrolled then the return would be:
* [
* 'start' => 1563244000,
* 'startoffset' => 0
* ]
*
* @param stdClass $course The course to fetch dates for.
* @param int $userid The user id to get dates for.
* @return array
*/
function course_get_course_dates_for_user_id(stdClass $course, int $userid): array {
return (course_get_course_dates_for_user_ids($course, [$userid]))[$userid];
}
File diff suppressed because it is too large Load Diff
+1
View File
@@ -46,6 +46,7 @@ $string['cachedef_coursecattree'] = 'Course categories tree';
$string['cachedef_coursecompletion'] = 'Course completion status';
$string['cachedef_coursecontacts'] = 'List of course contacts';
$string['cachedef_coursemodinfo'] = 'Accumulated information about modules and sections for each course';
$string['cachedef_course_user_dates'] = 'The user dates for courses set to relative dates mode';
$string['cachedef_completion'] = 'Activity completion status';
$string['cachedef_databasemeta'] = 'Database meta information';
$string['cachedef_eventinvalidation'] = 'Event invalidation';
+8
View File
@@ -400,4 +400,12 @@ $definitions = array(
'simplekeys' => true,
'staticacceleration' => true
],
// Cache the user dates for courses set to relative dates mode.
'course_user_dates' => [
'mode' => cache_store::MODE_REQUEST,
'simplekeys' => true,
'simpledata' => true,
'staticacceleration' => true
],
);
+1 -1
View File
@@ -1664,7 +1664,7 @@ function enrol_get_course_users($courseid = false, $onlyactive = false, $usersfi
$sql = "SELECT ue.id AS ueid, ue.status AS uestatus, ue.enrolid AS ueenrolid, ue.timestart AS uetimestart,
ue.timeend AS uetimeend, ue.modifierid AS uemodifierid, ue.timecreated AS uetimecreated,
ue.timemodified AS uetimemodified,
ue.timemodified AS uetimemodified, e.status AS estatus,
u.* FROM {user_enrolments} ue
JOIN {enrol} e ON e.id = ue.enrolid
JOIN {user} u ON ue.userid = u.id