MDL-21704 fixed recent regression
[moodle.git] / lib / grouplib.php
CommitLineData
e4f0a85e 1<?php
2
3// This file is part of Moodle - http://moodle.org/
4//
5// Moodle is free software: you can redistribute it and/or modify
6// it under the terms of the GNU General Public License as published by
7// the Free Software Foundation, either version 3 of the License, or
8// (at your option) any later version.
9//
10// Moodle is distributed in the hope that it will be useful,
11// but WITHOUT ANY WARRANTY; without even the implied warranty of
12// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13// GNU General Public License for more details.
14//
15// You should have received a copy of the GNU General Public License
16// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
17
18/**
19 * @copyright 1999 onwards Martin Dougiamas {@link http://moodle.com}
20 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
21 * @package moodlecore
22 */
2c386f82 23
13534ef7 24/**
ffc536af 25 * Groups not used in course or activity
13534ef7
ML
26 */
27define('NOGROUPS', 0);
28
29/**
ffc536af 30 * Groups used, users do not see other groups
13534ef7
ML
31 */
32define('SEPARATEGROUPS', 1);
5bf243d1 33
5bf243d1 34/**
ffc536af 35 * Groups used, students see other groups
13534ef7
ML
36 */
37define('VISIBLEGROUPS', 2);
38
39
40/**
41 * Determines if a group with a given groupid exists.
e4f0a85e 42 *
43 * @global object
5bf243d1 44 * @param int $groupid The groupid to check for
13534ef7
ML
45 * @return boolean True if the group exists, false otherwise or if an error
46 * occurred.
5bf243d1 47 */
48function groups_group_exists($groupid) {
f33e1ed4 49 global $DB;
50 return $DB->record_exists('groups', array('id'=>$groupid));
5bf243d1 51}
52
53/**
54 * Gets the name of a group with a specified id
e4f0a85e 55 *
56 * @global object
5bf243d1 57 * @param int $groupid The id of the group
58 * @return string The name of the group
59 */
60function groups_get_group_name($groupid) {
f33e1ed4 61 global $DB;
62 return $DB->get_field('groups', 'name', array('id'=>$groupid));
5bf243d1 63}
2c386f82 64
4d8e3407 65/**
66 * Gets the name of a grouping with a specified id
e4f0a85e 67 *
68 * @global object
4d8e3407 69 * @param int $groupingid The id of the grouping
70 * @return string The name of the grouping
71 */
72function groups_get_grouping_name($groupingid) {
f33e1ed4 73 global $DB;
74 return $DB->get_field('groupings', 'name', array('id'=>$groupingid));
4d8e3407 75}
76
2c386f82 77/**
78 * Returns the groupid of a group with the name specified for the course.
79 * Group names should be unique in course
e4f0a85e 80 *
81 * @global object
2c386f82 82 * @param int $courseid The id of the course
83 * @param string $name name of group (without magic quotes)
84 * @return int $groupid
85 */
86function groups_get_group_by_name($courseid, $name) {
f33e1ed4 87 global $DB;
88 if ($groups = $DB->get_records('groups', array('courseid'=>$courseid, 'name'=>$name))) {
ddff2fa8 89 return key($groups);
2c386f82 90 }
ddff2fa8 91 return false;
92}
2c386f82 93
ddff2fa8 94/**
95 * Returns the groupingid of a grouping with the name specified for the course.
96 * Grouping names should be unique in course
e4f0a85e 97 *
98 * @global object
ddff2fa8 99 * @param int $courseid The id of the course
100 * @param string $name name of group (without magic quotes)
101 * @return int $groupid
102 */
103function groups_get_grouping_by_name($courseid, $name) {
f33e1ed4 104 global $DB;
c70552d8 105 if ($groupings = $DB->get_records('groupings', array('courseid'=>$courseid, 'name'=>$name))) {
ddff2fa8 106 return key($groupings);
107 }
108 return false;
2c386f82 109}
110
111/**
112 * Get the group object
e4f0a85e 113 *
e4f0a85e 114 * @param int $groupid ID of the group.
115 * @return object group object
2c386f82 116 */
9a0df45a 117function groups_get_group($groupid, $fields='*', $strictness=IGNORE_MISSING) {
f33e1ed4 118 global $DB;
9a0df45a 119 return $DB->get_record('groups', array('id'=>$groupid), $fields, $strictness);
2c386f82 120}
121
f16fa0a3 122/**
123 * Get the grouping object
e4f0a85e 124 *
e4f0a85e 125 * @param int $groupingid ID of the group.
9a0df45a 126 * @param string $fields
e4f0a85e 127 * @return object group object
f16fa0a3 128 */
9a0df45a 129function groups_get_grouping($groupingid, $fields='*', $strictness=IGNORE_MISSING) {
f33e1ed4 130 global $DB;
9a0df45a 131 return $DB->get_record('groupings', array('id'=>$groupingid), $fields, $strictness);
f16fa0a3 132}
133
2c386f82 134/**
135 * Gets array of all groups in a specified course.
e4f0a85e 136 *
2c386f82 137 * @param int $courseid The id of the course.
65bcf17b 138 * @param mixed $userid optional user id or array of ids, returns only groups of the user.
62d63838 139 * @param int $groupingid optional returns only groups in the specified grouping.
e4f0a85e 140 * @param string $fields
141 * @return array|bool Returns an array of the group objects or false if no records
65bcf17b 142 * or an error occurred. (userid field returned if array in $userid)
2c386f82 143 */
65bcf17b 144function groups_get_all_groups($courseid, $userid=0, $groupingid=0, $fields='g.*') {
f33e1ed4 145 global $CFG, $DB;
2c386f82 146
7e4fdf25 147 // groupings are ignored when not enabled
c0d4238d 148 if (empty($CFG->enablegroupings)) {
149 $groupingid = 0;
150 }
151
f33e1ed4 152
65bcf17b 153 if (empty($userid)) {
62d63838 154 $userfrom = "";
155 $userwhere = "";
f33e1ed4 156 $params = array();
65bcf17b 157
158 } else {
f33e1ed4 159 list($usql, $params) = $DB->get_in_or_equal($userid);
160 $userfrom = ", {groups_members} gm";
161 $userwhere = "AND g.id = gm.groupid AND gm.userid $usql";
62d63838 162 }
2c386f82 163
62d63838 164 if (!empty($groupingid)) {
f33e1ed4 165 $groupingfrom = ", {groupings_groups} gg";
166 $groupingwhere = "AND g.id = gg.groupid AND gg.groupingid = ?";
167 $params[] = $groupingid;
2c386f82 168 } else {
62d63838 169 $groupingfrom = "";
170 $groupingwhere = "";
2c386f82 171 }
62d63838 172
f33e1ed4 173 array_unshift($params, $courseid);
174
175 return $DB->get_records_sql("SELECT $fields
176 FROM {groups} g $userfrom $groupingfrom
177 WHERE g.courseid = ? $userwhere $groupingwhere
178 ORDER BY name ASC", $params);
2c386f82 179}
180
dd97c328 181/**
182 * Returns info about user's groups in course.
e4f0a85e 183 *
184 * @global object
185 * @global object
186 * @global object
dd97c328 187 * @param int $courseid
188 * @param int $userid $USER if not specified
e4f0a85e 189 * @return array Array[groupingid][groupid] including grouping id 0 which means all groups
dd97c328 190 */
191function groups_get_user_groups($courseid, $userid=0) {
f33e1ed4 192 global $CFG, $USER, $DB;
dd97c328 193
194 if (empty($userid)) {
195 $userid = $USER->id;
196 }
197
f33e1ed4 198 $sql = "SELECT g.id, gg.groupingid
199 FROM {groups} g
200 JOIN {groups_members} gm ON gm.groupid = g.id
201 LEFT JOIN {groupings_groups} gg ON gg.groupid = g.id
202 WHERE gm.userid = ? AND g.courseid = ?";
203 $params = array($userid, $courseid);
204
205 if (!$rs = $DB->get_recordset_sql($sql, $params)) {
dd97c328 206 return array('0' => array());
207 }
208
0b943ef1 209 $result = array();
210 $allgroups = array();
117bd748 211
f33e1ed4 212 foreach ($rs as $group) {
ca182d90 213 $allgroups[$group->id] = $group->id;
dd97c328 214 if (is_null($group->groupingid)) {
215 continue;
216 }
217 if (!array_key_exists($group->groupingid, $result)) {
218 $result[$group->groupingid] = array();
219 }
220 $result[$group->groupingid][$group->id] = $group->id;
221 }
f33e1ed4 222 $rs->close();
0b943ef1 223
224 $result['0'] = array_keys($allgroups); // all groups
dd97c328 225
226 return $result;
227}
228
acf000b0 229/**
230 * Gets array of all groupings in a specified course.
117bd748 231 *
e4f0a85e 232 * @global object
233 * @global object
18d43e96 234 * @param int $courseid return only groupings in this with this courseid
e4f0a85e 235 * @return array|bool Returns an array of the grouping objects or false if no records
acf000b0 236 * or an error occurred.
237 */
238function groups_get_all_groupings($courseid) {
f33e1ed4 239 global $CFG, $DB;
acf000b0 240
241 // groupings are ignored when not enabled
242 if (empty($CFG->enablegroupings)) {
243 return(false);
244 }
f33e1ed4 245 return $DB->get_records_sql("SELECT *
246 FROM {groupings}
247 WHERE courseid = ?
248 ORDER BY name ASC", array($courseid));
acf000b0 249}
250
251
252
2c386f82 253/**
254 * Determines if the user is a member of the given group.
255 *
aaeba371 256 * If $userid is null, use the global object.
257 *
258 * @global object
e4f0a85e 259 * @global object
2c386f82 260 * @param int $groupid The group to check for membership.
261 * @param int $userid The user to check against the group.
262 * @return boolean True if the user is a member, false otherwise.
263 */
264function groups_is_member($groupid, $userid=null) {
f33e1ed4 265 global $USER, $DB;
2c386f82 266
267 if (!$userid) {
268 $userid = $USER->id;
269 }
270
f33e1ed4 271 return $DB->record_exists('groups_members', array('groupid'=>$groupid, 'userid'=>$userid));
2c386f82 272}
273
f8e3d5f0 274/**
275 * Determines if current or specified is member of any active group in activity
e4f0a85e 276 *
277 * @global object
278 * @global object
279 * @global object
280 * @staticvar array $cache
f8e3d5f0 281 * @param object $cm coruse module object
282 * @param int $userid id of user, null menas $USER->id
283 * @return booelan true if user member of at least one group used in activity
284 */
285function groups_has_membership($cm, $userid=null) {
f33e1ed4 286 global $CFG, $USER, $DB;
f16fa0a3 287
e0bc99e4 288 static $cache = array();
f16fa0a3 289
7e4fdf25 290 // groupings are ignored when not enabled
c0d4238d 291 if (empty($CFG->enablegroupings)) {
292 $cm->groupingid = 0;
293 }
294
f8e3d5f0 295 if (empty($userid)) {
296 $userid = $USER->id;
297 }
298
e0bc99e4 299 $cachekey = $userid.'|'.$cm->course.'|'.$cm->groupingid;
300 if (isset($cache[$cachekey])) {
301 return($cache[$cachekey]);
302 }
303
f8e3d5f0 304 if ($cm->groupingid) {
305 // find out if member of any group in selected activity grouping
306 $sql = "SELECT 'x'
f33e1ed4 307 FROM {groups_members} gm, {groupings_groups} gg
308 WHERE gm.userid = ? AND gm.groupid = gg.groupid AND gg.groupingid = ?";
309 $params = array($userid, $cm->groupingid);
f8e3d5f0 310
311 } else {
312 // no grouping used - check all groups in course
313 $sql = "SELECT 'x'
f33e1ed4 314 FROM {groups_members} gm, {groups} g
315 WHERE gm.userid = ? AND gm.groupid = g.id AND g.courseid = ?";
316 $params = array($userid, $cm->course);
f8e3d5f0 317 }
f16fa0a3 318
f33e1ed4 319 $cache[$cachekey] = $DB->record_exists_sql($sql, $params);
f16fa0a3 320
e0bc99e4 321 return $cache[$cachekey];
f8e3d5f0 322}
323
62d63838 324/**
325 * Returns the users in the specified group.
e4f0a85e 326 *
327 * @global object
62d63838 328 * @param int $groupid The groupid to get the users for
e6839677 329 * @param int $fields The fields to return
62d63838 330 * @param int $sort optional sorting of returned users
e4f0a85e 331 * @return array|bool Returns an array of the users for the specified
62d63838 332 * group or false if no users or an error returned.
333 */
e6839677 334function groups_get_members($groupid, $fields='u.*', $sort='lastname ASC') {
f33e1ed4 335 global $DB;
62d63838 336
f33e1ed4 337 return $DB->get_records_sql("SELECT $fields
338 FROM {user} u, {groups_members} gm
339 WHERE u.id = gm.userid AND gm.groupid = ?
340 ORDER BY $sort", array($groupid));
62d63838 341}
342
e6839677 343
344/**
345 * Returns the users in the specified grouping.
e4f0a85e 346 *
347 * @global object
e6839677 348 * @param int $groupingid The groupingid to get the users for
349 * @param int $fields The fields to return
350 * @param int $sort optional sorting of returned users
e4f0a85e 351 * @return array|bool Returns an array of the users for the specified
e6839677 352 * group or false if no users or an error returned.
353 */
354function groups_get_grouping_members($groupingid, $fields='u.*', $sort='lastname ASC') {
f33e1ed4 355 global $DB;
356
357 return $DB->get_records_sql("SELECT $fields
358 FROM {user} u
359 INNER JOIN {groups_members} gm ON u.id = gm.userid
360 INNER JOIN {groupings_groups} gg ON gm.groupid = gg.groupid
361 WHERE gg.groupingid = ?
362 ORDER BY $sort", array($groupingid));
e6839677 363}
364
b2bc96d1 365/**
366 * Returns effective groupmode used in course
117bd748 367 *
b2bc96d1 368 * @return integer group mode
369 */
370function groups_get_course_groupmode($course) {
371 return $course->groupmode;
372}
373
13534ef7
ML
374/**
375 * Returns effective groupmode used in activity, course setting
376 * overrides activity setting if groupmodeforce enabled.
e4f0a85e 377 *
378 * @global object
379 * @global object
380 * @param object $cm the course module object. Only the ->course and ->groupmode need to be set.
381 * @param object $course object optional course object to improve perf
13534ef7
ML
382 * @return integer group mode
383 */
dd97c328 384function groups_get_activity_groupmode($cm, $course=null) {
f33e1ed4 385 global $COURSE, $DB;
13534ef7
ML
386
387 // get course object (reuse COURSE if possible)
dd97c328 388 if (isset($course->id) and $course->id == $cm->course) {
389 //ok
390 } else if ($cm->course == $COURSE->id) {
13534ef7
ML
391 $course = $COURSE;
392 } else {
f33e1ed4 393 if (!$course = $DB->get_record('course', array('id'=>$cm->course))) {
06e84d52 394 print_error('invalidcourseid');
13534ef7
ML
395 }
396 }
397
398 return empty($course->groupmodeforce) ? $cm->groupmode : $course->groupmode;
399}
400
b2bc96d1 401/**
402 * Print group menu selector for course level.
e4f0a85e 403 *
404 * @global object
405 * @global object
b2bc96d1 406 * @param object $course course object
407 * @param string $urlroot return address
408 * @param boolean $return return as string instead of printing
409 * @return mixed void or string depending on $return param
410 */
411function groups_print_course_menu($course, $urlroot, $return=false) {
d81b05e7 412 global $CFG, $USER, $SESSION, $OUTPUT;
b2bc96d1 413
414 if (!$groupmode = $course->groupmode) {
415 if ($return) {
416 return '';
417 } else {
418 return;
419 }
420 }
421
422 $context = get_context_instance(CONTEXT_COURSE, $course->id);
423 if ($groupmode == VISIBLEGROUPS or has_capability('moodle/site:accessallgroups', $context)) {
25bc3cd3 424 $allowedgroups = groups_get_all_groups($course->id, 0, $course->defaultgroupingid);
89f39741 425 // detect changes related to groups and fix active group
426 if (!empty($SESSION->activegroup[$course->id][VISIBLEGROUPS][0])) {
427 if (!array_key_exists($SESSION->activegroup[$course->id][VISIBLEGROUPS][0], $allowedgroups)) {
428 // active does not exist anymore
429 unset($SESSION->activegroup[$course->id][VISIBLEGROUPS][0]);
dd97c328 430 }
89f39741 431 }
432 if (!empty($SESSION->activegroup[$course->id]['aag'][0])) {
433 if (!array_key_exists($SESSION->activegroup[$course->id]['aag'][0], $allowedgroups)) {
434 // active group does not exist anymore
435 unset($SESSION->activegroup[$course->id]['aag'][0]);
dd97c328 436 }
89f39741 437 }
438
b2bc96d1 439 } else {
25bc3cd3 440 $allowedgroups = groups_get_all_groups($course->id, $USER->id, $course->defaultgroupingid);
89f39741 441 // detect changes related to groups and fix active group
442 if (isset($SESSION->activegroup[$course->id][SEPARATEGROUPS][0])) {
443 if ($SESSION->activegroup[$course->id][SEPARATEGROUPS][0] == 0) {
444 if ($allowedgroups) {
445 // somebody must have assigned at least one group, we can select it now - yay!
446 unset($SESSION->activegroup[$course->id][SEPARATEGROUPS][0]);
447 }
448 } else {
449 if (!array_key_exists($SESSION->activegroup[$course->id][SEPARATEGROUPS][0], $allowedgroups)) {
450 // active group not allowed or does not exist anymore
451 unset($SESSION->activegroup[$course->id][SEPARATEGROUPS][0]);
dd97c328 452 }
89f39741 453 }
454 }
b2bc96d1 455 }
456
457 $activegroup = groups_get_course_group($course, true);
458
459 $groupsmenu = array();
460 if (!$allowedgroups or $groupmode == VISIBLEGROUPS or has_capability('moodle/site:accessallgroups', $context)) {
461 $groupsmenu[0] = get_string('allparticipants');
462 }
463
464 if ($allowedgroups) {
465 foreach ($allowedgroups as $group) {
466 $groupsmenu[$group->id] = format_string($group->name);
467 }
468 }
469
470 if ($groupmode == VISIBLEGROUPS) {
471 $grouplabel = get_string('groupsvisible');
472 } else {
473 $grouplabel = get_string('groupsseparate');
474 }
475
476 if (count($groupsmenu) == 1) {
477 $groupname = reset($groupsmenu);
478 $output = $grouplabel.': '.$groupname;
479 } else {
f8dab966
PS
480 $select = new single_select(new moodle_url($urlroot), 'group', $groupsmenu, $activegroup, null, 'selectgroup');
481 $select->label = $grouplabel;
482 $output = $OUTPUT->render($select);
b2bc96d1 483 }
484
485 $output = '<div class="groupselector">'.$output.'</div>';
486
487 if ($return) {
488 return $output;
489 } else {
490 echo $output;
491 }
492}
493
13534ef7
ML
494/**
495 * Print group menu selector for activity.
e4f0a85e 496 *
497 * @global object
498 * @global object
499 * @global object
13534ef7 500 * @param object $cm course module object
f16fa0a3 501 * @param string $urlroot return address that users get to if they choose an option;
f1035deb 502 * should include any parameters needed, e.g. "$CFG->wwwroot/mod/forum/view.php?id=34"
13534ef7 503 * @param boolean $return return as string instead of printing
f16fa0a3 504 * @param boolean $hideallparticipants If true, this prevents the 'All participants'
505 * option from appearing in cases where it normally would. This is intended for
506 * use only by activities that cannot display all groups together. (Note that
507 * selecting this option does not prevent groups_get_activity_group from
508 * returning 0; it will still do that if the user has chosen 'all participants'
509 * in another activity, or not chosen anything.)
13534ef7
ML
510 * @return mixed void or string depending on $return param
511 */
18d43e96 512function groups_print_activity_menu($cm, $urlroot, $return=false, $hideallparticipants=false) {
d81b05e7 513 global $CFG, $USER, $SESSION, $OUTPUT;
c0d4238d 514
f1035deb
SM
515 // Display error if urlroot is not absolute (this causes the non-JS version
516 // to break)
517 if (strpos($urlroot, 'http') !== 0) { // Will also work for https
518 debugging('groups_print_activity_menu requires absolute URL for ' .
519 '$urlroot, not <tt>' . s($urlroot) . '</tt>. Example: ' .
520 'groups_print_activity_menu($cm, $CFG->wwwroot . \'/mod/mymodule/view.php?id=13\');',
521 DEBUG_DEVELOPER);
522 }
523
7e4fdf25 524 // groupings are ignored when not enabled
c0d4238d 525 if (empty($CFG->enablegroupings)) {
526 $cm->groupingid = 0;
527 }
13534ef7
ML
528
529 if (!$groupmode = groups_get_activity_groupmode($cm)) {
530 if ($return) {
531 return '';
532 } else {
533 return;
534 }
535 }
536
537 $context = get_context_instance(CONTEXT_MODULE, $cm->id);
538 if ($groupmode == VISIBLEGROUPS or has_capability('moodle/site:accessallgroups', $context)) {
539 $allowedgroups = groups_get_all_groups($cm->course, 0, $cm->groupingid); // any group in grouping (all if groupings not used)
89f39741 540 // detect changes related to groups and fix active group
541 if (!empty($SESSION->activegroup[$cm->course][VISIBLEGROUPS][$cm->groupingid])) {
542 if (!array_key_exists($SESSION->activegroup[$cm->course][VISIBLEGROUPS][$cm->groupingid], $allowedgroups)) {
543 // active group does not exist anymore
544 unset($SESSION->activegroup[$cm->course][VISIBLEGROUPS][$cm->groupingid]);
dd97c328 545 }
89f39741 546 }
547 if (!empty($SESSION->activegroup[$cm->course]['aag'][$cm->groupingid])) {
548 if (!array_key_exists($SESSION->activegroup[$cm->course]['aag'][$cm->groupingid], $allowedgroups)) {
549 // active group does not exist anymore
550 unset($SESSION->activegroup[$cm->course]['aag'][$cm->groupingid]);
dd97c328 551 }
89f39741 552 }
553
13534ef7
ML
554 } else {
555 $allowedgroups = groups_get_all_groups($cm->course, $USER->id, $cm->groupingid); // only assigned groups
89f39741 556 // detect changes related to groups and fix active group
557 if (isset($SESSION->activegroup[$cm->course][SEPARATEGROUPS][$cm->groupingid])) {
558 if ($SESSION->activegroup[$cm->course][SEPARATEGROUPS][$cm->groupingid] == 0) {
559 if ($allowedgroups) {
560 // somebody must have assigned at least one group, we can select it now - yay!
561 unset($SESSION->activegroup[$cm->course][SEPARATEGROUPS][$cm->groupingid]);
562 }
563 } else {
564 if (!array_key_exists($SESSION->activegroup[$cm->course][SEPARATEGROUPS][$cm->groupingid], $allowedgroups)) {
565 // active group not allowed or does not exist anymore
566 unset($SESSION->activegroup[$cm->course][SEPARATEGROUPS][$cm->groupingid]);
dd97c328 567 }
89f39741 568 }
569 }
13534ef7
ML
570 }
571
572 $activegroup = groups_get_activity_group($cm, true);
573
574 $groupsmenu = array();
f16fa0a3 575 if ((!$allowedgroups or $groupmode == VISIBLEGROUPS or
18d43e96 576 has_capability('moodle/site:accessallgroups', $context)) and !$hideallparticipants) {
13534ef7
ML
577 $groupsmenu[0] = get_string('allparticipants');
578 }
579
580 if ($allowedgroups) {
581 foreach ($allowedgroups as $group) {
582 $groupsmenu[$group->id] = format_string($group->name);
583 }
584 }
585
586 if ($groupmode == VISIBLEGROUPS) {
587 $grouplabel = get_string('groupsvisible');
588 } else {
589 $grouplabel = get_string('groupsseparate');
590 }
591
592 if (count($groupsmenu) == 1) {
593 $groupname = reset($groupsmenu);
594 $output = $grouplabel.': '.$groupname;
595 } else {
c564ee2a 596 $select = new single_select(new moodle_url($urlroot), 'group', $groupsmenu, $activegroup, null, 'selectgroup');
f8dab966
PS
597 $select->label = $grouplabel;
598 $output = $OUTPUT->render($select);
13534ef7
ML
599 }
600
601 $output = '<div class="groupselector">'.$output.'</div>';
602
603 if ($return) {
604 return $output;
605 } else {
606 echo $output;
607 }
608}
609
b2bc96d1 610/**
611 * Returns group active in course, changes the group by default if 'group' page param present
612 *
e4f0a85e 613 * @global object
614 * @global object
615 * @global object
b2bc96d1 616 * @param object $course course bject
617 * @param boolean $update change active group if group param submitted
618 * @return mixed false if groups not used, int if groups used, 0 means all groups (access must be verified in SEPARATE mode)
619 */
620function groups_get_course_group($course, $update=false) {
621 global $CFG, $USER, $SESSION;
622
623 if (!$groupmode = $course->groupmode) {
624 // NOGROUPS used
625 return false;
626 }
627
628 // init activegroup array
177d5493 629 if (!isset($SESSION->activegroup)) {
b2bc96d1 630 $SESSION->activegroup = array();
631 }
632 if (!array_key_exists($course->id, $SESSION->activegroup)) {
b0dcd128 633 $SESSION->activegroup[$course->id] = array(SEPARATEGROUPS=>array(), VISIBLEGROUPS=>array(), 'aag'=>array());
634 }
635
e873679b 636 $context = get_context_instance(CONTEXT_COURSE, $course->id);
b0dcd128 637 if (has_capability('moodle/site:accessallgroups', $context)) {
638 $groupmode = 'aag';
b2bc96d1 639 }
640
641 // grouping used the first time - add first user group as default
642 if (!array_key_exists(0, $SESSION->activegroup[$course->id][$groupmode])) {
b0dcd128 643 if ($groupmode == 'aag') {
644 $SESSION->activegroup[$course->id][$groupmode][0] = 0; // all groups by default if user has accessallgroups
645
25bc3cd3 646 } else if ($usergroups = groups_get_all_groups($course->id, $USER->id, $course->defaultgroupingid)) {
b2bc96d1 647 $fistgroup = reset($usergroups);
648 $SESSION->activegroup[$course->id][$groupmode][0] = $fistgroup->id;
b0dcd128 649
b2bc96d1 650 } else {
651 // this happen when user not assigned into group in SEPARATEGROUPS mode or groups do not exist yet
652 // mod authors must add extra checks for this when SEPARATEGROUPS mode used (such as when posting to forum)
653 $SESSION->activegroup[$course->id][$groupmode][0] = 0;
654 }
655 }
656
657 // set new active group if requested
658 $changegroup = optional_param('group', -1, PARAM_INT);
659 if ($update and $changegroup != -1) {
b2bc96d1 660
661 if ($changegroup == 0) {
662 // do not allow changing to all groups without accessallgroups capability
b0dcd128 663 if ($groupmode == VISIBLEGROUPS or $groupmode == 'aag') {
b2bc96d1 664 $SESSION->activegroup[$course->id][$groupmode][0] = 0;
665 }
666
667 } else {
668 // first make list of allowed groups
b0dcd128 669 if ($groupmode == VISIBLEGROUPS or $groupmode == 'aag') {
25bc3cd3 670 $allowedgroups = groups_get_all_groups($course->id, 0, $course->defaultgroupingid);
b2bc96d1 671 } else {
25bc3cd3 672 $allowedgroups = groups_get_all_groups($course->id, $USER->id, $course->defaultgroupingid);
b2bc96d1 673 }
674
675 if ($allowedgroups and array_key_exists($changegroup, $allowedgroups)) {
676 $SESSION->activegroup[$course->id][$groupmode][0] = $changegroup;
677 }
678 }
679 }
680
681 return $SESSION->activegroup[$course->id][$groupmode][0];
682}
683
13534ef7
ML
684/**
685 * Returns group active in activity, changes the group by default if 'group' page param present
686 *
e4f0a85e 687 * @global object
688 * @global object
689 * @global object
13534ef7
ML
690 * @param object $cm course module object
691 * @param boolean $update change active group if group param submitted
692 * @return mixed false if groups not used, int if groups used, 0 means all groups (access must be verified in SEPARATE mode)
693 */
694function groups_get_activity_group($cm, $update=false) {
c0d4238d 695 global $CFG, $USER, $SESSION;
696
7e4fdf25 697 // groupings are ignored when not enabled
c0d4238d 698 if (empty($CFG->enablegroupings)) {
699 $cm->groupingid = 0;
700 }
13534ef7
ML
701
702 if (!$groupmode = groups_get_activity_groupmode($cm)) {
703 // NOGROUPS used
704 return false;
705 }
706
b2bc96d1 707 // init activegroup array
177d5493 708 if (!isset($SESSION->activegroup)) {
13534ef7
ML
709 $SESSION->activegroup = array();
710 }
711 if (!array_key_exists($cm->course, $SESSION->activegroup)) {
b0dcd128 712 $SESSION->activegroup[$cm->course] = array(SEPARATEGROUPS=>array(), VISIBLEGROUPS=>array(), 'aag'=>array());
713 }
714
715 $context = get_context_instance(CONTEXT_MODULE, $cm->id);
716 if (has_capability('moodle/site:accessallgroups', $context)) {
717 $groupmode = 'aag';
13534ef7
ML
718 }
719
720 // grouping used the first time - add first user group as default
721 if (!array_key_exists($cm->groupingid, $SESSION->activegroup[$cm->course][$groupmode])) {
b0dcd128 722 if ($groupmode == 'aag') {
723 $SESSION->activegroup[$cm->course][$groupmode][$cm->groupingid] = 0; // all groups by default if user has accessallgroups
724
725 } else if ($usergroups = groups_get_all_groups($cm->course, $USER->id, $cm->groupingid)) {
13534ef7
ML
726 $fistgroup = reset($usergroups);
727 $SESSION->activegroup[$cm->course][$groupmode][$cm->groupingid] = $fistgroup->id;
b0dcd128 728
13534ef7
ML
729 } else {
730 // this happen when user not assigned into group in SEPARATEGROUPS mode or groups do not exist yet
731 // mod authors must add extra checks for this when SEPARATEGROUPS mode used (such as when posting to forum)
732 $SESSION->activegroup[$cm->course][$groupmode][$cm->groupingid] = 0;
733 }
734 }
735
736 // set new active group if requested
737 $changegroup = optional_param('group', -1, PARAM_INT);
738 if ($update and $changegroup != -1) {
13534ef7
ML
739
740 if ($changegroup == 0) {
b0dcd128 741 // allgroups visible only in VISIBLEGROUPS or when accessallgroups
742 if ($groupmode == VISIBLEGROUPS or $groupmode == 'aag') {
13534ef7
ML
743 $SESSION->activegroup[$cm->course][$groupmode][$cm->groupingid] = 0;
744 }
745
746 } else {
747 // first make list of allowed groups
b0dcd128 748 if ($groupmode == VISIBLEGROUPS or $groupmode == 'aag') {
13534ef7
ML
749 $allowedgroups = groups_get_all_groups($cm->course, 0, $cm->groupingid); // any group in grouping (all if groupings not used)
750 } else {
751 $allowedgroups = groups_get_all_groups($cm->course, $USER->id, $cm->groupingid); // only assigned groups
752 }
753
754 if ($allowedgroups and array_key_exists($changegroup, $allowedgroups)) {
755 $SESSION->activegroup[$cm->course][$groupmode][$cm->groupingid] = $changegroup;
756 }
757 }
758 }
759
760 return $SESSION->activegroup[$cm->course][$groupmode][$cm->groupingid];
761}
62d63838 762
18d43e96 763/**
f16fa0a3 764 * Gets a list of groups that the user is allowed to access within the
18d43e96 765 * specified activity.
e4f0a85e 766 *
767 * @global object
18d43e96 768 * @param object $cm Course-module
769 * @param int $userid User ID (defaults to current user)
770 * @return array An array of group objects, or false if none
771 */
cdaa9410 772function groups_get_activity_allowed_groups($cm,$userid=0) {
18d43e96 773 // Use current user by default
774 global $USER;
775 if(!$userid) {
776 $userid=$USER->id;
777 }
f16fa0a3 778
18d43e96 779 // Get groupmode for activity, taking into account course settings
780 $groupmode=groups_get_activity_groupmode($cm);
781
782 // If visible groups mode, or user has the accessallgroups capability,
783 // then they can access all groups for the activity...
f16fa0a3 784 $context = get_context_instance(CONTEXT_MODULE, $cm->id);
18d43e96 785 if ($groupmode == VISIBLEGROUPS or has_capability('moodle/site:accessallgroups', $context)) {
f16fa0a3 786 return groups_get_all_groups($cm->course, 0, $cm->groupingid);
18d43e96 787 } else {
788 // ...otherwise they can only access groups they belong to
f16fa0a3 789 return groups_get_all_groups($cm->course, $userid, $cm->groupingid);
790 }
18d43e96 791}
792
dcd8db68 793/**
794 * Determine if a course module is currently visible to a user
aaeba371 795 *
796 * $USER If $userid is null, use the global object.
797 *
798 * @global object
e4f0a85e 799 * @global object
dcd8db68 800 * @param int $cm The course module
801 * @param int $userid The user to check against the group.
802 * @return boolean True if the user can view the course module, false otherwise.
803 */
804function groups_course_module_visible($cm, $userid=null) {
805 global $CFG, $USER;
f16fa0a3 806
dcd8db68 807 if (empty($userid)) {
808 $userid = $USER->id;
809 }
810 if (empty($CFG->enablegroupings)) {
dd97c328 811 return true;
dcd8db68 812 }
813 if (empty($cm->groupmembersonly)) {
dd97c328 814 return true;
dcd8db68 815 }
dd97c328 816 if (has_capability('moodle/site:accessallgroups', get_context_instance(CONTEXT_MODULE, $cm->id), $userid) or groups_has_membership($cm, $userid)) {
817 return true;
dcd8db68 818 }
dd97c328 819 return false;
dcd8db68 820}