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