Commit | Line | Data |
---|---|---|
f3f7610c ML |
1 | <?php |
2 | /** | |
ddff2fa8 | 3 | * Extra library for groups and groupings. |
f3f7610c ML |
4 | * |
5 | * @copyright © 2006 The Open University | |
6 | * @author J.White AT open.ac.uk | |
7 | * @license http://www.gnu.org/copyleft/gpl.html GNU Public License | |
8 | * @package groups | |
9 | */ | |
10 | ||
ddff2fa8 | 11 | /* |
12 | * INTERNAL FUNCTIONS - to be used by moodle core only | |
13 | * require_once $CFG->dirroot.'/group/lib.php' must be used | |
14 | */ | |
15 | ||
778918fd | 16 | /** |
17 | * Adds a specified user to a group | |
18 | * @param int $userid The user id | |
19 | * @param int $groupid The group id | |
f16fa0a3 | 20 | * @return boolean True if user added successfully or the user is already a |
21 | * member of the group, false otherwise. | |
778918fd | 22 | */ |
23 | function groups_add_member($groupid, $userid) { | |
dfdaabd6 | 24 | global $DB; |
25 | ||
778918fd | 26 | if (!groups_group_exists($groupid)) { |
27 | return false; | |
28 | } | |
29 | ||
30 | if (groups_is_member($groupid, $userid)) { | |
31 | return true; | |
32 | } | |
33 | ||
34 | $member = new object(); | |
35 | $member->groupid = $groupid; | |
36 | $member->userid = $userid; | |
37 | $member->timeadded = time(); | |
38 | ||
dfdaabd6 | 39 | if (!$DB->insert_record('groups_members', $member)) { |
778918fd | 40 | return false; |
41 | } | |
42 | ||
43 | //update group info | |
dfdaabd6 | 44 | $DB->set_field('groups', 'timemodified', $member->timeadded, array('id'=>$groupid)); |
778918fd | 45 | |
46 | // MDL-9983 | |
47 | $eventdata = new object(); | |
48 | $eventdata->groupid = $groupid; | |
49 | $eventdata->userid = $userid; | |
f16fa0a3 | 50 | events_trigger('group_user_added', $eventdata); |
778918fd | 51 | |
52 | return true; | |
53 | } | |
54 | ||
55 | /** | |
56 | * Deletes the link between the specified user and group. | |
57 | * @param int $groupid The group to delete the user from | |
58 | * @param int $userid The user to delete | |
59 | * @return boolean True if deletion was successful, false otherwise | |
60 | */ | |
61 | function groups_remove_member($groupid, $userid) { | |
dfdaabd6 | 62 | global $DB; |
63 | ||
778918fd | 64 | if (!groups_group_exists($groupid)) { |
65 | return false; | |
66 | } | |
67 | ||
68 | if (!groups_is_member($groupid, $userid)) { | |
69 | return true; | |
70 | } | |
71 | ||
dfdaabd6 | 72 | if (!$DB->delete_records('groups_members', array('groupid'=>$groupid, 'userid'=>$userid))) { |
778918fd | 73 | return false; |
f16fa0a3 | 74 | } |
778918fd | 75 | //update group info |
dfdaabd6 | 76 | $DB->set_field('groups', 'timemodified', time(), array('id'=>$groupid)); |
778918fd | 77 | |
78 | return true; | |
79 | } | |
80 | ||
ddff2fa8 | 81 | /** |
82 | * Add a new group | |
f16fa0a3 | 83 | * @param object $data group properties (with magic quotes) |
ddff2fa8 | 84 | * @param object $um upload manager with group picture |
85 | * @return id of group or false if error | |
86 | */ | |
87 | function groups_create_group($data, $um=false) { | |
dfdaabd6 | 88 | global $CFG, $DB; |
ddff2fa8 | 89 | require_once("$CFG->libdir/gdlib.php"); |
90 | ||
dfdaabd6 | 91 | $data->timecreated = time(); |
ddff2fa8 | 92 | $data->timemodified = $data->timecreated; |
dfdaabd6 | 93 | $data->name = trim($data->name); |
94 | $id = $DB->insert_record('groups', $data); | |
ddff2fa8 | 95 | |
96 | if ($id and $um) { | |
97 | //update image | |
98 | if (save_profile_image($id, $um, 'groups')) { | |
dfdaabd6 | 99 | $DB->set_field('groups', 'picture', 1, array('id'=>$id)); |
ddff2fa8 | 100 | } |
101 | } | |
102 | ||
103 | return $id; | |
104 | } | |
105 | ||
106 | /** | |
f16fa0a3 | 107 | * Add a new grouping |
108 | * @param object $data grouping properties (with magic quotes) | |
109 | * @return id of grouping or false if error | |
110 | */ | |
111 | function groups_create_grouping($data) { | |
dfdaabd6 | 112 | global $DB; |
f16fa0a3 | 113 | |
dfdaabd6 | 114 | $data->timecreated = time(); |
f16fa0a3 | 115 | $data->timemodified = $data->timecreated; |
dfdaabd6 | 116 | $data->name = trim($data->name); |
117 | return $DB->insert_record('groupings', $data); | |
f16fa0a3 | 118 | } |
119 | ||
120 | /** | |
121 | * Update group | |
122 | * @param object $data group properties (with magic quotes) | |
ddff2fa8 | 123 | * @param object $um upload manager with group picture |
124 | * @return boolean success | |
125 | */ | |
126 | function groups_update_group($data, $um=false) { | |
dfdaabd6 | 127 | global $CFG, $DB; |
ddff2fa8 | 128 | require_once("$CFG->libdir/gdlib.php"); |
129 | ||
130 | $data->timemodified = time(); | |
dfdaabd6 | 131 | $data->name = trim($data->name); |
132 | $result = $DB->update_record('groups', $data); | |
ddff2fa8 | 133 | |
134 | if ($result and $um) { | |
135 | //update image | |
136 | if (save_profile_image($data->id, $um, 'groups')) { | |
dfdaabd6 | 137 | $DB->set_field('groups', 'picture', 1, array('id'=>$data->id)); |
ddff2fa8 | 138 | } |
139 | } | |
140 | ||
141 | return $result; | |
142 | } | |
143 | ||
f16fa0a3 | 144 | /** |
145 | * Update grouping | |
146 | * @param object $data grouping properties (with magic quotes) | |
147 | * @return boolean success | |
148 | */ | |
149 | function groups_update_grouping($data) { | |
dfdaabd6 | 150 | global $DB; |
f16fa0a3 | 151 | $data->timemodified = time(); |
dfdaabd6 | 152 | $data->name = trim($data->name); |
153 | return $DB->update_record('groupings', $data); | |
f16fa0a3 | 154 | } |
155 | ||
ddff2fa8 | 156 | /** |
157 | * Delete a group best effort, first removing members and links with courses and groupings. | |
158 | * Removes group avatar too. | |
159 | * @param int $groupid The group to delete | |
160 | * @return boolean True if deletion was successful, false otherwise | |
161 | */ | |
162 | function groups_delete_group($groupid) { | |
dfdaabd6 | 163 | global $CFG, $DB; |
ddff2fa8 | 164 | require_once($CFG->libdir.'/gdlib.php'); |
165 | ||
166 | if (empty($groupid)) { | |
167 | return false; | |
168 | } | |
169 | ||
0b5a80a1 | 170 | // delete group calendar events |
dfdaabd6 | 171 | $DB->delete_records('event', array('groupid'=>$groupid)); |
ddff2fa8 | 172 | //first delete usage in groupings_groups |
dfdaabd6 | 173 | $DB->delete_records('groupings_groups', array('groupid'=>$groupid)); |
ddff2fa8 | 174 | //delete members |
dfdaabd6 | 175 | $DB->delete_records('groups_members', array('groupid'=>$groupid)); |
ddff2fa8 | 176 | //then imge |
177 | delete_profile_image($groupid, 'groups'); | |
178 | //group itself last | |
dfdaabd6 | 179 | return $DB->delete_records('groups', array('id'=>$groupid)); |
ddff2fa8 | 180 | } |
181 | ||
f16fa0a3 | 182 | /** |
183 | * Delete grouping | |
184 | * @param int $groupingid | |
185 | * @return bool success | |
186 | */ | |
ddff2fa8 | 187 | function groups_delete_grouping($groupingid) { |
dfdaabd6 | 188 | global $DB; |
189 | ||
ddff2fa8 | 190 | if (empty($groupingid)) { |
191 | return false; | |
192 | ||
193 | } | |
194 | ||
195 | //first delete usage in groupings_groups | |
dfdaabd6 | 196 | $DB->delete_records('groupings_groups', array('groupingid'=>$groupingid)); |
ddff2fa8 | 197 | // remove the default groupingid from course |
dfdaabd6 | 198 | $DB->set_field('course', 'defaultgroupingid', 0, array('defaultgroupingid'=>$groupingid)); |
ddff2fa8 | 199 | // remove the groupingid from all course modules |
dfdaabd6 | 200 | $DB->set_field('course_modules', 'groupingid', 0, array('groupingid'=>$groupingid)); |
ddff2fa8 | 201 | //group itself last |
dfdaabd6 | 202 | return $DB->delete_records('groupings', array('id'=>$groupingid)); |
ddff2fa8 | 203 | } |
204 | ||
f16fa0a3 | 205 | /** |
0b5a80a1 | 206 | * Remove all users from all groups in course |
f16fa0a3 | 207 | * @param int $courseid |
208 | * @param bool $showfeedback | |
209 | * @return bool success | |
210 | */ | |
ddff2fa8 | 211 | function groups_delete_group_members($courseid, $showfeedback=false) { |
dfdaabd6 | 212 | global $DB; |
ddff2fa8 | 213 | |
dfdaabd6 | 214 | $groupssql = "SELECT id FROM {groups} g WHERE g.courseid = ?"; |
215 | $DB->delete_records_select('groups_members', "groupid IN ($groupssql)", array($courseid)); | |
ddff2fa8 | 216 | |
ddff2fa8 | 217 | if ($showfeedback) { |
218 | notify(get_string('deleted').' groups_members'); | |
219 | } | |
220 | ||
221 | return true; | |
222 | } | |
223 | ||
0b5a80a1 | 224 | /** |
225 | * Remove all groups from all groupings in course | |
226 | * @param int $courseid | |
227 | * @param bool $showfeedback | |
228 | * @return bool success | |
229 | */ | |
230 | function groups_delete_groupings_groups($courseid, $showfeedback=false) { | |
dfdaabd6 | 231 | global $DB; |
0b5a80a1 | 232 | |
dfdaabd6 | 233 | $groupssql = "SELECT id FROM {groups} g WHERE g.courseid = ?"; |
234 | $DB->delete_records_select('groupings_groups', "groupid IN ($groupssql)", array($courseid)); | |
0b5a80a1 | 235 | |
236 | if ($showfeedback) { | |
237 | notify(get_string('deleted').' groupings_groups'); | |
238 | } | |
239 | ||
240 | return true; | |
241 | } | |
242 | ||
f16fa0a3 | 243 | /** |
244 | * Delete all groups from course | |
245 | * @param int $courseid | |
246 | * @param bool $showfeedback | |
247 | * @return bool success | |
248 | */ | |
ddff2fa8 | 249 | function groups_delete_groups($courseid, $showfeedback=false) { |
dfdaabd6 | 250 | global $CFG, $DB; |
ddff2fa8 | 251 | require_once($CFG->libdir.'/gdlib.php'); |
252 | ||
0b5a80a1 | 253 | // delete any uses of groups |
254 | groups_delete_groupings_groups($courseid, $showfeedback); | |
255 | groups_delete_group_members($courseid, $showfeedback); | |
ddff2fa8 | 256 | |
257 | // delete group pictures | |
dfdaabd6 | 258 | if ($groups = $DB->get_records('groups', array('courseid'=>$courseid))) { |
ddff2fa8 | 259 | foreach($groups as $group) { |
260 | delete_profile_image($group->id, 'groups'); | |
261 | } | |
262 | } | |
263 | ||
0b5a80a1 | 264 | // delete group calendar events |
dfdaabd6 | 265 | $groupssql = "SELECT id FROM {groups} g WHERE g.courseid = ?"; |
266 | $DB->delete_records_select('event', "groupid IN ($groupssql)", array($courseid)); | |
0b5a80a1 | 267 | |
dfdaabd6 | 268 | $DB->delete_records('groups', array('courseid'=>$courseid)); |
ddff2fa8 | 269 | if ($showfeedback) { |
270 | notify(get_string('deleted').' groups'); | |
271 | } | |
272 | ||
273 | return true; | |
274 | } | |
275 | ||
f16fa0a3 | 276 | /** |
277 | * Delete all groupings from course | |
278 | * @param int $courseid | |
279 | * @param bool $showfeedback | |
280 | * @return bool success | |
281 | */ | |
ddff2fa8 | 282 | function groups_delete_groupings($courseid, $showfeedback=false) { |
dfdaabd6 | 283 | global $DB; |
ddff2fa8 | 284 | |
285 | // delete any uses of groupings | |
dfdaabd6 | 286 | $sql = "DELETE FROM {groupings_groups} |
287 | WHERE groupingid in (SELECT id FROM {groupings} g WHERE g.courseid = ?)"; | |
288 | $DB->execute($sql, array($courseid)); | |
ddff2fa8 | 289 | |
290 | // remove the default groupingid from course | |
dfdaabd6 | 291 | $DB->set_field('course', 'defaultgroupingid', 0, array('id'=>$courseid)); |
ddff2fa8 | 292 | // remove the groupingid from all course modules |
dfdaabd6 | 293 | $DB->set_field('course_modules', 'groupingid', 0, array('course'=>$courseid)); |
ddff2fa8 | 294 | |
dfdaabd6 | 295 | $DB->delete_records('groupings', array('courseid'=>$courseid)); |
ddff2fa8 | 296 | if ($showfeedback) { |
297 | notify(get_string('deleted').' groupings'); | |
298 | } | |
299 | ||
300 | return true; | |
301 | } | |
302 | ||
303 | /* =================================== */ | |
304 | /* various functions used by groups UI */ | |
305 | /* =================================== */ | |
306 | ||
307 | /** | |
e254aa34 | 308 | * Gets the users for a course who are not in a specified group, and returns |
309 | * them in an array organised by role. For the array format, see | |
310 | * groups_get_members_by_role. | |
ddff2fa8 | 311 | * @param int $groupid The id of the group |
312 | * @param string searchtext similar to searchtext in role assign, search | |
e254aa34 | 313 | * @return array An array of role id or '*' => information about that role |
314 | * including a list of users | |
ddff2fa8 | 315 | */ |
e254aa34 | 316 | function groups_get_users_not_in_group_by_role($courseid, $groupid, $searchtext='', $sort = 'u.lastname ASC') { |
dfdaabd6 | 317 | global $CFG, $DB; |
ddff2fa8 | 318 | |
ddff2fa8 | 319 | $context = get_context_instance(CONTEXT_COURSE, $courseid); |
dfdaabd6 | 320 | |
321 | /// Get list of allowed roles | |
322 | if (!$validroleids = groups_get_possible_roles($context)) { | |
323 | return array(); | |
324 | } | |
325 | list($roleids, $params) = $DB->get_in_or_equal($validroleids, SQL_PARAMS_NAMED, $start='r0'); | |
e254aa34 | 326 | |
ddff2fa8 | 327 | if ($searchtext !== '') { // Search for a subset of remaining users |
dfdaabd6 | 328 | $LIKE = $DB->sql_ilike(); |
329 | $FULLNAME = $DB->sql_fullname(); | |
330 | $wheresearch = " AND u.id IN (SELECT id FROM {user} WHERE $FULLNAME $LIKE :search1 OR email $LIKE :search2)"; | |
331 | $params['search1'] = "%$searchtext%"; | |
332 | $params['search2'] = "%$searchtext%"; | |
ddff2fa8 | 333 | } else { |
334 | $wheresearch = ''; | |
335 | } | |
336 | ||
e254aa34 | 337 | /// Construct the main SQL |
dfdaabd6 | 338 | $sql = " SELECT r.id AS roleid,r.shortname AS roleshortname,r.name AS rolename, |
339 | u.id AS userid, u.firstname, u.lastname | |
340 | FROM {user} u | |
341 | JOIN {role_assignments} ra ON ra.userid = u.id | |
342 | JOIN {role} r ON r.id = ra.roleid | |
343 | WHERE ra.contextid ".get_related_contexts_string($context)." | |
344 | AND u.deleted = 0 | |
345 | AND ra.roleid $roleids | |
346 | AND u.id NOT IN (SELECT userid | |
347 | FROM {groups_members} | |
348 | WHERE groupid = :groupid) | |
349 | $wheresearch | |
350 | ORDER BY $sort"; | |
351 | $params['groupid'] = $groupid; | |
352 | ||
353 | $rs = $DB->get_recordset_sql($sql, $params); | |
354 | return groups_calculate_role_people($rs, $context); | |
e254aa34 | 355 | } |
356 | ||
357 | ||
358 | /** | |
359 | * Obtains a list of the possible roles that group members might come from, | |
360 | * on a course. Generally this includes all the roles who would have | |
361 | * course:view on that course, except the doanything roles. | |
362 | * @param object $context Context of course | |
363 | * @return Array of role ID integers, or false if error/none. | |
364 | */ | |
365 | function groups_get_possible_roles($context) { | |
ddff2fa8 | 366 | $capability = 'moodle/course:view'; |
367 | $doanything = false; | |
f3f7610c | 368 | |
ddff2fa8 | 369 | // find all possible "student" roles |
370 | if ($possibleroles = get_roles_with_capability($capability, CAP_ALLOW, $context)) { | |
371 | if (!$doanything) { | |
372 | if (!$sitecontext = get_context_instance(CONTEXT_SYSTEM)) { | |
373 | return false; // Something is seriously wrong | |
374 | } | |
375 | $doanythingroles = get_roles_with_capability('moodle/site:doanything', CAP_ALLOW, $sitecontext); | |
376 | } | |
f3f7610c | 377 | |
ddff2fa8 | 378 | $validroleids = array(); |
379 | foreach ($possibleroles as $possiblerole) { | |
380 | if (!$doanything) { | |
381 | if (isset($doanythingroles[$possiblerole->id])) { // We don't want these included | |
382 | continue; | |
383 | } | |
384 | } | |
385 | if ($caps = role_context_capabilities($possiblerole->id, $context, $capability)) { // resolved list | |
386 | if (isset($caps[$capability]) && $caps[$capability] > 0) { // resolved capability > 0 | |
387 | $validroleids[] = $possiblerole->id; | |
388 | } | |
389 | } | |
390 | } | |
391 | if (empty($validroleids)) { | |
392 | return false; | |
393 | } | |
e254aa34 | 394 | return $validroleids; |
ddff2fa8 | 395 | } else { |
396 | return false; // No need to continue, since no roles have this capability set | |
e254aa34 | 397 | } |
acf000b0 | 398 | } |
399 | ||
400 | ||
401 | /** | |
402 | * Gets potential group members for grouping | |
403 | * @param int $courseid The id of the course | |
404 | * @param int $roleid The role to select users from | |
405 | * @param string $orderby The colum to sort users by | |
406 | * @return array An array of the users | |
407 | */ | |
f16fa0a3 | 408 | function groups_get_potential_members($courseid, $roleid = null, $orderby = 'lastname,firstname') { |
dfdaabd6 | 409 | global $DB; |
f16fa0a3 | 410 | |
acf000b0 | 411 | $context = get_context_instance(CONTEXT_COURSE, $courseid); |
412 | $sitecontext = get_context_instance(CONTEXT_SYSTEM); | |
413 | $rolenames = array(); | |
414 | $avoidroles = array(); | |
415 | ||
416 | if ($roles = get_roles_used_in_context($context, true)) { | |
417 | ||
418 | $canviewroles = get_roles_with_capability('moodle/course:view', CAP_ALLOW, $context); | |
419 | $doanythingroles = get_roles_with_capability('moodle/site:doanything', CAP_ALLOW, $sitecontext); | |
420 | ||
421 | foreach ($roles as $role) { | |
422 | if (!isset($canviewroles[$role->id])) { // Avoid this role (eg course creator) | |
423 | $avoidroles[] = $role->id; | |
424 | unset($roles[$role->id]); | |
425 | continue; | |
426 | } | |
427 | if (isset($doanythingroles[$role->id])) { // Avoid this role (ie admin) | |
428 | $avoidroles[] = $role->id; | |
429 | unset($roles[$role->id]); | |
430 | continue; | |
431 | } | |
432 | $rolenames[$role->id] = strip_tags(role_get_name($role, $context)); // Used in menus etc later on | |
433 | } | |
434 | } | |
f16fa0a3 | 435 | |
acf000b0 | 436 | if ($avoidroles) { |
dfdaabd6 | 437 | list($adminroles, $params) = $DB->get_in_or_equal($avoidroles, SQL_PARAMS_NAMED, 'ar0', false); |
438 | $adminroles = "AND r.roleid $adminroles"; | |
acf000b0 | 439 | } else { |
dfdaabd6 | 440 | $adminroles = ""; |
441 | $params = array(); | |
acf000b0 | 442 | } |
443 | ||
444 | // we are looking for all users with this role assigned in this context or higher | |
445 | if ($usercontexts = get_parent_contexts($context)) { | |
dfdaabd6 | 446 | $listofcontexts = 'IN ('.implode(',', $usercontexts).')'; |
acf000b0 | 447 | } else { |
dfdaabd6 | 448 | $listofcontexts = '='.$sitecontext->id.')'; // must be site |
acf000b0 | 449 | } |
f16fa0a3 | 450 | |
acf000b0 | 451 | if ($roleid) { |
dfdaabd6 | 452 | $selectrole = "AND r.roleid = :roleid"; |
453 | $params['roleid'] = $roleid; | |
acf000b0 | 454 | } else { |
dfdaabd6 | 455 | $selectrole = ""; |
acf000b0 | 456 | } |
f16fa0a3 | 457 | |
dfdaabd6 | 458 | $sql = "SELECT u.id, u.username, u.firstname, u.lastname, u.idnumber |
459 | FROM {user} u | |
460 | JOIN {role_assignments} r on u.id=r.userid | |
461 | WHERE (r.contextid = :contextid OR r.contextid $listofcontexts) | |
462 | AND u.deleted = 0 AND u.username != 'guest' | |
463 | $selectrole $adminroles | |
464 | ORDER BY $orderby"; | |
465 | $params['contextid'] = $context->id; | |
f16fa0a3 | 466 | |
dfdaabd6 | 467 | return $DB->get_records_sql($sql, $params); |
f16fa0a3 | 468 | |
acf000b0 | 469 | } |
f3f7610c | 470 | |
acf000b0 | 471 | /** |
472 | * Parse a group name for characters to replace | |
473 | * @param string $format The format a group name will follow | |
474 | * @param int $groupnumber The number of the group to be used in the parsed format string | |
475 | * @return string the parsed format string | |
476 | */ | |
477 | function groups_parse_name($format, $groupnumber) { | |
acf000b0 | 478 | if (strstr($format, '@') !== false) { // Convert $groupnumber to a character series |
f16fa0a3 | 479 | $letter = 'A'; |
480 | for($i=0; $i<$groupnumber; $i++) { | |
481 | $letter++; | |
acf000b0 | 482 | } |
f16fa0a3 | 483 | $str = str_replace('@', $letter, $format); |
acf000b0 | 484 | } else { |
f16fa0a3 | 485 | $str = str_replace('#', $groupnumber+1, $format); |
acf000b0 | 486 | } |
487 | return($str); | |
ddff2fa8 | 488 | } |
f3f7610c | 489 | |
f16fa0a3 | 490 | /** |
491 | * Assigns group into grouping | |
492 | * @param int groupingid | |
493 | * @param int groupid | |
494 | * @return bool success | |
495 | */ | |
496 | function groups_assign_grouping($groupingid, $groupid) { | |
dfdaabd6 | 497 | global $DB; |
498 | ||
499 | if ($DB->record_exists('groupings_groups', array('groupingid'=>$groupingid, 'groupid'=>$groupid))) { | |
f16fa0a3 | 500 | return true; |
501 | } | |
502 | $assign = new object(); | |
503 | $assign->groupingid = $groupingid; | |
dfdaabd6 | 504 | $assign->groupid = $groupid; |
505 | $assign->timeadded = time(); | |
506 | return (bool)$DB->insert_record('groupings_groups', $assign); | |
f16fa0a3 | 507 | } |
508 | ||
509 | /** | |
510 | * Unassigns group grom grouping | |
511 | * @param int groupingid | |
512 | * @param int groupid | |
513 | * @return bool success | |
514 | */ | |
515 | function groups_unassign_grouping($groupingid, $groupid) { | |
dfdaabd6 | 516 | global $DB; |
517 | ||
518 | return $DB->delete_records('groupings_groups', array('groupingid'=>$groupingid, 'groupid'=>$groupid)); | |
f16fa0a3 | 519 | } |
520 | ||
e254aa34 | 521 | /** |
522 | * Lists users in a group based on their role on the course. | |
523 | * Returns false if there's an error or there are no users in the group. | |
524 | * Otherwise returns an array of role ID => role data, where role data includes: | |
525 | * (role) $id, $shortname, $name | |
526 | * $users: array of objects for each user which include the specified fields | |
527 | * Users who do not have a role are stored in the returned array with key '-' | |
528 | * and pseudo-role details (including a name, 'No role'). Users with multiple | |
529 | * roles, same deal with key '*' and name 'Multiple roles'. You can find out | |
530 | * which roles each has by looking in the $roles array of the user object. | |
531 | * @param int $groupid | |
532 | * @param int $courseid Course ID (should match the group's course) | |
533 | * @param string $fields List of fields from user table prefixed with u, default 'u.*' | |
534 | * @param string $sort SQL ORDER BY clause, default 'u.lastname ASC' | |
535 | * @return array Complex array as described above | |
536 | */ | |
537 | function groups_get_members_by_role($groupid, $courseid, $fields='u.*', $sort='u.lastname ASC') { | |
dfdaabd6 | 538 | global $CFG, $DB; |
e254aa34 | 539 | |
540 | // Retrieve information about all users and their roles on the course or | |
541 | // parent ('related') contexts | |
dfdaabd6 | 542 | $context = get_context_instance(CONTEXT_COURSE, $courseid); |
543 | ||
544 | $sql = "SELECT r.id AS roleid, r.shortname AS roleshortname, r.name AS rolename, | |
545 | u.id AS userid, $fields | |
546 | FROM {groups_members} gm | |
547 | JOIN {user} u ON u.id = gm.userid | |
548 | JOIN {role_assignments} ra ON ra.userid = u.id | |
549 | JOIN {role} r ON r.id = ra.roleid | |
550 | WHERE gm.groupid=? | |
551 | AND ra.contextid ".get_related_contexts_string($context)." | |
552 | ORDER BY r.sortorder, $sort"; | |
553 | $params = array($groupid); | |
554 | $rs = $DB->get_recordset_sql($sql, $params); | |
555 | ||
556 | return groups_calculate_role_people($rs, $context); | |
e254aa34 | 557 | } |
558 | ||
559 | /** | |
560 | * Internal function used by groups_get_members_by_role to handle the | |
561 | * results of a database query that includes a list of users and possible | |
562 | * roles on a course. | |
563 | * | |
564 | * @param object $rs The record set (may be false) | |
3540f2b3 | 565 | * @param int $contextid ID of course context |
e254aa34 | 566 | * @return array As described in groups_get_members_by_role |
567 | */ | |
dfdaabd6 | 568 | function groups_calculate_role_people($rs, $context) { |
569 | global $CFG, $DB; | |
570 | ||
571 | if (!$rs) { | |
572 | return array(); | |
3540f2b3 | 573 | } |
e254aa34 | 574 | |
dfdaabd6 | 575 | $roles = $DB->get_records_menu('role', null, 'name', 'id, name'); |
576 | $aliasnames = role_fix_names($roles, $context); | |
577 | ||
e254aa34 | 578 | // Array of all involved roles |
dfdaabd6 | 579 | $roles = array(); |
e254aa34 | 580 | // Array of all retrieved users |
dfdaabd6 | 581 | $users = array(); |
e254aa34 | 582 | // Fill arrays |
dfdaabd6 | 583 | foreach ($rs as $rec) { |
e254aa34 | 584 | // Create information about user if this is a new one |
dfdaabd6 | 585 | if (!array_key_exists($rec->userid, $users)) { |
e254aa34 | 586 | // User data includes all the optional fields, but not any of the |
587 | // stuff we added to get the role details | |
588 | $userdata=clone($rec); | |
589 | unset($userdata->roleid); | |
590 | unset($userdata->roleshortname); | |
591 | unset($userdata->rolename); | |
592 | unset($userdata->userid); | |
dfdaabd6 | 593 | $userdata->id = $rec->userid; |
e254aa34 | 594 | |
595 | // Make an array to hold the list of roles for this user | |
dfdaabd6 | 596 | $userdata->roles = array(); |
597 | $users[$rec->userid] = $userdata; | |
e254aa34 | 598 | } |
599 | // If user has a role... | |
dfdaabd6 | 600 | if (!is_null($rec->roleid)) { |
e254aa34 | 601 | // Create information about role if this is a new one |
dfdaabd6 | 602 | if (!array_key_exists($rec->roleid,$roles)) { |
603 | $roledata = new object(); | |
604 | $roledata->id = $rec->roleid; | |
605 | $roledata->shortname = $rec->roleshortname; | |
606 | if (array_key_exists($rec->roleid, $aliasnames)) { | |
607 | $roledata->name = $aliasnames[$rec->roleid]; | |
3540f2b3 | 608 | } else { |
dfdaabd6 | 609 | $roledata->name = $rec->rolename; |
3540f2b3 | 610 | } |
dfdaabd6 | 611 | $roledata->users = array(); |
612 | $roles[$roledata->id] = $roledata; | |
e254aa34 | 613 | } |
614 | // Record that user has role | |
615 | $users[$rec->userid]->roles[] = $roles[$rec->roleid]; | |
616 | } | |
617 | } | |
dfdaabd6 | 618 | $rs->close(); |
e254aa34 | 619 | |
620 | // Return false if there weren't any users | |
dfdaabd6 | 621 | if (count($users)==0) { |
e254aa34 | 622 | return false; |
623 | } | |
624 | ||
625 | // Add pseudo-role for multiple roles | |
dfdaabd6 | 626 | $roledata = new object(); |
627 | $roledata->name = get_string('multipleroles','role'); | |
628 | $roledata->users = array(); | |
629 | $roles['*'] = $roledata; | |
e254aa34 | 630 | |
631 | // Now we rearrange the data to store users by role | |
dfdaabd6 | 632 | foreach ($users as $userid=>$userdata) { |
633 | $rolecount = count($userdata->roles); | |
634 | if ($rolecount==0) { | |
e254aa34 | 635 | debugging("Unexpected: user $userid is missing roles"); |
636 | } else if($rolecount>1) { | |
dfdaabd6 | 637 | $roleid = '*'; |
e254aa34 | 638 | } else { |
dfdaabd6 | 639 | $roleid = $userdata->roles[0]->id; |
e254aa34 | 640 | } |
dfdaabd6 | 641 | $roles[$roleid]->users[$userid] = $userdata; |
e254aa34 | 642 | } |
643 | ||
644 | // Delete roles not used | |
dfdaabd6 | 645 | foreach ($roles as $key=>$roledata) { |
646 | if (count($roledata->users)===0) { | |
e254aa34 | 647 | unset($roles[$key]); |
648 | } | |
649 | } | |
650 | ||
651 | // Return list of roles containing their users | |
652 | return $roles; | |
653 | } | |
654 | ||
47d1ec41 | 655 | ?> |