diff --git a/enrol/database/config.html b/enrol/database/config.html index 6d2bea3..aea0492 100644 --- a/enrol/database/config.html +++ b/enrol/database/config.html @@ -83,6 +83,15 @@ + enrol_dbsystemtable: + + + + + + + + diff --git a/enrol/database/enrol.php b/enrol/database/enrol.php index 3957a33..66f5066 100644 --- a/enrol/database/enrol.php +++ b/enrol/database/enrol.php @@ -160,9 +160,55 @@ function setup_enrolments(&$user) { } } } else { - error_log('[ENROL_DB] Couldn\'t get rows from external db: '.$enroldb->ErrorMsg()); + error_log('[ENROL_DB] Couldn\'t get rows from external db for course roles: '.$enroldb->ErrorMsg()); } } + // SYSTEM ROLES START HERE + if (!empty($CFG->enrol_dbsystemtable) && !empty($CFG->enrol_db_remoterolefield)) { // not sensible to do this with no role settings + $sql = "SELECT * + FROM {$CFG->enrol_dbsystemtable} + WHERE {$CFG->enrol_remoteuserfield} = $useridfield + "; + if ($rs = $enroldb->Execute($sql)) { + + $systemcontext = get_system_context(); + // get the existing system role assignments + if (!$existing = get_records_sql("SELECT r.{$CFG->enrol_db_localrolefield},ra.* + FROM {$CFG->prefix}role r JOIN {$CFG->prefix}role_assignments ra ON ra.roleid = r.id + WHERE ra.userid = {$user->id} AND ra.contextid = {$systemcontext->id}")) { + $existing = array(); + } + if (!$rs->EOF) { // we found some results for this user + // need to go fetch the local roles too so we can match role.{$CFG->enrol_remoterolefield} -> local role id + if (!$roles = get_records('role', '','','',$CFG->enrol_db_localrolefield . ',*')) { + // we can't assign any roles if there aren't any. + } else { + while ($fields_obj = rs_fetch_next_record($rs)) { + if (array_key_exists($fields_obj->{$CFG->enrol_db_remoterolefield}, $existing)) { + // user already has this role in system context. skip. + unset($existing[$fields_obj->{$CFG->enrol_db_remoterolefield}]); + continue; + } + if (!array_key_exists($fields_obj->{$CFG->enrol_db_remoterolefield}, $roles)) { // can't assign it if it doesn't exist + continue; // TODO perhaps we should raise a warning here + } + role_assign($roles[$fields_obj->{$CFG->enrol_db_remoterolefield}]->id, $user->id, '', $systemcontext->id, 0, 0, 0, 'database'); + } + } + } + + if (!$CFG->enrol_db_disableunenrol) { + foreach ($existing as $role_assignment) { + if ($role_assignment->enrol == 'database') { + role_unassign($role_assignment->roleid, $user->id, '', $systemcontext->id); + } + } + } + } else { + error_log('[ENROL_DB] Couldn\'t get rows from external db for system roles: '.$enroldb->ErrorMsg()); + } + } + // END SYSTEM ROLES $this->enrol_disconnect($enroldb); } @@ -673,6 +719,85 @@ function role_fields($enroldb, $role) { return array($have_role, $remote_role_name, $remote_role_value); } + +function sync_system_roles() { + global $CFG, $db; + if (empty($CFG->enrol_dbsystemtable) || empty($CFG->enrol_db_remoterolefield)) { + return; + } + + $enroldb = $this->enrol_connect(); + echo "=== Syncing system enrolments ===\n"; + + $sql = "SELECT * FROM {$CFG->enrol_dbsystemtable}"; + if ($rs = $enroldb->Execute($sql)) { + + $systemcontext = get_system_context(); + // get the existing system role assignments + if (!$existing = get_records_sql("SELECT " + . sql_concat('r.' . $CFG->enrol_db_localrolefield, "'|'", 'u.' . $CFG->enrol_localuserfield) + . " AS unique, r.{$CFG->enrol_db_localrolefield}, u.{$CFG->enrol_localuserfield}, ra.* + FROM {$CFG->prefix}role r + JOIN {$CFG->prefix}role_assignments ra ON ra.roleid = r.id + JOIN {$CFG->prefix}user u ON ra.userid = u.id + WHERE ra.contextid = {$systemcontext->id}")) { + $existing = array(); + } + + begin_sql(); + + if (!$rs->EOF) { // we found some roles in the external db + $usercache = array(); // put the moodle user in there + $notfoundusercache = array(); // so we don't keep looking up again and again + if (!$roles = get_records('role', '', '', '', $CFG->enrol_db_localrolefield . ', *')) { + // we can't assign any roles if tehre aren't any + } else { + while ($fields_obj = rs_fetch_next_record($rs)) { + $key = $fields_obj->{$CFG->enrol_db_remoterolefield} . '|' . $fields_obj->{$CFG->enrol_remoteuserfield}; + if (array_key_exists($key, $existing)) { + unset($existing[$key]); + } + if (!array_key_exists($fields_obj->{$CFG->enrol_db_remoterolefield}, $roles)) { + continue; // TODO maybe raise a warning here + } + if (array_key_exists($fields_obj->{$CFG->enrol_remoteuserfield}, $notfoundusercache)) { + continue; // TODO maybe raise a warning here + } + // find the moodle user + if (!array_key_exists($fields_obj->{$CFG->enrol_remoteuserfield}, $usercache)) { + if ($u = get_record('user', $CFG->enrol_localuserfield, $fields_obj->{$CFG->enrol_remoteuserfield}, '','','','','id,id')) { + $usercache[$fields_obj->{$CFG->enrol_remoteuserfield}] = $u; + } else { + $notfoundusercache[$fields_obj->{$CFG->enrol_remoteuserfield}] = 1; + continue; + } + } + if (role_assign($roles[$fields_obj->{$CFG->enrol_db_remoterolefield}]->id, $usercache[$fields_obj->{$CFG->enrol_remoteuserfield}]->id, '', $systemcontext->id, 0, 0, 0, 'database')) { + error_log("assigned role " . $fields_obj->{$CFG->enrol_db_remoterolefield} . " to user " . $fields_obj->{$CFG->enrol_remoteuserfield} . " at system context"); + } else { + error_log("failed to assign role " . $fields_obj->{$CFG->enrol_db_remoterolefield} . " to user " . $fields_obj->{$CFG->enrol_remoteuserfield} . " at system context"); + } + } + } + if (!$CFG->enrol_db_disableunenrol) { + + foreach ($existing as $role_assignment) { + if ($role_assignment->enrol == 'database') { + error_log("unassigning role"); + role_unassign($role_assignment->roleid, $user->id, '', $systemcontext->id); + } + } + } + } else { + error_log('[ENROL_DB] (sync) Couldn\'t get rows from external db for system roles: '.$enroldb->ErrorMsg()); + } + commit_sql(); + } + $this->enrol_disconnect($enroldb); +} + + + } // end of class ?> diff --git a/enrol/database/enrol_database_sync.php b/enrol/database/enrol_database_sync.php index 322b1b2..cf27c70 100644 --- a/enrol/database/enrol_database_sync.php +++ b/enrol/database/enrol_database_sync.php @@ -34,6 +34,9 @@ $enrol->sync_enrolments($role); } + // sync system roles + $enrol->sync_system_roles(); + // sync metacourses if (function_exists('sync_metacourses')) { sync_metacourses();