Commit | Line | Data |
---|---|---|
df997f84 | 1 | <?php |
df997f84 PS |
2 | // This file is part of Moodle - http://moodle.org/ |
3 | // | |
4 | // Moodle is free software: you can redistribute it and/or modify | |
5 | // it under the terms of the GNU General Public License as published by | |
6 | // the Free Software Foundation, either version 3 of the License, or | |
7 | // (at your option) any later version. | |
8 | // | |
9 | // Moodle is distributed in the hope that it will be useful, | |
10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | // GNU General Public License for more details. | |
13 | // | |
14 | // You should have received a copy of the GNU General Public License | |
15 | // along with Moodle. If not, see <http://www.gnu.org/licenses/>. | |
16 | ||
17 | /** | |
18 | * Local stuff for meta course enrolment plugin. | |
19 | * | |
31ac2aef | 20 | * @package enrol_meta |
e2382027 PS |
21 | * @copyright 2010 Petr Skoda {@link http://skodak.org} |
22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later | |
df997f84 PS |
23 | */ |
24 | ||
e2382027 | 25 | defined('MOODLE_INTERNAL') || die(); |
df997f84 | 26 | |
ad68ed74 | 27 | |
df997f84 PS |
28 | /** |
29 | * Event handler for meta enrolment plugin. | |
30 | * | |
31 | * We try to keep everything in sync via listening to events, | |
32 | * it may fail sometimes, so we always do a full sync in cron too. | |
33 | */ | |
34 | class enrol_meta_handler { | |
ad68ed74 PS |
35 | |
36 | /** | |
37 | * Synchronise meta enrolments of this user in this course | |
38 | * @static | |
39 | * @param int $courseid | |
40 | * @param int $userid | |
41 | * @return void | |
42 | */ | |
43 | protected static function sync_course_instances($courseid, $userid) { | |
df997f84 PS |
44 | global $DB; |
45 | ||
ad68ed74 PS |
46 | static $preventrecursion = false; |
47 | ||
48 | // does anything want to sync with this parent? | |
49 | if (!$enrols = $DB->get_records('enrol', array('customint1'=>$courseid, 'enrol'=>'meta'), 'id ASC')) { | |
50 | return; | |
51 | } | |
52 | ||
53 | if ($preventrecursion) { | |
54 | return; | |
55 | } | |
56 | ||
57 | $preventrecursion = true; | |
58 | ||
59 | try { | |
60 | foreach ($enrols as $enrol) { | |
61 | self::sync_with_parent_course($enrol, $userid); | |
62 | } | |
63 | } catch (Exception $e) { | |
64 | $preventrecursion = false; | |
65 | throw $e; | |
66 | } | |
67 | ||
68 | $preventrecursion = false; | |
69 | } | |
70 | ||
71 | /** | |
72 | * Synchronise user enrolments in given instance as fast as possible. | |
73 | * | |
74 | * All roles are removed if the meta plugin disabled. | |
75 | * | |
76 | * @static | |
77 | * @param stdClass $instance | |
78 | * @param int $userid | |
79 | * @return void | |
80 | */ | |
81 | protected static function sync_with_parent_course(stdClass $instance, $userid) { | |
82 | global $DB, $CFG; | |
1165cab2 | 83 | require_once($CFG->dirroot . '/group/lib.php'); |
ad68ed74 PS |
84 | |
85 | $plugin = enrol_get_plugin('meta'); | |
86 | ||
87 | if ($instance->customint1 == $instance->courseid) { | |
88 | // can not sync with self!!! | |
89 | return; | |
90 | } | |
91 | ||
92 | $context = context_course::instance($instance->courseid); | |
93 | ||
ad68ed74 PS |
94 | // list of enrolments in parent course (we ignore meta enrols in parents completely) |
95 | list($enabled, $params) = $DB->get_in_or_equal(explode(',', $CFG->enrol_plugins_enabled), SQL_PARAMS_NAMED, 'e'); | |
96 | $params['userid'] = $userid; | |
97 | $params['parentcourse'] = $instance->customint1; | |
98 | $sql = "SELECT ue.* | |
99 | FROM {user_enrolments} ue | |
100 | JOIN {enrol} e ON (e.id = ue.enrolid AND e.enrol <> 'meta' AND e.courseid = :parentcourse AND e.enrol $enabled) | |
101 | WHERE ue.userid = :userid"; | |
102 | $parentues = $DB->get_records_sql($sql, $params); | |
103 | // current enrolments for this instance | |
104 | $ue = $DB->get_record('user_enrolments', array('enrolid'=>$instance->id, 'userid'=>$userid)); | |
105 | ||
106 | // first deal with users that are not enrolled in parent | |
107 | if (empty($parentues)) { | |
108 | self::user_not_supposed_to_be_here($instance, $ue, $context, $plugin); | |
109 | return; | |
110 | } | |
111 | ||
1344bc78 PS |
112 | if (!$parentcontext = context_course::instance($instance->customint1, IGNORE_MISSING)) { |
113 | // Weird, we should not get here. | |
ad68ed74 | 114 | return; |
df997f84 PS |
115 | } |
116 | ||
ad68ed74 PS |
117 | $skiproles = $plugin->get_config('nosyncroleids', ''); |
118 | $skiproles = empty($skiproles) ? array() : explode(',', $skiproles); | |
119 | $syncall = $plugin->get_config('syncall', 1); | |
120 | ||
121 | // roles in parent course (meta enrols must be ignored!) | |
122 | $parentroles = array(); | |
123 | list($ignoreroles, $params) = $DB->get_in_or_equal($skiproles, SQL_PARAMS_NAMED, 'ri', false, -1); | |
124 | $params['contextid'] = $parentcontext->id; | |
125 | $params['userid'] = $userid; | |
126 | $select = "contextid = :contextid AND userid = :userid AND component <> 'enrol_meta' AND roleid $ignoreroles"; | |
127 | foreach($DB->get_records_select('role_assignments', $select, $params) as $ra) { | |
128 | $parentroles[$ra->roleid] = $ra->roleid; | |
df997f84 PS |
129 | } |
130 | ||
ad68ed74 PS |
131 | // roles from this instance |
132 | $roles = array(); | |
133 | $ras = $DB->get_records('role_assignments', array('contextid'=>$context->id, 'userid'=>$userid, 'component'=>'enrol_meta', 'itemid'=>$instance->id)); | |
134 | foreach($ras as $ra) { | |
135 | $roles[$ra->roleid] = $ra->roleid; | |
df997f84 | 136 | } |
ad68ed74 | 137 | unset($ras); |
df997f84 | 138 | |
ad68ed74 PS |
139 | // do we want users without roles? |
140 | if (!$syncall and empty($parentroles)) { | |
141 | self::user_not_supposed_to_be_here($instance, $ue, $context, $plugin); | |
142 | return; | |
df997f84 PS |
143 | } |
144 | ||
ad68ed74 PS |
145 | // is parent enrol active? (we ignore enrol starts and ends, sorry it would be too complex) |
146 | $parentstatus = ENROL_USER_SUSPENDED; | |
147 | foreach ($parentues as $pue) { | |
148 | if ($pue->status == ENROL_USER_ACTIVE) { | |
149 | $parentstatus = ENROL_USER_ACTIVE; | |
150 | break; | |
df997f84 PS |
151 | } |
152 | } | |
153 | ||
ad68ed74 PS |
154 | // enrol user if not enrolled yet or fix status |
155 | if ($ue) { | |
156 | if ($parentstatus != $ue->status) { | |
157 | $plugin->update_user_enrol($instance, $userid, $parentstatus); | |
158 | $ue->status = $parentstatus; | |
159 | } | |
160 | } else { | |
161 | $plugin->enrol_user($instance, $userid, NULL, 0, 0, $parentstatus); | |
162 | $ue = new stdClass(); | |
163 | $ue->userid = $userid; | |
164 | $ue->enrolid = $instance->id; | |
165 | $ue->status = $parentstatus; | |
9e37d365 MG |
166 | if ($instance->customint2) { |
167 | groups_add_member($instance->customint2, $userid, 'enrol_meta', $instance->id); | |
168 | } | |
ad68ed74 PS |
169 | } |
170 | ||
1344bc78 PS |
171 | $unenrolaction = $plugin->get_config('unenrolaction', ENROL_EXT_REMOVED_SUSPENDNOROLES); |
172 | ||
ad68ed74 PS |
173 | // only active users in enabled instances are supposed to have roles (we can reassign the roles any time later) |
174 | if ($ue->status != ENROL_USER_ACTIVE or $instance->status != ENROL_INSTANCE_ENABLED) { | |
1344bc78 PS |
175 | if ($unenrolaction == ENROL_EXT_REMOVED_SUSPEND) { |
176 | // Always keep the roles. | |
177 | } else if ($roles) { | |
ad68ed74 | 178 | role_unassign_all(array('userid'=>$userid, 'contextid'=>$context->id, 'component'=>'enrol_meta', 'itemid'=>$instance->id)); |
df997f84 | 179 | } |
ad68ed74 PS |
180 | return; |
181 | } | |
df997f84 | 182 | |
ad68ed74 PS |
183 | // add new roles |
184 | foreach ($parentroles as $rid) { | |
185 | if (!isset($roles[$rid])) { | |
186 | role_assign($rid, $userid, $context->id, 'enrol_meta', $instance->id); | |
187 | } | |
df997f84 PS |
188 | } |
189 | ||
1344bc78 PS |
190 | if ($unenrolaction == ENROL_EXT_REMOVED_SUSPEND) { |
191 | // Always keep the roles. | |
192 | return; | |
193 | } | |
194 | ||
ad68ed74 PS |
195 | // remove roles |
196 | foreach ($roles as $rid) { | |
197 | if (!isset($parentroles[$rid])) { | |
198 | role_unassign($rid, $userid, $context->id, 'enrol_meta', $instance->id); | |
199 | } | |
200 | } | |
df997f84 PS |
201 | } |
202 | ||
ad68ed74 PS |
203 | /** |
204 | * Deal with users that are not supposed to be enrolled via this instance | |
205 | * @static | |
206 | * @param stdClass $instance | |
207 | * @param stdClass $ue | |
208 | * @param context_course $context | |
209 | * @param enrol_meta $plugin | |
210 | * @return void | |
211 | */ | |
212 | protected static function user_not_supposed_to_be_here($instance, $ue, context_course $context, $plugin) { | |
213 | if (!$ue) { | |
1344bc78 | 214 | // Not enrolled yet - simple! |
ad68ed74 PS |
215 | return; |
216 | } | |
217 | ||
218 | $userid = $ue->userid; | |
1344bc78 | 219 | $unenrolaction = $plugin->get_config('unenrolaction', ENROL_EXT_REMOVED_SUSPENDNOROLES); |
ad68ed74 PS |
220 | |
221 | if ($unenrolaction == ENROL_EXT_REMOVED_UNENROL) { | |
1344bc78 | 222 | // Purges grades, group membership, preferences, etc. - admins were warned! |
ad68ed74 | 223 | $plugin->unenrol_user($instance, $userid); |
ad68ed74 | 224 | |
1344bc78 | 225 | } else if ($unenrolaction == ENROL_EXT_REMOVED_SUSPEND) { |
ad68ed74 PS |
226 | if ($ue->status != ENROL_USER_SUSPENDED) { |
227 | $plugin->update_user_enrol($instance, $userid, ENROL_USER_SUSPENDED); | |
ad68ed74 | 228 | } |
1344bc78 PS |
229 | |
230 | } else if ($unenrolaction == ENROL_EXT_REMOVED_SUSPENDNOROLES) { | |
231 | if ($ue->status != ENROL_USER_SUSPENDED) { | |
232 | $plugin->update_user_enrol($instance, $userid, ENROL_USER_SUSPENDED); | |
233 | } | |
234 | role_unassign_all(array('userid'=>$userid, 'contextid'=>$context->id, 'component'=>'enrol_meta', 'itemid'=>$instance->id)); | |
235 | ||
236 | } else { | |
237 | debugging('Unknown unenrol action '.$unenrolaction); | |
ad68ed74 PS |
238 | } |
239 | } | |
df997f84 PS |
240 | } |
241 | ||
242 | /** | |
243 | * Sync all meta course links. | |
ad68ed74 | 244 | * |
df997f84 | 245 | * @param int $courseid one course, empty mean all |
ad68ed74 PS |
246 | * @param bool $verbose verbose CLI output |
247 | * @return int 0 means ok, 1 means error, 2 means plugin disabled | |
df997f84 | 248 | */ |
ad68ed74 | 249 | function enrol_meta_sync($courseid = NULL, $verbose = false) { |
df997f84 | 250 | global $CFG, $DB; |
98177a45 | 251 | require_once("{$CFG->dirroot}/group/lib.php"); |
df997f84 | 252 | |
ad68ed74 PS |
253 | // purge all roles if meta sync disabled, those can be recreated later here in cron |
254 | if (!enrol_is_enabled('meta')) { | |
255 | if ($verbose) { | |
256 | mtrace('Meta sync plugin is disabled, unassigning all plugin roles and stopping.'); | |
257 | } | |
258 | role_unassign_all(array('component'=>'enrol_meta')); | |
259 | return 2; | |
260 | } | |
261 | ||
262 | // unfortunately this may take a long time, execution can be interrupted safely | |
3ef7279f | 263 | core_php_time_limit::raise(); |
ad68ed74 | 264 | raise_memory_limit(MEMORY_HUGE); |
df997f84 | 265 | |
ad68ed74 PS |
266 | if ($verbose) { |
267 | mtrace('Starting user enrolment synchronisation...'); | |
268 | } | |
269 | ||
270 | $instances = array(); // cache instances | |
379434e4 | 271 | |
df997f84 PS |
272 | $meta = enrol_get_plugin('meta'); |
273 | ||
1344bc78 | 274 | $unenrolaction = $meta->get_config('unenrolaction', ENROL_EXT_REMOVED_SUSPENDNOROLES); |
ad68ed74 PS |
275 | $skiproles = $meta->get_config('nosyncroleids', ''); |
276 | $skiproles = empty($skiproles) ? array() : explode(',', $skiproles); | |
277 | $syncall = $meta->get_config('syncall', 1); | |
278 | ||
279 | $allroles = get_all_roles(); | |
280 | ||
df997f84 PS |
281 | |
282 | // iterate through all not enrolled yet users | |
ad68ed74 PS |
283 | $onecourse = $courseid ? "AND e.courseid = :courseid" : ""; |
284 | list($enabled, $params) = $DB->get_in_or_equal(explode(',', $CFG->enrol_plugins_enabled), SQL_PARAMS_NAMED, 'e'); | |
285 | $params['courseid'] = $courseid; | |
286 | $sql = "SELECT pue.userid, e.id AS enrolid, pue.status | |
287 | FROM {user_enrolments} pue | |
288 | JOIN {enrol} pe ON (pe.id = pue.enrolid AND pe.enrol <> 'meta' AND pe.enrol $enabled) | |
289 | JOIN {enrol} e ON (e.customint1 = pe.courseid AND e.enrol = 'meta' $onecourse) | |
f3bd4ea6 | 290 | JOIN {user} u ON (u.id = pue.userid AND u.deleted = 0) |
ad68ed74 PS |
291 | LEFT JOIN {user_enrolments} ue ON (ue.enrolid = e.id AND ue.userid = pue.userid) |
292 | WHERE ue.id IS NULL"; | |
293 | ||
294 | $rs = $DB->get_recordset_sql($sql, $params); | |
295 | foreach($rs as $ue) { | |
296 | if (!isset($instances[$ue->enrolid])) { | |
297 | $instances[$ue->enrolid] = $DB->get_record('enrol', array('id'=>$ue->enrolid)); | |
df997f84 | 298 | } |
ad68ed74 PS |
299 | $instance = $instances[$ue->enrolid]; |
300 | ||
301 | if (!$syncall) { | |
302 | // this may be slow if very many users are ignored in sync | |
303 | $parentcontext = context_course::instance($instance->customint1); | |
304 | list($ignoreroles, $params) = $DB->get_in_or_equal($skiproles, SQL_PARAMS_NAMED, 'ri', false, -1); | |
305 | $params['contextid'] = $parentcontext->id; | |
306 | $params['userid'] = $ue->userid; | |
307 | $select = "contextid = :contextid AND userid = :userid AND component <> 'enrol_meta' AND roleid $ignoreroles"; | |
308 | if (!$DB->record_exists_select('role_assignments', $select, $params)) { | |
309 | // bad luck, this user does not have any role we want in parent course | |
310 | if ($verbose) { | |
311 | mtrace(" skipping enrolling: $ue->userid ==> $instance->courseid (user without role)"); | |
312 | } | |
313 | continue; | |
df997f84 | 314 | } |
df997f84 | 315 | } |
ad68ed74 | 316 | |
f06d8d94 | 317 | $meta->enrol_user($instance, $ue->userid, null, 0, 0, $ue->status); |
9e37d365 MG |
318 | if ($instance->customint2) { |
319 | groups_add_member($instance->customint2, $ue->userid, 'enrol_meta', $instance->id); | |
320 | } | |
ad68ed74 PS |
321 | if ($verbose) { |
322 | mtrace(" enrolling: $ue->userid ==> $instance->courseid"); | |
323 | } | |
df997f84 | 324 | } |
ad68ed74 PS |
325 | $rs->close(); |
326 | ||
df997f84 | 327 | |
ad68ed74 PS |
328 | // unenrol as necessary - ignore enabled flag, we want to get rid of existing enrols in any case |
329 | $onecourse = $courseid ? "AND e.courseid = :courseid" : ""; | |
330 | list($enabled, $params) = $DB->get_in_or_equal(explode(',', $CFG->enrol_plugins_enabled), SQL_PARAMS_NAMED, 'e'); | |
331 | $params['courseid'] = $courseid; | |
332 | $sql = "SELECT ue.* | |
df997f84 PS |
333 | FROM {user_enrolments} ue |
334 | JOIN {enrol} e ON (e.id = ue.enrolid AND e.enrol = 'meta' $onecourse) | |
26a06fa7 | 335 | LEFT JOIN ({user_enrolments} xpue |
ad68ed74 | 336 | JOIN {enrol} xpe ON (xpe.id = xpue.enrolid AND xpe.enrol <> 'meta' AND xpe.enrol $enabled) |
26a06fa7 MA |
337 | ) ON (xpe.courseid = e.customint1 AND xpue.userid = ue.userid) |
338 | WHERE xpue.userid IS NULL"; | |
ad68ed74 | 339 | $rs = $DB->get_recordset_sql($sql, $params); |
df997f84 PS |
340 | foreach($rs as $ue) { |
341 | if (!isset($instances[$ue->enrolid])) { | |
342 | $instances[$ue->enrolid] = $DB->get_record('enrol', array('id'=>$ue->enrolid)); | |
343 | } | |
ad68ed74 PS |
344 | $instance = $instances[$ue->enrolid]; |
345 | ||
346 | if ($unenrolaction == ENROL_EXT_REMOVED_UNENROL) { | |
347 | $meta->unenrol_user($instance, $ue->userid); | |
348 | if ($verbose) { | |
349 | mtrace(" unenrolling: $ue->userid ==> $instance->courseid"); | |
350 | } | |
ad68ed74 | 351 | |
1344bc78 PS |
352 | } else if ($unenrolaction == ENROL_EXT_REMOVED_SUSPEND) { |
353 | if ($ue->status != ENROL_USER_SUSPENDED) { | |
354 | $meta->update_user_enrol($instance, $ue->userid, ENROL_USER_SUSPENDED); | |
355 | if ($verbose) { | |
356 | mtrace(" suspending: $ue->userid ==> $instance->courseid"); | |
357 | } | |
358 | } | |
359 | ||
360 | } else if ($unenrolaction == ENROL_EXT_REMOVED_SUSPENDNOROLES) { | |
ad68ed74 PS |
361 | if ($ue->status != ENROL_USER_SUSPENDED) { |
362 | $meta->update_user_enrol($instance, $ue->userid, ENROL_USER_SUSPENDED); | |
363 | $context = context_course::instance($instance->courseid); | |
1344bc78 | 364 | role_unassign_all(array('userid'=>$ue->userid, 'contextid'=>$context->id, 'component'=>'enrol_meta', 'itemid'=>$instance->id)); |
ad68ed74 PS |
365 | if ($verbose) { |
366 | mtrace(" suspending and removing all roles: $ue->userid ==> $instance->courseid"); | |
367 | } | |
368 | } | |
ad68ed74 | 369 | } |
df997f84 PS |
370 | } |
371 | $rs->close(); | |
df997f84 | 372 | |
ad68ed74 PS |
373 | |
374 | // update status - meta enrols + start and end dates are ignored, sorry | |
375 | // note the trick here is that the active enrolment and instance constants have value 0 | |
376 | $onecourse = $courseid ? "AND e.courseid = :courseid" : ""; | |
377 | list($enabled, $params) = $DB->get_in_or_equal(explode(',', $CFG->enrol_plugins_enabled), SQL_PARAMS_NAMED, 'e'); | |
378 | $params['courseid'] = $courseid; | |
379 | $sql = "SELECT ue.userid, ue.enrolid, pue.pstatus | |
380 | FROM {user_enrolments} ue | |
381 | JOIN {enrol} e ON (e.id = ue.enrolid AND e.enrol = 'meta' $onecourse) | |
382 | JOIN (SELECT xpue.userid, xpe.courseid, MIN(xpue.status + xpe.status) AS pstatus | |
383 | FROM {user_enrolments} xpue | |
384 | JOIN {enrol} xpe ON (xpe.id = xpue.enrolid AND xpe.enrol <> 'meta' AND xpe.enrol $enabled) | |
385 | GROUP BY xpue.userid, xpe.courseid | |
386 | ) pue ON (pue.courseid = e.customint1 AND pue.userid = ue.userid) | |
387 | WHERE (pue.pstatus = 0 AND ue.status > 0) OR (pue.pstatus > 0 and ue.status = 0)"; | |
388 | $rs = $DB->get_recordset_sql($sql, $params); | |
389 | foreach($rs as $ue) { | |
390 | if (!isset($instances[$ue->enrolid])) { | |
391 | $instances[$ue->enrolid] = $DB->get_record('enrol', array('id'=>$ue->enrolid)); | |
392 | } | |
393 | $instance = $instances[$ue->enrolid]; | |
394 | $ue->pstatus = ($ue->pstatus == ENROL_USER_ACTIVE) ? ENROL_USER_ACTIVE : ENROL_USER_SUSPENDED; | |
395 | ||
396 | if ($ue->pstatus == ENROL_USER_ACTIVE and !$syncall and $unenrolaction != ENROL_EXT_REMOVED_UNENROL) { | |
397 | // this may be slow if very many users are ignored in sync | |
398 | $parentcontext = context_course::instance($instance->customint1); | |
399 | list($ignoreroles, $params) = $DB->get_in_or_equal($skiproles, SQL_PARAMS_NAMED, 'ri', false, -1); | |
400 | $params['contextid'] = $parentcontext->id; | |
401 | $params['userid'] = $ue->userid; | |
402 | $select = "contextid = :contextid AND userid = :userid AND component <> 'enrol_meta' AND roleid $ignoreroles"; | |
403 | if (!$DB->record_exists_select('role_assignments', $select, $params)) { | |
404 | // bad luck, this user does not have any role we want in parent course | |
405 | if ($verbose) { | |
406 | mtrace(" skipping unsuspending: $ue->userid ==> $instance->courseid (user without role)"); | |
407 | } | |
408 | continue; | |
df997f84 | 409 | } |
ad68ed74 PS |
410 | } |
411 | ||
412 | $meta->update_user_enrol($instance, $ue->userid, $ue->pstatus); | |
413 | if ($verbose) { | |
414 | if ($ue->pstatus == ENROL_USER_ACTIVE) { | |
415 | mtrace(" unsuspending: $ue->userid ==> $instance->courseid"); | |
416 | } else { | |
417 | mtrace(" suspending: $ue->userid ==> $instance->courseid"); | |
418 | } | |
419 | } | |
420 | } | |
421 | $rs->close(); | |
422 | ||
423 | ||
424 | // now assign all necessary roles | |
425 | $enabled = explode(',', $CFG->enrol_plugins_enabled); | |
426 | foreach($enabled as $k=>$v) { | |
427 | if ($v === 'meta') { | |
428 | continue; // no meta sync of meta roles | |
429 | } | |
430 | $enabled[$k] = 'enrol_'.$v; | |
431 | } | |
77a5c093 | 432 | $enabled[] = ''; // manual assignments are replicated too |
ad68ed74 PS |
433 | |
434 | $onecourse = $courseid ? "AND e.courseid = :courseid" : ""; | |
435 | list($enabled, $params) = $DB->get_in_or_equal($enabled, SQL_PARAMS_NAMED, 'e'); | |
436 | $params['coursecontext'] = CONTEXT_COURSE; | |
437 | $params['courseid'] = $courseid; | |
438 | $params['activeuser'] = ENROL_USER_ACTIVE; | |
439 | $params['enabledinstance'] = ENROL_INSTANCE_ENABLED; | |
440 | $sql = "SELECT DISTINCT pra.roleid, pra.userid, c.id AS contextid, e.id AS enrolid, e.courseid | |
441 | FROM {role_assignments} pra | |
442 | JOIN {user} u ON (u.id = pra.userid AND u.deleted = 0) | |
443 | JOIN {context} pc ON (pc.id = pra.contextid AND pc.contextlevel = :coursecontext AND pra.component $enabled) | |
444 | JOIN {enrol} e ON (e.customint1 = pc.instanceid AND e.enrol = 'meta' $onecourse AND e.status = :enabledinstance) | |
445 | JOIN {user_enrolments} ue ON (ue.enrolid = e.id AND ue.userid = u.id AND ue.status = :activeuser) | |
446 | JOIN {context} c ON (c.contextlevel = pc.contextlevel AND c.instanceid = e.courseid) | |
447 | LEFT JOIN {role_assignments} ra ON (ra.contextid = c.id AND ra.userid = pra.userid AND ra.roleid = pra.roleid AND ra.itemid = e.id AND ra.component = 'enrol_meta') | |
448 | WHERE ra.id IS NULL"; | |
449 | ||
450 | if ($ignored = $meta->get_config('nosyncroleids')) { | |
451 | list($notignored, $xparams) = $DB->get_in_or_equal(explode(',', $ignored), SQL_PARAMS_NAMED, 'ig', false); | |
452 | $params = array_merge($params, $xparams); | |
453 | $sql = "$sql AND pra.roleid $notignored"; | |
df997f84 PS |
454 | } |
455 | ||
ad68ed74 PS |
456 | $rs = $DB->get_recordset_sql($sql, $params); |
457 | foreach($rs as $ra) { | |
458 | role_assign($ra->roleid, $ra->userid, $ra->contextid, 'enrol_meta', $ra->enrolid); | |
459 | if ($verbose) { | |
460 | mtrace(" assigning role: $ra->userid ==> $ra->courseid as ".$allroles[$ra->roleid]->shortname); | |
461 | } | |
462 | } | |
463 | $rs->close(); | |
464 | ||
465 | ||
df997f84 | 466 | // remove unwanted roles - include ignored roles and disabled plugins too |
ad68ed74 PS |
467 | $onecourse = $courseid ? "AND e.courseid = :courseid" : ""; |
468 | $params = array(); | |
469 | $params['coursecontext'] = CONTEXT_COURSE; | |
470 | $params['courseid'] = $courseid; | |
471 | $params['activeuser'] = ENROL_USER_ACTIVE; | |
472 | $params['enabledinstance'] = ENROL_INSTANCE_ENABLED; | |
df997f84 | 473 | if ($ignored = $meta->get_config('nosyncroleids')) { |
cf717dc2 | 474 | list($notignored, $xparams) = $DB->get_in_or_equal(explode(',', $ignored), SQL_PARAMS_NAMED, 'ig', false); |
df997f84 PS |
475 | $params = array_merge($params, $xparams); |
476 | $notignored = "AND pra.roleid $notignored"; | |
477 | } else { | |
478 | $notignored = ""; | |
479 | } | |
1344bc78 | 480 | |
ad68ed74 | 481 | $sql = "SELECT ra.roleid, ra.userid, ra.contextid, ra.itemid, e.courseid |
df997f84 PS |
482 | FROM {role_assignments} ra |
483 | JOIN {enrol} e ON (e.id = ra.itemid AND ra.component = 'enrol_meta' AND e.enrol = 'meta' $onecourse) | |
484 | JOIN {context} pc ON (pc.instanceid = e.customint1 AND pc.contextlevel = :coursecontext) | |
485 | LEFT JOIN {role_assignments} pra ON (pra.contextid = pc.id AND pra.userid = ra.userid AND pra.roleid = ra.roleid AND pra.component <> 'enrol_meta' $notignored) | |
ad68ed74 PS |
486 | LEFT JOIN {user_enrolments} ue ON (ue.enrolid = e.id AND ue.userid = ra.userid AND ue.status = :activeuser) |
487 | WHERE pra.id IS NULL OR ue.id IS NULL OR e.status <> :enabledinstance"; | |
df997f84 | 488 | |
1344bc78 PS |
489 | if ($unenrolaction != ENROL_EXT_REMOVED_SUSPEND) { |
490 | $rs = $DB->get_recordset_sql($sql, $params); | |
491 | foreach($rs as $ra) { | |
492 | role_unassign($ra->roleid, $ra->userid, $ra->contextid, 'enrol_meta', $ra->itemid); | |
493 | if ($verbose) { | |
494 | mtrace(" unassigning role: $ra->userid ==> $ra->courseid as ".$allroles[$ra->roleid]->shortname); | |
495 | } | |
ad68ed74 | 496 | } |
1344bc78 | 497 | $rs->close(); |
df997f84 | 498 | } |
df997f84 | 499 | |
ad68ed74 PS |
500 | |
501 | // kick out or suspend users without synced roles if syncall disabled | |
502 | if (!$syncall) { | |
503 | if ($unenrolaction == ENROL_EXT_REMOVED_UNENROL) { | |
504 | $onecourse = $courseid ? "AND e.courseid = :courseid" : ""; | |
505 | $params = array(); | |
506 | $params['coursecontext'] = CONTEXT_COURSE; | |
379434e4 | 507 | $params['courseid'] = $courseid; |
ad68ed74 PS |
508 | $sql = "SELECT ue.userid, ue.enrolid |
509 | FROM {user_enrolments} ue | |
510 | JOIN {enrol} e ON (e.id = ue.enrolid AND e.enrol = 'meta' $onecourse) | |
511 | JOIN {context} c ON (e.courseid = c.instanceid AND c.contextlevel = :coursecontext) | |
512 | LEFT JOIN {role_assignments} ra ON (ra.contextid = c.id AND ra.itemid = e.id AND ra.userid = ue.userid) | |
513 | WHERE ra.id IS NULL"; | |
514 | $ues = $DB->get_recordset_sql($sql, $params); | |
515 | foreach($ues as $ue) { | |
516 | if (!isset($instances[$ue->enrolid])) { | |
517 | $instances[$ue->enrolid] = $DB->get_record('enrol', array('id'=>$ue->enrolid)); | |
518 | } | |
519 | $instance = $instances[$ue->enrolid]; | |
520 | $meta->unenrol_user($instance, $ue->userid); | |
521 | if ($verbose) { | |
522 | mtrace(" unenrolling: $ue->userid ==> $instance->courseid (user without role)"); | |
523 | } | |
379434e4 | 524 | } |
ad68ed74 | 525 | $ues->close(); |
379434e4 | 526 | |
ad68ed74 PS |
527 | } else { |
528 | // just suspend the users | |
529 | $onecourse = $courseid ? "AND e.courseid = :courseid" : ""; | |
530 | $params = array(); | |
531 | $params['coursecontext'] = CONTEXT_COURSE; | |
379434e4 | 532 | $params['courseid'] = $courseid; |
ad68ed74 PS |
533 | $params['active'] = ENROL_USER_ACTIVE; |
534 | $sql = "SELECT ue.userid, ue.enrolid | |
535 | FROM {user_enrolments} ue | |
536 | JOIN {enrol} e ON (e.id = ue.enrolid AND e.enrol = 'meta' $onecourse) | |
537 | JOIN {context} c ON (e.courseid = c.instanceid AND c.contextlevel = :coursecontext) | |
538 | LEFT JOIN {role_assignments} ra ON (ra.contextid = c.id AND ra.itemid = e.id AND ra.userid = ue.userid) | |
539 | WHERE ra.id IS NULL AND ue.status = :active"; | |
540 | $ues = $DB->get_recordset_sql($sql, $params); | |
541 | foreach($ues as $ue) { | |
542 | if (!isset($instances[$ue->enrolid])) { | |
543 | $instances[$ue->enrolid] = $DB->get_record('enrol', array('id'=>$ue->enrolid)); | |
544 | } | |
545 | $instance = $instances[$ue->enrolid]; | |
546 | $meta->update_user_enrol($instance, $ue->userid, ENROL_USER_SUSPENDED); | |
547 | if ($verbose) { | |
548 | mtrace(" suspending: $ue->userid ==> $instance->courseid (user without role)"); | |
549 | } | |
379434e4 | 550 | } |
ad68ed74 | 551 | $ues->close(); |
379434e4 | 552 | } |
ad68ed74 | 553 | } |
379434e4 | 554 | |
98177a45 | 555 | // Finally sync groups. |
9c1561ef MG |
556 | $affectedusers = groups_sync_with_enrolment('meta', $courseid); |
557 | if ($verbose) { | |
558 | foreach ($affectedusers['removed'] as $gm) { | |
9e37d365 MG |
559 | mtrace("removing user from group: $gm->userid ==> $gm->courseid - $gm->groupname", 1); |
560 | } | |
9c1561ef | 561 | foreach ($affectedusers['added'] as $ue) { |
9e37d365 MG |
562 | mtrace("adding user to group: $ue->userid ==> $ue->courseid - $ue->groupname", 1); |
563 | } | |
98177a45 | 564 | } |
98177a45 | 565 | |
ad68ed74 PS |
566 | if ($verbose) { |
567 | mtrace('...user enrolment synchronisation finished.'); | |
379434e4 PS |
568 | } |
569 | ||
ad68ed74 | 570 | return 0; |
df997f84 | 571 | } |
e284e179 MG |
572 | |
573 | /** | |
574 | * Create a new group with the course's name. | |
575 | * | |
576 | * @param int $courseid | |
577 | * @param int $linkedcourseid | |
578 | * @return int $groupid Group ID for this cohort. | |
579 | */ | |
580 | function enrol_meta_create_new_group($courseid, $linkedcourseid) { | |
581 | global $DB, $CFG; | |
582 | ||
583 | require_once($CFG->dirroot.'/group/lib.php'); | |
584 | ||
585 | $coursename = $DB->get_field('course', 'fullname', array('id' => $linkedcourseid), MUST_EXIST); | |
586 | $a = new stdClass(); | |
587 | $a->name = $coursename; | |
588 | $a->increment = ''; | |
589 | $inc = 1; | |
590 | $groupname = trim(get_string('defaultgroupnametext', 'enrol_meta', $a)); | |
591 | // Check to see if the group name already exists in this course. Add an incremented number if it does. | |
592 | while ($DB->record_exists('groups', array('name' => $groupname, 'courseid' => $courseid))) { | |
593 | $a->increment = '(' . (++$inc) . ')'; | |
594 | $groupname = trim(get_string('defaultgroupnametext', 'enrol_meta', $a)); | |
595 | } | |
596 | // Create a new group for the course meta sync. | |
597 | $groupdata = new stdClass(); | |
598 | $groupdata->courseid = $courseid; | |
599 | $groupdata->name = $groupname; | |
600 | $groupid = groups_create_group($groupdata); | |
601 | ||
602 | return $groupid; | |
603 | } |