MDL-9636 fixed many sql injections in grade import code
[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/**
124 * Gets array of all groupings in a specified course.
125 * @param int $coursid return only groupings in this with this courseid
126 * @return array | false Returns an array of the group IDs or false if no records
127 * or an error occurred.
128 */
129function groups_get_all_groupings($courseid) {
130 global $CFG;
131
132 // groupings are ignored when not enabled
133 if (empty($CFG->enablegroupings)) {
134 return(false);
135 }
136 return get_records_sql("SELECT *
137 FROM {$CFG->prefix}groupings
138 WHERE courseid = $courseid
139 ORDER BY name ASC");
140}
141
142
143
2c386f82 144/**
145 * Determines if the user is a member of the given group.
146 *
147 * @uses $USER If $userid is null, use the global object.
148 * @param int $groupid The group to check for membership.
149 * @param int $userid The user to check against the group.
150 * @return boolean True if the user is a member, false otherwise.
151 */
152function groups_is_member($groupid, $userid=null) {
153 global $USER;
154
155 if (!$userid) {
156 $userid = $USER->id;
157 }
158
159 return record_exists('groups_members', 'groupid', $groupid, 'userid', $userid);
160}
161
f8e3d5f0 162/**
163 * Determines if current or specified is member of any active group in activity
164 * @param object $cm coruse module object
165 * @param int $userid id of user, null menas $USER->id
166 * @return booelan true if user member of at least one group used in activity
167 */
168function groups_has_membership($cm, $userid=null) {
169 global $CFG, $USER;
e0bc99e4 170
171 static $cache = array();
172
7e4fdf25 173 // groupings are ignored when not enabled
c0d4238d 174 if (empty($CFG->enablegroupings)) {
175 $cm->groupingid = 0;
176 }
177
f8e3d5f0 178 if (empty($userid)) {
179 $userid = $USER->id;
180 }
181
e0bc99e4 182 $cachekey = $userid.'|'.$cm->course.'|'.$cm->groupingid;
183 if (isset($cache[$cachekey])) {
184 return($cache[$cachekey]);
185 }
186
f8e3d5f0 187 if ($cm->groupingid) {
188 // find out if member of any group in selected activity grouping
189 $sql = "SELECT 'x'
190 FROM {$CFG->prefix}groups_members gm, {$CFG->prefix}groupings_groups gg
191 WHERE gm.userid = $userid AND gm.groupid = gg.groupid AND gg.groupingid = {$cm->groupingid}";
192
193 } else {
194 // no grouping used - check all groups in course
195 $sql = "SELECT 'x'
196 FROM {$CFG->prefix}groups_members gm, {$CFG->prefix}groups g
197 WHERE gm.userid = $userid AND gm.groupid = g.id AND g.courseid = {$cm->course}";
198 }
e0bc99e4 199
200 $cache[$cachekey] = record_exists_sql($sql);
201
202 return $cache[$cachekey];
f8e3d5f0 203}
204
62d63838 205/**
206 * Returns the users in the specified group.
207 * @param int $groupid The groupid to get the users for
e6839677 208 * @param int $fields The fields to return
62d63838 209 * @param int $sort optional sorting of returned users
210 * @return array | false Returns an array of the users for the specified
211 * group or false if no users or an error returned.
212 */
e6839677 213function groups_get_members($groupid, $fields='u.*', $sort='lastname ASC') {
62d63838 214 global $CFG;
215
e6839677 216 return get_records_sql("SELECT $fields
62d63838 217 FROM {$CFG->prefix}user u, {$CFG->prefix}groups_members gm
218 WHERE u.id = gm.userid AND gm.groupid = '$groupid'
219 ORDER BY $sort");
220}
221
e6839677 222
223/**
224 * Returns the users in the specified grouping.
225 * @param int $groupingid The groupingid to get the users for
226 * @param int $fields The fields to return
227 * @param int $sort optional sorting of returned users
228 * @return array | false Returns an array of the users for the specified
229 * group or false if no users or an error returned.
230 */
231function groups_get_grouping_members($groupingid, $fields='u.*', $sort='lastname ASC') {
232 global $CFG;
233
234 return get_records_sql("SELECT $fields
235 FROM {$CFG->prefix}user u
236 INNER JOIN {$CFG->prefix}groups_members gm ON u.id = gm.userid
237 INNER JOIN {$CFG->prefix}groupings_groups gg ON gm.groupid = gg.groupid
238 WHERE gg.groupingid = $groupingid
239 ORDER BY $sort");
240}
241
b2bc96d1 242/**
243 * Returns effective groupmode used in course
244 * @return integer group mode
245 */
246function groups_get_course_groupmode($course) {
247 return $course->groupmode;
248}
249
13534ef7
ML
250/**
251 * Returns effective groupmode used in activity, course setting
252 * overrides activity setting if groupmodeforce enabled.
253 * @return integer group mode
254 */
255function groups_get_activity_groupmode($cm) {
256 global $COURSE;
257
258 // get course object (reuse COURSE if possible)
259 if ($cm->course == $COURSE->id) {
260 $course = $COURSE;
261 } else {
262 if (!$course = get_record('course', 'id', $cm->course)) {
263 error('Incorrect course id in cm');
264 }
265 }
266
267 return empty($course->groupmodeforce) ? $cm->groupmode : $course->groupmode;
268}
269
b2bc96d1 270/**
271 * Print group menu selector for course level.
272 * @param object $course course object
273 * @param string $urlroot return address
274 * @param boolean $return return as string instead of printing
275 * @return mixed void or string depending on $return param
276 */
277function groups_print_course_menu($course, $urlroot, $return=false) {
278 global $CFG, $USER;
279
280 if (!$groupmode = $course->groupmode) {
281 if ($return) {
282 return '';
283 } else {
284 return;
285 }
286 }
287
288 $context = get_context_instance(CONTEXT_COURSE, $course->id);
289 if ($groupmode == VISIBLEGROUPS or has_capability('moodle/site:accessallgroups', $context)) {
290 $allowedgroups = groups_get_all_groups($course->id, 0);
291 } else {
292 $allowedgroups = groups_get_all_groups($course->id, $USER->id);
293 }
294
295 $activegroup = groups_get_course_group($course, true);
296
297 $groupsmenu = array();
298 if (!$allowedgroups or $groupmode == VISIBLEGROUPS or has_capability('moodle/site:accessallgroups', $context)) {
299 $groupsmenu[0] = get_string('allparticipants');
300 }
301
302 if ($allowedgroups) {
303 foreach ($allowedgroups as $group) {
304 $groupsmenu[$group->id] = format_string($group->name);
305 }
306 }
307
308 if ($groupmode == VISIBLEGROUPS) {
309 $grouplabel = get_string('groupsvisible');
310 } else {
311 $grouplabel = get_string('groupsseparate');
312 }
313
314 if (count($groupsmenu) == 1) {
315 $groupname = reset($groupsmenu);
316 $output = $grouplabel.': '.$groupname;
317 } else {
318 $output = popup_form($urlroot.'&amp;group=', $groupsmenu, 'selectgroup', $activegroup, '', '', '', true, 'self', $grouplabel);
319 }
320
321 $output = '<div class="groupselector">'.$output.'</div>';
322
323 if ($return) {
324 return $output;
325 } else {
326 echo $output;
327 }
328}
329
13534ef7
ML
330/**
331 * Print group menu selector for activity.
332 * @param object $cm course module object
333 * @param string $urlroot return address
334 * @param boolean $return return as string instead of printing
335 * @return mixed void or string depending on $return param
336 */
337function groups_print_activity_menu($cm, $urlroot, $return=false) {
c0d4238d 338 global $CFG, $USER;
339
7e4fdf25 340 // groupings are ignored when not enabled
c0d4238d 341 if (empty($CFG->enablegroupings)) {
342 $cm->groupingid = 0;
343 }
13534ef7
ML
344
345 if (!$groupmode = groups_get_activity_groupmode($cm)) {
346 if ($return) {
347 return '';
348 } else {
349 return;
350 }
351 }
352
353 $context = get_context_instance(CONTEXT_MODULE, $cm->id);
354 if ($groupmode == VISIBLEGROUPS or has_capability('moodle/site:accessallgroups', $context)) {
355 $allowedgroups = groups_get_all_groups($cm->course, 0, $cm->groupingid); // any group in grouping (all if groupings not used)
356 } else {
357 $allowedgroups = groups_get_all_groups($cm->course, $USER->id, $cm->groupingid); // only assigned groups
358 }
359
360 $activegroup = groups_get_activity_group($cm, true);
361
362 $groupsmenu = array();
363 if (!$allowedgroups or $groupmode == VISIBLEGROUPS or has_capability('moodle/site:accessallgroups', $context)) {
364 $groupsmenu[0] = get_string('allparticipants');
365 }
366
367 if ($allowedgroups) {
368 foreach ($allowedgroups as $group) {
369 $groupsmenu[$group->id] = format_string($group->name);
370 }
371 }
372
373 if ($groupmode == VISIBLEGROUPS) {
374 $grouplabel = get_string('groupsvisible');
375 } else {
376 $grouplabel = get_string('groupsseparate');
377 }
378
379 if (count($groupsmenu) == 1) {
380 $groupname = reset($groupsmenu);
381 $output = $grouplabel.': '.$groupname;
382 } else {
383 $output = popup_form($urlroot.'&amp;group=', $groupsmenu, 'selectgroup', $activegroup, '', '', '', true, 'self', $grouplabel);
384 }
385
386 $output = '<div class="groupselector">'.$output.'</div>';
387
388 if ($return) {
389 return $output;
390 } else {
391 echo $output;
392 }
393}
394
b2bc96d1 395/**
396 * Returns group active in course, changes the group by default if 'group' page param present
397 *
398 * @param object $course course bject
399 * @param boolean $update change active group if group param submitted
400 * @return mixed false if groups not used, int if groups used, 0 means all groups (access must be verified in SEPARATE mode)
401 */
402function groups_get_course_group($course, $update=false) {
403 global $CFG, $USER, $SESSION;
404
405 if (!$groupmode = $course->groupmode) {
406 // NOGROUPS used
407 return false;
408 }
409
410 // init activegroup array
411 if (!array_key_exists('activegroup', $SESSION)) {
412 $SESSION->activegroup = array();
413 }
414 if (!array_key_exists($course->id, $SESSION->activegroup)) {
415 $SESSION->activegroup[$course->id] = array(SEPARATEGROUPS=>array(), VISIBLEGROUPS=>array());
416 }
417
418 // grouping used the first time - add first user group as default
419 if (!array_key_exists(0, $SESSION->activegroup[$course->id][$groupmode])) {
420 if ($usergroups = groups_get_all_groups($course->id, $USER->id, 0)) {
421 $fistgroup = reset($usergroups);
422 $SESSION->activegroup[$course->id][$groupmode][0] = $fistgroup->id;
423 } else {
424 // this happen when user not assigned into group in SEPARATEGROUPS mode or groups do not exist yet
425 // mod authors must add extra checks for this when SEPARATEGROUPS mode used (such as when posting to forum)
426 $SESSION->activegroup[$course->id][$groupmode][0] = 0;
427 }
428 }
429
430 // set new active group if requested
431 $changegroup = optional_param('group', -1, PARAM_INT);
432 if ($update and $changegroup != -1) {
433 $context = get_context_instance(CONTEXT_COURSE, $course->id);
434
435 if ($changegroup == 0) {
436 // do not allow changing to all groups without accessallgroups capability
437 if ($groupmode == VISIBLEGROUPS or has_capability('moodle/site:accessallgroups', $context)) {
438 $SESSION->activegroup[$course->id][$groupmode][0] = 0;
439 }
440
441 } else {
442 // first make list of allowed groups
443 if ($groupmode == VISIBLEGROUPS or has_capability('moodle/site:accessallgroups', $context)) {
444 $allowedgroups = groups_get_all_groups($course->id, 0, 0);
445 } else {
446 $allowedgroups = groups_get_all_groups($course->id, $USER->id, 0);
447 }
448
449 if ($allowedgroups and array_key_exists($changegroup, $allowedgroups)) {
450 $SESSION->activegroup[$course->id][$groupmode][0] = $changegroup;
451 }
452 }
453 }
454
455 return $SESSION->activegroup[$course->id][$groupmode][0];
456}
457
13534ef7
ML
458/**
459 * Returns group active in activity, changes the group by default if 'group' page param present
460 *
461 * @param object $cm course module object
462 * @param boolean $update change active group if group param submitted
463 * @return mixed false if groups not used, int if groups used, 0 means all groups (access must be verified in SEPARATE mode)
464 */
465function groups_get_activity_group($cm, $update=false) {
c0d4238d 466 global $CFG, $USER, $SESSION;
467
7e4fdf25 468 // groupings are ignored when not enabled
c0d4238d 469 if (empty($CFG->enablegroupings)) {
470 $cm->groupingid = 0;
471 }
13534ef7
ML
472
473 if (!$groupmode = groups_get_activity_groupmode($cm)) {
474 // NOGROUPS used
475 return false;
476 }
477
b2bc96d1 478 // init activegroup array
13534ef7
ML
479 if (!array_key_exists('activegroup', $SESSION)) {
480 $SESSION->activegroup = array();
481 }
482 if (!array_key_exists($cm->course, $SESSION->activegroup)) {
483 $SESSION->activegroup[$cm->course] = array(SEPARATEGROUPS=>array(), VISIBLEGROUPS=>array());
484 }
485
486 // grouping used the first time - add first user group as default
487 if (!array_key_exists($cm->groupingid, $SESSION->activegroup[$cm->course][$groupmode])) {
488 if ($usergroups = groups_get_all_groups($cm->course, $USER->id, $cm->groupingid)) {
489 $fistgroup = reset($usergroups);
490 $SESSION->activegroup[$cm->course][$groupmode][$cm->groupingid] = $fistgroup->id;
491 } else {
492 // this happen when user not assigned into group in SEPARATEGROUPS mode or groups do not exist yet
493 // mod authors must add extra checks for this when SEPARATEGROUPS mode used (such as when posting to forum)
494 $SESSION->activegroup[$cm->course][$groupmode][$cm->groupingid] = 0;
495 }
496 }
497
498 // set new active group if requested
499 $changegroup = optional_param('group', -1, PARAM_INT);
500 if ($update and $changegroup != -1) {
501 $context = get_context_instance(CONTEXT_MODULE, $cm->id);
502
503 if ($changegroup == 0) {
504 // do not allow changing to all groups without accessallgroups capability
505 if ($groupmode == VISIBLEGROUPS or has_capability('moodle/site:accessallgroups', $context)) {
506 $SESSION->activegroup[$cm->course][$groupmode][$cm->groupingid] = 0;
507 }
508
509 } else {
510 // first make list of allowed groups
511 if ($groupmode == VISIBLEGROUPS or has_capability('moodle/site:accessallgroups', $context)) {
512 $allowedgroups = groups_get_all_groups($cm->course, 0, $cm->groupingid); // any group in grouping (all if groupings not used)
513 } else {
514 $allowedgroups = groups_get_all_groups($cm->course, $USER->id, $cm->groupingid); // only assigned groups
515 }
516
517 if ($allowedgroups and array_key_exists($changegroup, $allowedgroups)) {
518 $SESSION->activegroup[$cm->course][$groupmode][$cm->groupingid] = $changegroup;
519 }
520 }
521 }
522
523 return $SESSION->activegroup[$cm->course][$groupmode][$cm->groupingid];
524}
62d63838 525
dcd8db68 526/**
527 * Determine if a course module is currently visible to a user
528 * @uses $USER If $userid is null, use the global object.
529 * @param int $cm The course module
530 * @param int $userid The user to check against the group.
531 * @return boolean True if the user can view the course module, false otherwise.
532 */
533function groups_course_module_visible($cm, $userid=null) {
534 global $CFG, $USER;
535
536 if (empty($userid)) {
537 $userid = $USER->id;
538 }
539 if (empty($CFG->enablegroupings)) {
540 return(true);
541 }
542 if (empty($cm->groupmembersonly)) {
543 return(true);
544 }
e0bc99e4 545 if (groups_has_membership($cm, $userid) || has_capability('moodle/site:accessallgroups', get_context_instance(CONTEXT_MODULE, $cm->id), $userid)) {
dcd8db68 546 return(true);
547 }
548 return(false);
549}
550
2c386f82 551?>