Commit | Line | Data |
---|---|---|
f3f7610c ML |
1 | <?php |
2 | /** | |
ddff2fa8 | 3 | * Extra library for groups and groupings. |
f3f7610c ML |
4 | * |
5 | * @copyright © 2006 The Open University | |
6 | * @author J.White AT open.ac.uk | |
7 | * @license http://www.gnu.org/copyleft/gpl.html GNU Public License | |
8 | * @package groups | |
9 | */ | |
10 | ||
ddff2fa8 | 11 | /* |
12 | * INTERNAL FUNCTIONS - to be used by moodle core only | |
13 | * require_once $CFG->dirroot.'/group/lib.php' must be used | |
14 | */ | |
15 | ||
778918fd | 16 | /** |
17 | * Adds a specified user to a group | |
18 | * @param int $userid The user id | |
19 | * @param int $groupid The group id | |
f16fa0a3 | 20 | * @return boolean True if user added successfully or the user is already a |
21 | * member of the group, false otherwise. | |
778918fd | 22 | */ |
23 | function groups_add_member($groupid, $userid) { | |
24 | if (!groups_group_exists($groupid)) { | |
25 | return false; | |
26 | } | |
27 | ||
28 | if (groups_is_member($groupid, $userid)) { | |
29 | return true; | |
30 | } | |
31 | ||
32 | $member = new object(); | |
33 | $member->groupid = $groupid; | |
34 | $member->userid = $userid; | |
35 | $member->timeadded = time(); | |
36 | ||
37 | if (!insert_record('groups_members', $member)) { | |
38 | return false; | |
39 | } | |
40 | ||
41 | //update group info | |
42 | set_field('groups', 'timemodified', $member->timeadded, 'id', $groupid); | |
43 | ||
44 | // MDL-9983 | |
45 | $eventdata = new object(); | |
46 | $eventdata->groupid = $groupid; | |
47 | $eventdata->userid = $userid; | |
f16fa0a3 | 48 | events_trigger('group_user_added', $eventdata); |
778918fd | 49 | |
50 | return true; | |
51 | } | |
52 | ||
53 | /** | |
54 | * Deletes the link between the specified user and group. | |
55 | * @param int $groupid The group to delete the user from | |
56 | * @param int $userid The user to delete | |
57 | * @return boolean True if deletion was successful, false otherwise | |
58 | */ | |
59 | function groups_remove_member($groupid, $userid) { | |
60 | if (!groups_group_exists($groupid)) { | |
61 | return false; | |
62 | } | |
63 | ||
64 | if (!groups_is_member($groupid, $userid)) { | |
65 | return true; | |
66 | } | |
67 | ||
68 | if (!delete_records('groups_members', 'groupid', $groupid, 'userid', $userid)) { | |
69 | return false; | |
f16fa0a3 | 70 | } |
778918fd | 71 | //update group info |
72 | set_field('groups', 'timemodified', time(), 'id', $groupid); | |
73 | ||
74 | return true; | |
75 | } | |
76 | ||
ddff2fa8 | 77 | /** |
78 | * Add a new group | |
f16fa0a3 | 79 | * @param object $data group properties (with magic quotes) |
ddff2fa8 | 80 | * @param object $um upload manager with group picture |
81 | * @return id of group or false if error | |
82 | */ | |
83 | function groups_create_group($data, $um=false) { | |
84 | global $CFG; | |
85 | require_once("$CFG->libdir/gdlib.php"); | |
86 | ||
87 | $data->timecreated = time(); | |
88 | $data->timemodified = $data->timecreated; | |
f16fa0a3 | 89 | $data->name = trim($data->name); |
ddff2fa8 | 90 | $id = insert_record('groups', $data); |
91 | ||
92 | if ($id and $um) { | |
93 | //update image | |
94 | if (save_profile_image($id, $um, 'groups')) { | |
95 | set_field('groups', 'picture', 1, 'id', $id); | |
96 | } | |
97 | } | |
98 | ||
99 | return $id; | |
100 | } | |
101 | ||
102 | /** | |
f16fa0a3 | 103 | * Add a new grouping |
104 | * @param object $data grouping properties (with magic quotes) | |
105 | * @return id of grouping or false if error | |
106 | */ | |
107 | function groups_create_grouping($data) { | |
108 | global $CFG; | |
109 | ||
110 | $data->timecreated = time(); | |
111 | $data->timemodified = $data->timecreated; | |
112 | $data->name = trim($data->name); | |
113 | return insert_record('groupings', $data); | |
114 | } | |
115 | ||
116 | /** | |
117 | * Update group | |
118 | * @param object $data group properties (with magic quotes) | |
ddff2fa8 | 119 | * @param object $um upload manager with group picture |
120 | * @return boolean success | |
121 | */ | |
122 | function groups_update_group($data, $um=false) { | |
123 | global $CFG; | |
124 | require_once("$CFG->libdir/gdlib.php"); | |
125 | ||
126 | $data->timemodified = time(); | |
f16fa0a3 | 127 | $data->name = trim($data->name); |
ddff2fa8 | 128 | $result = update_record('groups', $data); |
129 | ||
130 | if ($result and $um) { | |
131 | //update image | |
132 | if (save_profile_image($data->id, $um, 'groups')) { | |
133 | set_field('groups', 'picture', 1, 'id', $data->id); | |
134 | } | |
135 | } | |
136 | ||
137 | return $result; | |
138 | } | |
139 | ||
f16fa0a3 | 140 | /** |
141 | * Update grouping | |
142 | * @param object $data grouping properties (with magic quotes) | |
143 | * @return boolean success | |
144 | */ | |
145 | function groups_update_grouping($data) { | |
146 | global $CFG; | |
147 | $data->timemodified = time(); | |
148 | $data->name = trim($data->name); | |
149 | return update_record('groupings', $data); | |
150 | } | |
151 | ||
ddff2fa8 | 152 | /** |
153 | * Delete a group best effort, first removing members and links with courses and groupings. | |
154 | * Removes group avatar too. | |
155 | * @param int $groupid The group to delete | |
156 | * @return boolean True if deletion was successful, false otherwise | |
157 | */ | |
158 | function groups_delete_group($groupid) { | |
159 | global $CFG; | |
160 | require_once($CFG->libdir.'/gdlib.php'); | |
161 | ||
162 | if (empty($groupid)) { | |
163 | return false; | |
164 | } | |
165 | ||
166 | //first delete usage in groupings_groups | |
167 | delete_records('groupings_groups', 'groupid', $groupid); | |
168 | //delete members | |
169 | delete_records('groups_members', 'groupid', $groupid); | |
170 | //then imge | |
171 | delete_profile_image($groupid, 'groups'); | |
172 | //group itself last | |
173 | return delete_records('groups', 'id', $groupid); | |
174 | } | |
175 | ||
f16fa0a3 | 176 | /** |
177 | * Delete grouping | |
178 | * @param int $groupingid | |
179 | * @return bool success | |
180 | */ | |
ddff2fa8 | 181 | function groups_delete_grouping($groupingid) { |
182 | if (empty($groupingid)) { | |
183 | return false; | |
184 | ||
185 | } | |
186 | ||
187 | //first delete usage in groupings_groups | |
188 | delete_records('groupings_groups', 'groupingid', $groupingid); | |
189 | // remove the default groupingid from course | |
190 | set_field('course', 'defaultgroupingid', 0, 'defaultgroupingid', $groupingid); | |
191 | // remove the groupingid from all course modules | |
192 | set_field('course_modules', 'groupingid', 0, 'groupingid', $groupingid); | |
193 | //group itself last | |
194 | return delete_records('groupings', 'id', $groupingid); | |
195 | } | |
196 | ||
f16fa0a3 | 197 | /** |
198 | * Remove all users from group | |
199 | * @param int $courseid | |
200 | * @param bool $showfeedback | |
201 | * @return bool success | |
202 | */ | |
ddff2fa8 | 203 | function groups_delete_group_members($courseid, $showfeedback=false) { |
204 | global $CFG; | |
205 | ||
206 | $sql = "DELETE FROM {$CFG->prefix}groups_members | |
207 | WHERE groupid in (SELECT id FROM {$CFG->prefix}groups g WHERE g.courseid = $courseid)"; | |
208 | ||
209 | execute_sql($sql, false); | |
210 | if ($showfeedback) { | |
211 | notify(get_string('deleted').' groups_members'); | |
212 | } | |
213 | ||
214 | return true; | |
215 | } | |
216 | ||
f16fa0a3 | 217 | /** |
218 | * Delete all groups from course | |
219 | * @param int $courseid | |
220 | * @param bool $showfeedback | |
221 | * @return bool success | |
222 | */ | |
ddff2fa8 | 223 | function groups_delete_groups($courseid, $showfeedback=false) { |
224 | global $CFG; | |
225 | require_once($CFG->libdir.'/gdlib.php'); | |
226 | ||
227 | // delete any uses of groups | |
228 | $sql = "DELETE FROM {$CFG->prefix}groupings_groups | |
229 | WHERE groupid in (SELECT id FROM {$CFG->prefix}groups g WHERE g.courseid = $courseid)"; | |
230 | execute_sql($sql, false); | |
231 | ||
232 | groups_delete_group_members($courseid, false); | |
233 | ||
234 | // delete group pictures | |
235 | if ($groups = get_records('groups', 'courseid', $courseid)) { | |
236 | foreach($groups as $group) { | |
237 | delete_profile_image($group->id, 'groups'); | |
238 | } | |
239 | } | |
240 | ||
241 | delete_records('groups', 'courseid', $courseid); | |
242 | if ($showfeedback) { | |
243 | notify(get_string('deleted').' groups'); | |
244 | } | |
245 | ||
246 | return true; | |
247 | } | |
248 | ||
f16fa0a3 | 249 | /** |
250 | * Delete all groupings from course | |
251 | * @param int $courseid | |
252 | * @param bool $showfeedback | |
253 | * @return bool success | |
254 | */ | |
ddff2fa8 | 255 | function groups_delete_groupings($courseid, $showfeedback=false) { |
256 | global $CFG; | |
257 | ||
258 | // delete any uses of groupings | |
259 | $sql = "DELETE FROM {$CFG->prefix}groupings_groups | |
260 | WHERE groupingid in (SELECT id FROM {$CFG->prefix}groupings g WHERE g.courseid = $courseid)"; | |
261 | execute_sql($sql, false); | |
262 | ||
263 | // remove the default groupingid from course | |
264 | set_field('course', 'defaultgroupingid', 0, 'id', $courseid); | |
265 | // remove the groupingid from all course modules | |
5f5faac0 | 266 | set_field('course_modules', 'groupingid', 0, 'course', $courseid); |
ddff2fa8 | 267 | |
268 | delete_records('groupings', 'courseid', $courseid); | |
269 | if ($showfeedback) { | |
270 | notify(get_string('deleted').' groupings'); | |
271 | } | |
272 | ||
273 | return true; | |
274 | } | |
275 | ||
276 | /* =================================== */ | |
277 | /* various functions used by groups UI */ | |
278 | /* =================================== */ | |
279 | ||
280 | /** | |
281 | * Gets the users for a course who are not in a specified group | |
282 | * @param int $groupid The id of the group | |
283 | * @param string searchtext similar to searchtext in role assign, search | |
284 | * @return array An array of the userids of the non-group members, or false if | |
285 | * an error occurred. | |
286 | * This function was changed to get_users_by_capability style | |
287 | * mostly because of the searchtext requirement | |
288 | */ | |
289 | function groups_get_users_not_in_group($courseid, $groupid, $searchtext='') { | |
290 | ||
291 | global $CFG; | |
292 | ||
293 | $context = get_context_instance(CONTEXT_COURSE, $courseid); | |
294 | ||
295 | if ($searchtext !== '') { // Search for a subset of remaining users | |
296 | $LIKE = sql_ilike(); | |
297 | $FULLNAME = sql_fullname(); | |
298 | $wheresearch = " AND u.id IN (SELECT id FROM {$CFG->prefix}user WHERE $FULLNAME $LIKE '%$searchtext%' OR email $LIKE '%$searchtext%' )"; | |
299 | } else { | |
300 | $wheresearch = ''; | |
301 | } | |
302 | ||
303 | $capability = 'moodle/course:view'; | |
304 | $doanything = false; | |
f3f7610c | 305 | |
ddff2fa8 | 306 | // find all possible "student" roles |
307 | if ($possibleroles = get_roles_with_capability($capability, CAP_ALLOW, $context)) { | |
308 | if (!$doanything) { | |
309 | if (!$sitecontext = get_context_instance(CONTEXT_SYSTEM)) { | |
310 | return false; // Something is seriously wrong | |
311 | } | |
312 | $doanythingroles = get_roles_with_capability('moodle/site:doanything', CAP_ALLOW, $sitecontext); | |
313 | } | |
f3f7610c | 314 | |
ddff2fa8 | 315 | $validroleids = array(); |
316 | foreach ($possibleroles as $possiblerole) { | |
317 | if (!$doanything) { | |
318 | if (isset($doanythingroles[$possiblerole->id])) { // We don't want these included | |
319 | continue; | |
320 | } | |
321 | } | |
322 | if ($caps = role_context_capabilities($possiblerole->id, $context, $capability)) { // resolved list | |
323 | if (isset($caps[$capability]) && $caps[$capability] > 0) { // resolved capability > 0 | |
324 | $validroleids[] = $possiblerole->id; | |
325 | } | |
326 | } | |
327 | } | |
328 | if (empty($validroleids)) { | |
329 | return false; | |
330 | } | |
331 | $roleids = '('.implode(',', $validroleids).')'; | |
332 | } else { | |
333 | return false; // No need to continue, since no roles have this capability set | |
334 | } | |
f3f7610c | 335 | |
ddff2fa8 | 336 | /// Construct the main SQL |
337 | $select = " SELECT u.id, u.firstname, u.lastname"; | |
338 | $from = " FROM {$CFG->prefix}user u | |
339 | INNER JOIN {$CFG->prefix}role_assignments ra ON ra.userid = u.id | |
340 | INNER JOIN {$CFG->prefix}role r ON r.id = ra.roleid"; | |
f16fa0a3 | 341 | |
ddff2fa8 | 342 | $where = " WHERE ra.contextid ".get_related_contexts_string($context)." |
343 | AND u.deleted = 0 | |
344 | AND ra.roleid in $roleids | |
345 | AND u.id NOT IN (SELECT userid | |
346 | FROM {$CFG->prefix}groups_members | |
347 | WHERE groupid = $groupid) | |
348 | $wheresearch"; | |
acf000b0 | 349 | $groupby = " GROUP BY u.id, u.firstname, u.lastname "; |
f16fa0a3 | 350 | |
acf000b0 | 351 | return get_records_sql($select.$from.$where.$groupby); |
352 | } | |
353 | ||
354 | ||
355 | /** | |
356 | * Gets potential group members for grouping | |
357 | * @param int $courseid The id of the course | |
358 | * @param int $roleid The role to select users from | |
359 | * @param string $orderby The colum to sort users by | |
360 | * @return array An array of the users | |
361 | */ | |
f16fa0a3 | 362 | function groups_get_potential_members($courseid, $roleid = null, $orderby = 'lastname,firstname') { |
acf000b0 | 363 | global $CFG; |
f16fa0a3 | 364 | |
acf000b0 | 365 | $context = get_context_instance(CONTEXT_COURSE, $courseid); |
366 | $sitecontext = get_context_instance(CONTEXT_SYSTEM); | |
367 | $rolenames = array(); | |
368 | $avoidroles = array(); | |
369 | ||
370 | if ($roles = get_roles_used_in_context($context, true)) { | |
371 | ||
372 | $canviewroles = get_roles_with_capability('moodle/course:view', CAP_ALLOW, $context); | |
373 | $doanythingroles = get_roles_with_capability('moodle/site:doanything', CAP_ALLOW, $sitecontext); | |
374 | ||
375 | foreach ($roles as $role) { | |
376 | if (!isset($canviewroles[$role->id])) { // Avoid this role (eg course creator) | |
377 | $avoidroles[] = $role->id; | |
378 | unset($roles[$role->id]); | |
379 | continue; | |
380 | } | |
381 | if (isset($doanythingroles[$role->id])) { // Avoid this role (ie admin) | |
382 | $avoidroles[] = $role->id; | |
383 | unset($roles[$role->id]); | |
384 | continue; | |
385 | } | |
386 | $rolenames[$role->id] = strip_tags(role_get_name($role, $context)); // Used in menus etc later on | |
387 | } | |
388 | } | |
f16fa0a3 | 389 | |
acf000b0 | 390 | $select = 'SELECT u.id, u.username, u.firstname, u.lastname, u.idnumber '; |
391 | $from = "FROM {$CFG->prefix}user u INNER JOIN | |
392 | {$CFG->prefix}role_assignments r on u.id=r.userid "; | |
393 | ||
394 | if ($avoidroles) { | |
395 | $adminroles = 'AND r.roleid NOT IN ('; | |
396 | $adminroles .= implode(',', $avoidroles); | |
397 | $adminroles .= ')'; | |
398 | } else { | |
399 | $adminroles = ''; | |
400 | } | |
401 | ||
402 | // we are looking for all users with this role assigned in this context or higher | |
403 | if ($usercontexts = get_parent_contexts($context)) { | |
404 | $listofcontexts = '('.implode(',', $usercontexts).')'; | |
405 | } else { | |
406 | $listofcontexts = '('.$sitecontext->id.')'; // must be site | |
407 | } | |
f16fa0a3 | 408 | |
acf000b0 | 409 | if ($roleid) { |
410 | $selectrole = " AND r.roleid = $roleid "; | |
411 | } else { | |
412 | $selectrole = " "; | |
413 | } | |
f16fa0a3 | 414 | |
acf000b0 | 415 | $where = "WHERE (r.contextid = $context->id OR r.contextid in $listofcontexts) |
f16fa0a3 | 416 | AND u.deleted = 0 $selectrole |
417 | AND u.username != 'guest' | |
418 | $adminroles "; | |
acf000b0 | 419 | $order = "ORDER BY $orderby "; |
f16fa0a3 | 420 | |
acf000b0 | 421 | return(get_records_sql($select.$from.$where.$order)); |
f16fa0a3 | 422 | |
acf000b0 | 423 | } |
f3f7610c | 424 | |
acf000b0 | 425 | /** |
426 | * Parse a group name for characters to replace | |
427 | * @param string $format The format a group name will follow | |
428 | * @param int $groupnumber The number of the group to be used in the parsed format string | |
429 | * @return string the parsed format string | |
430 | */ | |
431 | function groups_parse_name($format, $groupnumber) { | |
acf000b0 | 432 | if (strstr($format, '@') !== false) { // Convert $groupnumber to a character series |
f16fa0a3 | 433 | $letter = 'A'; |
434 | for($i=0; $i<$groupnumber; $i++) { | |
435 | $letter++; | |
acf000b0 | 436 | } |
f16fa0a3 | 437 | $str = str_replace('@', $letter, $format); |
acf000b0 | 438 | } else { |
f16fa0a3 | 439 | $str = str_replace('#', $groupnumber+1, $format); |
acf000b0 | 440 | } |
441 | return($str); | |
ddff2fa8 | 442 | } |
f3f7610c | 443 | |
f16fa0a3 | 444 | /** |
445 | * Assigns group into grouping | |
446 | * @param int groupingid | |
447 | * @param int groupid | |
448 | * @return bool success | |
449 | */ | |
450 | function groups_assign_grouping($groupingid, $groupid) { | |
451 | if (record_exists('groupings_groups', 'groupingid', $groupingid, 'groupid', $groupid)) { | |
452 | return true; | |
453 | } | |
454 | $assign = new object(); | |
455 | $assign->groupingid = $groupingid; | |
456 | $assign->groupid = $groupid; | |
457 | $assign->timeadded = time(); | |
458 | return (bool)insert_record('groupings_groups', $assign); | |
459 | } | |
460 | ||
461 | /** | |
462 | * Unassigns group grom grouping | |
463 | * @param int groupingid | |
464 | * @param int groupid | |
465 | * @return bool success | |
466 | */ | |
467 | function groups_unassign_grouping($groupingid, $groupid) { | |
468 | return delete_records('groupings_groups', 'groupingid', $groupingid, 'groupid', $groupid); | |
469 | } | |
470 | ||
429e531e | 471 | ?> |