From: martinlanghoff Date: Wed, 19 Sep 2007 07:07:45 +0000 (+0000) Subject: accesslib: get_context_users_bycap() draft for course participants... X-Git-Url: http://git.mjollnir.org/gw?a=commitdiff_plain;h=4d8ab2749e3e99a6d7ddc1a69532329983c3023a;p=moodle.git accesslib: get_context_users_bycap() draft for course participants... Introducing get_context_users_bycap() which gets the data in 2 DB queries, takes around 10ms on my laptop, and returns the records with a nice context property attached. Note Note Note: right now, some user recs do not have a context associated, so are _not_ returned. So this awaits Matt's fix to contexts maintenance to be 100% accurate... --- diff --git a/lib/accesslib.php b/lib/accesslib.php index 891d1752d4..c45e0e4eee 100755 --- a/lib/accesslib.php +++ b/lib/accesslib.php @@ -921,6 +921,124 @@ function get_context_users_byrole ($context, $roleid, $fields=NULL, $where=NULL, return $users; } +/* + * Draft - use for the course participants list page + * + * Uses 2 fast DB queries + * + * TODO: + * - automagically exclude roles that can-doanything sitewide (See callers) + * - perhaps also allow sitewide do-anything via flag + * - implement additional where clauses + * - sorting + * - get course participants list to use it! + * + * returns a users array, both sorted _and_ keyed + * on id (as get_my_courses() does) + * + * as a bonus, every user record comes with its own + * personal context, as our callers need it straight away + * {save 1 dbquery per user! yay!} + * + */ +function get_context_users_bycap ($context, $capability='moodle/course:view', $fields=NULL, $where=NULL, $sort=NULL, $limit=0) { + global $CFG; + + // Plan + // + // - Get all the *interesting* roles -- those that + // have some rolecap entry in our ctx.path contexts + // + // - Get all RAs for any of those roles in any of our + // interesting contexts, with userid & perm data + // in a nice (per user?) order + // + // - Walk the resultset, computing the permissions + // - actually - this is all a SQL subselect + // + // - Fetch user records against the subselect + // + + // Slim base fields, let callers ask for what they need... + $basefields = array('id', 'username'); + + if (!is_null($fields)) { + $fields = array_merge($basefields, $fields); + $fields = array_unique($fields); + } else { + $fields = $basefields; + } + $userfields = 'u.' .join(',u.', $fields); + + $contexts = substr($context->path, 1); // kill leading slash + $contexts = str_replace('/', ',', $contexts); + + $roles = array(); + $sql = "SELECT DISTINCT rc.roleid + FROM {$CFG->prefix}role_capabilities rc + WHERE rc.capability = '$capability' + AND rc.contextid IN ($contexts)"; + $rs = get_recordset_sql($sql); + if ($rs->RecordCount()) { + while ($u = rs_fetch_next_record($rs)) { + $roles[] = $u->roleid; + } + } + rs_close($rs); + $roles = join(',', $roles); + + // + // User permissions subselect SQL + // + // - the open join condition to + // role_capabilities + // + // - because both rc and ra entries are + // _at or above_ our context, we don't care + // about their depth, we just need to sum them + // + $sql = "SELECT ra.userid, SUM(rc.permission) AS permission + FROM {$CFG->prefix}role_assignments ra + JOIN {$CFG->prefix}role_capabilities rc + ON (ra.roleid = rc.roleid AND rc.contextid IN ($contexts)) + WHERE ra.contextid IN ($contexts) + AND ra.roleid IN ($roles) + GROUP BY ra.userid"; + + // Get users + $sql = "SELECT $userfields, + ctx.id AS ctxid, ctx.path AS ctxpath, ctx.depth as ctxdepth + FROM {$CFG->prefix}user u + JOIN {$CFG->prefix}context ctx + ON (u.id=ctx.instanceid AND ctx.contextlevel=".CONTEXT_USER.") + JOIN ($sql) up + ON u.id = up.userid + WHERE up.permission > 0 AND u.username != 'guest'"; + + $rs = get_recordset_sql($sql); + + $users = array(); + $cc = 0; // keep count + if ($rs->RecordCount()) { + while ($u = rs_fetch_next_record($rs)) { + // build the context obj + $ctx = new StdClass; + $ctx->id = $u->ctxid; unset($u->ctxid); + $ctx->path = $u->ctxpath; unset($u->ctxpath); + $ctx->depth = $u->ctxdepth; unset($u->ctxdepth); + $ctx->instanceid = $u->id; + $ctx->contextlevel = CONTEXT_USER; + $u->context = $ctx; + $users[] = $u; + if ($limit > 0 && $cc++ > $limit) { + break; + } + } + } + rs_close($rs); + return $users; +} + /** * It will return a nested array showing role assignments * all relevant role capabilities for the user at