Browse files

Merge branch 'w40_MDL-35701_m24_enroldb' of git://github.com/skodak/m…

…oodle
  • Loading branch information...
2 parents f7a506f + d156ec9 commit 5a2c3743265d7d19aba4b9e4c3a721c2aa23c28e @stronk7 stronk7 committed Oct 2, 2012
View
5 enrol/database/cli/sync.php
@@ -26,8 +26,7 @@
* - you need to change the "www-data" to match the apache user account
* - use "su" if "sudo" not available
*
- * @package enrol
- * @subpackage database
+ * @package enrol_database
* @copyright 2010 Petr Skoda {@link http://skodak.org}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
@@ -37,7 +36,7 @@
require(dirname(dirname(dirname(dirname(__FILE__)))).'/config.php');
require_once($CFG->libdir.'/clilib.php');
-// now get cli options
+// Now get cli options.
list($options, $unrecognized) = cli_get_params(array('verbose'=>false, 'help'=>false), array('v'=>'verbose', 'h'=>'help'));
if ($unrecognized) {
View
8 enrol/database/db/access.php
@@ -1,5 +1,4 @@
<?php
-
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
@@ -18,16 +17,15 @@
/**
* Capabilities for database enrolment plugin.
*
- * @package enrol
- * @subpackage database
+ * @package enrol_database
* @copyright 2010 Petr Skoda {@link http://skodak.org}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
$capabilities = array(
- /* This is used only when sync suspends users instead of full unenrolment */
+ /* This is used only when sync suspends users instead of full unenrolment. */
'enrol/database:unenrol' => array(
'captype' => 'write',
@@ -37,5 +35,3 @@
)
),
);
-
-
View
3 enrol/database/db/install.php
@@ -17,8 +17,7 @@
/**
* Database enrolment plugin installation.
*
- * @package enrol
- * @subpackage database
+ * @package enrol_database
* @copyright 2010 Petr Skoda {@link http://skodak.org}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
View
7 enrol/database/db/upgrade.php
@@ -17,8 +17,7 @@
/**
* Database enrolment plugin upgrade.
*
- * @package enrol
- * @subpackage database
+ * @package enrol_database
* @copyright 2011 Petr Skoda {@link http://skodak.org}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
@@ -30,8 +29,8 @@ function xmldb_enrol_database_upgrade($oldversion) {
$dbman = $DB->get_manager();
- // Moodle v2.3.0 release upgrade line
- // Put any upgrade step following this
+ // Moodle v2.3.0 release upgrade line.
+ // Put any upgrade step following this.
return true;
View
3 enrol/database/lang/en/enrol_database.php
@@ -1,5 +1,4 @@
<?php
-
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
@@ -16,7 +15,7 @@
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
- * Strings for component 'enrol_database', language 'en', branch 'MOODLE_20_STABLE'
+ * Strings for component 'enrol_database', language 'en'.
*
* @package enrol_database
* @copyright 1999 onwards Martin Dougiamas {@link http://moodle.com}
View
436 enrol/database/lib.php
@@ -19,8 +19,7 @@
*
* This plugin synchronises enrolment and roles with external database table.
*
- * @package enrol
- * @subpackage database
+ * @package enrol_database
* @copyright 2010 Petr Skoda {@link http://skodak.org}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
@@ -36,7 +35,7 @@ class enrol_database_plugin extends enrol_plugin {
/**
* Is it possible to delete enrol instance via standard UI?
*
- * @param object $instance
+ * @param stdClass $instance
* @return bool
*/
public function instance_deleteable($instance) {
@@ -69,7 +68,7 @@ public function allow_unenrol_user(stdClass $instance, stdClass $ue) {
}
/**
- * Gets an array of the user enrolment actions
+ * Gets an array of the user enrolment actions.
*
* @param course_enrolment_manager $manager
* @param stdClass $ue A user enrolment object
@@ -92,21 +91,26 @@ public function get_user_enrolment_actions(course_enrolment_manager $manager, $u
* Forces synchronisation of user enrolments with external database,
* does not create new courses.
*
- * @param object $user user record
+ * @param stdClass $user user record
* @return void
*/
public function sync_user_enrolments($user) {
global $CFG, $DB;
- // we do not create courses here intentionally because it requires full sync and is slow
+ // 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'));
+ $coursefield = trim($this->get_config('remotecoursefield'));
+ $userfield = trim($this->get_config('remoteuserfield'));
+ $rolefield = trim($this->get_config('remoterolefield'));
+
+ // Lowercased versions - necessary because we normalise the resultset with array_change_key_case().
+ $coursefield_l = strtolower($coursefield);
+ $userfield_l = strtolower($userfield);
+ $rolefield_l = strtolower($rolefield);
$localrolefield = $this->get_config('localrolefield');
$localuserfield = $this->get_config('localuserfield');
@@ -126,7 +130,7 @@ public function sync_user_enrolments($user) {
$user = $DB->get_record('user', array('id'=>$user->id));
}
- // create roles mapping
+ // Create roles mapping.
$allroles = get_all_roles();
if (!isset($allroles[$defaultrole])) {
$defaultrole = 0;
@@ -140,11 +144,11 @@ public function sync_user_enrolments($user) {
$instances = array();
if (!$extdb = $this->db_init()) {
- // can not connect to database, sorry
+ // Can not connect to database, sorry.
return;
}
- // read remote enrols and create instances
+ // Read remote enrols and create instances.
$sql = $this->db_get_sql($table, array($userfield=>$user->$localuserfield), array(), false);
if ($rs = $extdb->Execute($sql)) {
@@ -153,25 +157,25 @@ public function sync_user_enrolments($user) {
$fields = array_change_key_case($fields, CASE_LOWER);
$fields = $this->db_decode($fields);
- if (empty($fields[$coursefield])) {
- // missing course info
+ if (empty($fields[$coursefield_l])) {
+ // Missing course info.
continue;
}
- if (!$course = $DB->get_record('course', array($localcoursefield=>$fields[$coursefield]), 'id,visible')) {
+ if (!$course = $DB->get_record('course', array($localcoursefield=>$fields[$coursefield_l]), 'id,visible')) {
continue;
}
if (!$course->visible and $ignorehidden) {
continue;
}
- if (empty($fields[$rolefield]) or !isset($roles[$fields[$rolefield]])) {
+ if (empty($fields[$rolefield_l]) or !isset($roles[$fields[$rolefield_l]])) {
if (!$defaultrole) {
- // role is mandatory
+ // Role is mandatory.
continue;
}
$roleid = $defaultrole;
} else {
- $roleid = $roles[$fields[$rolefield]];
+ $roleid = $roles[$fields[$rolefield_l]];
}
if (empty($enrols[$course->id])) {
@@ -191,21 +195,21 @@ public function sync_user_enrolments($user) {
$rs->Close();
$extdb->Close();
} else {
- // bad luck, something is wrong with the db connection
+ // Bad luck, something is wrong with the db connection.
$extdb->Close();
return;
}
- // enrol user into courses and sync roles
+ // Enrol user into courses and sync roles.
foreach ($enrols as $courseid => $roles) {
if (!isset($instances[$courseid])) {
- // ignored
+ // 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
+ // Reenable enrolment when previously disable enrolment refreshed.
if ($e->status == ENROL_USER_SUSPENDED) {
$this->update_user_enrol($instance, $user->id, ENROL_USER_ACTIVE);
}
@@ -215,7 +219,7 @@ public function sync_user_enrolments($user) {
}
if (!$context = context_course::instance($instance->courseid, IGNORE_MISSING)) {
- //weird
+ // Weird.
continue;
}
$current = $DB->get_records('role_assignments', array('contextid'=>$context->id, 'userid'=>$user->id, 'component'=>'enrol_database', 'itemid'=>$instance->id), '', 'id, roleid');
@@ -235,7 +239,7 @@ public function sync_user_enrolments($user) {
}
}
- // unenrol as necessary
+ // 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
@@ -248,25 +252,24 @@ public function sync_user_enrolments($user) {
}
if (!$context = context_course::instance($instance->courseid, IGNORE_MISSING)) {
- //weird
+ // Very weird.
continue;
}
if (!empty($enrols[$instance->courseid])) {
- // we want this user enrolled
+ // We want this user enrolled.
continue;
}
- // deal with enrolments removed from external table
+ // 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
+ // Keep - only adding enrolments.
} else if ($unenrolaction == ENROL_EXT_REMOVED_SUSPEND or $unenrolaction == ENROL_EXT_REMOVED_SUSPENDNOROLES) {
- // disable
+ // Suspend users.
if ($instance->ustatus != ENROL_USER_SUSPENDED) {
$this->update_user_enrol($instance, $user->id, ENROL_USER_SUSPENDED);
}
@@ -282,12 +285,13 @@ public function sync_user_enrolments($user) {
* Forces synchronisation of all enrolments with external database.
*
* @param bool $verbose
+ * @param null|int $onecourse limit sync to one course only (used primarily in restore)
* @return int 0 means success, 1 db connect failure, 2 db read failure
*/
- public function sync_enrolments($verbose = false) {
+ public function sync_enrolments($verbose = false, $onecourse = null) {
global $CFG, $DB;
- // we do not create courses here intentionally because it requires full sync and is slow
+ // 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')) {
if ($verbose) {
mtrace('User enrolment synchronisation skipped.');
@@ -304,15 +308,19 @@ public function sync_enrolments($verbose = false) {
return 1;
}
- // we may need a lot of memory here
+ // We may need a lot of memory here.
@set_time_limit(0);
raise_memory_limit(MEMORY_HUGE);
- // 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'));
+ $coursefield = trim($this->get_config('remotecoursefield'));
+ $userfield = trim($this->get_config('remoteuserfield'));
+ $rolefield = trim($this->get_config('remoterolefield'));
+
+ // Lowercased versions - necessary because we normalise the resultset with array_change_key_case().
+ $coursefield_l = strtolower($coursefield);
+ $userfield_l = strtolower($userfield);
+ $rolefield_l = strtolower($rolefield);
$localrolefield = $this->get_config('localrolefield');
$localuserfield = $this->get_config('localuserfield');
@@ -321,7 +329,7 @@ public function sync_enrolments($verbose = false) {
$unenrolaction = $this->get_config('unenrolaction');
$defaultrole = $this->get_config('defaultrole');
- // create roles mapping
+ // Create roles mapping.
$allroles = get_all_roles();
if (!isset($allroles[$defaultrole])) {
$defaultrole = 0;
@@ -331,85 +339,111 @@ public function sync_enrolments($verbose = false) {
$roles[$role->$localrolefield] = $role->id;
}
- // get a list of courses to be synced that are in external table
- $externalcourses = array();
- $sql = $this->db_get_sql($table, array(), array($coursefield), true);
- if ($rs = $extdb->Execute($sql)) {
- if (!$rs->EOF) {
- while ($mapping = $rs->FetchRow()) {
- $mapping = reset($mapping);
- $mapping = $this->db_decode($mapping);
- if (empty($mapping)) {
- // invalid mapping
- continue;
+ if ($onecourse) {
+ $sql = "SELECT c.id, c.visible, c.$localcoursefield AS mapping, c.shortname, e.id AS enrolid
+ FROM {course} c
+ LEFT JOIN {enrol} e ON (e.courseid = c.id AND e.enrol = 'database')
+ WHERE c.id = :id";
+ if (!$course = $DB->get_record_sql($sql, array('id'=>$onecourse))) {
+ // Course does not exist, nothing to sync.
+ return 0;
+ }
+ if (empty($course->mapping)) {
+ // We can not map to this course, sorry.
+ return 0;
+ }
+ if (empty($course->enrolid)) {
+ $course->enrolid = $this->add_instance($course);
+ }
+ $existing = array($course->mapping=>$course);
+
+ // Feel free to unenrol everybody, no safety tricks here.
+ $preventfullunenrol = false;
+ // Course being restored are always hidden, we have to ignore the setting here.
+ $ignorehidden = false;
+
+ } else {
+ // Get a list of courses to be synced that are in external table.
+ $externalcourses = array();
+ $sql = $this->db_get_sql($table, array(), array($coursefield), true);
+ if ($rs = $extdb->Execute($sql)) {
+ if (!$rs->EOF) {
+ while ($mapping = $rs->FetchRow()) {
+ $mapping = reset($mapping);
+ $mapping = $this->db_decode($mapping);
+ if (empty($mapping)) {
+ // invalid mapping
+ continue;
+ }
+ $externalcourses[$mapping] = true;
}
- $externalcourses[$mapping] = true;
}
+ $rs->Close();
+ } else {
+ mtrace('Error reading data from the external enrolment table');
+ $extdb->Close();
+ return 2;
+ }
+ $preventfullunenrol = empty($externalcourses);
+ if ($preventfullunenrol and $unenrolaction == ENROL_EXT_REMOVED_UNENROL) {
+ mtrace(' Preventing unenrolment of all current users, because it might result in major data loss, there has to be at least one record in external enrol table, sorry.');
}
- $rs->Close();
- } else {
- mtrace('Error reading data from the external enrolment table');
- $extdb->Close();
- return 2;
- }
- $preventfullunenrol = empty($externalcourses);
- if ($preventfullunenrol and $unenrolaction == ENROL_EXT_REMOVED_UNENROL) {
- mtrace(' Preventing unenrolment of all current users, because it might result in major data loss, there has to be at least one record in external enrol table, sorry.');
- }
- // first find all existing courses with enrol instance
- $existing = array();
- $sql = "SELECT c.id, c.visible, c.$localcoursefield AS mapping, e.id AS enrolid, c.shortname
- FROM {course} c
- JOIN {enrol} e ON (e.courseid = c.id AND e.enrol = 'database')";
- $rs = $DB->get_recordset_sql($sql); // watch out for idnumber duplicates
- foreach ($rs as $course) {
- if (empty($course->mapping)) {
- continue;
+ // First find all existing courses with enrol instance.
+ $existing = array();
+ $sql = "SELECT c.id, c.visible, c.$localcoursefield AS mapping, e.id AS enrolid, c.shortname
+ FROM {course} c
+ JOIN {enrol} e ON (e.courseid = c.id AND e.enrol = 'database')";
+ $rs = $DB->get_recordset_sql($sql); // Watch out for idnumber duplicates.
+ foreach ($rs as $course) {
+ if (empty($course->mapping)) {
+ continue;
+ }
+ $existing[$course->mapping] = $course;
+ unset($externalcourses[$course->mapping]);
}
- $existing[$course->mapping] = $course;
- unset($externalcourses[$course->mapping]);
- }
- $rs->close();
+ $rs->close();
- // add necessary enrol instances that are not present yet
- $params = array();
- $localnotempty = "";
- if ($localcoursefield !== 'id') {
- $localnotempty = "AND c.$localcoursefield <> :lcfe";
- $params['lcfe'] = $DB->sql_empty();
- }
- $sql = "SELECT c.id, c.visible, c.$localcoursefield AS mapping, c.shortname
- FROM {course} c
- LEFT JOIN {enrol} e ON (e.courseid = c.id AND e.enrol = 'database')
- WHERE e.id IS NULL $localnotempty";
- $rs = $DB->get_recordset_sql($sql, $params);
- foreach ($rs as $course) {
- if (empty($course->mapping)) {
- continue;
+ // Add necessary enrol instances that are not present yet.
+ $params = array();
+ $localnotempty = "";
+ if ($localcoursefield !== 'id') {
+ $localnotempty = "AND c.$localcoursefield <> :lcfe";
+ $params['lcfe'] = $DB->sql_empty();
+ }
+ $sql = "SELECT c.id, c.visible, c.$localcoursefield AS mapping, c.shortname
+ FROM {course} c
+ LEFT JOIN {enrol} e ON (e.courseid = c.id AND e.enrol = 'database')
+ WHERE e.id IS NULL $localnotempty";
+ $rs = $DB->get_recordset_sql($sql, $params);
+ foreach ($rs as $course) {
+ if (empty($course->mapping)) {
+ continue;
+ }
+ if (!isset($externalcourses[$course->mapping])) {
+ // Course not synced or duplicate.
+ continue;
+ }
+ $course->enrolid = $this->add_instance($course);
+ $existing[$course->mapping] = $course;
+ unset($externalcourses[$course->mapping]);
}
- if (!isset($externalcourses[$course->mapping])) {
- // Course not synced or duplicate.
- continue;
+ $rs->close();
+
+ // Print list of missing courses.
+ if ($verbose and $externalcourses) {
+ $list = implode(', ', array_keys($externalcourses));
+ mtrace(" error: following courses do not exist - $list");
+ unset($list);
}
- $course->enrolid = $this->add_instance($course);
- $existing[$course->mapping] = $course;
- unset($externalcourses[$course->mapping]);
- }
- $rs->close();
- // Print list of missing courses.
- if ($verbose and $externalcourses) {
- $list = implode(', ', array_keys($externalcourses));
- mtrace(" error: following courses do not exist - $list");
- unset($list);
- }
+ // Free memory.
+ unset($externalcourses);
- // free memory
- unset($externalcourses);
+ $ignorehidden = $this->get_config('ignorehiddencourses');
+ }
- // sync enrolments
- $ignorehidden = $this->get_config('ignorehiddencourses');
+ // Sync user enrolments.
$sqlfields = array($userfield);
if ($rolefield) {
$sqlfields[] = $rolefield;
@@ -419,11 +453,11 @@ public function sync_enrolments($verbose = false) {
continue;
}
if (!$instance = $DB->get_record('enrol', array('id'=>$course->enrolid))) {
- continue; //weird
+ continue; // Weird!
}
$context = context_course::instance($course->id);
- // get current list of enrolled users with their roles
+ // Get current list of enrolled users with their roles.
$current_roles = array();
$current_status = array();
$user_mapping = array();
@@ -445,7 +479,7 @@ public function sync_enrolments($verbose = false) {
}
$rs->close();
- // get list of users that need to be enrolled and their roles
+ // Get list of users that need to be enrolled and their roles.
$requested_roles = array();
$sql = $this->db_get_sql($table, array($coursefield=>$course->mapping), $sqlfields);
if ($rs = $extdb->Execute($sql)) {
@@ -456,13 +490,13 @@ public function sync_enrolments($verbose = false) {
}
while ($fields = $rs->FetchRow()) {
$fields = array_change_key_case($fields, CASE_LOWER);
- if (empty($fields[$userfield])) {
+ if (empty($fields[$userfield_l])) {
if ($verbose) {
mtrace(" error: skipping user without mandatory $localuserfield in course '$course->mapping'");
}
continue;
}
- $mapping = $fields[$userfield];
+ $mapping = $fields[$userfield_l];
if (!isset($user_mapping[$mapping])) {
$usersearch[$localuserfield] = $mapping;
if (!$user = $DB->get_record('user', $usersearch, 'id', IGNORE_MULTIPLE)) {
@@ -476,7 +510,7 @@ public function sync_enrolments($verbose = false) {
} else {
$userid = $user_mapping[$mapping];
}
- if (empty($fields[$rolefield]) or !isset($roles[$fields[$rolefield]])) {
+ if (empty($fields[$rolefield_l]) or !isset($roles[$fields[$rolefield_l]])) {
if (!$defaultrole) {
if ($verbose) {
mtrace(" error: skipping user '$userid' in course '$course->mapping' - missing course and default role");
@@ -485,7 +519,7 @@ public function sync_enrolments($verbose = false) {
}
$roleid = $defaultrole;
} else {
- $roleid = $roles[$fields[$rolefield]];
+ $roleid = $roles[$fields[$rolefield_l]];
}
$requested_roles[$userid][$roleid] = $roleid;
@@ -498,7 +532,7 @@ public function sync_enrolments($verbose = false) {
}
unset($user_mapping);
- // enrol all users and sync roles
+ // Enrol all users and sync roles.
foreach ($requested_roles as $userid=>$userroles) {
foreach ($userroles as $roleid) {
if (empty($current_roles[$userid])) {
@@ -511,7 +545,7 @@ public function sync_enrolments($verbose = false) {
}
}
- // assign extra roles
+ // Assign extra roles.
foreach ($userroles as $roleid) {
if (empty($current_roles[$userid][$roleid])) {
role_assign($roleid, $userid, $context->id, 'enrol_database', $instance->id);
@@ -522,7 +556,7 @@ public function sync_enrolments($verbose = false) {
}
}
- // unassign removed roles
+ // Unassign removed roles.
foreach($current_roles[$userid] as $cr) {
if (empty($userroles[$cr])) {
role_unassign($cr, $userid, $context->id, 'enrol_database', $instance->id);
@@ -533,7 +567,7 @@ public function sync_enrolments($verbose = false) {
}
}
- // reenable enrolment when previously disable enrolment refreshed
+ // Reenable enrolment when previously disable enrolment refreshed.
if ($current_status[$userid] == ENROL_USER_SUSPENDED) {
$this->update_user_enrol($instance, $userid, ENROL_USER_ACTIVE);
if ($verbose) {
@@ -542,10 +576,10 @@ public function sync_enrolments($verbose = false) {
}
}
- // deal with enrolments removed from external table
+ // Deal with enrolments removed from external table.
if ($unenrolaction == ENROL_EXT_REMOVED_UNENROL) {
if (!$preventfullunenrol) {
- // unenrol
+ // Unenrol.
foreach ($current_status as $userid=>$status) {
if (isset($requested_roles[$userid])) {
continue;
@@ -558,10 +592,10 @@ public function sync_enrolments($verbose = false) {
}
} else if ($unenrolaction == ENROL_EXT_REMOVED_KEEP) {
- // keep - only adding enrolments
+ // Keep - only adding enrolments.
} else if ($unenrolaction == ENROL_EXT_REMOVED_SUSPEND or $unenrolaction == ENROL_EXT_REMOVED_SUSPENDNOROLES) {
- // disable
+ // Suspend enrolments.
foreach ($current_status as $userid=>$status) {
if (isset($requested_roles[$userid])) {
continue;
@@ -582,7 +616,7 @@ public function sync_enrolments($verbose = false) {
}
}
- // close db connection
+ // Close db connection.
$extdb->Close();
if ($verbose) {
@@ -604,7 +638,7 @@ public function sync_enrolments($verbose = false) {
public function sync_courses($verbose = false) {
global $CFG, $DB;
- // make sure we sync either enrolments or courses
+ // Make sure we sync either enrolments or courses.
if (!$this->get_config('dbtype') or !$this->get_config('dbhost') or !$this->get_config('newcoursetable') or !$this->get_config('newcoursefullname') or !$this->get_config('newcourseshortname')) {
if ($verbose) {
mtrace('Course synchronisation skipped.');
@@ -616,7 +650,7 @@ public function sync_courses($verbose = false) {
mtrace('Starting course synchronisation...');
}
- // we may need a lot of memory here
+ // We may need a lot of memory here.
@set_time_limit(0);
raise_memory_limit(MEMORY_HUGE);
@@ -625,14 +659,29 @@ public function sync_courses($verbose = false) {
return 1;
}
- // first create new courses
$table = $this->get_config('newcoursetable');
- $fullname = strtolower($this->get_config('newcoursefullname'));
- $shortname = strtolower($this->get_config('newcourseshortname'));
- $idnumber = strtolower($this->get_config('newcourseidnumber'));
- $category = strtolower($this->get_config('newcoursecategory'));
+ $fullname = trim($this->get_config('newcoursefullname'));
+ $shortname = trim($this->get_config('newcourseshortname'));
+ $idnumber = trim($this->get_config('newcourseidnumber'));
+ $category = trim($this->get_config('newcoursecategory'));
+
+ // Lowercased versions - necessary because we normalise the resultset with array_change_key_case().
+ $fullname_l = strtolower($fullname);
+ $shortname_l = strtolower($shortname);
+ $idnumber_l = strtolower($idnumber);
+ $category_l = strtolower($category);
$localcategoryfield = $this->get_config('localcategoryfield', 'id');
+ $defaultcategory = $this->get_config('defaultcategory');
+
+ if (!$DB->record_exists('course_categories', array('id'=>$defaultcategory))) {
+ if ($verbose) {
+ mtrace(" default course category does not exist!");
+ }
+ $categories = $DB->get_records('course_categories', array(), 'sortorder', 'id', 0, 1);
+ $first = reset($categories);
+ $defaultcategory = $first->id;
+ }
$sqlfields = array($fullname, $shortname);
if ($category) {
@@ -648,34 +697,45 @@ public function sync_courses($verbose = false) {
while ($fields = $rs->FetchRow()) {
$fields = array_change_key_case($fields, CASE_LOWER);
$fields = $this->db_decode($fields);
- if (empty($fields[$shortname]) or empty($fields[$fullname])) {
+ if (empty($fields[$shortname_l]) or empty($fields[$fullname_l])) {
if ($verbose) {
- mtrace(' error: invalid external course record, shortname and fullname are mandatory: ' . json_encode($fields)); // hopefully every geek can read JS, right?
+ mtrace(' error: invalid external course record, shortname and fullname are mandatory: ' . json_encode($fields)); // Hopefully every geek can read JS, right?
}
continue;
}
- if ($DB->record_exists('course', array('shortname'=>$fields[$shortname]))) {
- // already exists
+ if ($DB->record_exists('course', array('shortname'=>$fields[$shortname_l]))) {
+ // Already exists, skip.
continue;
}
- // allow empty idnumber but not duplicates
- if ($idnumber and $fields[$idnumber] !== '' and $fields[$idnumber] !== null and $DB->record_exists('course', array('idnumber'=>$fields[$idnumber]))) {
+ // Allow empty idnumber but not duplicates.
+ if ($idnumber and $fields[$idnumber_l] !== '' and $fields[$idnumber_l] !== null and $DB->record_exists('course', array('idnumber'=>$fields[$idnumber_l]))) {
if ($verbose) {
- mtrace(' error: duplicate idnumber, can not create course: '.$fields[$shortname].' ['.$fields[$idnumber].']');
+ mtrace(' error: duplicate idnumber, can not create course: '.$fields[$shortname_l].' ['.$fields[$idnumber_l].']');
}
continue;
}
- if ($category and !$coursecategory = $DB->get_record('course_categories', array($localcategoryfield=>$fields[$category]), 'id')) {
- if ($verbose) {
- mtrace(' error: invalid category '.$localcategoryfield.', can not create course: '.$fields[$shortname]);
+ $course = new stdClass();
+ $course->fullname = $fields[$fullname_l];
+ $course->shortname = $fields[$shortname_l];
+ $course->idnumber = $idnumber ? $fields[$idnumber_l] : '';
+ if ($category) {
+ if (empty($fields[$category_l])) {
+ // Empty category means use default.
+ $course->category = $defaultcategory;
+ } else if ($coursecategory = $DB->get_record('course_categories', array($localcategoryfield=>$fields[$category_l]), 'id')) {
+ // Yay, correctly specified category!
+ $course->category = $coursecategory->id;
+ unset($coursecategory);
+ } else {
+ // Bad luck, better not continue because unwanted ppl might get access to course in different category.
+ if ($verbose) {
+ mtrace(' error: invalid category '.$localcategoryfield.', can not create course: '.$fields[$shortname_l]);
+ }
+ continue;
}
- continue;
+ } else {
+ $course->category = $defaultcategory;
}
- $course = new stdClass();
- $course->fullname = $fields[$fullname];
- $course->shortname = $fields[$shortname];
- $course->idnumber = $idnumber ? $fields[$idnumber] : '';
- $course->category = $category ? $coursecategory->id : NULL;
$createcourses[] = $course;
}
}
@@ -689,7 +749,6 @@ public function sync_courses($verbose = false) {
require_once("$CFG->dirroot/course/lib.php");
$templatecourse = $this->get_config('templatecourse');
- $defaultcategory = $this->get_config('defaultcategory');
$template = false;
if ($templatecourse) {
@@ -722,21 +781,13 @@ public function sync_courses($verbose = false) {
$template->lang = $courseconfig->lang;
$template->groupmodeforce = $courseconfig->groupmodeforce;
}
- if (!$DB->record_exists('course_categories', array('id'=>$defaultcategory))) {
- if ($verbose) {
- mtrace(" default course category does not exist!");
- }
- $categories = $DB->get_records('course_categories', array(), 'sortorder', 'id', 0, 1);
- $first = reset($categories);
- $defaultcategory = $first->id;
- }
foreach ($createcourses as $fields) {
$newcourse = clone($template);
$newcourse->fullname = $fields->fullname;
$newcourse->shortname = $fields->shortname;
$newcourse->idnumber = $fields->idnumber;
- $newcourse->category = $fields->category ? $fields->category : $defaultcategory;
+ $newcourse->category = $fields->category;
// Detect duplicate data once again, above we can not find duplicates
// in external data using DB collation rules...
@@ -761,7 +812,7 @@ public function sync_courses($verbose = false) {
unset($template);
}
- // close db connection
+ // Close db connection.
$extdb->Close();
if ($verbose) {
@@ -802,14 +853,14 @@ protected function db_init() {
require_once($CFG->libdir.'/adodb/adodb.inc.php');
- // Connect to the external database (forcing new connection)
+ // Connect to the external database (forcing new connection).
$extdb = ADONewConnection($this->get_config('dbtype'));
if ($this->get_config('debugdb')) {
$extdb->debug = true;
- ob_start(); //start output buffer to allow later use of the page headers
+ ob_start(); // Start output buffer to allow later use of the page headers.
}
- // the dbtype my contain the new connection URL, so make sure we are not connected yet
+ // The dbtype my contain the new connection URL, so make sure we are not connected yet.
if (!$extdb->IsConnected()) {
$result = $extdb->Connect($this->get_config('dbhost'), $this->get_config('dbuser'), $this->get_config('dbpass'), $this->get_config('dbname'), true);
if (!$result) {
@@ -825,7 +876,7 @@ protected function db_init() {
}
protected function db_addslashes($text) {
- // using custom made function for now
+ // Use custom made function for now - it is better to not rely on adodb or php defaults.
if ($this->get_config('dbsybasequoting')) {
$text = str_replace('\\', '\\\\', $text);
$text = str_replace(array('\'', '"', "\0"), array('\\\'', '\\"', '\\0'), $text);
@@ -864,5 +915,68 @@ protected function db_decode($text) {
return textlib::convert($text, $dbenc, 'utf-8');
}
}
-}
+ /**
+ * Automatic enrol sync executed during restore.
+ * @param stdClass $course course record
+ */
+ public function restore_sync_course($course) {
+ $this->sync_enrolments(false, $course->id);
+ }
+
+ /**
+ * Restore instance and map settings.
+ *
+ * @param restore_enrolments_structure_step $step
+ * @param stdClass $data
+ * @param stdClass $course
+ * @param int $oldid
+ */
+ public function restore_instance(restore_enrolments_structure_step $step, stdClass $data, $course, $oldid) {
+ global $DB;
+
+ if ($instance = $DB->get_record('enrol', array('courseid'=>$course->id, 'enrol'=>$this->get_name()))) {
+ $instanceid = $instance->id;
+ } else {
+ $instanceid = $this->add_instance($course);
+ }
+ $step->set_mapping('enrol', $oldid, $instanceid);
+ }
+
+ /**
+ * Restore user enrolment.
+ *
+ * @param restore_enrolments_structure_step $step
+ * @param stdClass $data
+ * @param stdClass $instance
+ * @param int $oldinstancestatus
+ * @param int $userid
+ */
+ public function restore_user_enrolment(restore_enrolments_structure_step $step, $data, $instance, $userid, $oldinstancestatus) {
+ global $DB;
+
+ if ($this->get_config('unenrolaction') == ENROL_EXT_REMOVED_UNENROL) {
+ // Enrolments were already synchronised in restore_instance(), we do not want any suspended leftovers.
+ return;
+ }
+ if (!$DB->record_exists('user_enrolments', array('enrolid'=>$instance->id, 'userid'=>$userid))) {
+ $this->enrol_user($instance, $userid, null, 0, 0, ENROL_USER_SUSPENDED);
+ }
+ }
+
+ /**
+ * Restore role assignment.
+ *
+ * @param stdClass $instance
+ * @param int $roleid
+ * @param int $userid
+ * @param int $contextid
+ */
+ public function restore_role_assignment($instance, $roleid, $userid, $contextid) {
+ if ($this->get_config('unenrolaction') == ENROL_EXT_REMOVED_UNENROL or $this->get_config('unenrolaction') == ENROL_EXT_REMOVED_SUSPENDNOROLES) {
+ // Role assignments were already synchronised in restore_instance(), we do not want any leftovers.
+ return;
+ }
+ role_assign($roleid, $userid, $contextid, 'enrol_'.$this->get_name(), $instance->id);
+ }
+}
View
6 enrol/database/settings.php
@@ -1,5 +1,4 @@
<?php
-
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
@@ -18,8 +17,7 @@
/**
* Database enrolment plugin settings and presets.
*
- * @package enrol
- * @subpackage database
+ * @package enrol_database
* @copyright 2010 Petr Skoda {@link http://skodak.org}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
@@ -63,7 +61,7 @@
$options = array('id'=>'id', 'idnumber'=>'idnumber', 'email'=>'email', 'username'=>'username'); // only local users if username selected, no mnet users!
$settings->add(new admin_setting_configselect('enrol_database/localuserfield', get_string('localuserfield', 'enrol_database'), '', 'idnumber', $options));
- $options = array('id'=>'id', 'shortname'=>'shortname', 'fullname'=>'fullname');
+ $options = array('id'=>'id', 'shortname'=>'shortname');
$settings->add(new admin_setting_configselect('enrol_database/localrolefield', get_string('localrolefield', 'enrol_database'), '', 'shortname', $options));
$options = array('id'=>'id', 'idnumber'=>'idnumber');
View
121 enrol/database/tests/adodb_test.php
@@ -1,121 +0,0 @@
-<?php
-// This file is part of Moodle - http://moodle.org/
-//
-// Moodle is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// Moodle is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
-
-/**
- * basic adodb connection test
- *
- * @package enrol_database
- * @category phpunit
- * @copyright 2011 Petr Skoda {@link http://skodak.org}
- * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
- */
-
-defined('MOODLE_INTERNAL') || die();
-
-global $CFG;
-require_once($CFG->dirroot.'/enrol/database/lib.php');
-
-class core_adodb_testcase extends advanced_testcase {
- public function test_read_table() {
- global $DB, $CFG;
-
- $this->resetAfterTest();
-
- set_config('dbencoding', 'utf-8', 'enrol_database');
-
- set_config('dbhost', $CFG->dbhost, 'enrol_database');
- set_config('dbuser', $CFG->dbuser, 'enrol_database');
- set_config('dbpass', $CFG->dbpass, 'enrol_database');
- set_config('dbname', $CFG->dbname, 'enrol_database');
-
- if (!empty($CFG->dboptions['dbport'])) {
- set_config('dbhost', $CFG->dbhost.':'.$CFG->dboptions['dbport'], 'enrol_database');
- }
-
- switch (get_class($DB)) {
- case 'mssql_native_moodle_database':
- set_config('dbtype', 'mssql_n', 'enrol_database');
- set_config('dbsybasequoting', '1', 'enrol_database');
- break;
-
- case 'mysqli_native_moodle_database':
- set_config('dbtype', 'mysqli', 'enrol_database');
- set_config('dbsetupsql', 'SET NAMES \'UTF-8\'', 'enrol_database');
- set_config('dbsybasequoting', '0', 'enrol_database');
- if (!empty($CFG->dboptions['dbsocket'])) {
- set_config('dbtype', 'mysqli://'.rawurlencode($CFG->dbuser).':'.rawurlencode($CFG->dbpass).'@'.rawurlencode($CFG->dbhost).'/'.rawurlencode($CFG->dbname).'?socket='.rawurlencode($CFG->dboptions['dbsocket']), 'enrol_database');
- }
- break;
-
- case 'oci_native_moodle_database':
- set_config('dbtype', 'oci8po', 'enrol_database');
- set_config('dbsybasequoting', '1', 'enrol_database');
- break;
-
- case 'pgsql_native_moodle_database':
- set_config('dbtype', 'postgres7', 'enrol_database');
- set_config('dbsetupsql', 'SET NAMES \'UTF-8\'', 'enrol_database');
- set_config('dbsybasequoting', '0', 'enrol_database');
- if (!empty($CFG->dboptions['dbsocket']) and ($CFG->dbhost === 'localhost' or $CFG->dbhost === '127.0.0.1')) {
- if (strpos($CFG->dboptions['dbsocket'], '/') !== false) {
- set_config('dbhost', $CFG->dboptions['dbsocket'], 'enrol_database');
- } else {
- set_config('dbhost', '', 'enrol_database');
- }
- }
- break;
-
- case 'sqlsrv_native_moodle_database':
- set_config('dbtype', 'mssqlnative', 'enrol_database');
- set_config('dbsybasequoting', '1', 'enrol_database');
- break;
-
- default:
- $this->markTestSkipped('Unknown database driver.');
- return;
- }
-
- $plugin = new enrol_database_tester();
-
- // can we connect?
- $extdb = $plugin->test_get_db_init();
- $this->assertNotEmpty($extdb);
-
- // let's fetch one row
- $sql = $plugin->test_db_get_sql($CFG->prefix.'user', array('id'=>2), array('id', 'username'));
- $rs = $extdb->Execute($sql);
- $this->assertEmpty($rs->EOF);
- $row = $rs->FetchRow();
- $row = array_change_key_case($row, CASE_LOWER);
- $this->assertEquals('2', $row['id']);
- $this->assertEquals('admin', $row['username']);
- $this->assertEmpty($rs->FetchRow());
- $rs->Close();
-
- $extdb->Close();
- }
-}
-
-
-class enrol_database_tester extends enrol_database_plugin {
- public function test_get_db_init() {
- return self::db_init();
- }
-
- public function test_db_get_sql($table, array $conditions, array $fields, $distinct = false, $sort = "") {
- return self::db_get_sql($table, $conditions, $fields, $distinct, $sort);
- }
-}
View
709 enrol/database/tests/sync_test.php
@@ -0,0 +1,709 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * External database enrolment sync tests, this also tests adodb drivers
+ * that are matching our four supported Moodle database drivers.
+ *
+ * @package enrol_database
+ * @category phpunit
+ * @copyright 2011 Petr Skoda {@link http://skodak.org}
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+defined('MOODLE_INTERNAL') || die();
+
+class enrol_database_testcase extends advanced_testcase {
+ protected static $courses = array();
+ protected static $users = array();
+ protected static $roles = array();
+
+ protected function init_enrol_database() {
+ global $DB, $CFG;
+
+ $dbman = $DB->get_manager();
+
+ set_config('dbencoding', 'utf-8', 'enrol_database');
+
+ set_config('dbhost', $CFG->dbhost, 'enrol_database');
+ set_config('dbuser', $CFG->dbuser, 'enrol_database');
+ set_config('dbpass', $CFG->dbpass, 'enrol_database');
+ set_config('dbname', $CFG->dbname, 'enrol_database');
+
+ if (!empty($CFG->dboptions['dbport'])) {
+ set_config('dbhost', $CFG->dbhost.':'.$CFG->dboptions['dbport'], 'enrol_database');
+ }
+
+ switch (get_class($DB)) {
+ case 'mssql_native_moodle_database':
+ set_config('dbtype', 'mssql_n', 'enrol_database');
+ set_config('dbsybasequoting', '1', 'enrol_database');
+ break;
+
+ case 'mysqli_native_moodle_database':
+ set_config('dbtype', 'mysqli', 'enrol_database');
+ set_config('dbsetupsql', "SET NAMES 'UTF-8'", 'enrol_database');
+ set_config('dbsybasequoting', '0', 'enrol_database');
+ if (!empty($CFG->dboptions['dbsocket'])) {
+ set_config('dbtype', 'mysqli://'.rawurlencode($CFG->dbuser).':'.rawurlencode($CFG->dbpass).'@'.rawurlencode($CFG->dbhost).'/'.rawurlencode($CFG->dbname).'?socket='.rawurlencode($CFG->dboptions['dbsocket']), 'enrol_database');
+ }
+ break;
+
+ case 'oci_native_moodle_database':
+ set_config('dbtype', 'oci8po', 'enrol_database');
+ set_config('dbsybasequoting', '1', 'enrol_database');
+ break;
+
+ case 'pgsql_native_moodle_database':
+ set_config('dbtype', 'postgres7', 'enrol_database');
+ set_config('dbsetupsql', "SET NAMES 'UTF-8'", 'enrol_database');
+ set_config('dbsybasequoting', '0', 'enrol_database');
+ if (!empty($CFG->dboptions['dbsocket']) and ($CFG->dbhost === 'localhost' or $CFG->dbhost === '127.0.0.1')) {
+ if (strpos($CFG->dboptions['dbsocket'], '/') !== false) {
+ set_config('dbhost', $CFG->dboptions['dbsocket'], 'enrol_database');
+ } else {
+ set_config('dbhost', '', 'enrol_database');
+ }
+ }
+ break;
+
+ case 'sqlsrv_native_moodle_database':
+ set_config('dbtype', 'mssqlnative', 'enrol_database');
+ set_config('dbsybasequoting', '1', 'enrol_database');
+ break;
+
+ default:
+ throw new exception('Unknown database driver '.get_class($DB));
+ }
+
+ // NOTE: It is stongly discouraged to create new tables in advanced_testcase classes,
+ // but there is no other simple way to test ext database enrol sync, so let's
+ // disable transactions are try to cleanup after the tests.
+
+ $table = new xmldb_table('enrol_database_test_enrols');
+ $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
+ $table->add_field('courseid', XMLDB_TYPE_CHAR, '255', null, null, null);
+ $table->add_field('userid', XMLDB_TYPE_CHAR, '255', null, null, null);
+ $table->add_field('roleid', XMLDB_TYPE_CHAR, '255', null, null, null);
+ $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
+ if ($dbman->table_exists($table)) {
+ $dbman->drop_table($table);
+ }
+ $dbman->create_table($table);
+ set_config('remoteenroltable', $CFG->prefix.'enrol_database_test_enrols', 'enrol_database');
+ set_config('remotecoursefield', 'courseid', 'enrol_database');
+ set_config('remoteuserfield', 'userid', 'enrol_database');
+ set_config('remoterolefield', 'roleid', 'enrol_database');
+
+ $table = new xmldb_table('enrol_database_test_courses');
+ $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
+ $table->add_field('fullname', XMLDB_TYPE_CHAR, '255', null, null, null);
+ $table->add_field('shortname', XMLDB_TYPE_CHAR, '255', null, null, null);
+ $table->add_field('idnumber', XMLDB_TYPE_CHAR, '255', null, null, null);
+ $table->add_field('category', XMLDB_TYPE_CHAR, '255', null, null, null);
+ $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
+ if ($dbman->table_exists($table)) {
+ $dbman->drop_table($table);
+ }
+ $dbman->create_table($table);
+ set_config('newcoursetable', $CFG->prefix.'enrol_database_test_courses', 'enrol_database');
+ set_config('newcoursefullname', 'fullname', 'enrol_database');
+ set_config('newcourseshortname', 'shortname', 'enrol_database');
+ set_config('newcourseidnumber', 'idnumber', 'enrol_database');
+ set_config('newcoursecategory', 'category', 'enrol_database');
+
+ // Create some test users and courses.
+ for($i=1;$i<=3;$i++) {
+ self::$courses[$i] = $this->getDataGenerator()->create_course(array('fullname'=>'Test course '.$i, 'shortname'=>'tc'.$i, 'idnumber'=>'courseid'.$i));
+ }
+
+ for($i=1;$i<=10;$i++) {
+ self::$users[$i] = $this->getDataGenerator()->create_user(array('username'=>'username'.$i, 'idnumber'=>'userid'.$i, 'email'=>'user'.$i.'@example.com'));
+ }
+
+ foreach (get_all_roles() as $role) {
+ self::$roles[$role->shortname] = $role;
+ }
+ }
+
+ protected function cleanup_enrol_database() {
+ global $DB;
+
+ $dbman = $DB->get_manager();
+ $table = new xmldb_table('enrol_database_test_enrols');
+ $dbman->drop_table($table);
+ $table = new xmldb_table('enrol_database_test_courses');
+ $dbman->drop_table($table);
+
+ self::$courses = null;
+ self::$users = null;
+ self::$roles = null;
+ }
+
+ protected function reset_enrol_database() {
+ global $DB;
+
+ $DB->delete_records('enrol_database_test_enrols', array());
+ $DB->delete_records('enrol_database_test_courses', array());
+
+ $plugin = enrol_get_plugin('database');
+ $instances = $DB->get_records('enrol', array('enrol'=>'database'));
+ foreach($instances as $instance) {
+ $plugin->delete_instance($instance);
+ }
+ }
+
+ public function assertIsEnrolled($userindex, $courseindex, $status=null, $rolename = null) {
+ global $DB;
+ $dbinstance = $DB->get_record('enrol', array('courseid'=>self::$courses[$courseindex]->id, 'enrol'=>'database'), '*', MUST_EXIST);
+
+ $conditions = array('enrolid'=>$dbinstance->id, 'userid'=>self::$users[$userindex]->id);
+ if ($status !== null) {
+ $conditions['status'] = $status;
+ }
+ $this->assertTrue($DB->record_exists('user_enrolments', $conditions));
+
+ $coursecontext = context_course::instance(self::$courses[$courseindex]->id);
+ if ($rolename === false) {
+ $this->assertFalse($DB->record_exists('role_assignments', array('component'=>'enrol_database', 'itemid'=>$dbinstance->id, 'userid'=>self::$users[$userindex]->id, 'contextid'=>$coursecontext->id)));
+ } else if ($rolename !== null) {
+ $this->assertTrue($DB->record_exists('role_assignments', array('component'=>'enrol_database', 'itemid'=>$dbinstance->id, 'userid'=>self::$users[$userindex]->id, 'contextid'=>$coursecontext->id, 'roleid'=>self::$roles[$rolename]->id)));
+ }
+ }
+
+ public function assertIsNotEnrolled($userindex, $courseindex) {
+ global $DB;
+ if (!$dbinstance = $DB->get_record('enrol', array('courseid'=>self::$courses[$courseindex]->id, 'enrol'=>'database'))) {
+ return;
+ }
+ $this->assertFalse($DB->record_exists('user_enrolments', array('enrolid'=>$dbinstance->id, 'userid'=>self::$users[$userindex]->id)));
+ }
+
+ public function test_sync_user_enrolments() {
+ global $DB;
+
+ $this->init_enrol_database();
+
+ $this->resetAfterTest(false);
+ $this->preventResetByRollback();
+
+ $plugin = enrol_get_plugin('database');
+
+ // Test basic enrol sync for one user after login.
+
+ $this->reset_enrol_database();
+ $plugin->set_config('localcoursefield', 'idnumber');
+ $plugin->set_config('localuserfield', 'idnumber');
+ $plugin->set_config('localrolefield', 'shortname');
+
+ $plugin->set_config('defaultrole', self::$roles['student']->id);
+
+ $DB->insert_record('enrol_database_test_enrols', array('userid'=>'userid1', 'courseid'=>'courseid1', 'roleid'=>'student'));
+ $DB->insert_record('enrol_database_test_enrols', array('userid'=>'userid1', 'courseid'=>'courseid2', 'roleid'=>'teacher'));
+ $DB->insert_record('enrol_database_test_enrols', array('userid'=>'userid2', 'courseid'=>'courseid1', 'roleid'=>null));
+ $DB->insert_record('enrol_database_test_enrols', array('userid'=>'xxxxxxx', 'courseid'=>'courseid1', 'roleid'=>'student')); // Bogus record to be ignored.
+ $DB->insert_record('enrol_database_test_enrols', array('userid'=>'userid1', 'courseid'=>'xxxxxxxxx', 'roleid'=>'student')); // Bogus record to be ignored.
+
+ $this->assertEquals(0, $DB->count_records('user_enrolments', array()));
+ $this->assertEquals(0, $DB->count_records('enrol', array('enrol'=>'database')));
+ $this->assertEquals(0, $DB->count_records('role_assignments', array('component'=>'enrol_database')));
+
+ $plugin->sync_user_enrolments(self::$users[1]);
+ $this->assertEquals(2, $DB->count_records('user_enrolments', array()));
+ $this->assertEquals(2, $DB->count_records('enrol', array('enrol'=>'database')));
+ $this->assertEquals(2, $DB->count_records('role_assignments', array('component'=>'enrol_database')));
+ $this->assertIsEnrolled(1, 1, ENROL_USER_ACTIVE, 'student');
+ $this->assertIsEnrolled(1, 2, ENROL_USER_ACTIVE, 'teacher');
+
+ // Make sure there are no errors or changes on the next login.
+
+ $plugin->sync_user_enrolments(self::$users[1]);
+ $this->assertEquals(2, $DB->count_records('user_enrolments', array()));
+ $this->assertEquals(2, $DB->count_records('enrol', array('enrol'=>'database')));
+ $this->assertEquals(2, $DB->count_records('role_assignments', array('component'=>'enrol_database')));
+ $this->assertIsEnrolled(1, 1, ENROL_USER_ACTIVE, 'student');
+ $this->assertIsEnrolled(1, 2, ENROL_USER_ACTIVE, 'teacher');
+
+ $plugin->sync_user_enrolments(self::$users[2]);
+ $this->assertEquals(3, $DB->count_records('user_enrolments', array()));
+ $this->assertEquals(2, $DB->count_records('enrol', array('enrol'=>'database')));
+ $this->assertEquals(3, $DB->count_records('role_assignments', array('component'=>'enrol_database')));
+ $this->assertIsEnrolled(1, 1, ENROL_USER_ACTIVE, 'student');
+ $this->assertIsEnrolled(1, 2, ENROL_USER_ACTIVE, 'teacher');
+ $this->assertIsEnrolled(2, 1, ENROL_USER_ACTIVE, 'student');
+
+ // Enrolment removals.
+
+ $DB->delete_records('enrol_database_test_enrols', array('userid'=>'userid1', 'courseid'=>'courseid1', 'roleid'=>'student'));
+ $plugin->set_config('unenrolaction', ENROL_EXT_REMOVED_KEEP);
+ $plugin->sync_user_enrolments(self::$users[1]);
+ $this->assertEquals(3, $DB->count_records('user_enrolments', array()));
+ $this->assertEquals(2, $DB->count_records('enrol', array('enrol'=>'database')));
+ $this->assertEquals(3, $DB->count_records('role_assignments', array('component'=>'enrol_database')));
+ $this->assertIsEnrolled(1, 1, ENROL_USER_ACTIVE, 'student');
+ $this->assertIsEnrolled(1, 2, ENROL_USER_ACTIVE, 'teacher');
+
+
+ $plugin->set_config('unenrolaction', ENROL_EXT_REMOVED_SUSPEND);
+ $plugin->sync_user_enrolments(self::$users[1]);
+ $this->assertEquals(3, $DB->count_records('user_enrolments', array()));
+ $this->assertEquals(2, $DB->count_records('enrol', array('enrol'=>'database')));
+ $this->assertEquals(3, $DB->count_records('role_assignments', array('component'=>'enrol_database')));
+ $this->assertIsEnrolled(1, 1, ENROL_USER_SUSPENDED, 'student');
+ $this->assertIsEnrolled(1, 2, ENROL_USER_ACTIVE, 'teacher');
+
+ $DB->insert_record('enrol_database_test_enrols', array('userid'=>'userid1', 'courseid'=>'courseid1', 'roleid'=>'student'));
+ $plugin->sync_user_enrolments(self::$users[1]);
+ $this->assertEquals(3, $DB->count_records('user_enrolments', array()));
+ $this->assertEquals(2, $DB->count_records('enrol', array('enrol'=>'database')));
+ $this->assertEquals(3, $DB->count_records('role_assignments', array('component'=>'enrol_database')));
+ $this->assertIsEnrolled(1, 1, ENROL_USER_ACTIVE, 'student');
+ $this->assertIsEnrolled(1, 2, ENROL_USER_ACTIVE, 'teacher');
+
+
+ $DB->delete_records('enrol_database_test_enrols', array('userid'=>'userid1', 'courseid'=>'courseid1', 'roleid'=>'student'));
+ $plugin->set_config('unenrolaction', ENROL_EXT_REMOVED_SUSPENDNOROLES);
+ $plugin->sync_user_enrolments(self::$users[1]);
+ $this->assertEquals(3, $DB->count_records('user_enrolments', array()));
+ $this->assertEquals(2, $DB->count_records('enrol', array('enrol'=>'database')));
+ $this->assertEquals(2, $DB->count_records('role_assignments', array('component'=>'enrol_database')));
+ $this->assertIsEnrolled(1, 1, ENROL_USER_SUSPENDED, false);
+ $this->assertIsEnrolled(1, 2, ENROL_USER_ACTIVE, 'teacher');
+
+ $DB->insert_record('enrol_database_test_enrols', array('userid'=>'userid1', 'courseid'=>'courseid1', 'roleid'=>'student'));
+ $plugin->sync_user_enrolments(self::$users[1]);
+ $this->assertEquals(3, $DB->count_records('user_enrolments', array()));
+ $this->assertEquals(2, $DB->count_records('enrol', array('enrol'=>'database')));
+ $this->assertEquals(3, $DB->count_records('role_assignments', array('component'=>'enrol_database')));
+ $this->assertIsEnrolled(1, 1, ENROL_USER_ACTIVE, 'student');
+ $this->assertIsEnrolled(1, 2, ENROL_USER_ACTIVE, 'teacher');
+
+
+ $DB->delete_records('enrol_database_test_enrols', array('userid'=>'userid1', 'courseid'=>'courseid1', 'roleid'=>'student'));
+ $plugin->set_config('unenrolaction', ENROL_EXT_REMOVED_UNENROL);
+ $plugin->sync_user_enrolments(self::$users[1]);
+ $this->assertEquals(2, $DB->count_records('user_enrolments', array()));
+ $this->assertEquals(2, $DB->count_records('enrol', array('enrol'=>'database')));
+ $this->assertEquals(2, $DB->count_records('role_assignments', array('component'=>'enrol_database')));
+ $this->assertIsNotEnrolled(1, 1);
+ $this->assertIsEnrolled(1, 2, ENROL_USER_ACTIVE, 'teacher');
+
+
+ // Test all other mapping options.
+
+ $this->reset_enrol_database();
+
+ $this->assertEquals(0, $DB->count_records('user_enrolments', array()));
+ $this->assertEquals(0, $DB->count_records('enrol', array('enrol'=>'database')));
+ $this->assertEquals(0, $DB->count_records('role_assignments', array('component'=>'enrol_database')));
+
+ $plugin->set_config('localcoursefield', 'id');
+ $plugin->set_config('localuserfield', 'id');
+ $plugin->set_config('localrolefield', 'id');
+
+ $DB->insert_record('enrol_database_test_enrols', array('userid'=>self::$users[1]->id, 'courseid'=>self::$courses[1]->id, 'roleid'=>self::$roles['student']->id));
+ $DB->insert_record('enrol_database_test_enrols', array('userid'=>self::$users[1]->id, 'courseid'=>self::$courses[2]->id, 'roleid'=>self::$roles['teacher']->id));
+ $DB->insert_record('enrol_database_test_enrols', array('userid'=>self::$users[2]->id, 'courseid'=>self::$courses[1]->id, 'roleid'=>self::$roles['student']->id));
+
+ $plugin->sync_user_enrolments(self::$users[1]);
+ $this->assertEquals(2, $DB->count_records('user_enrolments', array()));
+ $this->assertEquals(2, $DB->count_records('enrol', array('enrol'=>'database')));
+ $this->assertEquals(2, $DB->count_records('role_assignments', array('component'=>'enrol_database')));
+ $this->assertIsEnrolled(1, 1, ENROL_USER_ACTIVE, 'student');
+ $this->assertIsEnrolled(1, 2, ENROL_USER_ACTIVE, 'teacher');
+
+
+ $this->reset_enrol_database();
+ $plugin->set_config('localcoursefield', 'shortname');
+ $plugin->set_config('localuserfield', 'email');
+ $plugin->set_config('localrolefield', 'id');
+
+ $DB->insert_record('enrol_database_test_enrols', array('userid'=>self::$users[1]->email, 'courseid'=>self::$courses[1]->shortname, 'roleid'=>self::$roles['student']->id));
+ $DB->insert_record('enrol_database_test_enrols', array('userid'=>self::$users[1]->email, 'courseid'=>self::$courses[2]->shortname, 'roleid'=>self::$roles['teacher']->id));
+ $DB->insert_record('enrol_database_test_enrols', array('userid'=>self::$users[2]->email, 'courseid'=>self::$courses[1]->shortname, 'roleid'=>self::$roles['student']->id));
+
+ $plugin->sync_user_enrolments(self::$users[1]);
+ $this->assertEquals(2, $DB->count_records('user_enrolments', array()));
+ $this->assertEquals(2, $DB->count_records('enrol', array('enrol'=>'database')));
+ $this->assertEquals(2, $DB->count_records('role_assignments', array('component'=>'enrol_database')));
+ $this->assertIsEnrolled(1, 1, ENROL_USER_ACTIVE, 'student');
+ $this->assertIsEnrolled(1, 2, ENROL_USER_ACTIVE, 'teacher');
+
+
+ $this->reset_enrol_database();
+ $plugin->set_config('localcoursefield', 'id');
+ $plugin->set_config('localuserfield', 'username');
+ $plugin->set_config('localrolefield', 'id');
+
+ $DB->insert_record('enrol_database_test_enrols', array('userid'=>self::$users[1]->username, 'courseid'=>self::$courses[1]->id, 'roleid'=>self::$roles['student']->id));
+ $DB->insert_record('enrol_database_test_enrols', array('userid'=>self::$users[1]->username, 'courseid'=>self::$courses[2]->id, 'roleid'=>self::$roles['teacher']->id));
+ $DB->insert_record('enrol_database_test_enrols', array('userid'=>self::$users[2]->username, 'courseid'=>self::$courses[1]->id, 'roleid'=>self::$roles['student']->id));
+
+ $plugin->sync_user_enrolments(self::$users[1]);
+ $this->assertEquals(2, $DB->count_records('user_enrolments', array()));
+ $this->assertEquals(2, $DB->count_records('enrol', array('enrol'=>'database')));
+ $this->assertEquals(2, $DB->count_records('role_assignments', array('component'=>'enrol_database')));
+ $this->assertIsEnrolled(1, 1, ENROL_USER_ACTIVE, 'student');
+ $this->assertIsEnrolled(1, 2, ENROL_USER_ACTIVE, 'teacher');
+ }
+
+ /**
+ * @depends test_sync_user_enrolments
+ */
+ public function test_sync_users() {
+ global $DB;
+
+ $this->resetAfterTest(false);
+ $this->preventResetByRollback();
+ $this->reset_enrol_database();
+
+ $plugin = enrol_get_plugin('database');
+
+ // Test basic enrol sync for one user after login.
+
+ $this->reset_enrol_database();
+ $plugin->set_config('localcoursefield', 'idnumber');
+ $plugin->set_config('localuserfield', 'idnumber');
+ $plugin->set_config('localrolefield', 'shortname');
+
+ $DB->insert_record('enrol_database_test_enrols', array('userid'=>'userid1', 'courseid'=>'courseid1', 'roleid'=>'student'));
+ $DB->insert_record('enrol_database_test_enrols', array('userid'=>'userid1', 'courseid'=>'courseid2', 'roleid'=>'editingteacher'));
+ $DB->insert_record('enrol_database_test_enrols', array('userid'=>'userid2', 'courseid'=>'courseid1', 'roleid'=>'student'));
+ $DB->insert_record('enrol_database_test_enrols', array('userid'=>'xxxxxxx', 'courseid'=>'courseid1', 'roleid'=>'student')); // Bogus record to be ignored.
+ $DB->insert_record('enrol_database_test_enrols', array('userid'=>'userid1', 'courseid'=>'xxxxxxxxx', 'roleid'=>'student')); // Bogus record to be ignored.
+ $this->assertEquals(0, $DB->count_records('user_enrolments', array()));
+ $this->assertEquals(0, $DB->count_records('enrol', array('enrol'=>'database')));
+ $this->assertEquals(0, $DB->count_records('role_assignments', array('component'=>'enrol_database')));
+
+ $plugin->sync_enrolments(false);
+ $this->assertEquals(3, $DB->count_records('user_enrolments', array()));
+ $this->assertEquals(2, $DB->count_records('enrol', array('enrol'=>'database')));
+ $this->assertEquals(3, $DB->count_records('role_assignments', array('component'=>'enrol_database')));
+ $this->assertIsEnrolled(1, 1, ENROL_USER_ACTIVE, 'student');
+ $this->assertIsEnrolled(1, 2, ENROL_USER_ACTIVE, 'editingteacher');
+ $this->assertIsEnrolled(2, 1, ENROL_USER_ACTIVE, 'student');
+
+ $plugin->set_config('defaultrole', self::$roles['teacher']->id);
+ $DB->insert_record('enrol_database_test_enrols', array('userid'=>'userid3', 'courseid'=>'courseid3'));
+ $plugin->sync_enrolments(false);
+ $this->assertEquals(4, $DB->count_records('user_enrolments', array()));
+ $this->assertEquals(3, $DB->count_records('enrol', array('enrol'=>'database')));
+ $this->assertEquals(4, $DB->count_records('role_assignments', array('component'=>'enrol_database')));
+ $this->assertIsEnrolled(1, 1, ENROL_USER_ACTIVE, 'student');
+ $this->assertIsEnrolled(1, 2, ENROL_USER_ACTIVE, 'editingteacher');
+ $this->assertIsEnrolled(2, 1, ENROL_USER_ACTIVE, 'student');
+ $this->assertIsEnrolled(3, 3, ENROL_USER_ACTIVE, 'teacher');
+
+
+ // Test different unenrolment options.
+
+ $DB->delete_records('enrol_database_test_enrols', array('userid'=>'userid1', 'courseid'=>'courseid1', 'roleid'=>'student'));
+ $plugin->set_config('unenrolaction', ENROL_EXT_REMOVED_KEEP);
+ $plugin->sync_enrolments(false);
+ $this->assertEquals(4, $DB->count_records('user_enrolments', array()));
+ $this->assertEquals(3, $DB->count_records('enrol', array('enrol'=>'database')));
+ $this->assertEquals(4, $DB->count_records('role_assignments', array('component'=>'enrol_database')));
+ $this->assertIsEnrolled(1, 1, ENROL_USER_ACTIVE, 'student');
+ $this->assertIsEnrolled(1, 2, ENROL_USER_ACTIVE, 'editingteacher');
+ $this->assertIsEnrolled(2, 1, ENROL_USER_ACTIVE, 'student');
+ $this->assertIsEnrolled(3, 3, ENROL_USER_ACTIVE, 'teacher');
+
+
+ $plugin->set_config('unenrolaction', ENROL_EXT_REMOVED_SUSPEND);
+ $plugin->sync_enrolments(false);
+ $this->assertEquals(4, $DB->count_records('user_enrolments', array()));
+ $this->assertEquals(3, $DB->count_records('enrol', array('enrol'=>'database')));
+ $this->assertEquals(4, $DB->count_records('role_assignments', array('component'=>'enrol_database')));
+ $this->assertIsEnrolled(1, 1, ENROL_USER_SUSPENDED, 'student');
+ $this->assertIsEnrolled(1, 2, ENROL_USER_ACTIVE, 'editingteacher');
+ $this->assertIsEnrolled(2, 1, ENROL_USER_ACTIVE, 'student');
+ $this->assertIsEnrolled(3, 3, ENROL_USER_ACTIVE, 'teacher');
+
+ $DB->insert_record('enrol_database_test_enrols', array('userid'=>'userid1', 'courseid'=>'courseid1', 'roleid'=>'student'));
+ $plugin->sync_enrolments(false);
+ $this->assertEquals(4, $DB->count_records('user_enrolments', array()));
+ $this->assertEquals(3, $DB->count_records('enrol', array('enrol'=>'database')));
+ $this->assertEquals(4, $DB->count_records('role_assignments', array('component'=>'enrol_database')));
+ $this->assertIsEnrolled(1, 1, ENROL_USER_ACTIVE, 'student');
+ $this->assertIsEnrolled(1, 2, ENROL_USER_ACTIVE, 'editingteacher');
+ $this->assertIsEnrolled(2, 1, ENROL_USER_ACTIVE, 'student');
+ $this->assertIsEnrolled(3, 3, ENROL_USER_ACTIVE, 'teacher');
+
+
+ $DB->delete_records('enrol_database_test_enrols', array('userid'=>'userid1', 'courseid'=>'courseid1', 'roleid'=>'student'));
+ $plugin->set_config('unenrolaction', ENROL_EXT_REMOVED_SUSPENDNOROLES);
+ $plugin->sync_enrolments(false);
+ $this->assertEquals(4, $DB->count_records('user_enrolments', array()));
+ $this->assertEquals(3, $DB->count_records('enrol', array('enrol'=>'database')));
+ $this->assertEquals(3, $DB->count_records('role_assignments', array('component'=>'enrol_database')));
+ $this->assertIsEnrolled(1, 1, ENROL_USER_SUSPENDED, false);
+ $this->assertIsEnrolled(1, 2, ENROL_USER_ACTIVE, 'editingteacher');
+ $this->assertIsEnrolled(2, 1, ENROL_USER_ACTIVE, 'student');
+ $this->assertIsEnrolled(3, 3, ENROL_USER_ACTIVE, 'teacher');
+
+ $DB->insert_record('enrol_database_test_enrols', array('userid'=>'userid1', 'courseid'=>'courseid1', 'roleid'=>'student'));
+ $plugin->sync_enrolments(false);
+ $this->assertEquals(4, $DB->count_records('user_enrolments', array()));
+ $this->assertEquals(3, $DB->count_records('enrol', array('enrol'=>'database')));
+ $this->assertEquals(4, $DB->count_records('role_assignments', array('component'=>'enrol_database')));
+ $this->assertIsEnrolled(1, 1, ENROL_USER_ACTIVE, 'student');
+ $this->assertIsEnrolled(1, 2, ENROL_USER_ACTIVE, 'editingteacher');
+ $this->assertIsEnrolled(2, 1, ENROL_USER_ACTIVE, 'student');
+ $this->assertIsEnrolled(3, 3, ENROL_USER_ACTIVE, 'teacher');
+
+
+ $DB->delete_records('enrol_database_test_enrols', array('userid'=>'userid1', 'courseid'=>'courseid1', 'roleid'=>'student'));
+ $plugin->set_config('unenrolaction', ENROL_EXT_REMOVED_UNENROL);
+ $plugin->sync_enrolments(false);
+ $this->assertEquals(3, $DB->count_records('user_enrolments', array()));
+ $this->assertEquals(3, $DB->count_records('enrol', array('enrol'=>'database')));
+ $this->assertEquals(3, $DB->count_records('role_assignments', array('component'=>'enrol_database')));
+ $this->assertIsNotEnrolled(1, 1);
+ $this->assertIsEnrolled(1, 2, ENROL_USER_ACTIVE, 'editingteacher');
+ $this->assertIsEnrolled(2, 1, ENROL_USER_ACTIVE, 'student');
+ $this->assertIsEnrolled(3, 3, ENROL_USER_ACTIVE, 'teacher');
+
+ $DB->insert_record('enrol_database_test_enrols', array('userid'=>'userid1', 'courseid'=>'courseid1', 'roleid'=>'student'));
+ $DB->insert_record('enrol_database_test_enrols', array('userid'=>'userid1', 'courseid'=>'courseid1', 'roleid'=>'teacher'));
+ $plugin->sync_enrolments(false);
+ $this->assertEquals(4, $DB->count_records('user_enrolments', array()));
+ $this->assertEquals(3, $DB->count_records('enrol', array('enrol'=>'database')));
+ $this->assertEquals(5, $DB->count_records('role_assignments', array('component'=>'enrol_database')));
+ $this->assertIsEnrolled(1, 1, ENROL_USER_ACTIVE, 'student');
+ $this->assertIsEnrolled(1, 1, ENROL_USER_ACTIVE, 'teacher');
+ $this->assertIsEnrolled(1, 2, ENROL_USER_ACTIVE, 'editingteacher');
+ $this->assertIsEnrolled(2, 1, ENROL_USER_ACTIVE, 'student');
+ $this->assertIsEnrolled(3, 3, ENROL_USER_ACTIVE, 'teacher');
+
+ $DB->delete_records('enrol_database_test_enrols', array('userid'=>'userid1', 'courseid'=>'courseid1', 'roleid'=>'teacher'));
+ $plugin->sync_enrolments(false);
+ $this->assertEquals(4, $DB->count_records('user_enrolments', array()));
+ $this->assertEquals(3, $DB->count_records('enrol', array('enrol'=>'database')));
+ $this->assertEquals(4, $DB->count_records('role_assignments', array('component'=>'enrol_database')));
+ $this->assertIsEnrolled(1, 1, ENROL_USER_ACTIVE, 'student');
+ $this->assertIsEnrolled(1, 2, ENROL_USER_ACTIVE, 'editingteacher');
+ $this->assertIsEnrolled(2, 1, ENROL_USER_ACTIVE, 'student');
+ $this->assertIsEnrolled(3, 3, ENROL_USER_ACTIVE, 'teacher');
+
+
+ // Test all other mapping options.
+
+ $this->reset_enrol_database();
+
+ $this->assertEquals(0, $DB->count_records('user_enrolments', array()));
+ $this->assertEquals(0, $DB->count_records('enrol', array('enrol'=>'database')));
+ $this->assertEquals(0, $DB->count_records('role_assignments', array('component'=>'enrol_database')));
+
+ $plugin->set_config('localcoursefield', 'id');
+ $plugin->set_config('localuserfield', 'id');
+ $plugin->set_config('localrolefield', 'id');
+
+ $DB->insert_record('enrol_database_test_enrols', array('userid'=>self::$users[1]->id, 'courseid'=>self::$courses[1]->id, 'roleid'=>self::$roles['student']->id));
+ $DB->insert_record('enrol_database_test_enrols', array('userid'=>self::$users[1]->id, 'courseid'=>self::$courses[2]->id, 'roleid'=>self::$roles['teacher']->id));
+ $DB->insert_record('enrol_database_test_enrols', array('userid'=>self::$users[2]->id, 'courseid'=>self::$courses[1]->id, 'roleid'=>self::$roles['student']->id));
+
+ $plugin->sync_enrolments(false);
+ $this->assertEquals(3, $DB->count_records('user_enrolments', array()));
+ $this->assertEquals(2, $DB->count_records('enrol', array('enrol'=>'database')));
+ $this->assertEquals(3, $DB->count_records('role_assignments', array('component'=>'enrol_database')));
+ $this->assertIsEnrolled(1, 1, ENROL_USER_ACTIVE, 'student');
+ $this->assertIsEnrolled(1, 2, ENROL_USER_ACTIVE, 'teacher');
+ $this->assertIsEnrolled(2, 1, ENROL_USER_ACTIVE, 'student');
+
+
+ $this->reset_enrol_database();
+ $plugin->set_config('localcoursefield', 'shortname');
+ $plugin->set_config('localuserfield', 'email');
+ $plugin->set_config('localrolefield', 'id');
+
+ $DB->insert_record('enrol_database_test_enrols', array('userid'=>self::$users[1]->email, 'courseid'=>self::$courses[1]->shortname, 'roleid'=>self::$roles['student']->id));
+ $DB->insert_record('enrol_database_test_enrols', array('userid'=>self::$users[1]->email, 'courseid'=>self::$courses[2]->shortname, 'roleid'=>self::$roles['teacher']->id));
+ $DB->insert_record('enrol_database_test_enrols', array('userid'=>self::$users[2]->email, 'courseid'=>self::$courses[1]->shortname, 'roleid'=>self::$roles['student']->id));
+
+ $plugin->sync_enrolments(false);
+ $this->assertEquals(3, $DB->count_records('user_enrolments', array()));
+ $this->assertEquals(2, $DB->count_records('enrol', array('enrol'=>'database')));
+ $this->assertEquals(3, $DB->count_records('role_assignments', array('component'=>'enrol_database')));
+ $this->assertIsEnrolled(1, 1, ENROL_USER_ACTIVE, 'student');
+ $this->assertIsEnrolled(1, 2, ENROL_USER_ACTIVE, 'teacher');
+ $this->assertIsEnrolled(2, 1, ENROL_USER_ACTIVE, 'student');
+
+
+ $this->reset_enrol_database();
+ $plugin->set_config('localcoursefield', 'id');
+ $plugin->set_config('localuserfield', 'username');
+ $plugin->set_config('localrolefield', 'id');
+
+ $DB->insert_record('enrol_database_test_enrols', array('userid'=>self::$users[1]->username, 'courseid'=>self::$courses[1]->id, 'roleid'=>self::$roles['student']->id));
+ $DB->insert_record('enrol_database_test_enrols', array('userid'=>self::$users[1]->username, 'courseid'=>self::$courses[2]->id, 'roleid'=>self::$roles['teacher']->id));
+ $DB->insert_record('enrol_database_test_enrols', array('userid'=>self::$users[2]->username, 'courseid'=>self::$courses[1]->id, 'roleid'=>self::$roles['student']->id));
+
+ $plugin->sync_enrolments(false);
+ $this->assertEquals(3, $DB->count_records('user_enrolments', array()));
+ $this->assertEquals(2, $DB->count_records('enrol', array('enrol'=>'database')));
+ $this->assertEquals(3, $DB->count_records('role_assignments', array('component'=>'enrol_database')));
+ $this->assertIsEnrolled(1, 1, ENROL_USER_ACTIVE, 'student');
+ $this->assertIsEnrolled(1, 2, ENROL_USER_ACTIVE, 'teacher');
+ $this->assertIsEnrolled(2, 1, ENROL_USER_ACTIVE, 'student');
+
+
+ // Test sync of one course only.
+
+ $this->reset_enrol_database();
+
+ $DB->insert_record('enrol_database_test_enrols', array('userid'=>self::$users[1]->username, 'courseid'=>self::$courses[1]->id, 'roleid'=>self::$roles['student']->id));
+ $DB->insert_record('enrol_database_test_enrols', array('userid'=>self::$users[1]->username, 'courseid'=>self::$courses[2]->id, 'roleid'=>self::$roles['teacher']->id));
+ $DB->insert_record('enrol_database_test_enrols', array('userid'=>self::$users[2]->username, 'courseid'=>self::$courses[1]->id, 'roleid'=>self::$roles['student']->id));
+
+ $this->assertEquals(0, $DB->count_records('user_enrolments', array()));
+ $this->assertEquals(0, $DB->count_records('enrol', array('enrol'=>'database')));
+ $this->assertEquals(0, $DB->count_records('role_assignments', array('component'=>'enrol_database')));
+
+ $plugin->sync_enrolments(false, self::$courses[3]->id);
+ $this->assertEquals(0, $DB->count_records('user_enrolments', array()));
+ $this->assertEquals(1, $DB->count_records('enrol', array('enrol'=>'database')));
+ $this->assertEquals(0, $DB->count_records('role_assignments', array('component'=>'enrol_database')));
+
+ $plugin->sync_enrolments(false, self::$courses[1]->id);
+ $this->assertEquals(2, $DB->count_records('user_enrolments', array()));
+ $this->assertEquals(2, $DB->count_records('enrol', array('enrol'=>'database')));
+ $this->assertEquals(2, $DB->count_records('role_assignments', array('component'=>'enrol_database')));
+ $this->assertIsEnrolled(1, 1, ENROL_USER_ACTIVE, 'student');
+ $this->assertIsEnrolled(2, 1, ENROL_USER_ACTIVE, 'student');
+
+ $plugin->sync_enrolments(false, self::$courses[2]->id);
+ $this->assertEquals(3, $DB->count_records('user_enrolments', array()));
+ $this->assertEquals(3, $DB->count_records('enrol', array('enrol'=>'database')));
+ $this->assertEquals(3, $DB->count_records('role_assignments', array('component'=>'enrol_database')));
+ $this->assertIsEnrolled(1, 1, ENROL_USER_ACTIVE, 'student');
+ $this->assertIsEnrolled(1, 2, ENROL_USER_ACTIVE, 'teacher');
+ $this->assertIsEnrolled(2, 1, ENROL_USER_ACTIVE, 'student');
+
+
+ $plugin->set_config('unenrolaction', ENROL_EXT_REMOVED_UNENROL);
+
+ $DB->delete_records('enrol_database_test_enrols', array());
+
+ $plugin->sync_enrolments(false, self::$courses[1]->id);
+ $this->assertEquals(1, $DB->count_records('user_enrolments', array()));
+ $this->assertEquals(3, $DB->count_records('enrol', array('enrol'=>'database')));
+ $this->assertEquals(1, $DB->count_records('role_assignments', array('component'=>'enrol_database')));
+ $this->assertIsEnrolled(1, 2, ENROL_USER_ACTIVE, 'teacher');
+
+ $plugin->sync_enrolments(false, self::$courses[2]->id);
+ $this->assertEquals(0, $DB->count_records('user_enrolments', array()));
+ $this->assertEquals(3, $DB->count_records('enrol', array('enrol'=>'database')));
+ $this->assertEquals(0, $DB->count_records('role_assignments', array('component'=>'enrol_database')));
+ }
+
+ /**
+ * @depends test_sync_users
+ */
+ public function test_sync_courses() {
+ global $DB;
+
+ $this->resetAfterTest(true);
+ $this->preventResetByRollback();
+ $this->reset_enrol_database();
+
+ $plugin = enrol_get_plugin('database');
+
+ $plugin->set_config('localcategoryfield', 'id');
+ $coursecat = $this->getDataGenerator()->create_category(array('name'=>'Test category 1', 'idnumber'=>'tcid1'));
+ $defcat = $DB->get_record('course_categories', array('id'=>$plugin->get_config('defaultcategory')));
+