Index: lib/accesslib.php =================================================================== RCS file: /cvsroot/moodle/moodle/lib/accesslib.php,v retrieving revision 1.166.2.30 diff -u -p -r1.166.2.30 accesslib.php --- lib/accesslib.php 5 Dec 2006 07:12:22 -0000 1.166.2.30 +++ lib/accesslib.php 17 Jan 2007 07:11:24 -0000 @@ -708,7 +708,9 @@ function load_user_capability($capabilit } else { // else, we load everything if ($userroles = get_records('role_assignments','userid',$userid)) { foreach ($userroles as $userrole) { - $usercontexts[] = $userrole->contextid; + if (!in_array($userrole->contextid, $usercontexts)) { + $usercontexts[] = $userrole->contextid; + } } } } @@ -755,9 +757,33 @@ function load_user_capability($capabilit $capsearch $timesql GROUP BY - rc.capability, (c1.contextlevel * 100), c1.id + 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 LEFT JOIN + {$CFG->prefix}role_capabilities rc on ra.roleid = rc.roleid LEFT JOIN + {$CFG->prefix}context c1 on ra.contextid = c1.id LEFT JOIN + {$CFG->prefix}context c2 on rc.contextid = c2.id LEFT JOIN + {$CFG->prefix}context_rel cr on cr.c1 = c2.id + WHERE + ra.userid=$userid AND + $searchcontexts1 + rc.contextid != $siteinstance->id + $capsearch + $timesql + AND cr.c2 = c1.id + GROUP BY + rc.capability, c1.id, c2.id, c1.contextlevel * 100 + c2.contextlevel + HAVING + SUM(rc.permission) != 0 + HAVING + SUM(rc.permission) != 0 ORDER BY aggrlevel ASC"; @@ -781,11 +807,13 @@ function load_user_capability($capabilit $capabilities[] = $temprecord; $rs->MoveNext(); } - } + } + // 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 @@ -808,8 +836,8 @@ function load_user_capability($capabilit ORDER BY aggrlevel ASC "; - - + */ + /* if (!$rs = get_recordset_sql($SQL2)) { error("Query failed in load_user_capability."); } @@ -834,13 +862,13 @@ function load_user_capability($capabilit $rs->MoveNext(); } } - + // 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 = SITEID @@ -1039,28 +1067,39 @@ function check_enrolment_plugins(&$user) 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; } } @@ -1073,17 +1112,19 @@ function capability_prohibits($capabilit case CONTEXT_PERSONAL: $parent = get_context_instance(CONTEXT_SYSTEM); - return capability_prohibits($capability, $parent); - break; + $prohibits[$capability][$context->id] = capability_prohibits($capability, $parent); + return $prohibits[$capability][$context->id]; break; case CONTEXT_USER: $parent = get_context_instance(CONTEXT_SYSTEM); - return capability_prohibits($capability, $parent); + $prohibits[$capability][$context->id] = capability_prohibits($capability, $parent); + return $prohibits[$capability][$context->id]; break; case CONTEXT_COURSECAT: // Coursecat -> coursecat or site. if (!$coursecat = get_record('course_categories','id',$context->instanceid)) { + $prohibits[$capability][$context->id] = false; return false; } if (!empty($coursecat->parent)) { @@ -1093,44 +1134,53 @@ function capability_prohibits($capabilit // Return site value. $parent = get_context_instance(CONTEXT_SYSTEM); } - return capability_prohibits($capability, $parent); + $prohibits[$capability][$context->id] = capability_prohibits($capability, $parent); + return $prohibits[$capability][$context->id]; break; case CONTEXT_COURSE: // 1 to 1 to course cat. // Find the course cat, and return its value. if (!$course = get_record('course','id',$context->instanceid)) { + $prohibits[$capability][$context->id] = false; return false; } $parent = get_context_instance(CONTEXT_COURSECAT, $course->category); - return capability_prohibits($capability, $parent); + $prohibits[$capability][$context->id] = capability_prohibits($capability, $parent); + return $prohibits[$capability][$context->id]; break; case CONTEXT_GROUP: // 1 to 1 to course. if (!$group = get_record('groups','id',$context->instanceid)) { + $prohibits[$capability][$context->id] = false; return false; } $parent = get_context_instance(CONTEXT_COURSE, $group->courseid); - return capability_prohibits($capability, $parent); + $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); - return capability_prohibits($capability, $parent); + $prohibits[$capability][$context->id] = capability_prohibits($capability, $parent); + return $prohibits[$capability][$context->id]; break; case CONTEXT_BLOCK: // 1 to 1 to course. if (!$block = get_record('block_instance','id',$context->instanceid)) { + $prohibits[$capability][$context->id] = false; return false; } $parent = get_context_instance(CONTEXT_COURSE, $block->pageid); // needs check - return capability_prohibits($capability, $parent); + $prohibits[$capability][$context->id] = capability_prohibits($capability, $parent); + return $prohibits[$capability][$context->id]; break; default: @@ -1434,7 +1484,10 @@ function create_context($contextlevel, $ $context->contextlevel = $contextlevel; $context->instanceid = $instanceid; if ($id = insert_record('context',$context)) { - return get_record('context','id',$id); + // we need to populate context_rel for every new context inserted + $c = get_record('context','id',$id); + insert_context_rel ($c); + return $c; } else { debugging('Error: could not insert new context level "'.s($contextlevel).'", instance "'.s($instanceid).'".'); return NULL; @@ -1453,10 +1506,12 @@ function create_context($contextlevel, $ * @return true if properly deleted */ function delete_context($contextlevel, $instanceid) { - if ($context = get_context_instance($contextlevel, $instanceid)) { + if ($context = get_context_instance($contextlevel, $instanceid)) { + delete_records('context_rel', 'c2', $context->id); // might not be a parent return delete_records('context', 'id', $context->id) && delete_records('role_assignments', 'contextid', $context->id) && - delete_records('role_capabilities', 'contextid', $context->id); + delete_records('role_capabilities', 'contextid', $context->id) && + delete_records('context_rel', 'c1', $context->id); } return true; } @@ -2501,6 +2556,11 @@ function role_context_capabilities($role */ function get_parent_contexts($context) { + static $pcontexts; // cache + if (isset($pcontexts[$context->id])) { + return ($pcontexts[$context->id]); + } + switch ($context->contextlevel) { case CONTEXT_SYSTEM: // no parent @@ -2511,7 +2571,9 @@ function get_parent_contexts($context) { if (!$parent = get_context_instance(CONTEXT_SYSTEM)) { return array(); } else { - return array($parent->id); + $res = array($parent->id); + $pcontexts[$context->id] = $res; + return $res; } break; @@ -2519,7 +2581,9 @@ function get_parent_contexts($context) { if (!$parent = get_context_instance(CONTEXT_SYSTEM)) { return array(); } else { - return array($parent->id); + $res = array($parent->id); + $pcontexts[$context->id] = $res; + return $res; } break; @@ -2529,10 +2593,14 @@ function get_parent_contexts($context) { } if (!empty($coursecat->parent)) { // return parent value if exist $parent = get_context_instance(CONTEXT_COURSECAT, $coursecat->parent); - return array_merge(array($parent->id), get_parent_contexts($parent)); + $res = array_merge(array($parent->id), get_parent_contexts($parent)); + $pcontexts[$context->id] = $res; + return $res; } else { // else return site value $parent = get_context_instance(CONTEXT_SYSTEM); - return array($parent->id); + $res = array($parent->id); + $pcontexts[$context->id] = $res; + return $res; } break; @@ -2542,7 +2610,9 @@ function get_parent_contexts($context) { } if (!empty($course->category)) { $parent = get_context_instance(CONTEXT_COURSECAT, $course->category); - return array_merge(array($parent->id), get_parent_contexts($parent)); + $res = array_merge(array($parent->id), get_parent_contexts($parent)); + $pcontexts[$context->id] = $res; + return $res; } else { return array(); } @@ -2553,7 +2623,9 @@ function get_parent_contexts($context) { return array(); } if ($parent = get_context_instance(CONTEXT_COURSE, $group->courseid)) { - return array_merge(array($parent->id), get_parent_contexts($parent)); + $res = array_merge(array($parent->id), get_parent_contexts($parent)); + $pcontexts[$context->id] = $res; + return $res; } else { return array(); } @@ -2564,7 +2636,9 @@ function get_parent_contexts($context) { return array(); } if ($parent = get_context_instance(CONTEXT_COURSE, $cm->course)) { - return array_merge(array($parent->id), get_parent_contexts($parent)); + $res = array_merge(array($parent->id), get_parent_contexts($parent)); + $pcontexts[$context->id] = $res; + return $res; } else { return array(); } @@ -2575,7 +2649,9 @@ function get_parent_contexts($context) { return array(); } if ($parent = get_context_instance(CONTEXT_COURSE, $block->pageid)) { - return array_merge(array($parent->id), get_parent_contexts($parent)); + $res = array_merge(array($parent->id), get_parent_contexts($parent)); + $pcontexts[$context->id] = $res; + return $res; } else { return array(); } @@ -3266,8 +3342,8 @@ function get_roles_with_assignment_on_co } - -/* find all user assignemnt of users for this role, on this context +/** + * Find all user assignemnt of users for this role, on this context */ function get_users_from_role_on_context($role, $context) { @@ -3279,7 +3355,8 @@ function get_users_from_role_on_context( AND roleid = $role->id"); } -/* + +/** * Simple function returning a boolean true if roles exist, otherwise false */ function user_has_role_assignment($userid, $roleid, $contextid=0) { @@ -3290,4 +3367,38 @@ function user_has_role_assignment($useri return record_exists('role_assignments', 'userid', $userid, 'roleid', $roleid); } } -?> + + +/** + * Inserts all parental context and self into context_rel table + */ +function insert_context_rel($context) { + // removes old records + delete_records('context_rel', 'c2', $context->id); + delete_records('context_rel', 'c1', $context->id); + // insert all parents + if ($parents = get_parent_contexts($context)) { + $parents[] = $context->id; + foreach ($parents as $parent) { + $rec = new object; + $rec ->c1 = $context->id; + $rec ->c2 = $parent; + insert_record('context_rel', $rec); + } + } +} + + +/** + * Rebuild context_rel table without deleting + */ +function build_context_rel() { + + if ($contexts = get_records('context')) { + foreach ($contexts as $context) { + insert_context_rel($context); + } + } +} + +?> \ No newline at end of file Index: lib/db/install.xml =================================================================== RCS file: /cvsroot/moodle/moodle/lib/db/install.xml,v retrieving revision 1.30.2.1 diff -u -p -r1.30.2.1 install.xml --- lib/db/install.xml 7 Nov 2006 08:58:53 -0000 1.30.2.1 +++ lib/db/install.xml 17 Jan 2007 07:11:25 -0000 @@ -1,5 +1,5 @@ - @@ -845,7 +845,7 @@ - +
@@ -859,7 +859,20 @@
- +
+ + + + + + + + + + + +
+ Index: lib/db/upgrade.php =================================================================== RCS file: /cvsroot/moodle/moodle/lib/db/upgrade.php,v retrieving revision 1.3.2.3 diff -u -p -r1.3.2.3 upgrade.php --- lib/db/upgrade.php 7 Dec 2006 06:08:02 -0000 1.3.2.3 +++ lib/db/upgrade.php 17 Jan 2007 07:11:25 -0000 @@ -71,6 +71,30 @@ function xmldb_main_upgrade($oldversion= } } + if ($result && $oldversion < 2006101010) { + + /// Define table context_rel to be created + $table = new XMLDBTable('context_rel'); + + /// Adding fields to table context_rel + $table->addFieldInfo('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null, null, null); + $table->addFieldInfo('c1', XMLDB_TYPE_INTEGER, '10', null, null, null, null, null, null); + $table->addFieldInfo('c2', XMLDB_TYPE_INTEGER, '10', null, null, null, null, null, null); + + /// Adding keys to table context_rel + $table->addKeyInfo('primary', XMLDB_KEY_PRIMARY, array('id')); + $table->addKeyInfo('c1', XMLDB_KEY_FOREIGN, array('c1'), 'context', array('id')); + $table->addKeyInfo('c2', XMLDB_KEY_FOREIGN, array('c2'), 'context', array('id')); + $table->addKeyInfo('c1c2', XMLDB_KEY_UNIQUE, array('c1', 'c2')); + + /// Launch create table for context_rel + $result = $result && create_table($table); + + /// code here to fill the context_rel table + /// use get record set to iterate slower + build_context_rel(); + } + return $result; }