mirror of
https://github.com/moodle/moodle.git
synced 2025-03-13 20:26:32 +01:00
accesslib: remove some functions we do not need anymore
This is *the* scary commit. No more scaffolding, no more training wheels. Remove the legacy has_capabilty_old() and several supporting functions. has_capability_old() capability_search() is_parent_context() roles_context_cmp() load_user_capability() capability_prohibits() I've grepped far and wide. Noone else uses the supporting functions anywhere in-the-known-universe. If I could not find it, it does not exist. [Thankful that cvs/git/whatever will hold on to them if I end up having to regret this.]
This commit is contained in:
parent
204a369c1e
commit
2219374865
@ -921,749 +921,6 @@ function get_context_users_byrole ($context, $roleid, $fields=NULL, $where=NULL,
|
||||
return $users;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function returns whether the current user has the capability of performing a function
|
||||
* For example, we can do has_capability('mod/forum:replypost',$context) in forum
|
||||
* This is a recursive function.
|
||||
* @uses $USER
|
||||
* @param string $capability - name of the capability (or debugcache or clearcache)
|
||||
* @param object $context - a context object (record from context table)
|
||||
* @param integer $userid - a userid number
|
||||
* @param bool $doanything - if false, ignore do anything
|
||||
* @return bool
|
||||
*/
|
||||
function has_capability_old($capability, $context=NULL, $userid=NULL, $doanything=true) {
|
||||
|
||||
global $USER, $CONTEXT, $CFG;
|
||||
|
||||
static $capcache = array(); // Cache of capabilities
|
||||
|
||||
|
||||
/// Cache management
|
||||
|
||||
if ($capability == 'clearcache') {
|
||||
$capcache = array(); // Clear ALL the capability cache
|
||||
return false;
|
||||
}
|
||||
|
||||
/// Some sanity checks
|
||||
if (debugging('',DEBUG_DEVELOPER)) {
|
||||
if ($capability == 'debugcache') {
|
||||
print_object($capcache);
|
||||
return true;
|
||||
}
|
||||
if (!record_exists('capabilities', 'name', $capability)) {
|
||||
debugging('Capability "'.$capability.'" was not found! This should be fixed in code.');
|
||||
}
|
||||
if ($doanything != true and $doanything != false) {
|
||||
debugging('Capability parameter "doanything" is wierd ("'.$doanything.'"). This should be fixed in code.');
|
||||
}
|
||||
if (!is_object($context) && $context !== NULL) {
|
||||
debugging('Incorrect context parameter "'.$context.'" for has_capability(), object expected! This should be fixed in code.');
|
||||
}
|
||||
}
|
||||
|
||||
/// Make sure we know the current context
|
||||
if (empty($context)) { // Use default CONTEXT if none specified
|
||||
if (empty($CONTEXT)) {
|
||||
return false;
|
||||
} else {
|
||||
$context = $CONTEXT;
|
||||
}
|
||||
} else { // A context was given to us
|
||||
if (empty($CONTEXT)) {
|
||||
$CONTEXT = $context; // Store FIRST used context in this global as future default
|
||||
}
|
||||
}
|
||||
|
||||
/// Check and return cache in case we've processed this one before.
|
||||
$requsteduser = empty($userid) ? $USER->id : $userid; // find out the requested user id, $USER->id might have been changed
|
||||
$cachekey = $capability.'_'.$context->id.'_'.intval($requsteduser).'_'.intval($doanything);
|
||||
|
||||
if (isset($capcache[$cachekey])) {
|
||||
return $capcache[$cachekey];
|
||||
}
|
||||
|
||||
|
||||
/// Load up the capabilities list or item as necessary
|
||||
if ($userid) {
|
||||
if (empty($USER->id) or ($userid != $USER->id) or empty($USER->capabilities)) {
|
||||
|
||||
//caching - helps user switching in cron
|
||||
static $guestuserid = false; // guest user id
|
||||
static $guestcaps = false; // guest caps
|
||||
static $defcaps = false; // default user caps - this might help cron
|
||||
|
||||
if ($guestuserid === false) {
|
||||
$guestuserid = get_field('user', 'id', 'username', 'guest');
|
||||
}
|
||||
|
||||
if ($userid == $guestuserid) {
|
||||
if ($guestcaps === false) {
|
||||
$guestcaps = load_guest_role(true);
|
||||
}
|
||||
$capabilities = $guestcaps;
|
||||
|
||||
} else {
|
||||
// This big SQL is expensive! We reduce it a little by avoiding checking for changed enrolments (false)
|
||||
$capabilities = load_user_capability($capability, $context, $userid, false);
|
||||
if ($defcaps === false) {
|
||||
$defcaps = load_defaultuser_role(true);
|
||||
}
|
||||
$capabilities = merge_role_caps($capabilities, $defcaps);
|
||||
}
|
||||
|
||||
} else { //$USER->id == $userid and needed capabilities already present
|
||||
$capabilities = $USER->capabilities;
|
||||
}
|
||||
|
||||
} else { // no userid
|
||||
if (empty($USER->capabilities)) {
|
||||
load_all_capabilities(); // expensive - but we have to do it once anyway
|
||||
}
|
||||
$capabilities = $USER->capabilities;
|
||||
$userid = $USER->id;
|
||||
}
|
||||
|
||||
/// We act a little differently when switchroles is active
|
||||
|
||||
$switchroleactive = false; // Assume it isn't active in this context
|
||||
|
||||
|
||||
/// First deal with the "doanything" capability
|
||||
|
||||
if ($doanything) {
|
||||
|
||||
/// First make sure that we aren't in a "switched role"
|
||||
|
||||
if (!empty($USER->switchrole)) { // Switchrole is active somewhere!
|
||||
if (!empty($USER->switchrole[$context->id])) { // Because of current context
|
||||
$switchroleactive = true;
|
||||
} else { // Check parent contexts
|
||||
if ($parentcontextids = get_parent_contexts($context)) {
|
||||
foreach ($parentcontextids as $parentcontextid) {
|
||||
if (!empty($USER->switchrole[$parentcontextid])) { // Yep, switchroles active here
|
||||
$switchroleactive = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Check the site context for doanything (most common) first
|
||||
|
||||
if (empty($switchroleactive)) { // Ignore site setting if switchrole is active
|
||||
$sitecontext = get_context_instance(CONTEXT_SYSTEM);
|
||||
if (isset($capabilities[$sitecontext->id]['moodle/site:doanything'])) {
|
||||
$result = (0 < $capabilities[$sitecontext->id]['moodle/site:doanything']);
|
||||
$capcache[$cachekey] = $result;
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
/// If it's not set at site level, it is possible to be set on other levels
|
||||
/// Though this usage is not common and can cause risks
|
||||
switch ($context->contextlevel) {
|
||||
|
||||
case CONTEXT_COURSECAT:
|
||||
// Check parent cats.
|
||||
$parentcats = get_parent_cats($context);
|
||||
foreach ($parentcats as $parentcat) {
|
||||
if (isset($capabilities[$parentcat]['moodle/site:doanything'])) {
|
||||
$result = (0 < $capabilities[$parentcat]['moodle/site:doanything']);
|
||||
$capcache[$cachekey] = $result;
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case CONTEXT_COURSE:
|
||||
// Check parent cat.
|
||||
$parentcats = get_parent_cats($context);
|
||||
|
||||
foreach ($parentcats as $parentcat) {
|
||||
if (isset($capabilities[$parentcat]['do_anything'])) {
|
||||
$result = (0 < $capabilities[$parentcat]['do_anything']);
|
||||
$capcache[$cachekey] = $result;
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case CONTEXT_GROUP:
|
||||
// Find course.
|
||||
$courseid = get_field('groups', 'courseid', 'id', $context->instanceid);
|
||||
$courseinstance = get_context_instance(CONTEXT_COURSE, $courseid);
|
||||
|
||||
$parentcats = get_parent_cats($courseinstance);
|
||||
foreach ($parentcats as $parentcat) {
|
||||
if (isset($capabilities[$parentcat]['do_anything'])) {
|
||||
$result = (0 < $capabilities[$parentcat]['do_anything']);
|
||||
$capcache[$cachekey] = $result;
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
|
||||
$coursecontext = '';
|
||||
if (isset($capabilities[$courseinstance->id]['do_anything'])) {
|
||||
$result = (0 < $capabilities[$courseinstance->id]['do_anything']);
|
||||
$capcache[$cachekey] = $result;
|
||||
return $result;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case CONTEXT_MODULE:
|
||||
// Find course.
|
||||
$cm = get_record('course_modules', 'id', $context->instanceid);
|
||||
$courseinstance = get_context_instance(CONTEXT_COURSE, $cm->course);
|
||||
|
||||
if ($parentcats = get_parent_cats($courseinstance)) {
|
||||
foreach ($parentcats as $parentcat) {
|
||||
if (isset($capabilities[$parentcat]['do_anything'])) {
|
||||
$result = (0 < $capabilities[$parentcat]['do_anything']);
|
||||
$capcache[$cachekey] = $result;
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($capabilities[$courseinstance->id]['do_anything'])) {
|
||||
$result = (0 < $capabilities[$courseinstance->id]['do_anything']);
|
||||
$capcache[$cachekey] = $result;
|
||||
return $result;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case CONTEXT_BLOCK:
|
||||
// not necessarily 1 to 1 to course.
|
||||
$block = get_record('block_instance','id',$context->instanceid);
|
||||
if ($block->pagetype == 'course-view') {
|
||||
$courseinstance = get_context_instance(CONTEXT_COURSE, $block->pageid); // needs check
|
||||
$parentcats = get_parent_cats($courseinstance);
|
||||
|
||||
foreach ($parentcats as $parentcat) {
|
||||
if (isset($capabilities[$parentcat]['do_anything'])) {
|
||||
$result = (0 < $capabilities[$parentcat]['do_anything']);
|
||||
$capcache[$cachekey] = $result;
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($capabilities[$courseinstance->id]['do_anything'])) {
|
||||
$result = (0 < $capabilities[$courseinstance->id]['do_anything']);
|
||||
$capcache[$cachekey] = $result;
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
// blocks that do not have course as parent do not need to do any more checks - already done above
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
// CONTEXT_SYSTEM: CONTEXT_PERSONAL: CONTEXT_USER:
|
||||
// Do nothing, because the parents are site context
|
||||
// which has been checked already
|
||||
break;
|
||||
}
|
||||
|
||||
// Last: check self.
|
||||
if (isset($capabilities[$context->id]['do_anything'])) {
|
||||
$result = (0 < $capabilities[$context->id]['do_anything']);
|
||||
$capcache[$cachekey] = $result;
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
// do_anything has not been set, we now look for it the normal way.
|
||||
$result = (0 < capability_search($capability, $context, $capabilities, $switchroleactive));
|
||||
$capcache[$cachekey] = $result;
|
||||
return $result;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* In a separate function so that we won't have to deal with do_anything.
|
||||
* again. Used by function has_capability().
|
||||
* @param $capability - capability string
|
||||
* @param $context - the context object
|
||||
* @param $capabilities - either $USER->capability or loaded array (for other users)
|
||||
* @return permission (int)
|
||||
*/
|
||||
function capability_search($capability, $context, $capabilities, $switchroleactive=false) {
|
||||
|
||||
global $USER, $CFG, $COURSE;
|
||||
|
||||
if (!isset($context->id)) {
|
||||
return 0;
|
||||
}
|
||||
// if already set in the array explicitly, no need to look for it in parent
|
||||
// context any longer
|
||||
if (isset($capabilities[$context->id][$capability])) {
|
||||
return ($capabilities[$context->id][$capability]);
|
||||
}
|
||||
|
||||
/* Then, we check the cache recursively */
|
||||
$permission = 0;
|
||||
|
||||
switch ($context->contextlevel) {
|
||||
|
||||
case CONTEXT_SYSTEM: // by now it's a definite an inherit
|
||||
$permission = 0;
|
||||
break;
|
||||
|
||||
case CONTEXT_PERSONAL:
|
||||
$parentcontext = get_context_instance(CONTEXT_SYSTEM);
|
||||
$permission = capability_search($capability, $parentcontext, $capabilities, $switchroleactive);
|
||||
break;
|
||||
|
||||
case CONTEXT_USER:
|
||||
$parentcontext = get_context_instance(CONTEXT_SYSTEM);
|
||||
$permission = capability_search($capability, $parentcontext, $capabilities, $switchroleactive);
|
||||
break;
|
||||
|
||||
case CONTEXT_COURSE:
|
||||
if ($switchroleactive) {
|
||||
// if switchrole active, do not check permissions above the course context, blocks are an exception
|
||||
break;
|
||||
}
|
||||
// break is not here intentionally - because the code is the same for category and course
|
||||
case CONTEXT_COURSECAT: // Coursecat -> coursecat or site
|
||||
$parents = get_parent_cats($context); // cached internally
|
||||
|
||||
// non recursive - should be faster
|
||||
foreach ($parents as $parentid) {
|
||||
$parentcontext = get_context_instance_by_id($parentid);
|
||||
if (isset($capabilities[$parentcontext->id][$capability])) {
|
||||
return ($capabilities[$parentcontext->id][$capability]);
|
||||
}
|
||||
}
|
||||
// finally check system context
|
||||
$parentcontext = get_context_instance(CONTEXT_SYSTEM);
|
||||
$permission = capability_search($capability, $parentcontext, $capabilities, $switchroleactive);
|
||||
break;
|
||||
|
||||
case CONTEXT_GROUP: // 1 to 1 to course
|
||||
$courseid = get_field('groups', 'courseid', 'id', $context->instanceid);
|
||||
$parentcontext = get_context_instance(CONTEXT_COURSE, $courseid);
|
||||
$permission = capability_search($capability, $parentcontext, $capabilities, $switchroleactive);
|
||||
break;
|
||||
|
||||
case CONTEXT_MODULE: // 1 to 1 to course
|
||||
$cm = get_record('course_modules','id',$context->instanceid);
|
||||
$parentcontext = get_context_instance(CONTEXT_COURSE, $cm->course);
|
||||
$permission = capability_search($capability, $parentcontext, $capabilities, $switchroleactive);
|
||||
break;
|
||||
|
||||
case CONTEXT_BLOCK: // not necessarily 1 to 1 to course
|
||||
$block = get_record('block_instance','id',$context->instanceid);
|
||||
if ($block->pagetype == 'course-view') {
|
||||
$parentcontext = get_context_instance(CONTEXT_COURSE, $block->pageid); // needs check
|
||||
} else {
|
||||
$parentcontext = get_context_instance(CONTEXT_SYSTEM);
|
||||
}
|
||||
// ignore the $switchroleactive beause we want the real block view capability defined in system context
|
||||
$permission = capability_search($capability, $parentcontext, $capabilities, false);
|
||||
break;
|
||||
|
||||
default:
|
||||
error ('This is an unknown context (' . $context->contextlevel . ') in capability_search!');
|
||||
return false;
|
||||
}
|
||||
|
||||
return $permission;
|
||||
}
|
||||
|
||||
/**
|
||||
* auxillary function for load_user_capabilities()
|
||||
* checks if context c1 is a parent (or itself) of context c2
|
||||
* @param int $c1 - context id of context 1
|
||||
* @param int $c2 - context id of context 2
|
||||
* @return bool
|
||||
*/
|
||||
function is_parent_context($c1, $c2) {
|
||||
static $parentsarray;
|
||||
|
||||
// context can be itself and this is ok
|
||||
if ($c1 == $c2) {
|
||||
return true;
|
||||
}
|
||||
// hit in cache?
|
||||
if (isset($parentsarray[$c1][$c2])) {
|
||||
return $parentsarray[$c1][$c2];
|
||||
}
|
||||
|
||||
if (!$co2 = get_record('context', 'id', $c2)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!$parents = get_parent_contexts($co2)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
foreach ($parents as $parent) {
|
||||
$parentsarray[$parent][$c2] = true;
|
||||
}
|
||||
|
||||
if (in_array($c1, $parents)) {
|
||||
return true;
|
||||
} else { // else not a parent, set the cache anyway
|
||||
$parentsarray[$c1][$c2] = false;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* auxillary function for load_user_capabilities()
|
||||
* handler in usort() to sort contexts according to level
|
||||
* @param object contexta
|
||||
* @param object contextb
|
||||
* @return int
|
||||
*/
|
||||
function roles_context_cmp($contexta, $contextb) {
|
||||
if ($contexta->contextlevel == $contextb->contextlevel) {
|
||||
return 0;
|
||||
}
|
||||
return ($contexta->contextlevel < $contextb->contextlevel) ? -1 : 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* It will build an array of all the capabilities at each level
|
||||
* i.e. site/metacourse/course_category/course/moduleinstance
|
||||
* Note we should only load capabilities if they are explicitly assigned already,
|
||||
* we should not load all module's capability!
|
||||
*
|
||||
* [Capabilities] => [26][forum_post] = 1
|
||||
* [26][forum_start] = -8990
|
||||
* [26][forum_edit] = -1
|
||||
* [273][blah blah] = 1
|
||||
* [273][blah blah blah] = 2
|
||||
*
|
||||
* @param $capability string - Only get a specific capability (string)
|
||||
* @param $context object - Only get capabilities for a specific context object
|
||||
* @param $userid integer - the id of the user whose capabilities we want to load
|
||||
* @param $checkenrolments boolean - Should we check enrolment plugins (potentially expensive)
|
||||
* @return array of permissions (or nothing if they get assigned to $USER)
|
||||
*/
|
||||
function load_user_capability($capability='', $context=NULL, $userid=NULL, $checkenrolments=true) {
|
||||
|
||||
global $USER, $CFG;
|
||||
|
||||
// this flag has not been set!
|
||||
// (not clean install, or upgraded successfully to 1.7 and up)
|
||||
if (empty($CFG->rolesactive)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (empty($userid)) {
|
||||
if (empty($USER->id)) { // We have no user to get capabilities for
|
||||
debugging('User not logged in for load_user_capability!');
|
||||
return false;
|
||||
}
|
||||
unset($USER->capabilities); // We don't want possible older capabilites hanging around
|
||||
unset($USER->access);
|
||||
|
||||
if ($checkenrolments) { // Call "enrol" system to ensure that we have the correct picture
|
||||
check_enrolment_plugins($USER);
|
||||
}
|
||||
|
||||
$userid = $USER->id;
|
||||
$otheruserid = false;
|
||||
} else {
|
||||
if (!$user = get_record('user', 'id', $userid)) {
|
||||
debugging('Non-existent userid in load_user_capability!');
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($checkenrolments) { // Call "enrol" system to ensure that we have the correct picture
|
||||
check_enrolment_plugins($user);
|
||||
}
|
||||
|
||||
$otheruserid = $userid;
|
||||
}
|
||||
|
||||
|
||||
/// First we generate a list of all relevant contexts of the user
|
||||
|
||||
$usercontexts = array();
|
||||
|
||||
if ($context) { // if context is specified
|
||||
$usercontexts = get_parent_contexts($context);
|
||||
$usercontexts[] = $context->id; // Add the current context as well
|
||||
} else { // else, we load everything
|
||||
if ($userroles = get_records('role_assignments','userid',$userid)) {
|
||||
foreach ($userroles as $userrole) {
|
||||
if (!in_array($userrole->contextid, $usercontexts)) {
|
||||
$usercontexts[] = $userrole->contextid;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Set up SQL fragments for searching contexts
|
||||
|
||||
if ($usercontexts) {
|
||||
$listofcontexts = '('.implode(',', $usercontexts).')';
|
||||
$searchcontexts1 = "c1.id IN $listofcontexts AND";
|
||||
} else {
|
||||
$searchcontexts1 = '';
|
||||
}
|
||||
|
||||
if ($capability) {
|
||||
// the doanything may override the requested capability
|
||||
$capsearch = " AND (rc.capability = '$capability' OR rc.capability = 'moodle/site:doanything') ";
|
||||
} else {
|
||||
$capsearch ="";
|
||||
}
|
||||
|
||||
/// Then we use 1 giant SQL to bring out all relevant capabilities.
|
||||
/// The first part gets the capabilities of orginal role.
|
||||
/// The second part gets the capabilities of overriden roles.
|
||||
|
||||
$siteinstance = get_context_instance(CONTEXT_SYSTEM);
|
||||
$capabilities = array(); // Reinitialize.
|
||||
|
||||
// SQL for normal capabilities
|
||||
$SQL1 = "SELECT rc.capability, c1.id as id1, c1.id as id2, (c1.contextlevel * 100) AS aggrlevel,
|
||||
SUM(rc.permission) AS sum
|
||||
FROM
|
||||
{$CFG->prefix}role_assignments ra,
|
||||
{$CFG->prefix}role_capabilities rc,
|
||||
{$CFG->prefix}context c1
|
||||
WHERE
|
||||
ra.contextid=c1.id AND
|
||||
ra.roleid=rc.roleid AND
|
||||
ra.userid=$userid AND
|
||||
$searchcontexts1
|
||||
rc.contextid=$siteinstance->id
|
||||
$capsearch
|
||||
GROUP BY
|
||||
rc.capability, c1.id, c1.contextlevel * 100
|
||||
HAVING
|
||||
SUM(rc.permission) != 0
|
||||
|
||||
UNION ALL
|
||||
|
||||
SELECT rc.capability, c1.id as id1, c2.id as id2, (c1.contextlevel * 100 + c2.contextlevel) AS aggrlevel,
|
||||
SUM(rc.permission) AS sum
|
||||
FROM
|
||||
{$CFG->prefix}role_assignments ra INNER JOIN
|
||||
{$CFG->prefix}role_capabilities rc on ra.roleid = rc.roleid INNER JOIN
|
||||
{$CFG->prefix}context c1 on ra.contextid = c1.id INNER JOIN
|
||||
{$CFG->prefix}context c2 on rc.contextid = c2.id INNER JOIN
|
||||
{$CFG->prefix}context_rel cr on cr.c1 = c2.id AND cr.c2 = c1.id
|
||||
WHERE
|
||||
ra.userid=$userid AND
|
||||
$searchcontexts1
|
||||
rc.contextid != $siteinstance->id
|
||||
$capsearch
|
||||
GROUP BY
|
||||
rc.capability, c1.id, c2.id, c1.contextlevel * 100 + c2.contextlevel
|
||||
HAVING
|
||||
SUM(rc.permission) != 0
|
||||
ORDER BY
|
||||
aggrlevel ASC";
|
||||
|
||||
if (!$rs = get_recordset_sql($SQL1)) {
|
||||
error("Query failed in load_user_capability.");
|
||||
}
|
||||
|
||||
if ($rs && $rs->RecordCount() > 0) {
|
||||
while ($caprec = rs_fetch_next_record($rs)) {
|
||||
$array = (array)$caprec;
|
||||
$temprecord = new object;
|
||||
|
||||
foreach ($array as $key=>$val) {
|
||||
if ($key == 'aggrlevel') {
|
||||
$temprecord->contextlevel = $val;
|
||||
} else {
|
||||
$temprecord->{$key} = $val;
|
||||
}
|
||||
}
|
||||
$capabilities[] = $temprecord;
|
||||
}
|
||||
rs_close($rs);
|
||||
}
|
||||
|
||||
// SQL for overrides
|
||||
// this is take out because we have no way of making sure c1 is indeed related to c2 (parent)
|
||||
// if we do not group by sum, it is possible to have multiple records of rc.capability, c1.id, c2.id, tuple having
|
||||
// different values, we can maually sum it when we go through the list
|
||||
|
||||
/*
|
||||
|
||||
$SQL2 = "SELECT rc.capability, c1.id as id1, c2.id as id2, (c1.contextlevel * 100 + c2.contextlevel) AS aggrlevel,
|
||||
rc.permission AS sum
|
||||
FROM
|
||||
{$CFG->prefix}role_assignments ra,
|
||||
{$CFG->prefix}role_capabilities rc,
|
||||
{$CFG->prefix}context c1,
|
||||
{$CFG->prefix}context c2
|
||||
WHERE
|
||||
ra.contextid=c1.id AND
|
||||
ra.roleid=rc.roleid AND
|
||||
ra.userid=$userid AND
|
||||
rc.contextid=c2.id AND
|
||||
$searchcontexts1
|
||||
rc.contextid != $siteinstance->id
|
||||
$capsearch
|
||||
|
||||
GROUP BY
|
||||
rc.capability, (c1.contextlevel * 100 + c2.contextlevel), c1.id, c2.id, rc.permission
|
||||
ORDER BY
|
||||
aggrlevel ASC
|
||||
";*/
|
||||
|
||||
/*
|
||||
if (!$rs = get_recordset_sql($SQL2)) {
|
||||
error("Query failed in load_user_capability.");
|
||||
}
|
||||
|
||||
if ($rs && $rs->RecordCount() > 0) {
|
||||
while ($caprec = rs_fetch_next_record($rs)) {
|
||||
$array = (array)$caprec;
|
||||
$temprecord = new object;
|
||||
|
||||
foreach ($array as $key=>$val) {
|
||||
if ($key == 'aggrlevel') {
|
||||
$temprecord->contextlevel = $val;
|
||||
} else {
|
||||
$temprecord->{$key} = $val;
|
||||
}
|
||||
}
|
||||
// for overrides, we have to make sure that context2 is a child of context1
|
||||
// otherwise the combination makes no sense
|
||||
//if (is_parent_context($temprecord->id1, $temprecord->id2)) {
|
||||
$capabilities[] = $temprecord;
|
||||
//} // only write if relevant
|
||||
}
|
||||
rs_close($rs);
|
||||
}
|
||||
|
||||
// this step sorts capabilities according to the contextlevel
|
||||
// it is very important because the order matters when we
|
||||
// go through each capabilities later. (i.e. higher level contextlevel
|
||||
// will override lower contextlevel settings
|
||||
usort($capabilities, 'roles_context_cmp');
|
||||
*/
|
||||
/* so up to this point we should have somethign like this
|
||||
* $capabilities[1] ->contextlevel = 1000
|
||||
->module = 0 // changed from SITEID in 1.8 (??)
|
||||
->capability = do_anything
|
||||
->id = 1 (id is the context id)
|
||||
->sum = 0
|
||||
|
||||
* $capabilities[2] ->contextlevel = 1000
|
||||
->module = 0 // changed from SITEID in 1.8 (??)
|
||||
->capability = post_messages
|
||||
->id = 1
|
||||
->sum = -9000
|
||||
|
||||
* $capabilittes[3] ->contextlevel = 3000
|
||||
->module = course
|
||||
->capability = view_course_activities
|
||||
->id = 25
|
||||
->sum = 1
|
||||
|
||||
* $capabilittes[4] ->contextlevel = 3000
|
||||
->module = course
|
||||
->capability = view_course_activities
|
||||
->id = 26
|
||||
->sum = 0 (this is another course)
|
||||
|
||||
* $capabilities[5] ->contextlevel = 3050
|
||||
->module = course
|
||||
->capability = view_course_activities
|
||||
->id = 25 (override in course 25)
|
||||
->sum = -1
|
||||
* ....
|
||||
* now we proceed to write the session array, going from top to bottom
|
||||
* at anypoint, we need to go up and check parent to look for prohibit
|
||||
*/
|
||||
// print_object($capabilities);
|
||||
|
||||
/* This is where we write to the actualy capabilities array
|
||||
* what we need to do from here on is
|
||||
* going down the array from lowest level to highest level
|
||||
* 1) recursively check for prohibit,
|
||||
* if any, we write prohibit
|
||||
* else, we write the value
|
||||
* 2) at an override level, we overwrite current level
|
||||
* if it's not set to prohibit already, and if different
|
||||
* ........ that should be it ........
|
||||
*/
|
||||
|
||||
// This is the flag used for detecting the current context level. Since we are going through
|
||||
// the array in ascending order of context level. For normal capabilities, there should only
|
||||
// be 1 value per (capability, contextlevel, context), because they are already summed. But,
|
||||
// for overrides, since we are processing them separate, we need to sum the relevcant entries.
|
||||
// We set this flag when we hit a new level.
|
||||
// If the flag is already set, we keep adding (summing), otherwise, we just override previous
|
||||
// settings (from lower level contexts)
|
||||
$capflags = array(); // (contextid, contextlevel, capability)
|
||||
$usercap = array(); // for other user's capabilities
|
||||
foreach ($capabilities as $capability) {
|
||||
|
||||
if (!$context = get_context_instance_by_id($capability->id2)) {
|
||||
continue; // incorrect stale context
|
||||
}
|
||||
|
||||
if (!empty($otheruserid)) { // we are pulling out other user's capabilities, do not write to session
|
||||
|
||||
if (capability_prohibits($capability->capability, $context, $capability->sum, $usercap)) {
|
||||
$usercap[$capability->id2][$capability->capability] = CAP_PROHIBIT;
|
||||
continue;
|
||||
}
|
||||
if (isset($usercap[$capability->id2][$capability->capability])) { // use isset because it can be sum 0
|
||||
if (!empty($capflags[$capability->id2][$capability->contextlevel][$capability->capability])) {
|
||||
$usercap[$capability->id2][$capability->capability] += $capability->sum;
|
||||
} else { // else we override, and update flag
|
||||
$usercap[$capability->id2][$capability->capability] = $capability->sum;
|
||||
$capflags[$capability->id2][$capability->contextlevel][$capability->capability] = true;
|
||||
}
|
||||
} else {
|
||||
$usercap[$capability->id2][$capability->capability] = $capability->sum;
|
||||
$capflags[$capability->id2][$capability->contextlevel][$capability->capability] = true;
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
if (capability_prohibits($capability->capability, $context, $capability->sum)) { // if any parent or parent's parent is set to prohibit
|
||||
$USER->capabilities[$capability->id2][$capability->capability] = CAP_PROHIBIT;
|
||||
continue;
|
||||
}
|
||||
|
||||
// if no parental prohibit set
|
||||
// just write to session, i am not sure this is correct yet
|
||||
// since 3050 shows up after 3000, and 3070 shows up after 3050,
|
||||
// it should be ok just to overwrite like this, provided that there's no
|
||||
// parental prohibits
|
||||
// we need to write even if it's 0, because it could be an inherit override
|
||||
if (isset($USER->capabilities[$capability->id2][$capability->capability])) {
|
||||
if (!empty($capflags[$capability->id2][$capability->contextlevel][$capability->capability])) {
|
||||
$USER->capabilities[$capability->id2][$capability->capability] += $capability->sum;
|
||||
} else { // else we override, and update flag
|
||||
$USER->capabilities[$capability->id2][$capability->capability] = $capability->sum;
|
||||
$capflags[$capability->id2][$capability->contextlevel][$capability->capability] = true;
|
||||
}
|
||||
} else {
|
||||
$USER->capabilities[$capability->id2][$capability->capability] = $capability->sum;
|
||||
$capflags[$capability->id2][$capability->contextlevel][$capability->capability] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// now we don't care about the huge array anymore, we can dispose it.
|
||||
unset($capabilities);
|
||||
unset($capflags);
|
||||
|
||||
if (!empty($otheruserid)) {
|
||||
return $usercap; // return the array
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* It will return a nested array showing role assignments
|
||||
* all relevant role capabilities for the user at
|
||||
@ -2226,139 +1483,6 @@ function check_enrolment_plugins(&$user) {
|
||||
unset($inprogress[$user->id]); // Unset the flag
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This is a recursive function that checks whether the capability in this
|
||||
* context, or the parent capabilities are set to prohibit.
|
||||
*
|
||||
* At this point, we can probably just use the values already set in the
|
||||
* session variable, since we are going down the level. Any prohit set in
|
||||
* parents would already reflect in the session.
|
||||
*
|
||||
* @param $capability - capability name
|
||||
* @param $sum - sum of all capabilities values
|
||||
* @param $context - the context object
|
||||
* @param $array - when loading another user caps, their caps are not stored in session but an array
|
||||
*/
|
||||
function capability_prohibits($capability, $context, $sum='', $array='') {
|
||||
global $USER;
|
||||
|
||||
// caching, mainly to save unnecessary sqls
|
||||
static $prohibits; //[capability][contextid]
|
||||
if (isset($prohibits[$capability][$context->id])) {
|
||||
return $prohibits[$capability][$context->id];
|
||||
}
|
||||
|
||||
if (empty($context->id)) {
|
||||
$prohibits[$capability][$context->id] = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (empty($capability)) {
|
||||
$prohibits[$capability][$context->id] = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($sum < (CAP_PROHIBIT/2)) {
|
||||
// If this capability is set to prohibit.
|
||||
$prohibits[$capability][$context->id] = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!empty($array)) {
|
||||
if (isset($array[$context->id][$capability])
|
||||
&& $array[$context->id][$capability] < (CAP_PROHIBIT/2)) {
|
||||
$prohibits[$capability][$context->id] = true;
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
// Else if set in session.
|
||||
if (isset($USER->capabilities[$context->id][$capability])
|
||||
&& $USER->capabilities[$context->id][$capability] < (CAP_PROHIBIT/2)) {
|
||||
$prohibits[$capability][$context->id] = true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
switch ($context->contextlevel) {
|
||||
|
||||
case CONTEXT_SYSTEM:
|
||||
// By now it's a definite an inherit.
|
||||
return 0;
|
||||
break;
|
||||
|
||||
case CONTEXT_PERSONAL:
|
||||
$parent = get_context_instance(CONTEXT_SYSTEM);
|
||||
$prohibits[$capability][$context->id] = capability_prohibits($capability, $parent);
|
||||
return $prohibits[$capability][$context->id];
|
||||
break;
|
||||
|
||||
case CONTEXT_USER:
|
||||
$parent = get_context_instance(CONTEXT_SYSTEM);
|
||||
$prohibits[$capability][$context->id] = capability_prohibits($capability, $parent);
|
||||
return $prohibits[$capability][$context->id];
|
||||
break;
|
||||
|
||||
case CONTEXT_COURSECAT:
|
||||
case CONTEXT_COURSE:
|
||||
$parents = get_parent_cats($context); // cached internally
|
||||
// no workaround for recursion now - it needs some more work and maybe fixing
|
||||
|
||||
if (empty($parents)) {
|
||||
// system context - this is either top category or frontpage course
|
||||
$parent = get_context_instance(CONTEXT_SYSTEM);
|
||||
} else {
|
||||
// parent context - recursion
|
||||
$parentid = array_pop($parents);
|
||||
$parent = get_context_instance_by_id($parentid);
|
||||
}
|
||||
$prohibits[$capability][$context->id] = capability_prohibits($capability, $parent);
|
||||
return $prohibits[$capability][$context->id];
|
||||
break;
|
||||
|
||||
case CONTEXT_GROUP:
|
||||
// 1 to 1 to course.
|
||||
if (!$courseid = get_field('groups', 'courseid', 'id', $context->instanceid)) {
|
||||
$prohibits[$capability][$context->id] = false;
|
||||
return false;
|
||||
}
|
||||
$parent = get_context_instance(CONTEXT_COURSE, $courseid);
|
||||
$prohibits[$capability][$context->id] = capability_prohibits($capability, $parent);
|
||||
return $prohibits[$capability][$context->id];
|
||||
break;
|
||||
|
||||
case CONTEXT_MODULE:
|
||||
// 1 to 1 to course.
|
||||
if (!$cm = get_record('course_modules','id',$context->instanceid)) {
|
||||
$prohibits[$capability][$context->id] = false;
|
||||
return false;
|
||||
}
|
||||
$parent = get_context_instance(CONTEXT_COURSE, $cm->course);
|
||||
$prohibits[$capability][$context->id] = capability_prohibits($capability, $parent);
|
||||
return $prohibits[$capability][$context->id];
|
||||
break;
|
||||
|
||||
case CONTEXT_BLOCK:
|
||||
// not necessarily 1 to 1 to course.
|
||||
if (!$block = get_record('block_instance','id',$context->instanceid)) {
|
||||
$prohibits[$capability][$context->id] = false;
|
||||
return false;
|
||||
}
|
||||
if ($block->pagetype == 'course-view') {
|
||||
$parent = get_context_instance(CONTEXT_COURSE, $block->pageid); // needs check
|
||||
} else {
|
||||
$parent = get_context_instance(CONTEXT_SYSTEM);
|
||||
}
|
||||
$prohibits[$capability][$context->id] = capability_prohibits($capability, $parent);
|
||||
return $prohibits[$capability][$context->id];
|
||||
break;
|
||||
|
||||
default:
|
||||
print_error('unknowncontext');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* A print form function. This should either grab all the capabilities from
|
||||
* files or a central table for that particular module instance, then present
|
||||
|
Loading…
x
Reference in New Issue
Block a user