Merge branch 'w43_MDL-29982_m22_canaccess' of git://github.com/skodak/moodle

This commit is contained in:
Eloy Lafuente (stronk7) 2011-11-01 12:26:31 +01:00
commit 302f45e8de
3 changed files with 113 additions and 54 deletions

View file

@ -1969,31 +1969,70 @@ function is_enrolled(context $context, $user = null, $withcapability = '', $only
* of this function can_access_course and require_login. Doing so WILL break future
* versions.
*
* @param context $context
* @param stdClass|null $user
* @param stdClass $course record
* @param stdClass|int|null $user user record or id, current user if null
* @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 $context, $user = null, $withcapability = '', $onlyactive = false, $trustcache = true) {
function can_access_course(stdClass $course, $user = null, $withcapability = '', $onlyactive = false) {
global $DB, $USER;
$coursecontext = $context->get_course_context();
$courseid = $coursecontext->instanceid;
// this function originally accepted $coursecontext parameter
if ($course instanceof context) {
if ($course instanceof context_course) {
debugging('deprecated context parameter, please use $course record');
$coursecontext = $course;
$course = $DB->get_record('course', array('id'=>$coursecontext->instanceid));
} else {
debugging('Invalid context parameter, please use $course record');
return false;
}
} else {
$coursecontext = context_course::instance($course->id);
}
// 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!
if (!isset($USER->id)) {
// should never happen
$USER->id = 0;
}
// make sure there is a user specified
if ($user === null) {
$userid = $USER->id;
} else {
$userid = is_object($user) ? $user->id : $user;
}
unset($user);
if ($withcapability and !has_capability($withcapability, $coursecontext, $userid)) {
return false;
}
if ($userid == $USER->id) {
if (!empty($USER->access['rsw'][$coursecontext->path])) {
// the fact that somebody switched role means they can access the course no matter to what role they switched
return true;
}
}
if (!$course->visible and !has_capability('moodle/course:viewhiddencourses', $coursecontext, $userid)) {
return false;
}
if (is_viewing($coursecontext, $userid)) {
return true;
}
$access = false;
if ($userid != $USER->id) {
// for performance reasons we do not verify temporary guest access for other users, sorry...
return is_enrolled($coursecontext, $userid, '', $onlyactive);
}
// === from here we deal only with $USER ===
// verify our caches
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.
@ -2003,41 +2042,64 @@ function can_access_course(context $context, $user = null, $withcapability = '',
$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 (isset($USER->enrol['enrolled'][$course->id])) {
if ($USER->enrol['enrolled'][$course->id] == 0) {
return true;
} else 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()) {
return true;
}
}
// 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]);
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);
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');
$enrols = enrol_get_plugins(true);
foreach($instances as $instance) {
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;
return true;
}
}
return $access;
unset($USER->enrol['tempguest'][$course->id]);
return false;
}
/**

View file

@ -1112,10 +1112,9 @@ class global_navigation extends navigation_node {
// 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);
// Not enrolled, can't view, and hasn't switched roles
if (!can_access_course($coursecontext)) {
if (!can_access_course($course)) {
// TODO: very ugly hack - do not force "parents" to enrol into course their child is enrolled in,
// this hack has been propagated from user/view.php to display the navigation node. (MDL-25805)
$isparent = false;
@ -1164,8 +1163,7 @@ class global_navigation extends navigation_node {
// 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 (!can_access_course($coursecontext)) {
if (!can_access_course($course)) {
$coursenode->make_active();
$canviewcourseprofile = false;
break;
@ -1232,8 +1230,7 @@ class global_navigation extends navigation_node {
// 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 (!can_access_course($coursecontext)) {
if (!can_access_course($course)) {
$coursenode->make_active();
$canviewcourseprofile = false;
break;
@ -2089,7 +2086,7 @@ class global_navigation extends navigation_node {
$usercoursenode->add(get_string('notes', 'notes'), $url, self::TYPE_SETTING);
}
if (can_access_course(get_context_instance(CONTEXT_COURSE, $usercourse->id), $user->id)) {
if (can_access_course($usercourse, $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', ''));
}
@ -3614,7 +3611,7 @@ class settings_navigation extends navigation_node {
} else {
$canviewusercourse = has_capability('moodle/user:viewdetails', $coursecontext);
$canaccessallgroups = has_capability('moodle/site:accessallgroups', $coursecontext);
if ((!$canviewusercourse && !$canviewuser) || !can_access_course($coursecontext, $user->id)) {
if ((!$canviewusercourse && !$canviewuser) || !can_access_course($course, $user->id)) {
return false;
}
if (!$canaccessallgroups && groups_get_course_groupmode($course) == SEPARATEGROUPS) {

View file

@ -8148,7 +8148,7 @@ function forum_get_posts_by_user($user, array $courses, $musthaveaccess = false,
} else {
// Check whether the current user is enrolled or has access to view the course
// if they don't we immediately have a problem.
if (!can_access_course($coursecontext)) {
if (!can_access_course($course)) {
if ($musthaveaccess) {
print_error('errorenrolmentrequired', 'forum');
}
@ -8157,7 +8157,7 @@ function forum_get_posts_by_user($user, array $courses, $musthaveaccess = false,
// Check whether the requested user is enrolled or has access to view the course
// if they don't we immediately have a problem.
if (!can_access_course($coursecontext, $user)) {
if (!can_access_course($course, $user)) {
if ($musthaveaccess) {
print_error('notenrolled', 'forum');
}