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