Updated the HEAD build version to 20080706
[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
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 */
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
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 */
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
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 */
87function 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 */
111function 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 */
126function 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 */
149function 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 */
162function 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 187function 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 211function 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 */
230function 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 249function 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 282function 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 316function 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 */
365function 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 408function 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 */
477function 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 */
496function 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 */
515function 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 */
537function 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 568function 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?>