MDL-30131 improve current user enrol caching

This commit is contained in:
Petr Skoda
2011-11-06 09:40:06 +01:00
parent 735de1c276
commit bbfdff344c
9 changed files with 222 additions and 133 deletions
+52 -69
View File
@@ -1122,7 +1122,9 @@ function load_all_capabilities() {
// Clear to force a refresh
unset($USER->mycourses);
unset($USER->enrol);
// init/reset internal enrol caches - active course enrolments and temp access
$USER->enrol = array('enrolled'=>array(), 'tempguest'=>array());
}
/**
@@ -1172,15 +1174,18 @@ function reload_all_capabilities() {
* @return void
*/
function load_temp_course_role(context_course $coursecontext, $roleid) {
global $USER;
//TODO: this gets removed if there are any dirty contexts, we should probably store list of these temp roles somewhere (skodak)
global $USER, $SITE;
if (empty($roleid)) {
debugging('invalid role specified in load_temp_course_role()');
return;
}
if ($coursecontext->instanceid == $SITE->id) {
debugging('Can not use temp roles on the frontpage');
return;
}
if (!isset($USER->access)) {
load_all_capabilities();
}
@@ -1207,7 +1212,12 @@ function load_temp_course_role(context_course $coursecontext, $roleid) {
* @return void
*/
function remove_temp_course_roles(context_course $coursecontext) {
global $DB, $USER;
global $DB, $USER, $SITE;
if ($coursecontext->instanceid == $SITE->id) {
debugging('Can not use temp roles on the frontpage');
return;
}
if (empty($USER->access['ra'][$coursecontext->path])) {
//no roles here, weird
@@ -1877,6 +1887,8 @@ function is_viewing(context $context, $user = null, $withcapability = '') {
* Returns true if user is enrolled (is participating) in course
* this is intended for students and teachers.
*
* Since 2.2 the result for active enrolments and current user are cached.
*
* @param context $context
* @param int|stdClass $user, if null $USER is used, otherwise user object or id expected
* @param string $withcapability extra capability name
@@ -1907,32 +1919,35 @@ function is_enrolled(context $context, $user = null, $withcapability = '', $only
if ($coursecontext->instanceid == SITEID) {
// everybody participates on frontpage
} else {
if ($onlyactive) {
$sql = "SELECT ue.*
FROM {user_enrolments} ue
JOIN {enrol} e ON (e.id = ue.enrolid AND e.courseid = :courseid)
JOIN {user} u ON u.id = ue.userid
WHERE ue.userid = :userid AND ue.status = :active AND e.status = :enabled AND u.deleted = 0";
$params = array('enabled'=>ENROL_INSTANCE_ENABLED, 'active'=>ENROL_USER_ACTIVE, 'userid'=>$userid, 'courseid'=>$coursecontext->instanceid);
// this result should be very small, better not do the complex time checks in sql for now ;-)
$enrolments = $DB->get_records_sql($sql, $params);
$now = time();
// make sure the enrol period is ok
$result = false;
foreach ($enrolments as $e) {
if ($e->timestart > $now) {
continue;
// try cached info first - the enrolled flag is set only when active enrolment present
if ($USER->id == $userid) {
$coursecontext->reload_if_dirty();
if (isset($USER->enrol['enrolled'][$coursecontext->instanceid])) {
if ($USER->enrol['enrolled'][$coursecontext->instanceid] > time()) {
return true;
}
if ($e->timeend and $e->timeend < $now) {
continue;
}
$result = true;
break;
}
if (!$result) {
}
if ($onlyactive) {
// look for active enrolments only
$until = enrol_get_enrolment_end($coursecontext->instanceid, $userid);
if ($until === false) {
return false;
}
if ($USER->id == $userid) {
if ($until == 0) {
$until = ENROL_MAX_TIMESTAMP;
}
$USER->enrol['enrolled'][$coursecontext->instanceid] = $until;
if (isset($USER->enrol['tempguest'][$coursecontext->instanceid])) {
unset($USER->enrol['tempguest'][$coursecontext->instanceid]);
remove_temp_course_roles($coursecontext);
}
}
} else {
// any enrolment is good for us here, even outdated, disabled or inactive
$sql = "SELECT 'x'
@@ -2031,57 +2046,22 @@ function can_access_course(stdClass $course, $user = null, $withcapability = '',
// === from here we deal only with $USER ===
// verify our caches
if (!isset($USER->enrol)) {
/**
* These flags within the $USER object should NEVER be used outside of this
* function can_access_course and the function require_login.
* Doing so WILL break future versions!!!!
*/
$USER->enrol = array();
$USER->enrol['enrolled'] = array();
$USER->enrol['tempguest'] = array();
}
$coursecontext->reload_if_dirty();
if (isset($USER->enrol['enrolled'][$course->id])) {
if ($USER->enrol['enrolled'][$course->id] == 0) {
return true;
} else if ($USER->enrol['enrolled'][$course->id] > time()) {
if ($USER->enrol['enrolled'][$course->id] > time()) {
return true;
}
}
if (isset($USER->enrol['tempguest'][$course->id])) {
if ($USER->enrol['tempguest'][$course->id] == 0) {
return true;
} else if ($USER->enrol['tempguest'][$course->id] > time()) {
if ($USER->enrol['tempguest'][$course->id] > time()) {
return true;
}
}
if (is_enrolled($coursecontext, $USER, '', true)) {
// active participants may always access
// TODO: refactor this into some new function
$now = time();
$sql = "SELECT MAX(ue.timeend)
FROM {user_enrolments} ue
JOIN {enrol} e ON (e.id = ue.enrolid AND e.courseid = :courseid)
JOIN {user} u ON u.id = ue.userid
WHERE ue.userid = :userid AND ue.status = :active AND e.status = :enabled AND u.deleted = 0
AND ue.timestart < :now1 AND (ue.timeend = 0 OR ue.timeend > :now2)";
$params = array('enabled'=>ENROL_INSTANCE_ENABLED, 'active'=>ENROL_USER_ACTIVE,
'userid'=>$USER->id, 'courseid'=>$coursecontext->instanceid, 'now1'=>$now, 'now2'=>$now);
$until = $DB->get_field_sql($sql, $params);
if (!$until or $until > time() + ENROL_REQUIRE_LOGIN_CACHE_PERIOD) {
$until = time() + ENROL_REQUIRE_LOGIN_CACHE_PERIOD;
}
$USER->enrol['enrolled'][$course->id] = $until;
// remove traces of previous temp guest access
remove_temp_course_roles($coursecontext);
if (is_enrolled($coursecontext, $USER, '', $onlyactive)) {
return true;
}
unset($USER->enrol['enrolled'][$course->id]);
// if not enrolled try to gain temporary guest access
$instances = $DB->get_records('enrol', array('courseid'=>$course->id, 'status'=>ENROL_INSTANCE_ENABLED), 'sortorder, id ASC');
@@ -2090,14 +2070,17 @@ function can_access_course(stdClass $course, $user = null, $withcapability = '',
if (!isset($enrols[$instance->enrol])) {
continue;
}
// Get a duration for the guestaccess, a timestamp in the future or false.
// Get a duration for the guest access, a timestamp in the future, 0 (always) or false.
$until = $enrols[$instance->enrol]->try_guestaccess($instance);
if ($until !== false) {
if ($until !== false and $until > time()) {
$USER->enrol['tempguest'][$course->id] = $until;
return true;
}
}
unset($USER->enrol['tempguest'][$course->id]);
if (isset($USER->enrol['tempguest'][$course->id])) {
unset($USER->enrol['tempguest'][$course->id]);
remove_temp_course_roles($coursecontext);
}
return false;
}