From: martinlanghoff Date: Sun, 6 Jan 2008 23:25:37 +0000 (+0000) Subject: accesslib: Introducing sort_by_roleassignment_authority() X-Git-Url: http://git.mjollnir.org/gw?a=commitdiff_plain;h=635bfbad21eaeee3667eed70f4412cdadfdda06a;p=moodle.git accesslib: Introducing sort_by_roleassignment_authority() This will help us bridge the gap from olden-style order-by user_teachers.id. From the phpdoc... Will re-sort a $users results array (from get_users_by_capability(), usually) based on a sorting policy. This is to support the odd practice of sorting teachers by 'authority', where authority was "lowest id of the role assignment". Will execute 1 database query. Only suitable for small numbers of users, as it uses an u.id IN() clause. Notes about the sorting criteria. As a default, we cannot rely on role.sortorder because then admins/coursecreators will always win. That is why the sane rule "is locality matters most", with sortorder as 2nd consideration. If you want role.sortorder, use the 'sortorder' policy, and name explicitly what roles you want to cover. It's probably a good idea to see what roles have the capabilities you want (array_diff() them against roiles that have 'can-do-anything' to weed out admin-ish roles. Or fetch a list of roles from variables like $CFG->coursemanagers . MDL-12452 --- diff --git a/lib/accesslib.php b/lib/accesslib.php index 1a33d57630..1c8529b158 100755 --- a/lib/accesslib.php +++ b/lib/accesslib.php @@ -4677,6 +4677,87 @@ function has_capability_from_rarc($ras, $roleperms, $capability, $doanything) { return false; } +/** + * Will re-sort a $users results array (from get_users_by_capability(), usually) + * based on a sorting policy. This is to support the odd practice of + * sorting teachers by 'authority', where authority was "lowest id of the role + * assignment". + * + * Will execute 1 database query. Only suitable for small numbers of users, as it + * uses an u.id IN() clause. + * + * Notes about the sorting criteria. + * + * As a default, we cannot rely on role.sortorder because then + * admins/coursecreators will always win. That is why the sane + * rule "is locality matters most", with sortorder as 2nd + * consideration. + * + * If you want role.sortorder, use the 'sortorder' policy, and + * name explicitly what roles you want to cover. It's probably + * a good idea to see what roles have the capabilities you want + * (array_diff() them against roiles that have 'can-do-anything' + * to weed out admin-ish roles. Or fetch a list of roles from + * variables like $CFG->coursemanagers . + * + * @param array users Users' array, keyed on userid + * @param object context + * @param array roles - ids of the roles to include, optional + * @param string policy - defaults to locality, more about + * @return array - sorted copy of the array + */ +function sort_by_roleassignment_authority($users, $context, $roles=array(), $sortpolicy='locality') { + global $CFG; + + $userswhere = ' ra.userid IN (' . implode(',',array_keys($users)) . ')'; + $contextwhere = ' ra.contextid IN ('.str_replace('/', ',',substr($context->path, 1)).')'; + if (empty($roles)) { + $roleswhere = ''; + } else { + $roleswhere = ' AND ra.roleid IN ('.implode(',',$roles).')'; + } + + $sql = "SELECT ra.userid + FROM {$CFG->prefix}role_assignments ra + JOIN {$CFG->prefix}role r + ON ra.roleid=r.id + JOIN {$CFG->prefix}context ctx + ON ra.contextid=ctx.id + WHERE + $userswhere + AND $contextwhere + $roleswhere + "; + + // Default 'locality' policy -- read PHPDoc notes + // about sort policies... + $orderby = 'ORDER BY + ctx.depth DESC, /* locality wins */ + r.sortorder ASC, /* rolesorting 2nd criteria */ + ra.id /* role assignment order tie-breaker */'; + if ($sortpolicy === 'sortorder') { + $orderby = 'ORDER BY + r.sortorder ASC, /* rolesorting 2nd criteria */ + ra.id /* role assignment order tie-breaker */'; + } + + $sortedids = get_fieldset_sql($sql . $orderby); + $sortedusers = array(); + $seen = array(); + + foreach ($sortedids as $id) { + // Avoid duplicates + if (isset($seen[$id])) { + continue; + } + $seen[$id] = true; + + // assign + $sortedusers[$id] = $users[$id]; + } + return $sortedusers; +} + /** * gets all the users assigned this role in this context or higher * @param int roleid (can also be an array of ints!)