fix some keys
[moodle.git] / lib / grouplib.php
CommitLineData
2c386f82 1<?php //$Id$
2
13534ef7 3/**
ffc536af 4 * Groups not used in course or activity
13534ef7
ML
5 */
6define('NOGROUPS', 0);
7
8/**
ffc536af 9 * Groups used, users do not see other groups
13534ef7
ML
10 */
11define('SEPARATEGROUPS', 1);
5bf243d1 12
5bf243d1 13/**
ffc536af 14 * Groups used, students see other groups
13534ef7
ML
15 */
16define('VISIBLEGROUPS', 2);
17
18
19/**
20 * Determines if a group with a given groupid exists.
5bf243d1 21 * @param int $groupid The groupid to check for
13534ef7
ML
22 * @return boolean True if the group exists, false otherwise or if an error
23 * occurred.
5bf243d1 24 */
25function groups_group_exists($groupid) {
26 return record_exists('groups', 'id', $groupid);
27}
28
29/**
30 * Gets the name of a group with a specified id
31 * @param int $groupid The id of the group
32 * @return string The name of the group
33 */
34function groups_get_group_name($groupid) {
35 return get_field('groups', 'name', 'id', $groupid);
36}
2c386f82 37
4d8e3407 38/**
39 * Gets the name of a grouping with a specified id
40 * @param int $groupingid The id of the grouping
41 * @return string The name of the grouping
42 */
43function groups_get_grouping_name($groupingid) {
44 return get_field('groupings', 'name', 'id', $groupingid);
45}
46
2c386f82 47/**
48 * Returns the groupid of a group with the name specified for the course.
49 * Group names should be unique in course
50 * @param int $courseid The id of the course
51 * @param string $name name of group (without magic quotes)
52 * @return int $groupid
53 */
54function groups_get_group_by_name($courseid, $name) {
ddff2fa8 55 if ($groups = get_records_select('groups', "courseid=$courseid AND name='".addslashes($name)."'")) {
56 return key($groups);
2c386f82 57 }
ddff2fa8 58 return false;
59}
2c386f82 60
ddff2fa8 61/**
62 * Returns the groupingid of a grouping with the name specified for the course.
63 * Grouping names should be unique in course
64 * @param int $courseid The id of the course
65 * @param string $name name of group (without magic quotes)
66 * @return int $groupid
67 */
68function groups_get_grouping_by_name($courseid, $name) {
69 if ($groupings = get_records_select('groupings', "courseid=$courseid AND name='".addslashes($name)."'")) {
70 return key($groupings);
71 }
72 return false;
2c386f82 73}
74
75/**
76 * Get the group object
77 * @param groupid ID of the group.
78 * @return group object
79 */
80function groups_get_group($groupid) {
81 return get_record('groups', 'id', $groupid);
82}
83
84/**
85 * Gets array of all groups in a specified course.
86 * @param int $courseid The id of the course.
87 * @param int $userid optional user id, returns only groups of the user.
62d63838 88 * @param int $groupingid optional returns only groups in the specified grouping.
d15da061 89 * @return array | false Returns an array of the group objects or false if no records
2c386f82 90 * or an error occurred.
91 */
62d63838 92function groups_get_all_groups($courseid, $userid=0, $groupingid=0) {
2c386f82 93 global $CFG;
94
7e4fdf25 95 // groupings are ignored when not enabled
c0d4238d 96 if (empty($CFG->enablegroupings)) {
97 $groupingid = 0;
98 }
99
62d63838 100 if (!empty($userid)) {
101 $userfrom = ", {$CFG->prefix}groups_members gm";
102 $userwhere = "AND g.id = gm.groupid AND gm.userid = '$userid'";
103 } else {
104 $userfrom = "";
105 $userwhere = "";
106 }
2c386f82 107
62d63838 108 if (!empty($groupingid)) {
109 $groupingfrom = ", {$CFG->prefix}groupings_groups gg";
110 $groupingwhere = "AND g.id = gg.groupid AND gg.groupingid = '$groupingid'";
2c386f82 111 } else {
62d63838 112 $groupingfrom = "";
113 $groupingwhere = "";
2c386f82 114 }
62d63838 115
116 return get_records_sql("SELECT g.*
117 FROM {$CFG->prefix}groups g $userfrom $groupingfrom
acf000b0 118 WHERE g.courseid = $courseid $userwhere $groupingwhere
62d63838 119 ORDER BY name ASC");
2c386f82 120}
121
acf000b0 122/**
123 * Gets array of all groupings in a specified course.
18d43e96 124 * @param int $courseid return only groupings in this with this courseid
125 * @return array | false Returns an array of the grouping objects or false if no records
acf000b0 126 * or an error occurred.
127 */
128function groups_get_all_groupings($courseid) {
129 global $CFG;
130
131 // groupings are ignored when not enabled
132 if (empty($CFG->enablegroupings)) {
133 return(false);
134 }
135 return get_records_sql("SELECT *
136 FROM {$CFG->prefix}groupings
137 WHERE courseid = $courseid
138 ORDER BY name ASC");
139}
140
141
142
2c386f82 143/**
144 * Determines if the user is a member of the given group.
145 *
146 * @uses $USER If $userid is null, use the global object.
147 * @param int $groupid The group to check for membership.
148 * @param int $userid The user to check against the group.
149 * @return boolean True if the user is a member, false otherwise.
150 */
151function groups_is_member($groupid, $userid=null) {
152 global $USER;
153
154 if (!$userid) {
155 $userid = $USER->id;
156 }
157
158 return record_exists('groups_members', 'groupid', $groupid, 'userid', $userid);
159}
160
f8e3d5f0 161/**
162 * Determines if current or specified is member of any active group in activity
163 * @param object $cm coruse module object
164 * @param int $userid id of user, null menas $USER->id
165 * @return booelan true if user member of at least one group used in activity
166 */
167function groups_has_membership($cm, $userid=null) {
168 global $CFG, $USER;
e0bc99e4 169
170 static $cache = array();
171
7e4fdf25 172 // groupings are ignored when not enabled
c0d4238d 173 if (empty($CFG->enablegroupings)) {
174 $cm->groupingid = 0;
175 }
176
f8e3d5f0 177 if (empty($userid)) {
178 $userid = $USER->id;
179 }
180
e0bc99e4 181 $cachekey = $userid.'|'.$cm->course.'|'.$cm->groupingid;
182 if (isset($cache[$cachekey])) {
183 return($cache[$cachekey]);
184 }
185
f8e3d5f0 186 if ($cm->groupingid) {
187 // find out if member of any group in selected activity grouping
188 $sql = "SELECT 'x'
189 FROM {$CFG->prefix}groups_members gm, {$CFG->prefix}groupings_groups gg
190 WHERE gm.userid = $userid AND gm.groupid = gg.groupid AND gg.groupingid = {$cm->groupingid}";
191
192 } else {
193 // no grouping used - check all groups in course
194 $sql = "SELECT 'x'
195 FROM {$CFG->prefix}groups_members gm, {$CFG->prefix}groups g
196 WHERE gm.userid = $userid AND gm.groupid = g.id AND g.courseid = {$cm->course}";
197 }
e0bc99e4 198
199 $cache[$cachekey] = record_exists_sql($sql);
200
201 return $cache[$cachekey];
f8e3d5f0 202}
203
62d63838 204/**
205 * Returns the users in the specified group.
206 * @param int $groupid The groupid to get the users for
e6839677 207 * @param int $fields The fields to return
62d63838 208 * @param int $sort optional sorting of returned users
209 * @return array | false Returns an array of the users for the specified
210 * group or false if no users or an error returned.
211 */
e6839677 212function groups_get_members($groupid, $fields='u.*', $sort='lastname ASC') {
62d63838 213 global $CFG;
214
e6839677 215 return get_records_sql("SELECT $fields
62d63838 216 FROM {$CFG->prefix}user u, {$CFG->prefix}groups_members gm
217 WHERE u.id = gm.userid AND gm.groupid = '$groupid'
218 ORDER BY $sort");
219}
220
e6839677 221
222/**
223 * Returns the users in the specified grouping.
224 * @param int $groupingid The groupingid to get the users for
225 * @param int $fields The fields to return
226 * @param int $sort optional sorting of returned users
227 * @return array | false Returns an array of the users for the specified
228 * group or false if no users or an error returned.
229 */
230function groups_get_grouping_members($groupingid, $fields='u.*', $sort='lastname ASC') {
231 global $CFG;
232
233 return get_records_sql("SELECT $fields
234 FROM {$CFG->prefix}user u
235 INNER JOIN {$CFG->prefix}groups_members gm ON u.id = gm.userid
236 INNER JOIN {$CFG->prefix}groupings_groups gg ON gm.groupid = gg.groupid
237 WHERE gg.groupingid = $groupingid
238 ORDER BY $sort");
239}
240
b2bc96d1 241/**
242 * Returns effective groupmode used in course
243 * @return integer group mode
244 */
245function groups_get_course_groupmode($course) {
246 return $course->groupmode;
247}
248
13534ef7
ML
249/**
250 * Returns effective groupmode used in activity, course setting
251 * overrides activity setting if groupmodeforce enabled.
252 * @return integer group mode
253 */
254function groups_get_activity_groupmode($cm) {
255 global $COURSE;
256
257 // get course object (reuse COURSE if possible)
258 if ($cm->course == $COURSE->id) {
259 $course = $COURSE;
260 } else {
261 if (!$course = get_record('course', 'id', $cm->course)) {
262 error('Incorrect course id in cm');
263 }
264 }
265
266 return empty($course->groupmodeforce) ? $cm->groupmode : $course->groupmode;
267}
268
b2bc96d1 269/**
270 * Print group menu selector for course level.
271 * @param object $course course object
272 * @param string $urlroot return address
273 * @param boolean $return return as string instead of printing
274 * @return mixed void or string depending on $return param
275 */
276function groups_print_course_menu($course, $urlroot, $return=false) {
277 global $CFG, $USER;
278
279 if (!$groupmode = $course->groupmode) {
280 if ($return) {
281 return '';
282 } else {
283 return;
284 }
285 }
286
287 $context = get_context_instance(CONTEXT_COURSE, $course->id);
288 if ($groupmode == VISIBLEGROUPS or has_capability('moodle/site:accessallgroups', $context)) {
289 $allowedgroups = groups_get_all_groups($course->id, 0);
290 } else {
291 $allowedgroups = groups_get_all_groups($course->id, $USER->id);
292 }
293
294 $activegroup = groups_get_course_group($course, true);
295
296 $groupsmenu = array();
297 if (!$allowedgroups or $groupmode == VISIBLEGROUPS or has_capability('moodle/site:accessallgroups', $context)) {
298 $groupsmenu[0] = get_string('allparticipants');
299 }
300
301 if ($allowedgroups) {
302 foreach ($allowedgroups as $group) {
303 $groupsmenu[$group->id] = format_string($group->name);
304 }
305 }
306
307 if ($groupmode == VISIBLEGROUPS) {
308 $grouplabel = get_string('groupsvisible');
309 } else {
310 $grouplabel = get_string('groupsseparate');
311 }
312
313 if (count($groupsmenu) == 1) {
314 $groupname = reset($groupsmenu);
315 $output = $grouplabel.': '.$groupname;
316 } else {
317 $output = popup_form($urlroot.'&amp;group=', $groupsmenu, 'selectgroup', $activegroup, '', '', '', true, 'self', $grouplabel);
318 }
319
320 $output = '<div class="groupselector">'.$output.'</div>';
321
322 if ($return) {
323 return $output;
324 } else {
325 echo $output;
326 }
327}
328
13534ef7
ML
329/**
330 * Print group menu selector for activity.
331 * @param object $cm course module object
18d43e96 332 * @param string $urlroot return address that users get to if they choose an option;
333 * should include any parameters needed, e.g. 'view.php?id=34'
13534ef7 334 * @param boolean $return return as string instead of printing
18d43e96 335 * @param boolean $hideallparticipants If true, this prevents the 'All participants'
336 * option from appearing in cases where it normally would. This is intended for
337 * use only by activities that cannot display all groups together. (Note that
338 * selecting this option does not prevent groups_get_activity_group from
339 * returning 0; it will still do that if the user has chosen 'all participants'
340 * in another activity, or not chosen anything.)
13534ef7
ML
341 * @return mixed void or string depending on $return param
342 */
18d43e96 343function groups_print_activity_menu($cm, $urlroot, $return=false, $hideallparticipants=false) {
c0d4238d 344 global $CFG, $USER;
345
7e4fdf25 346 // groupings are ignored when not enabled
c0d4238d 347 if (empty($CFG->enablegroupings)) {
348 $cm->groupingid = 0;
349 }
13534ef7
ML
350
351 if (!$groupmode = groups_get_activity_groupmode($cm)) {
352 if ($return) {
353 return '';
354 } else {
355 return;
356 }
357 }
358
359 $context = get_context_instance(CONTEXT_MODULE, $cm->id);
360 if ($groupmode == VISIBLEGROUPS or has_capability('moodle/site:accessallgroups', $context)) {
361 $allowedgroups = groups_get_all_groups($cm->course, 0, $cm->groupingid); // any group in grouping (all if groupings not used)
362 } else {
363 $allowedgroups = groups_get_all_groups($cm->course, $USER->id, $cm->groupingid); // only assigned groups
364 }
365
366 $activegroup = groups_get_activity_group($cm, true);
367
368 $groupsmenu = array();
18d43e96 369 if ((!$allowedgroups or $groupmode == VISIBLEGROUPS or
370 has_capability('moodle/site:accessallgroups', $context)) and !$hideallparticipants) {
13534ef7
ML
371 $groupsmenu[0] = get_string('allparticipants');
372 }
373
374 if ($allowedgroups) {
375 foreach ($allowedgroups as $group) {
376 $groupsmenu[$group->id] = format_string($group->name);
377 }
378 }
379
380 if ($groupmode == VISIBLEGROUPS) {
381 $grouplabel = get_string('groupsvisible');
382 } else {
383 $grouplabel = get_string('groupsseparate');
384 }
385
386 if (count($groupsmenu) == 1) {
387 $groupname = reset($groupsmenu);
388 $output = $grouplabel.': '.$groupname;
389 } else {
390 $output = popup_form($urlroot.'&amp;group=', $groupsmenu, 'selectgroup', $activegroup, '', '', '', true, 'self', $grouplabel);
391 }
392
393 $output = '<div class="groupselector">'.$output.'</div>';
394
395 if ($return) {
396 return $output;
397 } else {
398 echo $output;
399 }
400}
401
b2bc96d1 402/**
403 * Returns group active in course, changes the group by default if 'group' page param present
404 *
405 * @param object $course course bject
406 * @param boolean $update change active group if group param submitted
407 * @return mixed false if groups not used, int if groups used, 0 means all groups (access must be verified in SEPARATE mode)
408 */
409function groups_get_course_group($course, $update=false) {
410 global $CFG, $USER, $SESSION;
411
412 if (!$groupmode = $course->groupmode) {
413 // NOGROUPS used
414 return false;
415 }
416
417 // init activegroup array
418 if (!array_key_exists('activegroup', $SESSION)) {
419 $SESSION->activegroup = array();
420 }
421 if (!array_key_exists($course->id, $SESSION->activegroup)) {
b0dcd128 422 $SESSION->activegroup[$course->id] = array(SEPARATEGROUPS=>array(), VISIBLEGROUPS=>array(), 'aag'=>array());
423 }
424
e873679b 425 $context = get_context_instance(CONTEXT_COURSE, $course->id);
b0dcd128 426 if (has_capability('moodle/site:accessallgroups', $context)) {
427 $groupmode = 'aag';
b2bc96d1 428 }
429
430 // grouping used the first time - add first user group as default
431 if (!array_key_exists(0, $SESSION->activegroup[$course->id][$groupmode])) {
b0dcd128 432 if ($groupmode == 'aag') {
433 $SESSION->activegroup[$course->id][$groupmode][0] = 0; // all groups by default if user has accessallgroups
434
435 } else if ($usergroups = groups_get_all_groups($course->id, $USER->id, 0)) {
b2bc96d1 436 $fistgroup = reset($usergroups);
437 $SESSION->activegroup[$course->id][$groupmode][0] = $fistgroup->id;
b0dcd128 438
b2bc96d1 439 } else {
440 // this happen when user not assigned into group in SEPARATEGROUPS mode or groups do not exist yet
441 // mod authors must add extra checks for this when SEPARATEGROUPS mode used (such as when posting to forum)
442 $SESSION->activegroup[$course->id][$groupmode][0] = 0;
443 }
444 }
445
446 // set new active group if requested
447 $changegroup = optional_param('group', -1, PARAM_INT);
448 if ($update and $changegroup != -1) {
b2bc96d1 449
450 if ($changegroup == 0) {
451 // do not allow changing to all groups without accessallgroups capability
b0dcd128 452 if ($groupmode == VISIBLEGROUPS or $groupmode == 'aag') {
b2bc96d1 453 $SESSION->activegroup[$course->id][$groupmode][0] = 0;
454 }
455
456 } else {
457 // first make list of allowed groups
b0dcd128 458 if ($groupmode == VISIBLEGROUPS or $groupmode == 'aag') {
b2bc96d1 459 $allowedgroups = groups_get_all_groups($course->id, 0, 0);
460 } else {
461 $allowedgroups = groups_get_all_groups($course->id, $USER->id, 0);
462 }
463
464 if ($allowedgroups and array_key_exists($changegroup, $allowedgroups)) {
465 $SESSION->activegroup[$course->id][$groupmode][0] = $changegroup;
466 }
467 }
468 }
469
470 return $SESSION->activegroup[$course->id][$groupmode][0];
471}
472
13534ef7
ML
473/**
474 * Returns group active in activity, changes the group by default if 'group' page param present
475 *
476 * @param object $cm course module object
477 * @param boolean $update change active group if group param submitted
478 * @return mixed false if groups not used, int if groups used, 0 means all groups (access must be verified in SEPARATE mode)
479 */
480function groups_get_activity_group($cm, $update=false) {
c0d4238d 481 global $CFG, $USER, $SESSION;
482
7e4fdf25 483 // groupings are ignored when not enabled
c0d4238d 484 if (empty($CFG->enablegroupings)) {
485 $cm->groupingid = 0;
486 }
13534ef7
ML
487
488 if (!$groupmode = groups_get_activity_groupmode($cm)) {
489 // NOGROUPS used
490 return false;
491 }
492
b2bc96d1 493 // init activegroup array
13534ef7
ML
494 if (!array_key_exists('activegroup', $SESSION)) {
495 $SESSION->activegroup = array();
496 }
497 if (!array_key_exists($cm->course, $SESSION->activegroup)) {
b0dcd128 498 $SESSION->activegroup[$cm->course] = array(SEPARATEGROUPS=>array(), VISIBLEGROUPS=>array(), 'aag'=>array());
499 }
500
501 $context = get_context_instance(CONTEXT_MODULE, $cm->id);
502 if (has_capability('moodle/site:accessallgroups', $context)) {
503 $groupmode = 'aag';
13534ef7
ML
504 }
505
506 // grouping used the first time - add first user group as default
507 if (!array_key_exists($cm->groupingid, $SESSION->activegroup[$cm->course][$groupmode])) {
b0dcd128 508 if ($groupmode == 'aag') {
509 $SESSION->activegroup[$cm->course][$groupmode][$cm->groupingid] = 0; // all groups by default if user has accessallgroups
510
511 } else if ($usergroups = groups_get_all_groups($cm->course, $USER->id, $cm->groupingid)) {
13534ef7
ML
512 $fistgroup = reset($usergroups);
513 $SESSION->activegroup[$cm->course][$groupmode][$cm->groupingid] = $fistgroup->id;
b0dcd128 514
13534ef7
ML
515 } else {
516 // this happen when user not assigned into group in SEPARATEGROUPS mode or groups do not exist yet
517 // mod authors must add extra checks for this when SEPARATEGROUPS mode used (such as when posting to forum)
518 $SESSION->activegroup[$cm->course][$groupmode][$cm->groupingid] = 0;
519 }
520 }
521
522 // set new active group if requested
523 $changegroup = optional_param('group', -1, PARAM_INT);
524 if ($update and $changegroup != -1) {
13534ef7
ML
525
526 if ($changegroup == 0) {
b0dcd128 527 // allgroups visible only in VISIBLEGROUPS or when accessallgroups
528 if ($groupmode == VISIBLEGROUPS or $groupmode == 'aag') {
13534ef7
ML
529 $SESSION->activegroup[$cm->course][$groupmode][$cm->groupingid] = 0;
530 }
531
532 } else {
533 // first make list of allowed groups
b0dcd128 534 if ($groupmode == VISIBLEGROUPS or $groupmode == 'aag') {
13534ef7
ML
535 $allowedgroups = groups_get_all_groups($cm->course, 0, $cm->groupingid); // any group in grouping (all if groupings not used)
536 } else {
537 $allowedgroups = groups_get_all_groups($cm->course, $USER->id, $cm->groupingid); // only assigned groups
538 }
539
540 if ($allowedgroups and array_key_exists($changegroup, $allowedgroups)) {
541 $SESSION->activegroup[$cm->course][$groupmode][$cm->groupingid] = $changegroup;
542 }
543 }
544 }
545
546 return $SESSION->activegroup[$cm->course][$groupmode][$cm->groupingid];
547}
62d63838 548
18d43e96 549/**
550 * Gets a list of groups that the user is allowed to access within the
551 * specified activity.
552 * @param object $cm Course-module
553 * @param int $userid User ID (defaults to current user)
554 * @return array An array of group objects, or false if none
555 */
cdaa9410 556function groups_get_activity_allowed_groups($cm,$userid=0) {
18d43e96 557 // Use current user by default
558 global $USER;
559 if(!$userid) {
560 $userid=$USER->id;
561 }
562
563 // Get groupmode for activity, taking into account course settings
564 $groupmode=groups_get_activity_groupmode($cm);
565
566 // If visible groups mode, or user has the accessallgroups capability,
567 // then they can access all groups for the activity...
568 $context = get_context_instance(CONTEXT_MODULE, $cm->id);
569 if ($groupmode == VISIBLEGROUPS or has_capability('moodle/site:accessallgroups', $context)) {
570 return groups_get_all_groups($cm->course, 0, $cm->groupingid);
571 } else {
572 // ...otherwise they can only access groups they belong to
573 return groups_get_all_groups($cm->course, $userid, $cm->groupingid);
574 }
575}
576
dcd8db68 577/**
578 * Determine if a course module is currently visible to a user
579 * @uses $USER If $userid is null, use the global object.
580 * @param int $cm The course module
581 * @param int $userid The user to check against the group.
582 * @return boolean True if the user can view the course module, false otherwise.
583 */
584function groups_course_module_visible($cm, $userid=null) {
585 global $CFG, $USER;
586
587 if (empty($userid)) {
588 $userid = $USER->id;
589 }
590 if (empty($CFG->enablegroupings)) {
591 return(true);
592 }
593 if (empty($cm->groupmembersonly)) {
594 return(true);
595 }
e0bc99e4 596 if (groups_has_membership($cm, $userid) || has_capability('moodle/site:accessallgroups', get_context_instance(CONTEXT_MODULE, $cm->id), $userid)) {
dcd8db68 597 return(true);
598 }
599 return(false);
600}
601
2c386f82 602?>