}
/**
- * Forces synchronisation of user enrolments with external database.
+ * Forces synchronisation of user enrolments with external database,
+ * does not create new courses.
*
* @param object $user user record
* @return void
*/
- public function sync_user_enrolments($user = NULL) {
+ public function sync_user_enrolments($user) {
+ global $CFG, $DB;
+
+ // we do not create courses here intentionally because it requires full sync and is slow
+ if (!$this->get_config('dbtype') or !$this->get_config('dbhost') or !$this->get_config('remoteenroltable') or !$this->get_config('remotecoursefield') or !$this->get_config('remoteuserfield')) {
+ return;
+ }
+
+ $table = $this->get_config('remoteenroltable');
+ $coursefield = strtolower($this->get_config('remotecoursefield'));
+ $userfield = strtolower($this->get_config('remoteuserfield'));
+ $rolefield = strtolower($this->get_config('remoterolefield'));
+
+ $localrolefield = $this->get_config('localrolefield');
+ $localuserfield = $this->get_config('localuserfield');
+ $localcoursefiled = $this->get_config('localcoursefield');
+
+ $unenrolaction = $this->get_config('unenrolaction');
+ $defaultrole = $this->get_config('defaultrole');
+
+ $ignorehidden = $this->get_config('ignorehiddencourses');
+
+ // create roles mapping
+ $allroles = get_all_roles();
+ if (!isset($allroles[$defaultrole])) {
+ $defaultrole = 0;
+ }
+ $roles = array();
+ foreach ($allroles as $role) {
+ $roles[$role->$localrolefield] = $role->id;
+ }
+
+ $enrols = array();
+ $instances = array();
+
+ $extdb = $this->db_init();
+
+ // read remote enrols and create instances
+ $sql = $this->db_get_sql($table, array($userfield=>$user->$localuserfield), array(), false);
+
+ if ($rs = $extdb->Execute($sql)) {
+ if (!$rs->EOF) {
+ while ($fields = $rs->FetchRow()) {
+ $fields = $this->db_decode($fields);
+
+ if (empty($fields[$coursefield])) {
+ // missing course info
+ continue;
+ }
+ if (!$course = $DB->get_record('course', array($localcoursefiled=>$fields[$coursefield]), 'id,visible')) {
+ continue;
+ }
+ if (!$course->visible and $ignorehidden) {
+ continue;
+ }
+
+ if (empty($fields[$rolefield]) or !isset($roles[$fields[$rolefield]])) {
+ if (!$defaultrole) {
+ // role is mandatory
+ continue;
+ }
+ $roleid = $defaultrole;
+ } else {
+ $roleid = $roles[$fields[$rolefield]];
+ }
+
+ if (empty($enrols[$course->id])) {
+ $enrols[$course->id] = array();
+ }
+ $enrols[$course->id][] = $roleid;
+
+ if ($instance = $DB->get_record('enrol', array('courseid'=>$course->id, 'enrol'=>'database'), '*', IGNORE_MULTIPLE)) {
+ $instances[$course->id] = $instance;
+ continue;
+ }
+
+ $enrolid = $this->add_instance($course);
+ $instances[$course->id] = $DB->get_record('enrol', array('id'=>$enrolid));
+ }
+ }
+ $rs->Close();
+ $extdb->Close();
+ } else {
+ // bad luck, something is wrong with the db connection
+ $extdb->Close();
+ return;
+ }
+
+ // enrol user into courses and sync roles
+ foreach ($enrols as $courseid => $roles) {
+ if (!isset($instances[$courseid])) {
+ // ignored
+ continue;
+ }
+ $instance = $instances[$courseid];
+
+ if ($e = $DB->get_record('user_enrolments', array('userid'=>$user->id, 'enrolid'=>$instance->id))) {
+ // reenable enrolment when previously disable enrolment refreshed
+ if ($e->status == ENROL_USER_SUSPENDED) {
+ $DB->set_field('user_enrolments', 'status', ENROL_USER_ACTIVE, array('enrolid'=>$instance->id, 'userid'=>$user->id));
+ }
+ } else {
+ $roleid = reset($roles);
+ $this->enrol_user($instance, $user->id, $roleid);
+ }
+
+ if (!$context = get_context_instance(CONTEXT_COURSE, $instance->courseid)) {
+ //weird
+ continue;
+ }
+ $current = $DB->get_records('role_assignments', array('contextid'=>$context->id, 'userid'=>$user->id, 'component'=>'enrol_database', 'itemid'=>$instance->id), '', 'id, roleid');
+
+ $existing = array();
+ foreach ($current as $r) {
+ if (in_array($r->id, $roles)) {
+ $existing[$r->roleid] = $r->roleid;
+ } else {
+ role_unassign($r->roleid, $user->id, $context->id, 'enrol_database', $instance->id);
+ }
+ }
+ foreach ($roles as $rid) {
+ if (!isset($existing[$rid])) {
+ role_assign($rid, $user->id, $context->id, 'enrol_database', $instance->id);
+ }
+ }
+ }
+
+ // unenrol as necessary
+ $sql = "SELECT e.*, c.visible AS cvisible, ue.status AS ustatus
+ FROM {enrol} e
+ JOIN {user_enrolments} ue ON ue.enrolid = e.id
+ JOIN {course} c ON c.id = e.courseid
+ WHERE ue.userid = :userid AND e.enrol = 'database'";
+ $rs = $DB->get_recordset_sql($sql, array('userid'=>$user->id));
+ foreach ($rs as $instance) {
+ if (!$instance->cvisible and $ignorehidden) {
+ continue;
+ }
+
+ if (!$context = get_context_instance(CONTEXT_COURSE, $instance->courseid)) {
+ //weird
+ continue;
+ }
+
+ if (!empty($enrols[$instance->courseid])) {
+ // we want this user enrolled
+ continue;
+ }
- //TODO: full sync with external system is very expensive, it could cause big perf problems if we did that during each log-in,
- // so do the sync only once in a while or rely on cron
+ // deal with enrolments removed from external table
+ if ($unenrolaction == ENROL_EXT_REMOVED_UNENROL) {
+ // unenrol
+ $this->unenrol_user($instance, $user->id);
+
+ } else if ($unenrolaction == ENROL_EXT_REMOVED_KEEP) {
+ // keep - only adding enrolments
+
+ } else if ($unenrolaction == ENROL_EXT_REMOVED_SUSPEND or $unenrolaction == ENROL_EXT_REMOVED_SUSPENDNOROLES) {
+ // disable
+ if ($instance->ustatus != ENROL_USER_SUSPENDED) {
+ $DB->set_field('user_enrolments', 'status', ENROL_USER_SUSPENDED, array('enrolid'=>$instance->id, 'userid'=>$user->id));
+ }
+ if ($unenrolaction == ENROL_EXT_REMOVED_SUSPENDNOROLES) {
+ role_unassign_all(array('contextid'=>$context->id, 'userid'=>$user->id, 'component'=>'enrol_database', 'itemid'=>$instance->id));
+ }
+ }
+ }
+ $rs->close();
}
/**
$extdb = $this->db_init();
// second step is to sync instances and users
- $table = $this->get_config('remoteenroltable');
- $coursefield = strtolower($this->get_config('remotecoursefield'));
- $userfield = strtolower($this->get_config('remoteuserfield'));
- $rolefield = strtolower($this->get_config('remoterolefield'));
- $localrolefield = $this->get_config('localrolefield');
- $localuserfield = $this->get_config('localuserfield');
- $unenrolaction = $this->get_config('unenrolaction');
+ $table = $this->get_config('remoteenroltable');
+ $coursefield = strtolower($this->get_config('remotecoursefield'));
+ $userfield = strtolower($this->get_config('remoteuserfield'));
+ $rolefield = strtolower($this->get_config('remoterolefield'));
+
+ $localrolefield = $this->get_config('localrolefield');
+ $localuserfield = $this->get_config('localuserfield');
+ $localcoursefiled = $this->get_config('localcoursefield');
+
+ $unenrolaction = $this->get_config('unenrolaction');
+ $defaultrole = $this->get_config('defaultrole');
// create roles mapping
$allroles = get_all_roles();
- $defaultrole = $this->get_config('defaultrole');
if (!isset($allroles[$defaultrole])) {
$defaultrole = 0;
}
}
// first find all existing courses with enrol instance
- $localcoursefiled = $this->get_config('localcoursefield');
$sql = "SELECT c.id, c.visible, c.$localcoursefiled AS mapping, e.id AS enrolid
FROM {course} c
JOIN {enrol} e ON (e.courseid = c.id AND e.enrol = 'database')";