[ Index ] |
PHP Cross Reference of Unnamed Project |
[Summary view] [Print] [Text view]
1 <?php 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 * 20 * @package enrol_meta 21 * @copyright 2010 Petr Skoda {@link http://skodak.org} 22 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 */ 24 25 defined('MOODLE_INTERNAL') || die(); 26 27 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 { 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) { 44 global $DB; 45 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; 83 require_once($CFG->dirroot . '/group/lib.php'); 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 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.*, e.status AS enrolstatus 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 112 if (!$parentcontext = context_course::instance($instance->customint1, IGNORE_MISSING)) { 113 // Weird, we should not get here. 114 return; 115 } 116 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; 129 } 130 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; 136 } 137 unset($ras); 138 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; 143 } 144 145 // Is parent enrol active? Find minimum timestart and maximum timeend of all active enrolments. 146 $parentstatus = ENROL_USER_SUSPENDED; 147 $parenttimeend = null; 148 $parenttimestart = null; 149 foreach ($parentues as $pue) { 150 if ($pue->status == ENROL_USER_ACTIVE && $pue->enrolstatus == ENROL_INSTANCE_ENABLED) { 151 $parentstatus = ENROL_USER_ACTIVE; 152 if ($parenttimeend === null || $pue->timeend == 0 || ($parenttimeend && $parenttimeend < $pue->timeend)) { 153 $parenttimeend = $pue->timeend; 154 } 155 if ($parenttimestart === null || $parenttimestart > $pue->timestart) { 156 $parenttimestart = $pue->timestart; 157 } 158 } 159 } 160 161 // Enrol user if not enrolled yet or fix status/timestart/timeend. Use the minimum timestart and maximum timeend found above. 162 if ($ue) { 163 if ($parentstatus != $ue->status || 164 ($parentstatus == ENROL_USER_ACTIVE && ($parenttimestart != $ue->timestart || $parenttimeend != $ue->timeend))) { 165 $plugin->update_user_enrol($instance, $userid, $parentstatus, $parenttimestart, $parenttimeend); 166 $ue->status = $parentstatus; 167 $ue->timestart = $parenttimestart; 168 $ue->timeend = $parenttimeend; 169 } 170 } else { 171 $plugin->enrol_user($instance, $userid, NULL, (int)$parenttimestart, (int)$parenttimeend, $parentstatus); 172 $ue = new stdClass(); 173 $ue->userid = $userid; 174 $ue->enrolid = $instance->id; 175 $ue->status = $parentstatus; 176 if ($instance->customint2) { 177 groups_add_member($instance->customint2, $userid, 'enrol_meta', $instance->id); 178 } 179 } 180 181 $unenrolaction = $plugin->get_config('unenrolaction', ENROL_EXT_REMOVED_SUSPENDNOROLES); 182 183 // Only active users in enabled instances are supposed to have roles (we can reassign the roles any time later). 184 if ($ue->status != ENROL_USER_ACTIVE or $instance->status != ENROL_INSTANCE_ENABLED or 185 ($parenttimeend and $parenttimeend < time()) or ($parenttimestart > time())) { 186 if ($unenrolaction == ENROL_EXT_REMOVED_SUSPEND) { 187 // Always keep the roles. 188 } else if ($roles) { 189 // This will only unassign roles that were assigned in this enrolment method, leaving all manual role assignments intact. 190 role_unassign_all(array('userid'=>$userid, 'contextid'=>$context->id, 'component'=>'enrol_meta', 'itemid'=>$instance->id)); 191 } 192 return; 193 } 194 195 // add new roles 196 foreach ($parentroles as $rid) { 197 if (!isset($roles[$rid])) { 198 role_assign($rid, $userid, $context->id, 'enrol_meta', $instance->id); 199 } 200 } 201 202 if ($unenrolaction == ENROL_EXT_REMOVED_SUSPEND) { 203 // Always keep the roles. 204 return; 205 } 206 207 // remove roles 208 foreach ($roles as $rid) { 209 if (!isset($parentroles[$rid])) { 210 role_unassign($rid, $userid, $context->id, 'enrol_meta', $instance->id); 211 } 212 } 213 } 214 215 /** 216 * Deal with users that are not supposed to be enrolled via this instance 217 * @static 218 * @param stdClass $instance 219 * @param stdClass $ue 220 * @param context_course $context 221 * @param enrol_meta $plugin 222 * @return void 223 */ 224 protected static function user_not_supposed_to_be_here($instance, $ue, context_course $context, $plugin) { 225 if (!$ue) { 226 // Not enrolled yet - simple! 227 return; 228 } 229 230 $userid = $ue->userid; 231 $unenrolaction = $plugin->get_config('unenrolaction', ENROL_EXT_REMOVED_SUSPENDNOROLES); 232 233 if ($unenrolaction == ENROL_EXT_REMOVED_UNENROL) { 234 // Purges grades, group membership, preferences, etc. - admins were warned! 235 $plugin->unenrol_user($instance, $userid); 236 237 } else if ($unenrolaction == ENROL_EXT_REMOVED_SUSPEND) { 238 if ($ue->status != ENROL_USER_SUSPENDED) { 239 $plugin->update_user_enrol($instance, $userid, ENROL_USER_SUSPENDED); 240 } 241 242 } else if ($unenrolaction == ENROL_EXT_REMOVED_SUSPENDNOROLES) { 243 if ($ue->status != ENROL_USER_SUSPENDED) { 244 $plugin->update_user_enrol($instance, $userid, ENROL_USER_SUSPENDED); 245 } 246 role_unassign_all(array('userid'=>$userid, 'contextid'=>$context->id, 'component'=>'enrol_meta', 'itemid'=>$instance->id)); 247 248 } else { 249 debugging('Unknown unenrol action '.$unenrolaction); 250 } 251 } 252 } 253 254 /** 255 * Sync all meta course links. 256 * 257 * @param int $courseid one course, empty mean all 258 * @param bool $verbose verbose CLI output 259 * @return int 0 means ok, 1 means error, 2 means plugin disabled 260 */ 261 function enrol_meta_sync($courseid = NULL, $verbose = false) { 262 global $CFG, $DB; 263 require_once("{$CFG->dirroot}/group/lib.php"); 264 265 // purge all roles if meta sync disabled, those can be recreated later here in cron 266 if (!enrol_is_enabled('meta')) { 267 if ($verbose) { 268 mtrace('Meta sync plugin is disabled, unassigning all plugin roles and stopping.'); 269 } 270 role_unassign_all(array('component'=>'enrol_meta')); 271 return 2; 272 } 273 274 // unfortunately this may take a long time, execution can be interrupted safely 275 core_php_time_limit::raise(); 276 raise_memory_limit(MEMORY_HUGE); 277 278 if ($verbose) { 279 mtrace('Starting user enrolment synchronisation...'); 280 } 281 282 $instances = array(); // cache instances 283 284 $meta = enrol_get_plugin('meta'); 285 286 $unenrolaction = $meta->get_config('unenrolaction', ENROL_EXT_REMOVED_SUSPENDNOROLES); 287 $skiproles = $meta->get_config('nosyncroleids', ''); 288 $skiproles = empty($skiproles) ? array() : explode(',', $skiproles); 289 $syncall = $meta->get_config('syncall', 1); 290 291 $allroles = get_all_roles(); 292 293 294 // Iterate through all not enrolled yet users. For each active enrolment of each user find the minimum 295 // enrolment startdate and maximum enrolment enddate. 296 // This SQL relies on the fact that ENROL_USER_ACTIVE < ENROL_USER_SUSPENDED 297 // and ENROL_INSTANCE_ENABLED < ENROL_INSTANCE_DISABLED. Condition "pue.status + pe.status = 0" means 298 // that enrolment is active. When MIN(pue.status + pe.status)=0 it means there exists an active 299 // enrolment. 300 $onecourse = $courseid ? "AND e.courseid = :courseid" : ""; 301 list($enabled, $params) = $DB->get_in_or_equal(explode(',', $CFG->enrol_plugins_enabled), SQL_PARAMS_NAMED, 'e'); 302 $params['courseid'] = $courseid; 303 $sql = "SELECT pue.userid, e.id AS enrolid, MIN(pue.status + pe.status) AS status, 304 MIN(CASE WHEN (pue.status + pe.status = 0) THEN pue.timestart ELSE 9999999999 END) AS timestart, 305 MAX(CASE WHEN (pue.status + pe.status = 0) THEN 306 (CASE WHEN pue.timeend = 0 THEN 9999999999 ELSE pue.timeend END) 307 ELSE 0 END) AS timeend 308 FROM {user_enrolments} pue 309 JOIN {enrol} pe ON (pe.id = pue.enrolid AND pe.enrol <> 'meta' AND pe.enrol $enabled) 310 JOIN {enrol} e ON (e.customint1 = pe.courseid AND e.enrol = 'meta' $onecourse) 311 JOIN {user} u ON (u.id = pue.userid AND u.deleted = 0) 312 LEFT JOIN {user_enrolments} ue ON (ue.enrolid = e.id AND ue.userid = pue.userid) 313 WHERE ue.id IS NULL 314 GROUP BY pue.userid, e.id"; 315 316 $rs = $DB->get_recordset_sql($sql, $params); 317 foreach($rs as $ue) { 318 if (!isset($instances[$ue->enrolid])) { 319 $instances[$ue->enrolid] = $DB->get_record('enrol', array('id'=>$ue->enrolid)); 320 } 321 $instance = $instances[$ue->enrolid]; 322 323 if (!$syncall) { 324 // this may be slow if very many users are ignored in sync 325 $parentcontext = context_course::instance($instance->customint1); 326 list($ignoreroles, $params) = $DB->get_in_or_equal($skiproles, SQL_PARAMS_NAMED, 'ri', false, -1); 327 $params['contextid'] = $parentcontext->id; 328 $params['userid'] = $ue->userid; 329 $select = "contextid = :contextid AND userid = :userid AND component <> 'enrol_meta' AND roleid $ignoreroles"; 330 if (!$DB->record_exists_select('role_assignments', $select, $params)) { 331 // bad luck, this user does not have any role we want in parent course 332 if ($verbose) { 333 mtrace(" skipping enrolling: $ue->userid ==> $instance->courseid (user without role)"); 334 } 335 continue; 336 } 337 } 338 339 // So now we have aggregated values that we will use for the meta enrolment status, timeend and timestart. 340 // Again, we use the fact that active=0 and disabled/suspended=1. Only when MIN(pue.status + pe.status)=0 the enrolment is active: 341 $ue->status = ($ue->status == ENROL_USER_ACTIVE + ENROL_INSTANCE_ENABLED) ? ENROL_USER_ACTIVE : ENROL_USER_SUSPENDED; 342 // Timeend 9999999999 was used instead of 0 in the "MAX()" function: 343 $ue->timeend = ($ue->timeend == 9999999999) ? 0 : (int)$ue->timeend; 344 // Timestart 9999999999 is only possible when there are no active enrolments: 345 $ue->timestart = ($ue->timestart == 9999999999) ? 0 : (int)$ue->timestart; 346 347 $meta->enrol_user($instance, $ue->userid, null, $ue->timestart, $ue->timeend, $ue->status); 348 if ($instance->customint2) { 349 groups_add_member($instance->customint2, $ue->userid, 'enrol_meta', $instance->id); 350 } 351 if ($verbose) { 352 mtrace(" enrolling: $ue->userid ==> $instance->courseid"); 353 } 354 } 355 $rs->close(); 356 357 358 // unenrol as necessary - ignore enabled flag, we want to get rid of existing enrols in any case 359 $onecourse = $courseid ? "AND e.courseid = :courseid" : ""; 360 list($enabled, $params) = $DB->get_in_or_equal(explode(',', $CFG->enrol_plugins_enabled), SQL_PARAMS_NAMED, 'e'); 361 $params['courseid'] = $courseid; 362 $sql = "SELECT ue.* 363 FROM {user_enrolments} ue 364 JOIN {enrol} e ON (e.id = ue.enrolid AND e.enrol = 'meta' $onecourse) 365 LEFT JOIN ({user_enrolments} xpue 366 JOIN {enrol} xpe ON (xpe.id = xpue.enrolid AND xpe.enrol <> 'meta' AND xpe.enrol $enabled) 367 ) ON (xpe.courseid = e.customint1 AND xpue.userid = ue.userid) 368 WHERE xpue.userid IS NULL"; 369 $rs = $DB->get_recordset_sql($sql, $params); 370 foreach($rs as $ue) { 371 if (!isset($instances[$ue->enrolid])) { 372 $instances[$ue->enrolid] = $DB->get_record('enrol', array('id'=>$ue->enrolid)); 373 } 374 $instance = $instances[$ue->enrolid]; 375 376 if ($unenrolaction == ENROL_EXT_REMOVED_UNENROL) { 377 $meta->unenrol_user($instance, $ue->userid); 378 if ($verbose) { 379 mtrace(" unenrolling: $ue->userid ==> $instance->courseid"); 380 } 381 382 } else if ($unenrolaction == ENROL_EXT_REMOVED_SUSPEND) { 383 if ($ue->status != ENROL_USER_SUSPENDED) { 384 $meta->update_user_enrol($instance, $ue->userid, ENROL_USER_SUSPENDED); 385 if ($verbose) { 386 mtrace(" suspending: $ue->userid ==> $instance->courseid"); 387 } 388 } 389 390 } else if ($unenrolaction == ENROL_EXT_REMOVED_SUSPENDNOROLES) { 391 if ($ue->status != ENROL_USER_SUSPENDED) { 392 $meta->update_user_enrol($instance, $ue->userid, ENROL_USER_SUSPENDED); 393 $context = context_course::instance($instance->courseid); 394 role_unassign_all(array('userid'=>$ue->userid, 'contextid'=>$context->id, 'component'=>'enrol_meta', 'itemid'=>$instance->id)); 395 if ($verbose) { 396 mtrace(" suspending and removing all roles: $ue->userid ==> $instance->courseid"); 397 } 398 } 399 } 400 } 401 $rs->close(); 402 403 404 // Update status - meta enrols are ignored to avoid recursion. 405 // Note the trick here is that the active enrolment and instance constants have value 0. 406 $onecourse = $courseid ? "AND e.courseid = :courseid" : ""; 407 list($enabled, $params) = $DB->get_in_or_equal(explode(',', $CFG->enrol_plugins_enabled), SQL_PARAMS_NAMED, 'e'); 408 $params['courseid'] = $courseid; 409 $sql = "SELECT ue.userid, ue.enrolid, pue.pstatus, pue.ptimestart, pue.ptimeend 410 FROM {user_enrolments} ue 411 JOIN {enrol} e ON (e.id = ue.enrolid AND e.enrol = 'meta' $onecourse) 412 JOIN (SELECT xpue.userid, xpe.courseid, MIN(xpue.status + xpe.status) AS pstatus, 413 MIN(CASE WHEN (xpue.status + xpe.status = 0) THEN xpue.timestart ELSE 9999999999 END) AS ptimestart, 414 MAX(CASE WHEN (xpue.status + xpe.status = 0) THEN 415 (CASE WHEN xpue.timeend = 0 THEN 9999999999 ELSE xpue.timeend END) 416 ELSE 0 END) AS ptimeend 417 FROM {user_enrolments} xpue 418 JOIN {enrol} xpe ON (xpe.id = xpue.enrolid AND xpe.enrol <> 'meta' AND xpe.enrol $enabled) 419 GROUP BY xpue.userid, xpe.courseid 420 ) pue ON (pue.courseid = e.customint1 AND pue.userid = ue.userid) 421 WHERE (pue.pstatus = 0 AND ue.status > 0) OR (pue.pstatus > 0 and ue.status = 0) 422 OR ((CASE WHEN pue.ptimestart = 9999999999 THEN 0 ELSE pue.ptimestart END) <> ue.timestart) 423 OR ((CASE WHEN pue.ptimeend = 9999999999 THEN 0 ELSE pue.ptimeend END) <> ue.timeend)"; 424 $rs = $DB->get_recordset_sql($sql, $params); 425 foreach($rs as $ue) { 426 if (!isset($instances[$ue->enrolid])) { 427 $instances[$ue->enrolid] = $DB->get_record('enrol', array('id'=>$ue->enrolid)); 428 } 429 $instance = $instances[$ue->enrolid]; 430 $ue->pstatus = ($ue->pstatus == ENROL_USER_ACTIVE + ENROL_INSTANCE_ENABLED) ? ENROL_USER_ACTIVE : ENROL_USER_SUSPENDED; 431 $ue->ptimeend = ($ue->ptimeend == 9999999999) ? 0 : (int)$ue->ptimeend; 432 $ue->ptimestart = ($ue->ptimestart == 9999999999) ? 0 : (int)$ue->ptimestart; 433 434 if ($ue->pstatus == ENROL_USER_ACTIVE and (!$ue->ptimeend || $ue->ptimeend > time()) 435 and !$syncall and $unenrolaction != ENROL_EXT_REMOVED_UNENROL) { 436 // this may be slow if very many users are ignored in sync 437 $parentcontext = context_course::instance($instance->customint1); 438 list($ignoreroles, $params) = $DB->get_in_or_equal($skiproles, SQL_PARAMS_NAMED, 'ri', false, -1); 439 $params['contextid'] = $parentcontext->id; 440 $params['userid'] = $ue->userid; 441 $select = "contextid = :contextid AND userid = :userid AND component <> 'enrol_meta' AND roleid $ignoreroles"; 442 if (!$DB->record_exists_select('role_assignments', $select, $params)) { 443 // bad luck, this user does not have any role we want in parent course 444 if ($verbose) { 445 mtrace(" skipping unsuspending: $ue->userid ==> $instance->courseid (user without role)"); 446 } 447 continue; 448 } 449 } 450 451 $meta->update_user_enrol($instance, $ue->userid, $ue->pstatus, $ue->ptimestart, $ue->ptimeend); 452 if ($verbose) { 453 if ($ue->pstatus == ENROL_USER_ACTIVE) { 454 mtrace(" unsuspending: $ue->userid ==> $instance->courseid"); 455 } else { 456 mtrace(" suspending: $ue->userid ==> $instance->courseid"); 457 } 458 } 459 } 460 $rs->close(); 461 462 463 // now assign all necessary roles 464 $enabled = explode(',', $CFG->enrol_plugins_enabled); 465 foreach($enabled as $k=>$v) { 466 if ($v === 'meta') { 467 continue; // no meta sync of meta roles 468 } 469 $enabled[$k] = 'enrol_'.$v; 470 } 471 $enabled[] = ''; // manual assignments are replicated too 472 473 $onecourse = $courseid ? "AND e.courseid = :courseid" : ""; 474 list($enabled, $params) = $DB->get_in_or_equal($enabled, SQL_PARAMS_NAMED, 'e'); 475 $params['coursecontext'] = CONTEXT_COURSE; 476 $params['courseid'] = $courseid; 477 $params['activeuser'] = ENROL_USER_ACTIVE; 478 $params['enabledinstance'] = ENROL_INSTANCE_ENABLED; 479 $sql = "SELECT DISTINCT pra.roleid, pra.userid, c.id AS contextid, e.id AS enrolid, e.courseid 480 FROM {role_assignments} pra 481 JOIN {user} u ON (u.id = pra.userid AND u.deleted = 0) 482 JOIN {context} pc ON (pc.id = pra.contextid AND pc.contextlevel = :coursecontext AND pra.component $enabled) 483 JOIN {enrol} e ON (e.customint1 = pc.instanceid AND e.enrol = 'meta' $onecourse AND e.status = :enabledinstance) 484 JOIN {user_enrolments} ue ON (ue.enrolid = e.id AND ue.userid = u.id AND ue.status = :activeuser) 485 JOIN {context} c ON (c.contextlevel = pc.contextlevel AND c.instanceid = e.courseid) 486 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') 487 WHERE ra.id IS NULL"; 488 489 if ($ignored = $meta->get_config('nosyncroleids')) { 490 list($notignored, $xparams) = $DB->get_in_or_equal(explode(',', $ignored), SQL_PARAMS_NAMED, 'ig', false); 491 $params = array_merge($params, $xparams); 492 $sql = "$sql AND pra.roleid $notignored"; 493 } 494 495 $rs = $DB->get_recordset_sql($sql, $params); 496 foreach($rs as $ra) { 497 role_assign($ra->roleid, $ra->userid, $ra->contextid, 'enrol_meta', $ra->enrolid); 498 if ($verbose) { 499 mtrace(" assigning role: $ra->userid ==> $ra->courseid as ".$allroles[$ra->roleid]->shortname); 500 } 501 } 502 $rs->close(); 503 504 505 // remove unwanted roles - include ignored roles and disabled plugins too 506 $onecourse = $courseid ? "AND e.courseid = :courseid" : ""; 507 $params = array(); 508 $params['coursecontext'] = CONTEXT_COURSE; 509 $params['courseid'] = $courseid; 510 $params['activeuser'] = ENROL_USER_ACTIVE; 511 $params['enabledinstance'] = ENROL_INSTANCE_ENABLED; 512 if ($ignored = $meta->get_config('nosyncroleids')) { 513 list($notignored, $xparams) = $DB->get_in_or_equal(explode(',', $ignored), SQL_PARAMS_NAMED, 'ig', false); 514 $params = array_merge($params, $xparams); 515 $notignored = "AND pra.roleid $notignored"; 516 } else { 517 $notignored = ""; 518 } 519 520 $sql = "SELECT ra.roleid, ra.userid, ra.contextid, ra.itemid, e.courseid 521 FROM {role_assignments} ra 522 JOIN {enrol} e ON (e.id = ra.itemid AND ra.component = 'enrol_meta' AND e.enrol = 'meta' $onecourse) 523 JOIN {context} pc ON (pc.instanceid = e.customint1 AND pc.contextlevel = :coursecontext) 524 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) 525 LEFT JOIN {user_enrolments} ue ON (ue.enrolid = e.id AND ue.userid = ra.userid AND ue.status = :activeuser) 526 WHERE pra.id IS NULL OR ue.id IS NULL OR e.status <> :enabledinstance"; 527 528 if ($unenrolaction != ENROL_EXT_REMOVED_SUSPEND) { 529 $rs = $DB->get_recordset_sql($sql, $params); 530 foreach($rs as $ra) { 531 role_unassign($ra->roleid, $ra->userid, $ra->contextid, 'enrol_meta', $ra->itemid); 532 if ($verbose) { 533 mtrace(" unassigning role: $ra->userid ==> $ra->courseid as ".$allroles[$ra->roleid]->shortname); 534 } 535 } 536 $rs->close(); 537 } 538 539 540 // kick out or suspend users without synced roles if syncall disabled 541 if (!$syncall) { 542 if ($unenrolaction == ENROL_EXT_REMOVED_UNENROL) { 543 $onecourse = $courseid ? "AND e.courseid = :courseid" : ""; 544 $params = array(); 545 $params['coursecontext'] = CONTEXT_COURSE; 546 $params['courseid'] = $courseid; 547 $sql = "SELECT ue.userid, ue.enrolid 548 FROM {user_enrolments} ue 549 JOIN {enrol} e ON (e.id = ue.enrolid AND e.enrol = 'meta' $onecourse) 550 JOIN {context} c ON (e.courseid = c.instanceid AND c.contextlevel = :coursecontext) 551 LEFT JOIN {role_assignments} ra ON (ra.contextid = c.id AND ra.itemid = e.id AND ra.userid = ue.userid) 552 WHERE ra.id IS NULL"; 553 $ues = $DB->get_recordset_sql($sql, $params); 554 foreach($ues as $ue) { 555 if (!isset($instances[$ue->enrolid])) { 556 $instances[$ue->enrolid] = $DB->get_record('enrol', array('id'=>$ue->enrolid)); 557 } 558 $instance = $instances[$ue->enrolid]; 559 $meta->unenrol_user($instance, $ue->userid); 560 if ($verbose) { 561 mtrace(" unenrolling: $ue->userid ==> $instance->courseid (user without role)"); 562 } 563 } 564 $ues->close(); 565 566 } else { 567 // just suspend the users 568 $onecourse = $courseid ? "AND e.courseid = :courseid" : ""; 569 $params = array(); 570 $params['coursecontext'] = CONTEXT_COURSE; 571 $params['courseid'] = $courseid; 572 $params['active'] = ENROL_USER_ACTIVE; 573 $sql = "SELECT ue.userid, ue.enrolid 574 FROM {user_enrolments} ue 575 JOIN {enrol} e ON (e.id = ue.enrolid AND e.enrol = 'meta' $onecourse) 576 JOIN {context} c ON (e.courseid = c.instanceid AND c.contextlevel = :coursecontext) 577 LEFT JOIN {role_assignments} ra ON (ra.contextid = c.id AND ra.itemid = e.id AND ra.userid = ue.userid) 578 WHERE ra.id IS NULL AND ue.status = :active"; 579 $ues = $DB->get_recordset_sql($sql, $params); 580 foreach($ues as $ue) { 581 if (!isset($instances[$ue->enrolid])) { 582 $instances[$ue->enrolid] = $DB->get_record('enrol', array('id'=>$ue->enrolid)); 583 } 584 $instance = $instances[$ue->enrolid]; 585 $meta->update_user_enrol($instance, $ue->userid, ENROL_USER_SUSPENDED); 586 if ($verbose) { 587 mtrace(" suspending: $ue->userid ==> $instance->courseid (user without role)"); 588 } 589 } 590 $ues->close(); 591 } 592 } 593 594 // Finally sync groups. 595 $affectedusers = groups_sync_with_enrolment('meta', $courseid); 596 if ($verbose) { 597 foreach ($affectedusers['removed'] as $gm) { 598 mtrace("removing user from group: $gm->userid ==> $gm->courseid - $gm->groupname", 1); 599 } 600 foreach ($affectedusers['added'] as $ue) { 601 mtrace("adding user to group: $ue->userid ==> $ue->courseid - $ue->groupname", 1); 602 } 603 } 604 605 if ($verbose) { 606 mtrace('...user enrolment synchronisation finished.'); 607 } 608 609 return 0; 610 } 611 612 /** 613 * Create a new group with the course's name. 614 * 615 * @param int $courseid 616 * @param int $linkedcourseid 617 * @return int $groupid Group ID for this cohort. 618 */ 619 function enrol_meta_create_new_group($courseid, $linkedcourseid) { 620 global $DB, $CFG; 621 622 require_once($CFG->dirroot.'/group/lib.php'); 623 624 $coursename = $DB->get_field('course', 'fullname', array('id' => $linkedcourseid), MUST_EXIST); 625 $a = new stdClass(); 626 $a->name = $coursename; 627 $a->increment = ''; 628 $inc = 1; 629 $groupname = trim(get_string('defaultgroupnametext', 'enrol_meta', $a)); 630 // Check to see if the group name already exists in this course. Add an incremented number if it does. 631 while ($DB->record_exists('groups', array('name' => $groupname, 'courseid' => $courseid))) { 632 $a->increment = '(' . (++$inc) . ')'; 633 $groupname = trim(get_string('defaultgroupnametext', 'enrol_meta', $a)); 634 } 635 // Create a new group for the course meta sync. 636 $groupdata = new stdClass(); 637 $groupdata->courseid = $courseid; 638 $groupdata->name = $groupname; 639 $groupid = groups_create_group($groupdata); 640 641 return $groupid; 642 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Thu Aug 11 10:00:09 2016 | Cross-referenced by PHPXref 0.7.1 |