I ended up addressing this by overriding get_graders() for my custom assignment type with the code below. Basically, I get a list of roles that are granted grading permission on the assignment, and then look for users assigned that role relative to the submitter.
If found, for my use-case I want to use those graders instead of ones assigned at higher levels, but the code could just as easily merge these results with the default list (users assigned to those roles relative to the module/course/category/system).
I guess I am left with two questions:
- Does what I'm doing here look completely silly to anyone?
- If not, why do we not normally look for people assigned to the desired role at the user/module/course/category/system level, instead of starting at the module level?
Here's the code:
/*
Check for users assigned roles with grading rights for
this assignment, relative to the given user.
If none are found, fall back on the default behavior
of getting users assigned to such roles at the module
level or higher.
*/
// Get contexts relevant to this assignment
list($contextids, $contextpaths) = get_context_info_list($this->context);
list($incontexts, $cparams) = $DB->get_in_or_equal($contextids, SQL_PARAMS_NAMED, 'ctx');
// Find roles with grade permission in those contexts
// Return users assigned those roles relative to the given user
$cparams['student_id'] = $user->id;
$cparams['cap'] = 'mod/assignment:grade';
$cparams['context_user'] = CONTEXT_USER;
$sql = "select u.*
from mdluser u
join mdlrole_assignments ra
on u.id = ra.userid
and roleid in (
select distinct r.id
from mdlrole r
join mdlrole_capabilities rc
on r.id=rc.roleid
and rc.contextid $incontexts
and rc.capability=:cap
)
join mdlcontext x
on ra.contextid = x.id
and x.contextlevel=:context_user
and x.instanceid=:student_id";
$potgraders = $DB->get_records_sql($sql, $cparams);
if (sizeof($potgraders) == 0) {
// default behavior…
}
// Unchanged from here on