Skip to content

Commit

Permalink
MDL-66144 course: add function to calculate user course dates
Browse files Browse the repository at this point in the history
  • Loading branch information
ryanwyllie committed Jul 17, 2019
1 parent f7e1084 commit 00a6639
Show file tree
Hide file tree
Showing 5 changed files with 1,466 additions and 1 deletion.
151 changes: 151 additions & 0 deletions course/lib.php
Expand Up @@ -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];
}

0 comments on commit 00a6639

Please sign in to comment.