As part of this patch I also introduced a new method in accesslib can_access_course that can be used
to check a users access to a course.
I also fixed a minor issue with guest access flag caching in require_login
// Temporarily assign them some guest role for this context
$context = get_context_instance(CONTEXT_COURSE, $instance->courseid);
$USER->access = load_temp_role($context, $CFG->guestroleid, $USER->access);
- return ENROL_REQUIRE_LOGIN_CACHE_PERIOD;
+ return ENROL_REQUIRE_LOGIN_CACHE_PERIOD + time();
}
return false;
return true;
}
+/**
+ * Returns true if the user is able to access the course.
+ *
+ * This function is in no way, shape, or form a substitute for require_login.
+ * It should only be used in circumstances where it is not possible to call require_login
+ * such as the navigation.
+ *
+ * This function checks many of the methods of access to a course such as the view
+ * capability, enrollments, and guest access. It also makes use of the cache
+ * generated by require_login for guest access.
+ *
+ * The flags within the $USER object that are used here should NEVER be used outside
+ * of this function can_access_course and require_login. Doing so WILL break future
+ * versions.
+ *
+ * @global moodle_database $DB
+ * @param stdClass $context
+ * @param stdClass|null $user
+ * @param string $withcapability Check for this capability as well.
+ * @param bool $onlyactive consider only active enrolments in enabled plugins and time restrictions
+ * @param boolean $trustcache If set to false guest access will always be checked
+ * against the enrolment plugins from the course, rather
+ * than the cache generated by require_login.
+ * @return boolean Returns true if the user is able to access the course
+ */
+function can_access_course($context, $user = null, $withcapability = '', $onlyactive = false, $trustcache = true) {
+ global $DB, $USER;
+
+ $coursecontext = get_course_context($context);
+ $courseid = $coursecontext->instanceid;
+
+ // First check the obvious, is the user viewing or is the user enrolled.
+ if (is_viewing($coursecontext, $user, $withcapability) || is_enrolled($coursecontext, $user, $withcapability, $onlyactive)) {
+ // How easy was that!
+ return true;
+ }
+
+ $access = false;
+ if (!isset($USER->enrol)) {
+ // Cache hasn't been generated yet so we can't trust it
+ $trustcache = false;
+ /**
+ * 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();
+ }
+
+ // If we don't trust the cache we need to check with the courses enrolment
+ // plugin instances to see if the user can access the course as a guest.
+ if (!$trustcache) {
+ // Ok, off to the database we go!
+ $instances = $DB->get_records('enrol', array('courseid'=>$courseid, 'status'=>ENROL_INSTANCE_ENABLED), 'sortorder, id ASC');
+ $enrols = enrol_get_plugins(true);
+ foreach($instances as $instance) {
+ if (!isset($enrols[$instance->enrol])) {
+ continue;
+ }
+ $until = $enrols[$instance->enrol]->try_guestaccess($instance);
+ if ($until !== false) {
+ // Never use me anywhere but here and require_login
+ $USER->enrol['tempguest'][$courseid] = $until;
+ $access = true;
+ break;
+ }
+ }
+ }
+
+ // If we don't already have access (from above) check the cache and see whether
+ // there is record of it in there.
+ if (!$access && isset($USER->enrol['tempguest'][$courseid])) {
+ // Never use me anywhere but here and require_login
+ if ($USER->enrol['tempguest'][$courseid] == 0) {
+ $access = true;
+ } else if ($USER->enrol['tempguest'][$courseid] > time()) {
+ $access = true;
+ } else {
+ //expired
+ unset($USER->enrol['tempguest'][$courseid]);
+ }
+ }
+ return $access;
+}
+
/**
* Returns array with sql code and parameters returning all ids
* of users enrolled into course.
* Attempt to automatically enrol current user in course without any interaction,
* calling code has to make sure the plugin and instance are active.
*
+ * This should return either a timestamp in the future or false.
+ *
* @param stdClass $instance course enrol instance
* @param stdClass $user record
* @return bool|int false means not enrolled, integer means timeend
* Attempt to automatically gain temporary guest access to course,
* calling code has to make sure the plugin and instance are active.
*
+ * This should return either a timestamp in the future or false.
+ *
* @param stdClass $instance course enrol instance
* @param stdClass $user record
* @return bool|int false means no guest access, integer means timeend
if (!isset($enrols[$instance->enrol])) {
continue;
}
+ // Get a duration for the guestaccess, a timestamp in the future or false.
$until = $enrols[$instance->enrol]->try_autoenrol($instance);
if ($until !== false) {
$USER->enrol['enrolled'][$course->id] = $until;
if (!isset($enrols[$instance->enrol])) {
continue;
}
+ // Get a duration for the guestaccess, a timestamp in the future or false.
$until = $enrols[$instance->enrol]->try_guestaccess($instance);
if ($until !== false) {
$USER->enrol['tempguest'][$course->id] = $until;
// course node and not populate it.
$coursecontext = get_context_instance(CONTEXT_COURSE, $course->id);
// Not enrolled, can't view, and hasn't switched roles
- if ((!is_enrolled($coursecontext) && !has_capability('moodle/course:view', $coursecontext) && !is_role_switched($course->id))) {
+
+ if (!can_access_course($coursecontext)) {
$coursenode->make_active();
$canviewcourseprofile = false;
break;
// If the user is not enrolled then we only want to show the
// course node and not populate it.
$coursecontext = get_context_instance(CONTEXT_COURSE, $course->id);
- if ($course->id !== SITEID && !is_enrolled($coursecontext) && !has_capability('moodle/course:view', $coursecontext)) {
+ if (can_access_course($coursecontext)) {
if ($coursenode) {
$coursenode->make_active();
}
// If the user is not enrolled then we only want to show the
// course node and not populate it.
$coursecontext = get_context_instance(CONTEXT_COURSE, $course->id);
- if (!is_enrolled($coursecontext) && !has_capability('moodle/course:view', $coursecontext)) {
+ if (can_access_course($coursecontext)) {
$coursenode->make_active();
$canviewcourseprofile = false;
break;
$usercoursenode->add(get_string('notes', 'notes'), $url, self::TYPE_SETTING);
}
- if (has_capability('moodle/course:view', get_context_instance(CONTEXT_COURSE, $usercourse->id))) {
+ if (can_access_course(get_context_instance(CONTEXT_COURSE, $usercourse->id), $user->id)) {
$usercoursenode->add(get_string('entercourse'), new moodle_url('/course/view.php', array('id'=>$usercourse->id)), self::TYPE_SETTING, null, null, new pix_icon('i/course', ''));
}
return false;
}
} else {
- if ((!has_capability('moodle/user:viewdetails', $coursecontext) && !has_capability('moodle/user:viewdetails', $usercontext)) || !is_enrolled($coursecontext, $user->id)) {
+ if ((!has_capability('moodle/user:viewdetails', $coursecontext) && !has_capability('moodle/user:viewdetails', $usercontext)) || !can_access_course($coursecontext, $user->id)) {
return false;
}
if (groups_get_course_groupmode($course) == SEPARATEGROUPS && !has_capability('moodle/site:accessallgroups', $coursecontext)) {