mirror of
https://github.com/moodle/moodle.git
synced 2025-08-08 02:16:41 +02:00
MDL-43721 Assign + groups: Improve performance of assign grading table
Add a function to the groups lib to filter a list of users down to the ones who can see the module. Required because calling groups_course_module_visible() for a list of users is too slow and we shouldn't spread group logic outside of grouplib.php. Using it in the assign grading table reduces DB queries from 6198/1 to 256/3. This is 12secs down to 2.5secs.
This commit is contained in:
parent
3ff7c4e389
commit
0a0c276e28
2 changed files with 88 additions and 10 deletions
|
@ -848,6 +848,77 @@ function groups_get_activity_allowed_groups($cm,$userid=0) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Filter a user list and return only the users that can see the course module based on
|
||||||
|
* groups/permissions etc. It is assumed that the users are pre-filtered to those who are enrolled in the course.
|
||||||
|
*
|
||||||
|
* @category group
|
||||||
|
* @param stdClass $cm The course module
|
||||||
|
* @param array $users An array of users, indexed by userid
|
||||||
|
* @return array A filtered list of users that can see the module, indexed by userid.
|
||||||
|
*/
|
||||||
|
function groups_filter_users_by_course_module_visible($cm, $users) {
|
||||||
|
global $CFG, $DB;
|
||||||
|
|
||||||
|
if (empty($CFG->enablegroupmembersonly)) {
|
||||||
|
return $users;
|
||||||
|
}
|
||||||
|
if (empty($cm->groupmembersonly)) {
|
||||||
|
return $users;
|
||||||
|
}
|
||||||
|
list($usql, $uparams) = $DB->get_in_or_equal(array_keys($users), SQL_PARAMS_NAMED, 'userid', true);
|
||||||
|
|
||||||
|
// Group membership sub-query.
|
||||||
|
if ($cm->groupingid) {
|
||||||
|
// Find out if member of any group in selected activity grouping.
|
||||||
|
$igsql = "SELECT gm.userid
|
||||||
|
FROM {groups_members} gm
|
||||||
|
LEFT JOIN {groupings_groups} gg
|
||||||
|
ON gm.groupid = gg.groupid
|
||||||
|
WHERE gm.userid $usql AND gg.groupingid = :groupingid";
|
||||||
|
$igparams = array_merge($uparams, array('groupingid' => $cm->groupingid));
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// No grouping used - check all groups in course.
|
||||||
|
$igsql = "SELECT gm.userid
|
||||||
|
FROM {groups_members} gm
|
||||||
|
LEFT JOIN {groups} g
|
||||||
|
ON gm.groupid = g.id
|
||||||
|
WHERE gm.userid $usql AND g.courseid = :courseid";
|
||||||
|
$igparams = array_merge($uparams, array('courseid' => $cm->course));
|
||||||
|
}
|
||||||
|
|
||||||
|
$context = context_module::instance($cm->id);
|
||||||
|
|
||||||
|
// Get the list of users in a valid group.
|
||||||
|
$usersingroup = $DB->get_records_sql($igsql, $igparams);
|
||||||
|
if (!$usersingroup) {
|
||||||
|
$usersingroup = array();
|
||||||
|
} else {
|
||||||
|
$usersingroup = array_keys($usersingroup);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the list of users who can access all groups.
|
||||||
|
list($accessallgroupssql, $accessallgroupsparams) = get_enrolled_sql($context, 'moodle/site:accessallgroups');
|
||||||
|
|
||||||
|
$userswithaccessallgroups = $DB->get_records_sql($accessallgroupssql, $accessallgroupsparams);
|
||||||
|
if (!$userswithaccessallgroups) {
|
||||||
|
$userswithaccessallgroups = array();
|
||||||
|
} else {
|
||||||
|
$userswithaccessallgroups = array_keys($userswithaccessallgroups);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Explaining this array mangling:
|
||||||
|
// $users is an array of $user[$userid] => stdClass etc
|
||||||
|
// $userswithaccessallgroups is an array of $userswithaccessallgroups[random int] = $userid
|
||||||
|
// $usersingroup is an array of $usersingroup[random int] = $userid
|
||||||
|
// so - the inner array_merge combines the values of the 2 arrays disregarding the keys (because they are ints)
|
||||||
|
// this is then flipped so the values become the keys (and the values are now nonsense)
|
||||||
|
// this is then intersected with the users array only by looking at the keys - this
|
||||||
|
// returns only the users from the original array that had a value in one of the two $usersxxx lists.
|
||||||
|
return array_intersect_key($users, array_flip(array_merge($userswithaccessallgroups, $usersingroup)));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determine if a course module is currently visible to a user
|
* Determine if a course module is currently visible to a user
|
||||||
*
|
*
|
||||||
|
|
|
@ -131,6 +131,9 @@ class assign {
|
||||||
/** @var array list of suspended user IDs in form of ([id1] => id1) */
|
/** @var array list of suspended user IDs in form of ([id1] => id1) */
|
||||||
public $susers = null;
|
public $susers = null;
|
||||||
|
|
||||||
|
/** @var array cached list of participants for this assignment. The cache key will be group, showactive and the context id */
|
||||||
|
private $participants = array();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor for the base assign class.
|
* Constructor for the base assign class.
|
||||||
*
|
*
|
||||||
|
@ -1292,22 +1295,26 @@ class assign {
|
||||||
* @return array List of user records
|
* @return array List of user records
|
||||||
*/
|
*/
|
||||||
public function list_participants($currentgroup, $idsonly) {
|
public function list_participants($currentgroup, $idsonly) {
|
||||||
if ($idsonly) {
|
$key = $this->context->id . '-' . $currentgroup . '-' . $this->show_only_active_users();
|
||||||
$users = get_enrolled_users($this->context, 'mod/assign:submit', $currentgroup, 'u.id', null, null, null,
|
if (!isset($this->participants[$key])) {
|
||||||
$this->show_only_active_users());
|
|
||||||
} else {
|
|
||||||
$users = get_enrolled_users($this->context, 'mod/assign:submit', $currentgroup, 'u.*', null, null, null,
|
$users = get_enrolled_users($this->context, 'mod/assign:submit', $currentgroup, 'u.*', null, null, null,
|
||||||
$this->show_only_active_users());
|
$this->show_only_active_users());
|
||||||
|
|
||||||
|
$cm = $this->get_course_module();
|
||||||
|
$users = groups_filter_users_by_course_module_visible($cm, $users);
|
||||||
|
|
||||||
|
$this->participants[$key] = $users;
|
||||||
}
|
}
|
||||||
|
|
||||||
$cm = $this->get_course_module();
|
if ($idsonly) {
|
||||||
foreach ($users as $userid => $user) {
|
$idslist = array();
|
||||||
if (!groups_course_module_visible($cm, $userid)) {
|
foreach ($this->participants[$key] as $id => $user) {
|
||||||
unset($users[$userid]);
|
$idslist[$id] = new stdClass();
|
||||||
|
$idslist[$id]->id = $id;
|
||||||
}
|
}
|
||||||
|
return $idslist;
|
||||||
}
|
}
|
||||||
|
return $this->participants[$key];
|
||||||
return $users;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue