2 // This file is part of Moodle - http://moodle.org/
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.
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.
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/>.
18 * External database enrolment sync tests, this also tests adodb drivers
19 * that are matching our four supported Moodle database drivers.
21 * @package enrol_database
23 * @copyright 2011 Petr Skoda {@link http://skodak.org}
24 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
27 defined('MOODLE_INTERNAL') || die();
29 class enrol_database_testcase extends advanced_testcase {
30 protected static $courses = array();
31 protected static $users = array();
32 protected static $roles = array();
34 /** @var string Original error log */
37 protected function init_enrol_database() {
40 // Discard error logs from AdoDB.
41 $this->oldlog = ini_get('error_log');
42 ini_set('error_log', "$CFG->dataroot/testlog.log");
44 $dbman = $DB->get_manager();
46 set_config('dbencoding', 'utf-8', 'enrol_database');
48 set_config('dbhost', $CFG->dbhost, 'enrol_database');
49 set_config('dbuser', $CFG->dbuser, 'enrol_database');
50 set_config('dbpass', $CFG->dbpass, 'enrol_database');
51 set_config('dbname', $CFG->dbname, 'enrol_database');
53 if (!empty($CFG->dboptions['dbport'])) {
54 set_config('dbhost', $CFG->dbhost.':'.$CFG->dboptions['dbport'], 'enrol_database');
57 switch (get_class($DB)) {
58 case 'mssql_native_moodle_database':
59 set_config('dbtype', 'mssql_n', 'enrol_database');
60 set_config('dbsybasequoting', '1', 'enrol_database');
63 case 'mariadb_native_moodle_database':
64 case 'mysqli_native_moodle_database':
65 set_config('dbtype', 'mysqli', 'enrol_database');
66 set_config('dbsetupsql', "SET NAMES 'UTF-8'", 'enrol_database');
67 set_config('dbsybasequoting', '0', 'enrol_database');
68 if (!empty($CFG->dboptions['dbsocket'])) {
69 $dbsocket = $CFG->dboptions['dbsocket'];
70 if ((strpos($dbsocket, '/') === false and strpos($dbsocket, '\\') === false)) {
71 $dbsocket = ini_get('mysqli.default_socket');
73 set_config('dbtype', 'mysqli://'.rawurlencode($CFG->dbuser).':'.rawurlencode($CFG->dbpass).'@'.rawurlencode($CFG->dbhost).'/'.rawurlencode($CFG->dbname).'?socket='.rawurlencode($dbsocket), 'enrol_database');
77 case 'oci_native_moodle_database':
78 set_config('dbtype', 'oci8po', 'enrol_database');
79 set_config('dbsybasequoting', '1', 'enrol_database');
82 case 'pgsql_native_moodle_database':
83 set_config('dbtype', 'postgres7', 'enrol_database');
84 $setupsql = "SET NAMES 'UTF-8'";
85 if (!empty($CFG->dboptions['dbschema'])) {
86 $setupsql .= "; SET search_path = '".$CFG->dboptions['dbschema']."'";
88 set_config('dbsetupsql', $setupsql, 'enrol_database');
89 set_config('dbsybasequoting', '0', 'enrol_database');
90 if (!empty($CFG->dboptions['dbsocket']) and ($CFG->dbhost === 'localhost' or $CFG->dbhost === '127.0.0.1')) {
91 if (strpos($CFG->dboptions['dbsocket'], '/') !== false) {
92 $socket = $CFG->dboptions['dbsocket'];
93 if (!empty($CFG->dboptions['dbport'])) {
94 $socket .= ':' . $CFG->dboptions['dbport'];
96 set_config('dbhost', $socket, 'enrol_database');
98 set_config('dbhost', '', 'enrol_database');
103 case 'sqlsrv_native_moodle_database':
104 set_config('dbtype', 'mssqlnative', 'enrol_database');
105 set_config('dbsybasequoting', '1', 'enrol_database');
109 throw new exception('Unknown database driver '.get_class($DB));
112 // NOTE: It is stongly discouraged to create new tables in advanced_testcase classes,
113 // but there is no other simple way to test ext database enrol sync, so let's
114 // disable transactions are try to cleanup after the tests.
116 $table = new xmldb_table('enrol_database_test_enrols');
117 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
118 $table->add_field('courseid', XMLDB_TYPE_CHAR, '255', null, null, null);
119 $table->add_field('userid', XMLDB_TYPE_CHAR, '255', null, null, null);
120 $table->add_field('roleid', XMLDB_TYPE_CHAR, '255', null, null, null);
121 $table->add_field('otheruser', XMLDB_TYPE_CHAR, '1', null, XMLDB_NOTNULL, null, '0');
122 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
123 if ($dbman->table_exists($table)) {
124 $dbman->drop_table($table);
126 $dbman->create_table($table);
127 set_config('remoteenroltable', $CFG->prefix.'enrol_database_test_enrols', 'enrol_database');
128 set_config('remotecoursefield', 'courseid', 'enrol_database');
129 set_config('remoteuserfield', 'userid', 'enrol_database');
130 set_config('remoterolefield', 'roleid', 'enrol_database');
131 set_config('remoteotheruserfield', 'otheruser', 'enrol_database');
133 $table = new xmldb_table('enrol_database_test_courses');
134 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
135 $table->add_field('fullname', XMLDB_TYPE_CHAR, '255', null, null, null);
136 $table->add_field('shortname', XMLDB_TYPE_CHAR, '255', null, null, null);
137 $table->add_field('idnumber', XMLDB_TYPE_CHAR, '255', null, null, null);
138 $table->add_field('category', XMLDB_TYPE_CHAR, '255', null, null, null);
139 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
140 if ($dbman->table_exists($table)) {
141 $dbman->drop_table($table);
143 $dbman->create_table($table);
144 set_config('newcoursetable', $CFG->prefix.'enrol_database_test_courses', 'enrol_database');
145 set_config('newcoursefullname', 'fullname', 'enrol_database');
146 set_config('newcourseshortname', 'shortname', 'enrol_database');
147 set_config('newcourseidnumber', 'idnumber', 'enrol_database');
148 set_config('newcoursecategory', 'category', 'enrol_database');
150 // Create some test users and courses.
151 for ($i = 1; $i <= 4; $i++) {
152 self::$courses[$i] = $this->getDataGenerator()->create_course(array('fullname' => 'Test course '.$i, 'shortname' => 'tc'.$i, 'idnumber' => 'courseid'.$i));
155 for ($i = 1; $i <= 10; $i++) {
156 self::$users[$i] = $this->getDataGenerator()->create_user(array('username' => 'username'.$i, 'idnumber' => 'userid'.$i, 'email' => 'user'.$i.'@example.com'));
159 foreach (get_all_roles() as $role) {
160 self::$roles[$role->shortname] = $role;
164 protected function cleanup_enrol_database() {
167 $dbman = $DB->get_manager();
168 $table = new xmldb_table('enrol_database_test_enrols');
169 $dbman->drop_table($table);
170 $table = new xmldb_table('enrol_database_test_courses');
171 $dbman->drop_table($table);
173 self::$courses = null;
177 ini_set('error_log', $this->oldlog);
180 protected function reset_enrol_database() {
183 $DB->delete_records('enrol_database_test_enrols', array());
184 $DB->delete_records('enrol_database_test_courses', array());
186 $plugin = enrol_get_plugin('database');
187 $instances = $DB->get_records('enrol', array('enrol' => 'database'));
188 foreach($instances as $instance) {
189 $plugin->delete_instance($instance);
193 protected function assertIsEnrolled($userindex, $courseindex, $status=null, $rolename = null) {
195 $dbinstance = $DB->get_record('enrol', array('courseid' => self::$courses[$courseindex]->id, 'enrol' => 'database'), '*', MUST_EXIST);
197 $conditions = array('enrolid' => $dbinstance->id, 'userid' => self::$users[$userindex]->id);
198 if ($status !== null) {
199 $conditions['status'] = $status;
201 $this->assertTrue($DB->record_exists('user_enrolments', $conditions));
203 $this->assertHasRoleAssignment($userindex, $courseindex, $rolename);
206 protected function assertHasRoleAssignment($userindex, $courseindex, $rolename = null) {
208 $dbinstance = $DB->get_record('enrol', array('courseid' => self::$courses[$courseindex]->id, 'enrol' => 'database'), '*', MUST_EXIST);
210 $coursecontext = context_course::instance(self::$courses[$courseindex]->id);
211 if ($rolename === false) {
212 $this->assertFalse($DB->record_exists('role_assignments', array('component' => 'enrol_database', 'itemid' => $dbinstance->id, 'userid' => self::$users[$userindex]->id, 'contextid' => $coursecontext->id)));
213 } else if ($rolename !== null) {
214 $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)));
218 protected function assertIsNotEnrolled($userindex, $courseindex) {
220 if (!$dbinstance = $DB->get_record('enrol', array('courseid' => self::$courses[$courseindex]->id, 'enrol' => 'database'))) {
223 $this->assertFalse($DB->record_exists('user_enrolments', array('enrolid' => $dbinstance->id, 'userid' => self::$users[$userindex]->id)));
226 public function test_sync_user_enrolments() {
229 $this->init_enrol_database();
231 $this->resetAfterTest(false);
232 $this->preventResetByRollback();
234 $plugin = enrol_get_plugin('database');
236 // Test basic enrol sync for one user after login.
238 $this->reset_enrol_database();
239 $plugin->set_config('localcoursefield', 'idnumber');
240 $plugin->set_config('localuserfield', 'idnumber');
241 $plugin->set_config('localrolefield', 'shortname');
243 $plugin->set_config('defaultrole', self::$roles['student']->id);
245 $DB->insert_record('enrol_database_test_enrols', array('userid' => 'userid1', 'courseid' => 'courseid1', 'roleid' => 'student'));
246 $DB->insert_record('enrol_database_test_enrols', array('userid' => 'userid1', 'courseid' => 'courseid2', 'roleid' => 'teacher'));
247 $DB->insert_record('enrol_database_test_enrols', array('userid' => 'userid2', 'courseid' => 'courseid1', 'roleid' => null));
248 $DB->insert_record('enrol_database_test_enrols', array('userid' => 'userid4', 'courseid' => 'courseid4', 'roleid' => 'editingteacher', 'otheruser' => '1'));
249 $DB->insert_record('enrol_database_test_enrols', array('userid' => 'xxxxxxx', 'courseid' => 'courseid1', 'roleid' => 'student')); // Bogus record to be ignored.
250 $DB->insert_record('enrol_database_test_enrols', array('userid' => 'userid1', 'courseid' => 'xxxxxxxxx', 'roleid' => 'student')); // Bogus record to be ignored.
252 $this->assertEquals(0, $DB->count_records('user_enrolments', array()));
253 $this->assertEquals(0, $DB->count_records('enrol', array('enrol' => 'database')));
254 $this->assertEquals(0, $DB->count_records('role_assignments', array('component' => 'enrol_database')));
256 $plugin->sync_user_enrolments(self::$users[1]);
257 $this->assertEquals(2, $DB->count_records('user_enrolments', array()));
258 $this->assertEquals(2, $DB->count_records('enrol', array('enrol' => 'database')));
259 $this->assertEquals(2, $DB->count_records('role_assignments', array('component' => 'enrol_database')));
260 $this->assertIsEnrolled(1, 1, ENROL_USER_ACTIVE, 'student');
261 $this->assertIsEnrolled(1, 2, ENROL_USER_ACTIVE, 'teacher');
263 // Make sure there are no errors or changes on the next login.
265 $plugin->sync_user_enrolments(self::$users[1]);
266 $this->assertEquals(2, $DB->count_records('user_enrolments', array()));
267 $this->assertEquals(2, $DB->count_records('enrol', array('enrol' => 'database')));
268 $this->assertEquals(2, $DB->count_records('role_assignments', array('component' => 'enrol_database')));
269 $this->assertIsEnrolled(1, 1, ENROL_USER_ACTIVE, 'student');
270 $this->assertIsEnrolled(1, 2, ENROL_USER_ACTIVE, 'teacher');
272 $plugin->sync_user_enrolments(self::$users[2]);
273 $this->assertEquals(3, $DB->count_records('user_enrolments', array()));
274 $this->assertEquals(2, $DB->count_records('enrol', array('enrol' => 'database')));
275 $this->assertEquals(3, $DB->count_records('role_assignments', array('component' => 'enrol_database')));
276 $this->assertIsEnrolled(1, 1, ENROL_USER_ACTIVE, 'student');
277 $this->assertIsEnrolled(1, 2, ENROL_USER_ACTIVE, 'teacher');
278 $this->assertIsEnrolled(2, 1, ENROL_USER_ACTIVE, 'student');
280 $plugin->sync_user_enrolments(self::$users[4]);
281 $this->assertEquals(3, $DB->count_records('user_enrolments', array()));
282 $this->assertEquals(3, $DB->count_records('enrol', array('enrol' => 'database')));
283 $this->assertEquals(4, $DB->count_records('role_assignments', array('component' => 'enrol_database')));
284 $this->assertIsEnrolled(1, 1, ENROL_USER_ACTIVE, 'student');
285 $this->assertIsEnrolled(1, 2, ENROL_USER_ACTIVE, 'teacher');
286 $this->assertIsEnrolled(2, 1, ENROL_USER_ACTIVE, 'student');
287 $this->assertIsNotEnrolled(4, 4);
288 $this->assertHasRoleAssignment(4, 4, 'editingteacher');
290 // Enrolment removals.
292 $DB->delete_records('enrol_database_test_enrols', array('userid' => 'userid1', 'courseid' => 'courseid1', 'roleid' => 'student'));
293 $plugin->set_config('unenrolaction', ENROL_EXT_REMOVED_KEEP);
294 $plugin->sync_user_enrolments(self::$users[1]);
295 $this->assertEquals(3, $DB->count_records('user_enrolments', array()));
296 $this->assertEquals(3, $DB->count_records('enrol', array('enrol' => 'database')));
297 $this->assertEquals(4, $DB->count_records('role_assignments', array('component' => 'enrol_database')));
298 $this->assertIsEnrolled(1, 1, ENROL_USER_ACTIVE, 'student');
299 $this->assertIsEnrolled(1, 2, ENROL_USER_ACTIVE, 'teacher');
302 $plugin->set_config('unenrolaction', ENROL_EXT_REMOVED_SUSPEND);
303 $plugin->sync_user_enrolments(self::$users[1]);
304 $this->assertEquals(3, $DB->count_records('user_enrolments', array()));
305 $this->assertEquals(3, $DB->count_records('enrol', array('enrol' => 'database')));
306 $this->assertEquals(4, $DB->count_records('role_assignments', array('component' => 'enrol_database')));
307 $this->assertIsEnrolled(1, 1, ENROL_USER_SUSPENDED, 'student');
308 $this->assertIsEnrolled(1, 2, ENROL_USER_ACTIVE, 'teacher');
310 $DB->insert_record('enrol_database_test_enrols', array('userid' => 'userid1', 'courseid' => 'courseid1', 'roleid' => 'student'));
311 $plugin->sync_user_enrolments(self::$users[1]);
312 $this->assertEquals(3, $DB->count_records('user_enrolments', array()));
313 $this->assertEquals(3, $DB->count_records('enrol', array('enrol' => 'database')));
314 $this->assertEquals(4, $DB->count_records('role_assignments', array('component' => 'enrol_database')));
315 $this->assertIsEnrolled(1, 1, ENROL_USER_ACTIVE, 'student');
316 $this->assertIsEnrolled(1, 2, ENROL_USER_ACTIVE, 'teacher');
319 $DB->delete_records('enrol_database_test_enrols', array('userid' => 'userid1', 'courseid' => 'courseid1', 'roleid' => 'student'));
320 $plugin->set_config('unenrolaction', ENROL_EXT_REMOVED_SUSPENDNOROLES);
321 $plugin->sync_user_enrolments(self::$users[1]);
322 $this->assertEquals(3, $DB->count_records('user_enrolments', array()));
323 $this->assertEquals(3, $DB->count_records('enrol', array('enrol' => 'database')));
324 $this->assertEquals(3, $DB->count_records('role_assignments', array('component' => 'enrol_database')));
325 $this->assertIsEnrolled(1, 1, ENROL_USER_SUSPENDED, false);
326 $this->assertIsEnrolled(1, 2, ENROL_USER_ACTIVE, 'teacher');
328 $DB->insert_record('enrol_database_test_enrols', array('userid' => 'userid1', 'courseid' => 'courseid1', 'roleid' => 'student'));
329 $plugin->sync_user_enrolments(self::$users[1]);
330 $this->assertEquals(3, $DB->count_records('user_enrolments', array()));
331 $this->assertEquals(3, $DB->count_records('enrol', array('enrol' => 'database')));
332 $this->assertEquals(4, $DB->count_records('role_assignments', array('component' => 'enrol_database')));
333 $this->assertIsEnrolled(1, 1, ENROL_USER_ACTIVE, 'student');
334 $this->assertIsEnrolled(1, 2, ENROL_USER_ACTIVE, 'teacher');
337 $DB->delete_records('enrol_database_test_enrols', array('userid' => 'userid1', 'courseid' => 'courseid1', 'roleid' => 'student'));
338 $plugin->set_config('unenrolaction', ENROL_EXT_REMOVED_UNENROL);
339 $plugin->sync_user_enrolments(self::$users[1]);
340 $this->assertEquals(2, $DB->count_records('user_enrolments', array()));
341 $this->assertEquals(3, $DB->count_records('enrol', array('enrol' => 'database')));
342 $this->assertEquals(3, $DB->count_records('role_assignments', array('component' => 'enrol_database')));
343 $this->assertIsNotEnrolled(1, 1);
344 $this->assertIsEnrolled(1, 2, ENROL_USER_ACTIVE, 'teacher');
346 $DB->delete_records('enrol_database_test_enrols', array('userid' => 'userid4', 'courseid' => 'courseid4', 'roleid' => 'editingteacher'));
347 $plugin->set_config('unenrolaction', ENROL_EXT_REMOVED_SUSPENDNOROLES);
348 $plugin->sync_user_enrolments(self::$users[4]);
349 $this->assertEquals(2, $DB->count_records('user_enrolments', array()));
350 $this->assertEquals(3, $DB->count_records('enrol', array('enrol' => 'database')));
351 $this->assertEquals(2, $DB->count_records('role_assignments', array('component' => 'enrol_database')));
352 $this->assertIsNotEnrolled(4, 4);
353 $this->assertHasRoleAssignment(4, 4, false);
355 // Test all other mapping options.
357 $this->reset_enrol_database();
359 $this->assertEquals(0, $DB->count_records('user_enrolments', array()));
360 $this->assertEquals(0, $DB->count_records('enrol', array('enrol' => 'database')));
361 $this->assertEquals(0, $DB->count_records('role_assignments', array('component' => 'enrol_database')));
363 $plugin->set_config('localcoursefield', 'id');
364 $plugin->set_config('localuserfield', 'id');
365 $plugin->set_config('localrolefield', 'id');
367 $DB->insert_record('enrol_database_test_enrols', array('userid' => self::$users[1]->id, 'courseid' => self::$courses[1]->id, 'roleid' => self::$roles['student']->id));
368 $DB->insert_record('enrol_database_test_enrols', array('userid' => self::$users[1]->id, 'courseid' => self::$courses[2]->id, 'roleid' => self::$roles['teacher']->id));
369 $DB->insert_record('enrol_database_test_enrols', array('userid' => self::$users[2]->id, 'courseid' => self::$courses[1]->id, 'roleid' => self::$roles['student']->id));
371 $plugin->sync_user_enrolments(self::$users[1]);
372 $this->assertEquals(2, $DB->count_records('user_enrolments', array()));
373 $this->assertEquals(2, $DB->count_records('enrol', array('enrol' => 'database')));
374 $this->assertEquals(2, $DB->count_records('role_assignments', array('component' => 'enrol_database')));
375 $this->assertIsEnrolled(1, 1, ENROL_USER_ACTIVE, 'student');
376 $this->assertIsEnrolled(1, 2, ENROL_USER_ACTIVE, 'teacher');
379 $this->reset_enrol_database();
380 $plugin->set_config('localcoursefield', 'shortname');
381 $plugin->set_config('localuserfield', 'email');
382 $plugin->set_config('localrolefield', 'id');
384 $DB->insert_record('enrol_database_test_enrols', array('userid' => self::$users[1]->email, 'courseid' => self::$courses[1]->shortname, 'roleid' => self::$roles['student']->id));
385 $DB->insert_record('enrol_database_test_enrols', array('userid' => self::$users[1]->email, 'courseid' => self::$courses[2]->shortname, 'roleid' => self::$roles['teacher']->id));
386 $DB->insert_record('enrol_database_test_enrols', array('userid' => self::$users[2]->email, 'courseid' => self::$courses[1]->shortname, 'roleid' => self::$roles['student']->id));
388 $plugin->sync_user_enrolments(self::$users[1]);
389 $this->assertEquals(2, $DB->count_records('user_enrolments', array()));
390 $this->assertEquals(2, $DB->count_records('enrol', array('enrol' => 'database')));
391 $this->assertEquals(2, $DB->count_records('role_assignments', array('component' => 'enrol_database')));
392 $this->assertIsEnrolled(1, 1, ENROL_USER_ACTIVE, 'student');
393 $this->assertIsEnrolled(1, 2, ENROL_USER_ACTIVE, 'teacher');
396 $this->reset_enrol_database();
397 $plugin->set_config('localcoursefield', 'id');
398 $plugin->set_config('localuserfield', 'username');
399 $plugin->set_config('localrolefield', 'id');
401 $DB->insert_record('enrol_database_test_enrols', array('userid' => self::$users[1]->username, 'courseid' => self::$courses[1]->id, 'roleid' => self::$roles['student']->id));
402 $DB->insert_record('enrol_database_test_enrols', array('userid' => self::$users[1]->username, 'courseid' => self::$courses[2]->id, 'roleid' => self::$roles['teacher']->id));
403 $DB->insert_record('enrol_database_test_enrols', array('userid' => self::$users[2]->username, 'courseid' => self::$courses[1]->id, 'roleid' => self::$roles['student']->id));
405 $plugin->sync_user_enrolments(self::$users[1]);
406 $this->assertEquals(2, $DB->count_records('user_enrolments', array()));
407 $this->assertEquals(2, $DB->count_records('enrol', array('enrol' => 'database')));
408 $this->assertEquals(2, $DB->count_records('role_assignments', array('component' => 'enrol_database')));
409 $this->assertIsEnrolled(1, 1, ENROL_USER_ACTIVE, 'student');
410 $this->assertIsEnrolled(1, 2, ENROL_USER_ACTIVE, 'teacher');
414 * @depends test_sync_user_enrolments
416 public function test_sync_users() {
419 $this->resetAfterTest(false);
420 $this->preventResetByRollback();
421 $this->reset_enrol_database();
423 $plugin = enrol_get_plugin('database');
425 $trace = new null_progress_trace();
427 // Test basic enrol sync for one user after login.
429 $this->reset_enrol_database();
430 $plugin->set_config('localcoursefield', 'idnumber');
431 $plugin->set_config('localuserfield', 'idnumber');
432 $plugin->set_config('localrolefield', 'shortname');
434 $DB->insert_record('enrol_database_test_enrols', array('userid' => 'userid1', 'courseid' => 'courseid1', 'roleid' => 'student'));
435 $DB->insert_record('enrol_database_test_enrols', array('userid' => 'userid1', 'courseid' => 'courseid2', 'roleid' => 'editingteacher'));
436 $DB->insert_record('enrol_database_test_enrols', array('userid' => 'userid2', 'courseid' => 'courseid1', 'roleid' => 'student'));
437 $DB->insert_record('enrol_database_test_enrols', array('userid' => 'userid4', 'courseid' => 'courseid4', 'roleid' => 'editingteacher', 'otheruser' => '1'));
438 $DB->insert_record('enrol_database_test_enrols', array('userid' => 'xxxxxxx', 'courseid' => 'courseid1', 'roleid' => 'student')); // Bogus record to be ignored.
439 $DB->insert_record('enrol_database_test_enrols', array('userid' => 'userid1', 'courseid' => 'xxxxxxxxx', 'roleid' => 'student')); // Bogus record to be ignored.
440 $this->assertEquals(0, $DB->count_records('user_enrolments', array()));
441 $this->assertEquals(0, $DB->count_records('enrol', array('enrol' => 'database')));
442 $this->assertEquals(0, $DB->count_records('role_assignments', array('component' => 'enrol_database')));
444 $plugin->sync_enrolments($trace);
445 $this->assertEquals(3, $DB->count_records('user_enrolments', array()));
446 $this->assertEquals(3, $DB->count_records('enrol', array('enrol' => 'database')));
447 $this->assertEquals(4, $DB->count_records('role_assignments', array('component' => 'enrol_database')));
448 $this->assertIsEnrolled(1, 1, ENROL_USER_ACTIVE, 'student');
449 $this->assertIsEnrolled(1, 2, ENROL_USER_ACTIVE, 'editingteacher');
450 $this->assertIsEnrolled(2, 1, ENROL_USER_ACTIVE, 'student');
451 $this->assertIsNotEnrolled(4, 4);
452 $this->assertHasRoleAssignment(4, 4, 'editingteacher');
454 $plugin->set_config('defaultrole', self::$roles['teacher']->id);
455 $DB->insert_record('enrol_database_test_enrols', array('userid' => 'userid3', 'courseid' => 'courseid3'));
456 $plugin->sync_enrolments($trace);
457 $this->assertEquals(4, $DB->count_records('user_enrolments', array()));
458 $this->assertEquals(4, $DB->count_records('enrol', array('enrol' => 'database')));
459 $this->assertEquals(5, $DB->count_records('role_assignments', array('component' => 'enrol_database')));
460 $this->assertIsEnrolled(1, 1, ENROL_USER_ACTIVE, 'student');
461 $this->assertIsEnrolled(1, 2, ENROL_USER_ACTIVE, 'editingteacher');
462 $this->assertIsEnrolled(2, 1, ENROL_USER_ACTIVE, 'student');
463 $this->assertIsNotEnrolled(4, 4);
464 $this->assertHasRoleAssignment(4, 4, 'editingteacher');
465 $this->assertIsEnrolled(3, 3, ENROL_USER_ACTIVE, 'teacher');
468 // Test different unenrolment options.
470 $DB->delete_records('enrol_database_test_enrols', array('userid' => 'userid1', 'courseid' => 'courseid1', 'roleid' => 'student'));
471 $plugin->set_config('unenrolaction', ENROL_EXT_REMOVED_KEEP);
472 $plugin->sync_enrolments($trace);
473 $this->assertEquals(4, $DB->count_records('user_enrolments', array()));
474 $this->assertEquals(4, $DB->count_records('enrol', array('enrol' => 'database')));
475 $this->assertEquals(5, $DB->count_records('role_assignments', array('component' => 'enrol_database')));
476 $this->assertIsEnrolled(1, 1, ENROL_USER_ACTIVE, 'student');
477 $this->assertIsEnrolled(1, 2, ENROL_USER_ACTIVE, 'editingteacher');
478 $this->assertIsEnrolled(2, 1, ENROL_USER_ACTIVE, 'student');
479 $this->assertIsNotEnrolled(4, 4);
480 $this->assertHasRoleAssignment(4, 4, 'editingteacher');
481 $this->assertIsEnrolled(3, 3, ENROL_USER_ACTIVE, 'teacher');
484 $plugin->set_config('unenrolaction', ENROL_EXT_REMOVED_SUSPEND);
485 $plugin->sync_enrolments($trace);
486 $this->assertEquals(4, $DB->count_records('user_enrolments', array()));
487 $this->assertEquals(4, $DB->count_records('enrol', array('enrol' => 'database')));
488 $this->assertEquals(5, $DB->count_records('role_assignments', array('component' => 'enrol_database')));
489 $this->assertIsEnrolled(1, 1, ENROL_USER_SUSPENDED, 'student');
490 $this->assertIsEnrolled(1, 2, ENROL_USER_ACTIVE, 'editingteacher');
491 $this->assertIsEnrolled(2, 1, ENROL_USER_ACTIVE, 'student');
492 $this->assertIsNotEnrolled(4, 4);
493 $this->assertHasRoleAssignment(4, 4, 'editingteacher');
494 $this->assertIsEnrolled(3, 3, ENROL_USER_ACTIVE, 'teacher');
496 $DB->insert_record('enrol_database_test_enrols', array('userid' => 'userid1', 'courseid' => 'courseid1', 'roleid' => 'student'));
497 $plugin->sync_enrolments($trace);
498 $this->assertEquals(4, $DB->count_records('user_enrolments', array()));
499 $this->assertEquals(4, $DB->count_records('enrol', array('enrol' => 'database')));
500 $this->assertEquals(5, $DB->count_records('role_assignments', array('component' => 'enrol_database')));
501 $this->assertIsEnrolled(1, 1, ENROL_USER_ACTIVE, 'student');
502 $this->assertIsEnrolled(1, 2, ENROL_USER_ACTIVE, 'editingteacher');
503 $this->assertIsEnrolled(2, 1, ENROL_USER_ACTIVE, 'student');
504 $this->assertIsNotEnrolled(4, 4);
505 $this->assertHasRoleAssignment(4, 4, 'editingteacher');
506 $this->assertIsEnrolled(3, 3, ENROL_USER_ACTIVE, 'teacher');
509 $DB->delete_records('enrol_database_test_enrols', array('userid' => 'userid1', 'courseid' => 'courseid1', 'roleid' => 'student'));
510 $plugin->set_config('unenrolaction', ENROL_EXT_REMOVED_SUSPENDNOROLES);
511 $plugin->sync_enrolments($trace);
512 $this->assertEquals(4, $DB->count_records('user_enrolments', array()));
513 $this->assertEquals(4, $DB->count_records('enrol', array('enrol' => 'database')));
514 $this->assertEquals(4, $DB->count_records('role_assignments', array('component' => 'enrol_database')));
515 $this->assertIsEnrolled(1, 1, ENROL_USER_SUSPENDED, false);
516 $this->assertIsEnrolled(1, 2, ENROL_USER_ACTIVE, 'editingteacher');
517 $this->assertIsEnrolled(2, 1, ENROL_USER_ACTIVE, 'student');
518 $this->assertIsNotEnrolled(4, 4);
519 $this->assertHasRoleAssignment(4, 4, 'editingteacher');
520 $this->assertIsEnrolled(3, 3, ENROL_USER_ACTIVE, 'teacher');
522 $DB->insert_record('enrol_database_test_enrols', array('userid' => 'userid1', 'courseid' => 'courseid1', 'roleid' => 'student'));
523 $plugin->sync_enrolments($trace);
524 $this->assertEquals(4, $DB->count_records('user_enrolments', array()));
525 $this->assertEquals(4, $DB->count_records('enrol', array('enrol' => 'database')));
526 $this->assertEquals(5, $DB->count_records('role_assignments', array('component' => 'enrol_database')));
527 $this->assertIsEnrolled(1, 1, ENROL_USER_ACTIVE, 'student');
528 $this->assertIsEnrolled(1, 2, ENROL_USER_ACTIVE, 'editingteacher');
529 $this->assertIsEnrolled(2, 1, ENROL_USER_ACTIVE, 'student');
530 $this->assertIsNotEnrolled(4, 4);
531 $this->assertHasRoleAssignment(4, 4, 'editingteacher');
532 $this->assertIsEnrolled(3, 3, ENROL_USER_ACTIVE, 'teacher');
535 $DB->delete_records('enrol_database_test_enrols', array('userid' => 'userid1', 'courseid' => 'courseid1', 'roleid' => 'student'));
536 $plugin->set_config('unenrolaction', ENROL_EXT_REMOVED_UNENROL);
537 $plugin->sync_enrolments($trace);
538 $this->assertEquals(3, $DB->count_records('user_enrolments', array()));
539 $this->assertEquals(4, $DB->count_records('enrol', array('enrol' => 'database')));
540 $this->assertEquals(4, $DB->count_records('role_assignments', array('component' => 'enrol_database')));
541 $this->assertIsNotEnrolled(1, 1);
542 $this->assertIsEnrolled(1, 2, ENROL_USER_ACTIVE, 'editingteacher');
543 $this->assertIsEnrolled(2, 1, ENROL_USER_ACTIVE, 'student');
544 $this->assertIsNotEnrolled(4, 4);
545 $this->assertHasRoleAssignment(4, 4, 'editingteacher');
546 $this->assertIsEnrolled(3, 3, ENROL_USER_ACTIVE, 'teacher');
548 $DB->insert_record('enrol_database_test_enrols', array('userid' => 'userid1', 'courseid' => 'courseid1', 'roleid' => 'student'));
549 $DB->insert_record('enrol_database_test_enrols', array('userid' => 'userid1', 'courseid' => 'courseid1', 'roleid' => 'teacher'));
550 $plugin->sync_enrolments($trace);
551 $this->assertEquals(4, $DB->count_records('user_enrolments', array()));
552 $this->assertEquals(4, $DB->count_records('enrol', array('enrol' => 'database')));
553 $this->assertEquals(6, $DB->count_records('role_assignments', array('component' => 'enrol_database')));
554 $this->assertIsEnrolled(1, 1, ENROL_USER_ACTIVE, 'student');
555 $this->assertIsEnrolled(1, 1, ENROL_USER_ACTIVE, 'teacher');
556 $this->assertIsEnrolled(1, 2, ENROL_USER_ACTIVE, 'editingteacher');
557 $this->assertIsEnrolled(2, 1, ENROL_USER_ACTIVE, 'student');
558 $this->assertIsNotEnrolled(4, 4);
559 $this->assertHasRoleAssignment(4, 4, 'editingteacher');
560 $this->assertIsEnrolled(3, 3, ENROL_USER_ACTIVE, 'teacher');
562 $DB->delete_records('enrol_database_test_enrols', array('userid' => 'userid1', 'courseid' => 'courseid1', 'roleid' => 'teacher'));
563 $plugin->sync_enrolments($trace);
564 $this->assertEquals(4, $DB->count_records('user_enrolments', array()));
565 $this->assertEquals(4, $DB->count_records('enrol', array('enrol' => 'database')));
566 $this->assertEquals(5, $DB->count_records('role_assignments', array('component' => 'enrol_database')));
567 $this->assertIsEnrolled(1, 1, ENROL_USER_ACTIVE, 'student');
568 $this->assertIsEnrolled(1, 2, ENROL_USER_ACTIVE, 'editingteacher');
569 $this->assertIsEnrolled(2, 1, ENROL_USER_ACTIVE, 'student');
570 $this->assertIsNotEnrolled(4, 4);
571 $this->assertHasRoleAssignment(4, 4, 'editingteacher');
572 $this->assertIsEnrolled(3, 3, ENROL_USER_ACTIVE, 'teacher');
575 // Test all other mapping options.
577 $this->reset_enrol_database();
579 $this->assertEquals(0, $DB->count_records('user_enrolments', array()));
580 $this->assertEquals(0, $DB->count_records('enrol', array('enrol' => 'database')));
581 $this->assertEquals(0, $DB->count_records('role_assignments', array('component' => 'enrol_database')));
583 $plugin->set_config('localcoursefield', 'id');
584 $plugin->set_config('localuserfield', 'id');
585 $plugin->set_config('localrolefield', 'id');
587 $DB->insert_record('enrol_database_test_enrols', array('userid' => self::$users[1]->id, 'courseid' => self::$courses[1]->id, 'roleid' => self::$roles['student']->id));
588 $DB->insert_record('enrol_database_test_enrols', array('userid' => self::$users[1]->id, 'courseid' => self::$courses[2]->id, 'roleid' => self::$roles['teacher']->id));
589 $DB->insert_record('enrol_database_test_enrols', array('userid' => self::$users[2]->id, 'courseid' => self::$courses[1]->id, 'roleid' => self::$roles['student']->id));
591 $plugin->sync_enrolments($trace);
592 $this->assertEquals(3, $DB->count_records('user_enrolments', array()));
593 $this->assertEquals(2, $DB->count_records('enrol', array('enrol' => 'database')));
594 $this->assertEquals(3, $DB->count_records('role_assignments', array('component' => 'enrol_database')));
595 $this->assertIsEnrolled(1, 1, ENROL_USER_ACTIVE, 'student');
596 $this->assertIsEnrolled(1, 2, ENROL_USER_ACTIVE, 'teacher');
597 $this->assertIsEnrolled(2, 1, ENROL_USER_ACTIVE, 'student');
600 $this->reset_enrol_database();
601 $plugin->set_config('localcoursefield', 'shortname');
602 $plugin->set_config('localuserfield', 'email');
603 $plugin->set_config('localrolefield', 'id');
605 $DB->insert_record('enrol_database_test_enrols', array('userid' => self::$users[1]->email, 'courseid' => self::$courses[1]->shortname, 'roleid' => self::$roles['student']->id));
606 $DB->insert_record('enrol_database_test_enrols', array('userid' => self::$users[1]->email, 'courseid' => self::$courses[2]->shortname, 'roleid' => self::$roles['teacher']->id));
607 $DB->insert_record('enrol_database_test_enrols', array('userid' => self::$users[2]->email, 'courseid' => self::$courses[1]->shortname, 'roleid' => self::$roles['student']->id));
609 $plugin->sync_enrolments($trace);
610 $this->assertEquals(3, $DB->count_records('user_enrolments', array()));
611 $this->assertEquals(2, $DB->count_records('enrol', array('enrol' => 'database')));
612 $this->assertEquals(3, $DB->count_records('role_assignments', array('component' => 'enrol_database')));
613 $this->assertIsEnrolled(1, 1, ENROL_USER_ACTIVE, 'student');
614 $this->assertIsEnrolled(1, 2, ENROL_USER_ACTIVE, 'teacher');
615 $this->assertIsEnrolled(2, 1, ENROL_USER_ACTIVE, 'student');
618 $this->reset_enrol_database();
619 $plugin->set_config('localcoursefield', 'id');
620 $plugin->set_config('localuserfield', 'username');
621 $plugin->set_config('localrolefield', 'id');
623 $DB->insert_record('enrol_database_test_enrols', array('userid' => self::$users[1]->username, 'courseid' => self::$courses[1]->id, 'roleid' => self::$roles['student']->id));
624 $DB->insert_record('enrol_database_test_enrols', array('userid' => self::$users[1]->username, 'courseid' => self::$courses[2]->id, 'roleid' => self::$roles['teacher']->id));
625 $DB->insert_record('enrol_database_test_enrols', array('userid' => self::$users[2]->username, 'courseid' => self::$courses[1]->id, 'roleid' => self::$roles['student']->id));
627 $plugin->sync_enrolments($trace);
628 $this->assertEquals(3, $DB->count_records('user_enrolments', array()));
629 $this->assertEquals(2, $DB->count_records('enrol', array('enrol' => 'database')));
630 $this->assertEquals(3, $DB->count_records('role_assignments', array('component' => 'enrol_database')));
631 $this->assertIsEnrolled(1, 1, ENROL_USER_ACTIVE, 'student');
632 $this->assertIsEnrolled(1, 2, ENROL_USER_ACTIVE, 'teacher');
633 $this->assertIsEnrolled(2, 1, ENROL_USER_ACTIVE, 'student');
636 // Test sync of one course only.
638 $this->reset_enrol_database();
640 $DB->insert_record('enrol_database_test_enrols', array('userid' => self::$users[1]->username, 'courseid' => self::$courses[1]->id, 'roleid' => self::$roles['student']->id));
641 $DB->insert_record('enrol_database_test_enrols', array('userid' => self::$users[1]->username, 'courseid' => self::$courses[2]->id, 'roleid' => self::$roles['teacher']->id));
642 $DB->insert_record('enrol_database_test_enrols', array('userid' => self::$users[2]->username, 'courseid' => self::$courses[1]->id, 'roleid' => self::$roles['student']->id));
644 $this->assertEquals(0, $DB->count_records('user_enrolments', array()));
645 $this->assertEquals(0, $DB->count_records('enrol', array('enrol' => 'database')));
646 $this->assertEquals(0, $DB->count_records('role_assignments', array('component' => 'enrol_database')));
648 $plugin->sync_enrolments($trace, self::$courses[3]->id);
649 $this->assertEquals(0, $DB->count_records('user_enrolments', array()));
650 $this->assertEquals(1, $DB->count_records('enrol', array('enrol' => 'database')));
651 $this->assertEquals(0, $DB->count_records('role_assignments', array('component' => 'enrol_database')));
653 $plugin->sync_enrolments($trace, self::$courses[1]->id);
654 $this->assertEquals(2, $DB->count_records('user_enrolments', array()));
655 $this->assertEquals(2, $DB->count_records('enrol', array('enrol' => 'database')));
656 $this->assertEquals(2, $DB->count_records('role_assignments', array('component' => 'enrol_database')));
657 $this->assertIsEnrolled(1, 1, ENROL_USER_ACTIVE, 'student');
658 $this->assertIsEnrolled(2, 1, ENROL_USER_ACTIVE, 'student');
660 $plugin->sync_enrolments($trace, self::$courses[2]->id);
661 $this->assertEquals(3, $DB->count_records('user_enrolments', array()));
662 $this->assertEquals(3, $DB->count_records('enrol', array('enrol' => 'database')));
663 $this->assertEquals(3, $DB->count_records('role_assignments', array('component' => 'enrol_database')));
664 $this->assertIsEnrolled(1, 1, ENROL_USER_ACTIVE, 'student');
665 $this->assertIsEnrolled(1, 2, ENROL_USER_ACTIVE, 'teacher');
666 $this->assertIsEnrolled(2, 1, ENROL_USER_ACTIVE, 'student');
669 $plugin->set_config('unenrolaction', ENROL_EXT_REMOVED_UNENROL);
671 $DB->delete_records('enrol_database_test_enrols', array());
673 $plugin->sync_enrolments($trace, self::$courses[1]->id);
674 $this->assertEquals(1, $DB->count_records('user_enrolments', array()));
675 $this->assertEquals(3, $DB->count_records('enrol', array('enrol' => 'database')));
676 $this->assertEquals(1, $DB->count_records('role_assignments', array('component' => 'enrol_database')));
677 $this->assertIsEnrolled(1, 2, ENROL_USER_ACTIVE, 'teacher');
679 $plugin->sync_enrolments($trace, self::$courses[2]->id);
680 $this->assertEquals(0, $DB->count_records('user_enrolments', array()));
681 $this->assertEquals(3, $DB->count_records('enrol', array('enrol' => 'database')));
682 $this->assertEquals(0, $DB->count_records('role_assignments', array('component' => 'enrol_database')));
686 * @depends test_sync_users
688 public function test_sync_courses() {
691 $this->resetAfterTest(true);
692 $this->preventResetByRollback();
693 $this->reset_enrol_database();
695 $plugin = enrol_get_plugin('database');
697 $trace = new null_progress_trace();
699 $plugin->set_config('localcategoryfield', 'id');
700 $coursecat = $this->getDataGenerator()->create_category(array('name' => 'Test category 1', 'idnumber' => 'tcid1'));
701 $defcat = $DB->get_record('course_categories', array('id' => $plugin->get_config('defaultcategory')));
703 $course1 = array('fullname' => 'New course 1', 'shortname' => 'nc1', 'idnumber' => 'ncid1', 'category' => $coursecat->id);
704 $course2 = array('fullname' => 'New course 2', 'shortname' => 'nc2', 'idnumber' => 'ncid2', 'category' => null);
705 // Duplicate records are to be ignored.
706 $course3 = array('fullname' => 'New course 3', 'shortname' => 'xx', 'idnumber' => 'yy2', 'category' => $defcat->id);
707 $course4 = array('fullname' => 'New course 4', 'shortname' => 'xx', 'idnumber' => 'yy3', 'category' => $defcat->id);
708 $course5 = array('fullname' => 'New course 5', 'shortname' => 'xx1', 'idnumber' => 'yy', 'category' => $defcat->id);
709 $course6 = array('fullname' => 'New course 6', 'shortname' => 'xx2', 'idnumber' => 'yy', 'category' => $defcat->id);
711 $DB->insert_record('enrol_database_test_courses', $course1);
712 $DB->insert_record('enrol_database_test_courses', $course2);
713 $DB->insert_record('enrol_database_test_courses', $course3);
714 $DB->insert_record('enrol_database_test_courses', $course4);
715 $DB->insert_record('enrol_database_test_courses', $course5);
716 $DB->insert_record('enrol_database_test_courses', $course6);
718 $this->assertEquals(1+count(self::$courses), $DB->count_records('course'));
720 $plugin->sync_courses($trace);
722 $this->assertEquals(4+1+count(self::$courses), $DB->count_records('course'));
724 $this->assertTrue($DB->record_exists('course', $course1));
725 $course2['category'] = $defcat->id;
726 $this->assertTrue($DB->record_exists('course', $course2));
729 // People should NOT push duplicates there because the results are UNDEFINED! But anyway skip the duplicates.
731 $this->assertEquals(1, $DB->count_records('course', array('idnumber' => 'yy')));
732 $this->assertEquals(1, $DB->count_records('course', array('shortname' => 'xx')));
735 // Test category mapping via idnumber.
737 $plugin->set_config('localcategoryfield', 'idnumber');
738 $course7 = array('fullname' => 'New course 7', 'shortname' => 'nc7', 'idnumber' => 'ncid7', 'category' => 'tcid1');
739 $DB->insert_record('enrol_database_test_courses', $course7);
740 $plugin->sync_courses($trace);
742 $this->assertEquals(1+4+1+count(self::$courses), $DB->count_records('course'));
743 $this->assertTrue($DB->record_exists('course', $course1));
744 $this->assertTrue($DB->record_exists('course', $course2));
745 $course7['category'] = $coursecat->id;
746 $this->assertTrue($DB->record_exists('course', $course7));
749 // Test course template.
751 $template = $this->getDataGenerator()->create_course(array('numsections' => 666, 'shortname' => 'crstempl'));
752 $plugin->set_config('templatecourse', 'crstempl');
754 $course8 = array('fullname' => 'New course 8', 'shortname' => 'nc8', 'idnumber' => 'ncid8', 'category' => null);
755 $DB->insert_record('enrol_database_test_courses', $course8);
756 $plugin->sync_courses($trace);
758 $this->assertEquals(2+1+4+1+count(self::$courses), $DB->count_records('course'));
759 $course8['category'] = $defcat->id;
760 $record = $DB->get_record('course', $course8);
761 $this->assertFalse(empty($record));
762 $courseformatoptions = course_get_format($record)->get_format_options();
763 $this->assertEquals($courseformatoptions['numsections'], 666);
765 // Test invalid category.
767 $course9 = array('fullname' => 'New course 9', 'shortname' => 'nc9', 'idnumber' => 'ncid9', 'category' => 'xxxxxxx');
768 $DB->insert_record('enrol_database_test_courses', $course9);
769 $plugin->sync_courses($trace);
770 $this->assertEquals(2+1+4+1+count(self::$courses), $DB->count_records('course'));
771 $this->assertFalse($DB->record_exists('course', array('idnumber' => 'ncid9')));
774 // Test when categories not specified.
776 $plugin->set_config('newcoursecategory', '');
777 $plugin->sync_courses($trace);
778 $this->assertEquals(1+2+1+4+1+count(self::$courses), $DB->count_records('course'));
779 $this->assertTrue($DB->record_exists('course', array('idnumber' => 'ncid9')));
782 // Final cleanup - remove extra tables, fixtures and caches.
783 $this->cleanup_enrol_database();