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 | |
20 | * @return boolean True if user added successfully or the user is already a | |
21 | * member of the group, false otherwise. | |
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; | |
48 | events_trigger('group_user_added', $eventdata); | |
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; | |
70 | } | |
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 | |
79 | * @param object $data group properties (with magic quotes); | |
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; | |
89 | $id = insert_record('groups', $data); | |
90 | ||
91 | if ($id and $um) { | |
92 | //update image | |
93 | if (save_profile_image($id, $um, 'groups')) { | |
94 | set_field('groups', 'picture', 1, 'id', $id); | |
95 | } | |
96 | } | |
97 | ||
98 | return $id; | |
99 | } | |
100 | ||
101 | /** | |
102 | * Add a new group | |
103 | * @param object $data group properties (with magic quotes); | |
104 | * @param object $um upload manager with group picture | |
105 | * @return boolean success | |
106 | */ | |
107 | function groups_update_group($data, $um=false) { | |
108 | global $CFG; | |
109 | require_once("$CFG->libdir/gdlib.php"); | |
110 | ||
111 | $data->timemodified = time(); | |
112 | $result = update_record('groups', $data); | |
113 | ||
114 | if ($result and $um) { | |
115 | //update image | |
116 | if (save_profile_image($data->id, $um, 'groups')) { | |
117 | set_field('groups', 'picture', 1, 'id', $data->id); | |
118 | } | |
119 | } | |
120 | ||
121 | return $result; | |
122 | } | |
123 | ||
124 | /** | |
125 | * Delete a group best effort, first removing members and links with courses and groupings. | |
126 | * Removes group avatar too. | |
127 | * @param int $groupid The group to delete | |
128 | * @return boolean True if deletion was successful, false otherwise | |
129 | */ | |
130 | function groups_delete_group($groupid) { | |
131 | global $CFG; | |
132 | require_once($CFG->libdir.'/gdlib.php'); | |
133 | ||
134 | if (empty($groupid)) { | |
135 | return false; | |
136 | } | |
137 | ||
138 | //first delete usage in groupings_groups | |
139 | delete_records('groupings_groups', 'groupid', $groupid); | |
140 | //delete members | |
141 | delete_records('groups_members', 'groupid', $groupid); | |
142 | //then imge | |
143 | delete_profile_image($groupid, 'groups'); | |
144 | //group itself last | |
145 | return delete_records('groups', 'id', $groupid); | |
146 | } | |
147 | ||
148 | function groups_delete_grouping($groupingid) { | |
149 | if (empty($groupingid)) { | |
150 | return false; | |
151 | ||
152 | } | |
153 | ||
154 | //first delete usage in groupings_groups | |
155 | delete_records('groupings_groups', 'groupingid', $groupingid); | |
156 | // remove the default groupingid from course | |
157 | set_field('course', 'defaultgroupingid', 0, 'defaultgroupingid', $groupingid); | |
158 | // remove the groupingid from all course modules | |
159 | set_field('course_modules', 'groupingid', 0, 'groupingid', $groupingid); | |
160 | //group itself last | |
161 | return delete_records('groupings', 'id', $groupingid); | |
162 | } | |
163 | ||
164 | function groups_delete_group_members($courseid, $showfeedback=false) { | |
165 | global $CFG; | |
166 | ||
167 | $sql = "DELETE FROM {$CFG->prefix}groups_members | |
168 | WHERE groupid in (SELECT id FROM {$CFG->prefix}groups g WHERE g.courseid = $courseid)"; | |
169 | ||
170 | execute_sql($sql, false); | |
171 | if ($showfeedback) { | |
172 | notify(get_string('deleted').' groups_members'); | |
173 | } | |
174 | ||
175 | return true; | |
176 | } | |
177 | ||
178 | function groups_delete_groups($courseid, $showfeedback=false) { | |
179 | global $CFG; | |
180 | require_once($CFG->libdir.'/gdlib.php'); | |
181 | ||
182 | // delete any uses of groups | |
183 | $sql = "DELETE FROM {$CFG->prefix}groupings_groups | |
184 | WHERE groupid in (SELECT id FROM {$CFG->prefix}groups g WHERE g.courseid = $courseid)"; | |
185 | execute_sql($sql, false); | |
186 | ||
187 | groups_delete_group_members($courseid, false); | |
188 | ||
189 | // delete group pictures | |
190 | if ($groups = get_records('groups', 'courseid', $courseid)) { | |
191 | foreach($groups as $group) { | |
192 | delete_profile_image($group->id, 'groups'); | |
193 | } | |
194 | } | |
195 | ||
196 | delete_records('groups', 'courseid', $courseid); | |
197 | if ($showfeedback) { | |
198 | notify(get_string('deleted').' groups'); | |
199 | } | |
200 | ||
201 | return true; | |
202 | } | |
203 | ||
204 | function groups_delete_groupings($courseid, $showfeedback=false) { | |
205 | global $CFG; | |
206 | ||
207 | // delete any uses of groupings | |
208 | $sql = "DELETE FROM {$CFG->prefix}groupings_groups | |
209 | WHERE groupingid in (SELECT id FROM {$CFG->prefix}groupings g WHERE g.courseid = $courseid)"; | |
210 | execute_sql($sql, false); | |
211 | ||
212 | // remove the default groupingid from course | |
213 | set_field('course', 'defaultgroupingid', 0, 'id', $courseid); | |
214 | // remove the groupingid from all course modules | |
5f5faac0 | 215 | set_field('course_modules', 'groupingid', 0, 'course', $courseid); |
ddff2fa8 | 216 | |
217 | delete_records('groupings', 'courseid', $courseid); | |
218 | if ($showfeedback) { | |
219 | notify(get_string('deleted').' groupings'); | |
220 | } | |
221 | ||
222 | return true; | |
223 | } | |
224 | ||
225 | /* =================================== */ | |
226 | /* various functions used by groups UI */ | |
227 | /* =================================== */ | |
228 | ||
229 | /** | |
230 | * Gets the users for a course who are not in a specified group | |
231 | * @param int $groupid The id of the group | |
232 | * @param string searchtext similar to searchtext in role assign, search | |
233 | * @return array An array of the userids of the non-group members, or false if | |
234 | * an error occurred. | |
235 | * This function was changed to get_users_by_capability style | |
236 | * mostly because of the searchtext requirement | |
237 | */ | |
238 | function groups_get_users_not_in_group($courseid, $groupid, $searchtext='') { | |
239 | ||
240 | global $CFG; | |
241 | ||
242 | $context = get_context_instance(CONTEXT_COURSE, $courseid); | |
243 | ||
244 | if ($searchtext !== '') { // Search for a subset of remaining users | |
245 | $LIKE = sql_ilike(); | |
246 | $FULLNAME = sql_fullname(); | |
247 | $wheresearch = " AND u.id IN (SELECT id FROM {$CFG->prefix}user WHERE $FULLNAME $LIKE '%$searchtext%' OR email $LIKE '%$searchtext%' )"; | |
248 | } else { | |
249 | $wheresearch = ''; | |
250 | } | |
251 | ||
252 | $capability = 'moodle/course:view'; | |
253 | $doanything = false; | |
f3f7610c | 254 | |
ddff2fa8 | 255 | // find all possible "student" roles |
256 | if ($possibleroles = get_roles_with_capability($capability, CAP_ALLOW, $context)) { | |
257 | if (!$doanything) { | |
258 | if (!$sitecontext = get_context_instance(CONTEXT_SYSTEM)) { | |
259 | return false; // Something is seriously wrong | |
260 | } | |
261 | $doanythingroles = get_roles_with_capability('moodle/site:doanything', CAP_ALLOW, $sitecontext); | |
262 | } | |
f3f7610c | 263 | |
ddff2fa8 | 264 | $validroleids = array(); |
265 | foreach ($possibleroles as $possiblerole) { | |
266 | if (!$doanything) { | |
267 | if (isset($doanythingroles[$possiblerole->id])) { // We don't want these included | |
268 | continue; | |
269 | } | |
270 | } | |
271 | if ($caps = role_context_capabilities($possiblerole->id, $context, $capability)) { // resolved list | |
272 | if (isset($caps[$capability]) && $caps[$capability] > 0) { // resolved capability > 0 | |
273 | $validroleids[] = $possiblerole->id; | |
274 | } | |
275 | } | |
276 | } | |
277 | if (empty($validroleids)) { | |
278 | return false; | |
279 | } | |
280 | $roleids = '('.implode(',', $validroleids).')'; | |
281 | } else { | |
282 | return false; // No need to continue, since no roles have this capability set | |
283 | } | |
f3f7610c | 284 | |
ddff2fa8 | 285 | /// Construct the main SQL |
286 | $select = " SELECT u.id, u.firstname, u.lastname"; | |
287 | $from = " FROM {$CFG->prefix}user u | |
288 | INNER JOIN {$CFG->prefix}role_assignments ra ON ra.userid = u.id | |
289 | INNER JOIN {$CFG->prefix}role r ON r.id = ra.roleid"; | |
acf000b0 | 290 | |
ddff2fa8 | 291 | $where = " WHERE ra.contextid ".get_related_contexts_string($context)." |
292 | AND u.deleted = 0 | |
293 | AND ra.roleid in $roleids | |
294 | AND u.id NOT IN (SELECT userid | |
295 | FROM {$CFG->prefix}groups_members | |
296 | WHERE groupid = $groupid) | |
297 | $wheresearch"; | |
acf000b0 | 298 | $groupby = " GROUP BY u.id, u.firstname, u.lastname "; |
299 | ||
300 | return get_records_sql($select.$from.$where.$groupby); | |
301 | } | |
302 | ||
303 | ||
304 | /** | |
305 | * Gets potential group members for grouping | |
306 | * @param int $courseid The id of the course | |
307 | * @param int $roleid The role to select users from | |
308 | * @param string $orderby The colum to sort users by | |
309 | * @return array An array of the users | |
310 | */ | |
311 | function groups_get_potental_members($courseid, $roleid = null, $orderby = 'lastname') { | |
312 | global $CFG; | |
313 | ||
314 | $context = get_context_instance(CONTEXT_COURSE, $courseid); | |
315 | $sitecontext = get_context_instance(CONTEXT_SYSTEM); | |
316 | $rolenames = array(); | |
317 | $avoidroles = array(); | |
318 | ||
319 | if ($roles = get_roles_used_in_context($context, true)) { | |
320 | ||
321 | $canviewroles = get_roles_with_capability('moodle/course:view', CAP_ALLOW, $context); | |
322 | $doanythingroles = get_roles_with_capability('moodle/site:doanything', CAP_ALLOW, $sitecontext); | |
323 | ||
324 | foreach ($roles as $role) { | |
325 | if (!isset($canviewroles[$role->id])) { // Avoid this role (eg course creator) | |
326 | $avoidroles[] = $role->id; | |
327 | unset($roles[$role->id]); | |
328 | continue; | |
329 | } | |
330 | if (isset($doanythingroles[$role->id])) { // Avoid this role (ie admin) | |
331 | $avoidroles[] = $role->id; | |
332 | unset($roles[$role->id]); | |
333 | continue; | |
334 | } | |
335 | $rolenames[$role->id] = strip_tags(role_get_name($role, $context)); // Used in menus etc later on | |
336 | } | |
337 | } | |
338 | ||
339 | $select = 'SELECT u.id, u.username, u.firstname, u.lastname, u.idnumber '; | |
340 | $from = "FROM {$CFG->prefix}user u INNER JOIN | |
341 | {$CFG->prefix}role_assignments r on u.id=r.userid "; | |
342 | ||
343 | if ($avoidroles) { | |
344 | $adminroles = 'AND r.roleid NOT IN ('; | |
345 | $adminroles .= implode(',', $avoidroles); | |
346 | $adminroles .= ')'; | |
347 | } else { | |
348 | $adminroles = ''; | |
349 | } | |
350 | ||
351 | // we are looking for all users with this role assigned in this context or higher | |
352 | if ($usercontexts = get_parent_contexts($context)) { | |
353 | $listofcontexts = '('.implode(',', $usercontexts).')'; | |
354 | } else { | |
355 | $listofcontexts = '('.$sitecontext->id.')'; // must be site | |
356 | } | |
357 | ||
358 | if ($roleid) { | |
359 | $selectrole = " AND r.roleid = $roleid "; | |
360 | } else { | |
361 | $selectrole = " "; | |
362 | } | |
363 | ||
364 | $where = "WHERE (r.contextid = $context->id OR r.contextid in $listofcontexts) | |
365 | AND u.deleted = 0 $selectrole | |
366 | AND u.username != 'guest' | |
367 | $adminroles | |
368 | "; | |
369 | $order = "ORDER BY $orderby "; | |
370 | ||
371 | return(get_records_sql($select.$from.$where.$order)); | |
372 | ||
373 | } | |
f3f7610c | 374 | |
acf000b0 | 375 | /** |
376 | * Parse a group name for characters to replace | |
377 | * @param string $format The format a group name will follow | |
378 | * @param int $groupnumber The number of the group to be used in the parsed format string | |
379 | * @return string the parsed format string | |
380 | */ | |
381 | function groups_parse_name($format, $groupnumber) { | |
382 | ||
383 | if (strstr($format, '@') !== false) { // Convert $groupnumber to a character series | |
384 | $tmp = $groupnumber; | |
385 | $places = 1; | |
386 | $serial = ''; | |
387 | ||
388 | if ($groupnumber > 25) { | |
389 | while (floor($groupnumber / pow(25, $places)) > 0) { | |
390 | $places++; | |
391 | } | |
392 | ||
393 | } else { | |
394 | $places = 1; | |
395 | } | |
396 | ||
397 | for($i=$places;$i>0;$i--) { | |
398 | if ($i>1) { | |
399 | $serial .= chr(65+floor($tmp/ pow(26, $i))); | |
400 | $tmp -= floor($tmp/ pow(26, $i))*pow(26, $i); | |
401 | } else { | |
402 | $serial .= chr(65+$tmp%26); | |
403 | } | |
404 | } | |
405 | $str = preg_replace('/[@]/', $serial, $format); | |
406 | } else { | |
407 | $str = preg_replace('/[#]/', $groupnumber+1, $format); | |
408 | } | |
409 | return($str); | |
ddff2fa8 | 410 | } |
f3f7610c | 411 | |
429e531e | 412 | ?> |