MDL-30797 - backup groups: Added a parameter to the groups_assign_grouping function.
[moodle.git] / group / lib.php
CommitLineData
f3f7610c 1<?php
4d8e2417
AG
2// This file is part of Moodle - http://moodle.org/
3//
4// Moodle is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8//
9// Moodle is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12// GNU General Public License for more details.
13//
14// You should have received a copy of the GNU General Public License
15// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
16
17
f3f7610c 18/**
ddff2fa8 19 * Extra library for groups and groupings.
f3f7610c 20 *
4d8e2417
AG
21 * @copyright 2006 The Open University, J.White AT open.ac.uk, Petr Skoda (skodak)
22 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
23 * @package core_group
f3f7610c
ML
24 */
25
ddff2fa8 26/*
27 * INTERNAL FUNCTIONS - to be used by moodle core only
28 * require_once $CFG->dirroot.'/group/lib.php' must be used
29 */
30
778918fd 31/**
32 * Adds a specified user to a group
4d8e2417
AG
33 *
34 * @param mixed $grouporid The group id or group object
35 * @param mixed $userorid The user id or user object
36 * @return bool True if user added successfully or the user is already a
f16fa0a3 37 * member of the group, false otherwise.
778918fd 38 */
9a0df45a 39function groups_add_member($grouporid, $userorid) {
dfdaabd6 40 global $DB;
41
9a0df45a 42 if (is_object($userorid)) {
43 $userid = $userorid->id;
44 $user = $userorid;
45 } else {
46 $userid = $userorid;
b18e25d5 47 $user = $DB->get_record('user', array('id'=>$userid), '*', MUST_EXIST);
2061e59c 48 }
49
9a0df45a 50 if (is_object($grouporid)) {
51 $groupid = $grouporid->id;
52 $group = $grouporid;
53 } else {
54 $groupid = $grouporid;
55 $group = $DB->get_record('groups', array('id'=>$groupid), '*', MUST_EXIST);
778918fd 56 }
57
0d4723ee 58 //check if the user a participant of the group course
4f0c2d00 59 if (!is_enrolled(get_context_instance(CONTEXT_COURSE, $group->courseid), $userid)) {
9a0df45a 60 return false;
0d4723ee 61 }
62
778918fd 63 if (groups_is_member($groupid, $userid)) {
64 return true;
65 }
66
ace9051c 67 $member = new stdClass();
778918fd 68 $member->groupid = $groupid;
69 $member->userid = $userid;
70 $member->timeadded = time();
71
b25263ff 72 $DB->insert_record('groups_members', $member);
778918fd 73
74 //update group info
dfdaabd6 75 $DB->set_field('groups', 'timemodified', $member->timeadded, array('id'=>$groupid));
778918fd 76
2942a5cd 77 //trigger groups events
ace9051c 78 $eventdata = new stdClass();
778918fd 79 $eventdata->groupid = $groupid;
2942a5cd 80 $eventdata->userid = $userid;
81 events_trigger('groups_member_added', $eventdata);
778918fd 82
83 return true;
84}
85
86/**
87 * Deletes the link between the specified user and group.
4d8e2417
AG
88 *
89 * @param mixed $grouporid The group id or group object
90 * @param mixed $userorid The user id or user object
91 * @return bool True if deletion was successful, false otherwise
778918fd 92 */
9a0df45a 93function groups_remove_member($grouporid, $userorid) {
dfdaabd6 94 global $DB;
95
9a0df45a 96 if (is_object($userorid)) {
97 $userid = $userorid->id;
98 $user = $userorid;
99 } else {
100 $userid = $userorid;
b18e25d5 101 $user = $DB->get_record('user', array('id'=>$userid), '*', MUST_EXIST);
2061e59c 102 }
103
9a0df45a 104 if (is_object($grouporid)) {
105 $groupid = $grouporid->id;
106 $group = $grouporid;
107 } else {
108 $groupid = $grouporid;
109 $group = $DB->get_record('groups', array('id'=>$groupid), '*', MUST_EXIST);
778918fd 110 }
111
112 if (!groups_is_member($groupid, $userid)) {
113 return true;
114 }
115
b25263ff 116 $DB->delete_records('groups_members', array('groupid'=>$groupid, 'userid'=>$userid));
117
778918fd 118 //update group info
dfdaabd6 119 $DB->set_field('groups', 'timemodified', time(), array('id'=>$groupid));
778918fd 120
2942a5cd 121 //trigger groups events
ace9051c 122 $eventdata = new stdClass();
2942a5cd 123 $eventdata->groupid = $groupid;
124 $eventdata->userid = $userid;
125 events_trigger('groups_member_removed', $eventdata);
126
778918fd 127 return true;
128}
129
ddff2fa8 130/**
131 * Add a new group
4d8e2417
AG
132 *
133 * @param stdClass $data group properties
134 * @param stdClass $editform
135 * @param array $editoroptions
ddff2fa8 136 * @return id of group or false if error
137 */
e88dd876 138function groups_create_group($data, $editform = false, $editoroptions = false) {
dfdaabd6 139 global $CFG, $DB;
6f5e0852 140
2061e59c 141 //check that courseid exists
9a0df45a 142 $course = $DB->get_record('course', array('id' => $data->courseid), '*', MUST_EXIST);
e88dd876 143 $context = get_context_instance(CONTEXT_COURSE, $course->id);
ddff2fa8 144
dfdaabd6 145 $data->timecreated = time();
ddff2fa8 146 $data->timemodified = $data->timecreated;
dfdaabd6 147 $data->name = trim($data->name);
74b714df
ARN
148 if (isset($data->idnumber)) {
149 $data->idnumber = trim($data->idnumber);
150 if (groups_get_group_by_idnumber($course->id, $data->idnumber)) {
151 throw new moodle_exception('idnumbertaken');
152 }
153 }
8bdc9cac 154
e88dd876 155 if ($editform and $editoroptions) {
8bdc9cac
SH
156 $data->description = $data->description_editor['text'];
157 $data->descriptionformat = $data->description_editor['format'];
158 }
159
e88dd876
PS
160 $data->id = $DB->insert_record('groups', $data);
161
162 if ($editform and $editoroptions) {
163 // Update description from editor with fixed files
164 $data = file_postupdate_standard_editor($data, 'description', $editoroptions, $context, 'group', 'description', $data->id);
ace9051c 165 $upd = new stdClass();
e88dd876
PS
166 $upd->id = $data->id;
167 $upd->description = $data->description;
168 $upd->descriptionformat = $data->descriptionformat;
169 $DB->update_record('groups', $upd);
170 }
171
172 $group = $DB->get_record('groups', array('id'=>$data->id));
ddff2fa8 173
b25263ff 174 if ($editform) {
e88dd876 175 groups_update_group_icon($group, $data, $editform);
ddff2fa8 176 }
177
b25263ff 178 //trigger groups events
e88dd876 179 events_trigger('groups_group_created', $group);
b25263ff 180
e88dd876 181 return $group->id;
ddff2fa8 182}
183
184/**
f16fa0a3 185 * Add a new grouping
4d8e2417
AG
186 *
187 * @param stdClass $data grouping properties
188 * @param array $editoroptions
f16fa0a3 189 * @return id of grouping or false if error
190 */
8bdc9cac 191function groups_create_grouping($data, $editoroptions=null) {
dfdaabd6 192 global $DB;
f16fa0a3 193
dfdaabd6 194 $data->timecreated = time();
f16fa0a3 195 $data->timemodified = $data->timecreated;
dfdaabd6 196 $data->name = trim($data->name);
74b714df
ARN
197 if (isset($data->idnumber)) {
198 $data->idnumber = trim($data->idnumber);
199 if (groups_get_grouping_by_idnumber($data->courseid, $data->idnumber)) {
200 throw new moodle_exception('idnumbertaken');
201 }
202 }
8bdc9cac
SH
203
204 if ($editoroptions !== null) {
205 $data->description = $data->description_editor['text'];
206 $data->descriptionformat = $data->description_editor['format'];
207 }
208
2942a5cd 209 $id = $DB->insert_record('groupings', $data);
210
b25263ff 211 //trigger groups events
212 $data->id = $id;
8bdc9cac
SH
213
214 if ($editoroptions !== null) {
215 $description = new stdClass;
216 $description->id = $data->id;
217 $description->description_editor = $data->description_editor;
64f93798 218 $description = file_postupdate_standard_editor($description, 'description', $editoroptions, $editoroptions['context'], 'grouping', 'description', $description->id);
8bdc9cac
SH
219 $DB->update_record('groupings', $description);
220 }
221
b25263ff 222 events_trigger('groups_grouping_created', $data);
2942a5cd 223
224 return $id;
f16fa0a3 225}
226
e88dd876
PS
227/**
228 * Update the group icon from form data
4d8e2417
AG
229 *
230 * @param stdClass $group group information
231 * @param stdClass $data
232 * @param stdClass $editform
e88dd876
PS
233 */
234function groups_update_group_icon($group, $data, $editform) {
235 global $CFG, $DB;
236 require_once("$CFG->libdir/gdlib.php");
237
238 $fs = get_file_storage();
239 $context = get_context_instance(CONTEXT_COURSE, $group->courseid, MUST_EXIST);
240
241 //TODO: it would make sense to allow picture deleting too (skodak)
40755f95
MN
242 if (!empty($CFG->gdversion)) {
243 if ($iconfile = $editform->save_temp_file('imagefile')) {
244 if (process_new_icon($context, 'group', 'icon', $group->id, $iconfile)) {
245 $DB->set_field('groups', 'picture', 1, array('id'=>$group->id));
246 $group->picture = 1;
247 } else {
248 $fs->delete_area_files($context->id, 'group', 'icon', $group->id);
249 $DB->set_field('groups', 'picture', 0, array('id'=>$group->id));
250 $group->picture = 0;
251 }
252 @unlink($iconfile);
e88dd876 253 }
e88dd876
PS
254 }
255}
256
f16fa0a3 257/**
258 * Update group
4d8e2417
AG
259 *
260 * @param stdClass $data group properties (with magic quotes)
261 * @param stdClass $editform
e88dd876 262 * @param array $editoroptions
4d8e2417 263 * @return bool true or exception
ddff2fa8 264 */
e88dd876 265function groups_update_group($data, $editform = false, $editoroptions = false) {
dfdaabd6 266 global $CFG, $DB;
e88dd876
PS
267
268 $context = get_context_instance(CONTEXT_COURSE, $data->courseid);
ddff2fa8 269
270 $data->timemodified = time();
dfdaabd6 271 $data->name = trim($data->name);
74b714df
ARN
272 if (isset($data->idnumber)) {
273 $data->idnumber = trim($data->idnumber);
274 if (($existing = groups_get_group_by_idnumber($data->courseid, $data->idnumber)) && $existing->id != $data->id) {
275 throw new moodle_exception('idnumbertaken');
276 }
277 }
8bdc9cac 278
e88dd876
PS
279 if ($editform and $editoroptions) {
280 $data = file_postupdate_standard_editor($data, 'description', $editoroptions, $context, 'group', 'description', $data->id);
8bdc9cac
SH
281 }
282
b25263ff 283 $DB->update_record('groups', $data);
2942a5cd 284
e88dd876
PS
285 $group = $DB->get_record('groups', array('id'=>$data->id));
286
b25263ff 287 if ($editform) {
e88dd876 288 groups_update_group_icon($group, $data, $editform);
ddff2fa8 289 }
290
b25263ff 291 //trigger groups events
e88dd876
PS
292 events_trigger('groups_group_updated', $group);
293
b25263ff 294
295 return true;
ddff2fa8 296}
297
f16fa0a3 298/**
299 * Update grouping
4d8e2417
AG
300 *
301 * @param stdClass $data grouping properties (with magic quotes)
302 * @param array $editoroptions
303 * @return bool true or exception
f16fa0a3 304 */
8bdc9cac 305function groups_update_grouping($data, $editoroptions=null) {
dfdaabd6 306 global $DB;
f16fa0a3 307 $data->timemodified = time();
dfdaabd6 308 $data->name = trim($data->name);
74b714df
ARN
309 if (isset($data->idnumber)) {
310 $data->idnumber = trim($data->idnumber);
311 if (($existing = groups_get_grouping_by_idnumber($data->courseid, $data->idnumber)) && $existing->id != $data->id) {
312 throw new moodle_exception('idnumbertaken');
313 }
314 }
8bdc9cac 315 if ($editoroptions !== null) {
64f93798 316 $data = file_postupdate_standard_editor($data, 'description', $editoroptions, $editoroptions['context'], 'grouping', 'description', $data->id);
8bdc9cac 317 }
b25263ff 318 $DB->update_record('groupings', $data);
319 //trigger groups events
320 events_trigger('groups_grouping_updated', $data);
321
322 return true;
f16fa0a3 323}
324
ddff2fa8 325/**
326 * Delete a group best effort, first removing members and links with courses and groupings.
327 * Removes group avatar too.
4d8e2417 328 *
2942a5cd 329 * @param mixed $grouporid The id of group to delete or full group object
4d8e2417 330 * @return bool True if deletion was successful, false otherwise
ddff2fa8 331 */
2942a5cd 332function groups_delete_group($grouporid) {
b7e8cfb6 333 global $CFG, $DB;
334 require_once("$CFG->libdir/gdlib.php");
ddff2fa8 335
2942a5cd 336 if (is_object($grouporid)) {
337 $groupid = $grouporid->id;
338 $group = $grouporid;
339 } else {
340 $groupid = $grouporid;
341 if (!$group = $DB->get_record('groups', array('id'=>$groupid))) {
9a0df45a 342 //silently ignore attempts to delete missing already deleted groups ;-)
343 return true;
2942a5cd 344 }
ddff2fa8 345 }
346
0b5a80a1 347 // delete group calendar events
dfdaabd6 348 $DB->delete_records('event', array('groupid'=>$groupid));
ddff2fa8 349 //first delete usage in groupings_groups
dfdaabd6 350 $DB->delete_records('groupings_groups', array('groupid'=>$groupid));
ddff2fa8 351 //delete members
dfdaabd6 352 $DB->delete_records('groups_members', array('groupid'=>$groupid));
ddff2fa8 353 //group itself last
b25263ff 354 $DB->delete_records('groups', array('id'=>$groupid));
8bdc9cac
SH
355
356 // Delete all files associated with this group
70e0f41e 357 $context = get_context_instance(CONTEXT_COURSE, $group->courseid);
8bdc9cac 358 $fs = get_file_storage();
e88dd876
PS
359 $fs->delete_area_files($context->id, 'group', 'description', $groupid);
360 $fs->delete_area_files($context->id, 'group', 'icon', $groupid);
8bdc9cac 361
b25263ff 362 //trigger groups events
363 events_trigger('groups_group_deleted', $group);
2942a5cd 364
b25263ff 365 return true;
ddff2fa8 366}
367
f16fa0a3 368/**
369 * Delete grouping
4d8e2417 370 *
16ef46e7 371 * @param int $groupingorid
f16fa0a3 372 * @return bool success
373 */
2942a5cd 374function groups_delete_grouping($groupingorid) {
dfdaabd6 375 global $DB;
376
2942a5cd 377 if (is_object($groupingorid)) {
378 $groupingid = $groupingorid->id;
379 $grouping = $groupingorid;
380 } else {
381 $groupingid = $groupingorid;
382 if (!$grouping = $DB->get_record('groupings', array('id'=>$groupingorid))) {
9a0df45a 383 //silently ignore attempts to delete missing already deleted groupings ;-)
384 return true;
2942a5cd 385 }
ddff2fa8 386 }
387
388 //first delete usage in groupings_groups
dfdaabd6 389 $DB->delete_records('groupings_groups', array('groupingid'=>$groupingid));
ddff2fa8 390 // remove the default groupingid from course
dfdaabd6 391 $DB->set_field('course', 'defaultgroupingid', 0, array('defaultgroupingid'=>$groupingid));
ddff2fa8 392 // remove the groupingid from all course modules
dfdaabd6 393 $DB->set_field('course_modules', 'groupingid', 0, array('groupingid'=>$groupingid));
ddff2fa8 394 //group itself last
b25263ff 395 $DB->delete_records('groupings', array('id'=>$groupingid));
8bdc9cac 396
70e0f41e 397 $context = get_context_instance(CONTEXT_COURSE, $grouping->courseid);
8bdc9cac 398 $fs = get_file_storage();
64f93798 399 $files = $fs->get_area_files($context->id, 'grouping', 'description', $groupingid);
8bdc9cac
SH
400 foreach ($files as $file) {
401 $file->delete();
402 }
403
b25263ff 404 //trigger groups events
405 events_trigger('groups_grouping_deleted', $grouping);
2942a5cd 406
b25263ff 407 return true;
ddff2fa8 408}
409
f16fa0a3 410/**
ffc670d9 411 * Remove all users (or one user) from all groups in course
4d8e2417 412 *
f16fa0a3 413 * @param int $courseid
ffc670d9 414 * @param int $userid 0 means all users
f16fa0a3 415 * @param bool $showfeedback
416 * @return bool success
417 */
ffc670d9 418function groups_delete_group_members($courseid, $userid=0, $showfeedback=false) {
a1c54f7a 419 global $DB, $OUTPUT;
ddff2fa8 420
ffc670d9 421 if (is_bool($userid)) {
422 debugging('Incorrect userid function parameter');
423 return false;
424 }
425
426 $params = array('courseid'=>$courseid);
427
428 if ($userid) {
429 $usersql = "AND userid = :userid";
430 $params['userid'] = $userid;
431 } else {
432 $usersql = "";
433 }
434
435 $groupssql = "SELECT id FROM {groups} g WHERE g.courseid = :courseid";
436 $DB->delete_records_select('groups_members', "groupid IN ($groupssql) $usersql", $params);
ddff2fa8 437
2942a5cd 438 //trigger groups events
ace9051c 439 $eventdata = new stdClass();
ffc670d9 440 $eventdata->courseid = $courseid;
441 $eventdata->userid = $userid;
442 events_trigger('groups_members_removed', $eventdata);
2942a5cd 443
ddff2fa8 444 if ($showfeedback) {
16ef46e7 445 echo $OUTPUT->notification(get_string('deleted').' - '.get_string('groupmembers', 'group'), 'notifysuccess');
ddff2fa8 446 }
447
448 return true;
449}
450
0b5a80a1 451/**
452 * Remove all groups from all groupings in course
4d8e2417 453 *
0b5a80a1 454 * @param int $courseid
455 * @param bool $showfeedback
456 * @return bool success
457 */
458function groups_delete_groupings_groups($courseid, $showfeedback=false) {
a1c54f7a 459 global $DB, $OUTPUT;
0b5a80a1 460
dfdaabd6 461 $groupssql = "SELECT id FROM {groups} g WHERE g.courseid = ?";
462 $DB->delete_records_select('groupings_groups', "groupid IN ($groupssql)", array($courseid));
0b5a80a1 463
2942a5cd 464 //trigger groups events
465 events_trigger('groups_groupings_groups_removed', $courseid);
466
16ef46e7 467 // no need to show any feedback here - we delete usually first groupings and then groups
0b5a80a1 468
469 return true;
470}
471
f16fa0a3 472/**
473 * Delete all groups from course
4d8e2417 474 *
f16fa0a3 475 * @param int $courseid
476 * @param bool $showfeedback
477 * @return bool success
478 */
ddff2fa8 479function groups_delete_groups($courseid, $showfeedback=false) {
a1c54f7a 480 global $CFG, $DB, $OUTPUT;
ddff2fa8 481
0b5a80a1 482 // delete any uses of groups
8bdc9cac 483 // Any associated files are deleted as part of groups_delete_groupings_groups
0b5a80a1 484 groups_delete_groupings_groups($courseid, $showfeedback);
ffc670d9 485 groups_delete_group_members($courseid, 0, $showfeedback);
ddff2fa8 486
d08787af
PS
487 // delete group pictures and descriptions
488 $context = get_context_instance(CONTEXT_COURSE, $courseid);
489 $fs = get_file_storage();
490 $fs->delete_area_files($context->id, 'group');
ddff2fa8 491
0b5a80a1 492 // delete group calendar events
dfdaabd6 493 $groupssql = "SELECT id FROM {groups} g WHERE g.courseid = ?";
494 $DB->delete_records_select('event', "groupid IN ($groupssql)", array($courseid));
0b5a80a1 495
64f93798
PS
496 $context = get_context_instance(CONTEXT_COURSE, $courseid);
497 $fs = get_file_storage();
498 $fs->delete_area_files($context->id, 'group');
499
dfdaabd6 500 $DB->delete_records('groups', array('courseid'=>$courseid));
2942a5cd 501
16ef46e7 502 // trigger groups events
2942a5cd 503 events_trigger('groups_groups_deleted', $courseid);
504
ddff2fa8 505 if ($showfeedback) {
16ef46e7 506 echo $OUTPUT->notification(get_string('deleted').' - '.get_string('groups', 'group'), 'notifysuccess');
ddff2fa8 507 }
508
509 return true;
510}
511
f16fa0a3 512/**
513 * Delete all groupings from course
4d8e2417 514 *
f16fa0a3 515 * @param int $courseid
516 * @param bool $showfeedback
517 * @return bool success
518 */
ddff2fa8 519function groups_delete_groupings($courseid, $showfeedback=false) {
a1c54f7a 520 global $DB, $OUTPUT;
ddff2fa8 521
522 // delete any uses of groupings
dfdaabd6 523 $sql = "DELETE FROM {groupings_groups}
524 WHERE groupingid in (SELECT id FROM {groupings} g WHERE g.courseid = ?)";
525 $DB->execute($sql, array($courseid));
ddff2fa8 526
527 // remove the default groupingid from course
dfdaabd6 528 $DB->set_field('course', 'defaultgroupingid', 0, array('id'=>$courseid));
ddff2fa8 529 // remove the groupingid from all course modules
dfdaabd6 530 $DB->set_field('course_modules', 'groupingid', 0, array('course'=>$courseid));
ddff2fa8 531
8bdc9cac 532 // Delete all files associated with groupings for this course
70e0f41e 533 $context = get_context_instance(CONTEXT_COURSE, $courseid);
8bdc9cac 534 $fs = get_file_storage();
64f93798
PS
535 $fs->delete_area_files($context->id, 'grouping');
536
537 $DB->delete_records('groupings', array('courseid'=>$courseid));
8bdc9cac 538
16ef46e7 539 // trigger groups events
2942a5cd 540 events_trigger('groups_groupings_deleted', $courseid);
541
ddff2fa8 542 if ($showfeedback) {
16ef46e7 543 echo $OUTPUT->notification(get_string('deleted').' - '.get_string('groupings', 'group'), 'notifysuccess');
ddff2fa8 544 }
545
546 return true;
547}
548
549/* =================================== */
550/* various functions used by groups UI */
551/* =================================== */
552
e254aa34 553/**
554 * Obtains a list of the possible roles that group members might come from,
df997f84 555 * on a course. Generally this includes only profile roles.
4d8e2417
AG
556 *
557 * @param context $context Context of course
e254aa34 558 * @return Array of role ID integers, or false if error/none.
559 */
560function groups_get_possible_roles($context) {
df997f84
PS
561 $roles = get_profile_roles($context);
562 return array_keys($roles);
acf000b0 563}
564
565
566/**
567 * Gets potential group members for grouping
4d8e2417 568 *
acf000b0 569 * @param int $courseid The id of the course
570 * @param int $roleid The role to select users from
92343cd2 571 * @param int $cohortid restrict to cohort id
64fa9aa7 572 * @param string $orderby The column to sort users by
acf000b0 573 * @return array An array of the users
574 */
92343cd2 575function groups_get_potential_members($courseid, $roleid = null, $cohortid = null, $orderby = 'lastname ASC, firstname ASC') {
4454447d 576 global $DB;
f16fa0a3 577
acf000b0 578 $context = get_context_instance(CONTEXT_COURSE, $courseid);
acf000b0 579
580 // we are looking for all users with this role assigned in this context or higher
4f0c2d00 581 $listofcontexts = get_related_contexts_string($context);
f16fa0a3 582
4f0c2d00 583 list($esql, $params) = get_enrolled_sql($context);
64f93798 584
acf000b0 585 if ($roleid) {
dfdaabd6 586 $params['roleid'] = $roleid;
4f0c2d00
PS
587 $where = "WHERE u.id IN (SELECT userid
588 FROM {role_assignments}
589 WHERE roleid = :roleid AND contextid $listofcontexts)";
acf000b0 590 } else {
4f0c2d00 591 $where = "";
acf000b0 592 }
f16fa0a3 593
92343cd2 594 if ($cohortid) {
d490ca81
PS
595 $cohortjoin = "JOIN {cohort_members} cm ON (cm.userid = u.id AND cm.cohortid = :cohortid)";
596 $params['cohortid'] = $cohortid;
92343cd2
PS
597 } else {
598 $cohortjoin = "";
599 }
600
dfdaabd6 601 $sql = "SELECT u.id, u.username, u.firstname, u.lastname, u.idnumber
602 FROM {user} u
4f0c2d00 603 JOIN ($esql) e ON e.id = u.id
92343cd2 604 $cohortjoin
4f0c2d00 605 $where
dfdaabd6 606 ORDER BY $orderby";
f16fa0a3 607
dfdaabd6 608 return $DB->get_records_sql($sql, $params);
f16fa0a3 609
acf000b0 610}
f3f7610c 611
acf000b0 612/**
613 * Parse a group name for characters to replace
4d8e2417 614 *
acf000b0 615 * @param string $format The format a group name will follow
616 * @param int $groupnumber The number of the group to be used in the parsed format string
617 * @return string the parsed format string
618 */
619function groups_parse_name($format, $groupnumber) {
acf000b0 620 if (strstr($format, '@') !== false) { // Convert $groupnumber to a character series
f16fa0a3 621 $letter = 'A';
622 for($i=0; $i<$groupnumber; $i++) {
623 $letter++;
acf000b0 624 }
f16fa0a3 625 $str = str_replace('@', $letter, $format);
acf000b0 626 } else {
4454447d 627 $str = str_replace('#', $groupnumber+1, $format);
acf000b0 628 }
629 return($str);
ddff2fa8 630}
f3f7610c 631
f16fa0a3 632/**
633 * Assigns group into grouping
4d8e2417 634 *
f16fa0a3 635 * @param int groupingid
636 * @param int groupid
e25a7aa2 637 * @param int $timeadded The time the group was added to the grouping.
b25263ff 638 * @return bool true or exception
f16fa0a3 639 */
e25a7aa2 640function groups_assign_grouping($groupingid, $groupid, $timeadded = null) {
dfdaabd6 641 global $DB;
642
643 if ($DB->record_exists('groupings_groups', array('groupingid'=>$groupingid, 'groupid'=>$groupid))) {
f16fa0a3 644 return true;
645 }
ace9051c 646 $assign = new stdClass();
f16fa0a3 647 $assign->groupingid = $groupingid;
dfdaabd6 648 $assign->groupid = $groupid;
e25a7aa2
AG
649 if ($timeadded != null) {
650 $assign->timeadded = (integer)$timeadded;
651 } else {
652 $assign->timeadded = time();
653 }
b25263ff 654 $DB->insert_record('groupings_groups', $assign);
655
656 return true;
f16fa0a3 657}
658
659/**
660 * Unassigns group grom grouping
4d8e2417 661 *
f16fa0a3 662 * @param int groupingid
663 * @param int groupid
664 * @return bool success
665 */
666function groups_unassign_grouping($groupingid, $groupid) {
dfdaabd6 667 global $DB;
b25263ff 668 $DB->delete_records('groupings_groups', array('groupingid'=>$groupingid, 'groupid'=>$groupid));
dfdaabd6 669
b25263ff 670 return true;
f16fa0a3 671}
672
e254aa34 673/**
674 * Lists users in a group based on their role on the course.
6f5e0852 675 * Returns false if there's an error or there are no users in the group.
e254aa34 676 * Otherwise returns an array of role ID => role data, where role data includes:
677 * (role) $id, $shortname, $name
678 * $users: array of objects for each user which include the specified fields
679 * Users who do not have a role are stored in the returned array with key '-'
680 * and pseudo-role details (including a name, 'No role'). Users with multiple
681 * roles, same deal with key '*' and name 'Multiple roles'. You can find out
682 * which roles each has by looking in the $roles array of the user object.
4d8e2417 683 *
e254aa34 684 * @param int $groupid
685 * @param int $courseid Course ID (should match the group's course)
686 * @param string $fields List of fields from user table prefixed with u, default 'u.*'
687 * @param string $sort SQL ORDER BY clause, default 'u.lastname ASC'
97873016 688 * @param string $extrawheretest extra SQL conditions ANDed with the existing where clause.
4f0c2d00 689 * @param array $whereparams any parameters required by $extrawheretest (named parameters).
e254aa34 690 * @return array Complex array as described above
691 */
97873016 692function groups_get_members_by_role($groupid, $courseid, $fields='u.*',
693 $sort='u.lastname ASC', $extrawheretest='', $whereparams=array()) {
dfdaabd6 694 global $CFG, $DB;
e254aa34 695
696 // Retrieve information about all users and their roles on the course or
6f5e0852 697 // parent ('related') contexts
dfdaabd6 698 $context = get_context_instance(CONTEXT_COURSE, $courseid);
699
97873016 700 if ($extrawheretest) {
701 $extrawheretest = ' AND ' . $extrawheretest;
702 }
703
dfdaabd6 704 $sql = "SELECT r.id AS roleid, r.shortname AS roleshortname, r.name AS rolename,
705 u.id AS userid, $fields
706 FROM {groups_members} gm
707 JOIN {user} u ON u.id = gm.userid
1c7a2f84
PS
708 LEFT JOIN {role_assignments} ra ON (ra.userid = u.id AND ra.contextid ".get_related_contexts_string($context).")
709 LEFT JOIN {role} r ON r.id = ra.roleid
4f0c2d00 710 WHERE gm.groupid=:mgroupid
1c7a2f84 711 ".$extrawheretest."
dfdaabd6 712 ORDER BY r.sortorder, $sort";
4f0c2d00 713 $whereparams['mgroupid'] = $groupid;
97873016 714 $rs = $DB->get_recordset_sql($sql, $whereparams);
dfdaabd6 715
716 return groups_calculate_role_people($rs, $context);
e254aa34 717}
718
719/**
720 * Internal function used by groups_get_members_by_role to handle the
721 * results of a database query that includes a list of users and possible
722 * roles on a course.
723 *
4d8e2417
AG
724 * @param moodle_recordset $rs The record set (may be false)
725 * @param int $context ID of course context
6f5e0852 726 * @return array As described in groups_get_members_by_role
e254aa34 727 */
dfdaabd6 728function groups_calculate_role_people($rs, $context) {
729 global $CFG, $DB;
730
731 if (!$rs) {
732 return array();
3540f2b3 733 }
e254aa34 734
dfdaabd6 735 $roles = $DB->get_records_menu('role', null, 'name', 'id, name');
736 $aliasnames = role_fix_names($roles, $context);
737
e254aa34 738 // Array of all involved roles
dfdaabd6 739 $roles = array();
e254aa34 740 // Array of all retrieved users
dfdaabd6 741 $users = array();
e254aa34 742 // Fill arrays
dfdaabd6 743 foreach ($rs as $rec) {
e254aa34 744 // Create information about user if this is a new one
dfdaabd6 745 if (!array_key_exists($rec->userid, $users)) {
e254aa34 746 // User data includes all the optional fields, but not any of the
747 // stuff we added to get the role details
1c7a2f84 748 $userdata = clone($rec);
e254aa34 749 unset($userdata->roleid);
750 unset($userdata->roleshortname);
751 unset($userdata->rolename);
752 unset($userdata->userid);
dfdaabd6 753 $userdata->id = $rec->userid;
e254aa34 754
755 // Make an array to hold the list of roles for this user
dfdaabd6 756 $userdata->roles = array();
757 $users[$rec->userid] = $userdata;
e254aa34 758 }
759 // If user has a role...
dfdaabd6 760 if (!is_null($rec->roleid)) {
e254aa34 761 // Create information about role if this is a new one
dfdaabd6 762 if (!array_key_exists($rec->roleid,$roles)) {
ace9051c 763 $roledata = new stdClass();
dfdaabd6 764 $roledata->id = $rec->roleid;
765 $roledata->shortname = $rec->roleshortname;
766 if (array_key_exists($rec->roleid, $aliasnames)) {
767 $roledata->name = $aliasnames[$rec->roleid];
3540f2b3 768 } else {
dfdaabd6 769 $roledata->name = $rec->rolename;
3540f2b3 770 }
dfdaabd6 771 $roledata->users = array();
772 $roles[$roledata->id] = $roledata;
e254aa34 773 }
774 // Record that user has role
775 $users[$rec->userid]->roles[] = $roles[$rec->roleid];
776 }
777 }
dfdaabd6 778 $rs->close();
e254aa34 779
780 // Return false if there weren't any users
1c7a2f84 781 if (count($users) == 0) {
e254aa34 782 return false;
783 }
784
785 // Add pseudo-role for multiple roles
ace9051c 786 $roledata = new stdClass();
dfdaabd6 787 $roledata->name = get_string('multipleroles','role');
788 $roledata->users = array();
789 $roles['*'] = $roledata;
e254aa34 790
1c7a2f84
PS
791 $roledata = new stdClass();
792 $roledata->name = get_string('noroles','role');
793 $roledata->users = array();
794 $roles[0] = $roledata;
795
e254aa34 796 // Now we rearrange the data to store users by role
dfdaabd6 797 foreach ($users as $userid=>$userdata) {
798 $rolecount = count($userdata->roles);
1c7a2f84
PS
799 if ($rolecount == 0) {
800 // does not have any roles
801 $roleid = 0;
802 } else if($rolecount > 1) {
dfdaabd6 803 $roleid = '*';
e254aa34 804 } else {
dfdaabd6 805 $roleid = $userdata->roles[0]->id;
e254aa34 806 }
dfdaabd6 807 $roles[$roleid]->users[$userid] = $userdata;
e254aa34 808 }
809
810 // Delete roles not used
dfdaabd6 811 foreach ($roles as $key=>$roledata) {
812 if (count($roledata->users)===0) {
e254aa34 813 unset($roles[$key]);
814 }
815 }
816
817 // Return list of roles containing their users
818 return $roles;
819}