weekly back-to-dev release 5.0dev
[moodle.git] / enrol / database / tests / sync_test.php
blob62c164de2c68a63bc868815cf1093456657d3539
1 <?php
2 // This file is part of Moodle - http://moodle.org/
3 //
4 // Moodle is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation, either version 3 of the License, or
7 // (at your option) any later version.
8 //
9 // Moodle is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
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/>.
17 namespace enrol_database;
19 /**
20 * External database enrolment sync tests
22 * This also tests adodb drivers that are matching
23 * our four supported Moodle database drivers.
25 * @package enrol_database
26 * @category test
27 * @copyright 2011 Petr Skoda {@link http://skodak.org}
28 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
30 class sync_test extends \advanced_testcase {
31 protected static $courses = array();
32 protected static $users = array();
33 protected static $roles = array();
35 /** @var string Original error log */
36 protected $oldlog;
38 public static function tearDownAfterClass(): void {
39 global $DB;
40 // Apply sqlsrv native driver error and logging default
41 // settings while finishing the AdoDB tests.
42 if ($DB->get_dbfamily() === 'mssql') {
43 sqlsrv_configure("WarningsReturnAsErrors", false);
44 sqlsrv_configure("LogSubsystems", SQLSRV_LOG_SYSTEM_OFF);
45 sqlsrv_configure("LogSeverity", SQLSRV_LOG_SEVERITY_ERROR);
47 parent::tearDownAfterClass();
50 protected function init_enrol_database() {
51 global $DB, $CFG;
53 // Discard error logs from AdoDB.
54 $this->oldlog = ini_get('error_log');
55 ini_set('error_log', "$CFG->dataroot/testlog.log");
57 $dbman = $DB->get_manager();
59 set_config('dbencoding', 'utf-8', 'enrol_database');
61 set_config('dbhost', $CFG->dbhost, 'enrol_database');
62 set_config('dbuser', $CFG->dbuser, 'enrol_database');
63 set_config('dbpass', $CFG->dbpass, 'enrol_database');
64 set_config('dbname', $CFG->dbname, 'enrol_database');
66 if (!empty($CFG->dboptions['dbport'])) {
67 set_config('dbhost', $CFG->dbhost.':'.$CFG->dboptions['dbport'], 'enrol_database');
70 switch ($DB->get_dbfamily()) {
72 case 'mysql':
73 set_config('dbtype', 'mysqli', 'enrol_database');
74 set_config('dbsetupsql', "SET NAMES 'UTF-8'", 'enrol_database');
75 set_config('dbsybasequoting', '0', 'enrol_database');
76 if (!empty($CFG->dboptions['dbsocket'])) {
77 $dbsocket = $CFG->dboptions['dbsocket'];
78 if ((strpos($dbsocket, '/') === false and strpos($dbsocket, '\\') === false)) {
79 $dbsocket = ini_get('mysqli.default_socket');
81 set_config('dbtype', 'mysqli://'.rawurlencode($CFG->dbuser).':'.rawurlencode($CFG->dbpass).'@'.rawurlencode($CFG->dbhost).'/'.rawurlencode($CFG->dbname).'?socket='.rawurlencode($dbsocket), 'enrol_database');
83 break;
85 case 'oracle':
86 set_config('dbtype', 'oci8po', 'enrol_database');
87 set_config('dbsybasequoting', '1', 'enrol_database');
88 break;
90 case 'postgres':
91 set_config('dbtype', 'postgres7', 'enrol_database');
92 $setupsql = "SET NAMES 'UTF-8'";
93 if (!empty($CFG->dboptions['dbschema'])) {
94 $setupsql .= "; SET search_path = '".$CFG->dboptions['dbschema']."'";
96 set_config('dbsetupsql', $setupsql, 'enrol_database');
97 set_config('dbsybasequoting', '0', 'enrol_database');
98 if (!empty($CFG->dboptions['dbsocket']) and ($CFG->dbhost === 'localhost' or $CFG->dbhost === '127.0.0.1')) {
99 if (strpos($CFG->dboptions['dbsocket'], '/') !== false) {
100 $socket = $CFG->dboptions['dbsocket'];
101 if (!empty($CFG->dboptions['dbport'])) {
102 $socket .= ':' . $CFG->dboptions['dbport'];
104 set_config('dbhost', $socket, 'enrol_database');
105 } else {
106 set_config('dbhost', '', 'enrol_database');
109 break;
111 case 'mssql':
112 set_config('dbtype', 'mssqlnative', 'enrol_database');
113 set_config('dbsybasequoting', '1', 'enrol_database');
115 // The native sqlsrv driver uses a comma as separator between host and port.
116 $dbhost = $CFG->dbhost;
117 if (!empty($dboptions['dbport'])) {
118 $dbhost .= ',' . $dboptions['dbport'];
120 set_config('dbhost', $dbhost, 'enrol_database');
121 break;
123 default:
124 throw new exception('Unknown database driver '.get_class($DB));
127 // NOTE: It is stongly discouraged to create new tables in advanced_testcase classes,
128 // but there is no other simple way to test ext database enrol sync, so let's
129 // disable transactions are try to cleanup after the tests.
131 $table = new \xmldb_table('enrol_database_test_enrols');
132 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
133 $table->add_field('courseid', XMLDB_TYPE_CHAR, '255', null, null, null);
134 $table->add_field('userid', XMLDB_TYPE_CHAR, '255', null, null, null);
135 $table->add_field('roleid', XMLDB_TYPE_CHAR, '255', null, null, null);
136 $table->add_field('otheruser', XMLDB_TYPE_CHAR, '1', null, XMLDB_NOTNULL, null, '0');
137 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
138 if ($dbman->table_exists($table)) {
139 $dbman->drop_table($table);
141 $dbman->create_table($table);
142 set_config('remoteenroltable', $CFG->prefix.'enrol_database_test_enrols', 'enrol_database');
143 set_config('remotecoursefield', 'courseid', 'enrol_database');
144 set_config('remoteuserfield', 'userid', 'enrol_database');
145 set_config('remoterolefield', 'roleid', 'enrol_database');
146 set_config('remoteotheruserfield', 'otheruser', 'enrol_database');
148 $table = new \xmldb_table('enrol_database_test_courses');
149 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
150 $table->add_field('fullname', XMLDB_TYPE_CHAR, '255', null, null, null);
151 $table->add_field('shortname', XMLDB_TYPE_CHAR, '255', null, null, null);
152 $table->add_field('idnumber', XMLDB_TYPE_CHAR, '255', null, null, null);
153 $table->add_field('category', XMLDB_TYPE_CHAR, '255', null, null, null);
154 $table->add_field('startdate', XMLDB_TYPE_CHAR, '255', null, null, null);
155 $table->add_field('enddate', XMLDB_TYPE_CHAR, '255', null, null, null);
156 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
157 if ($dbman->table_exists($table)) {
158 $dbman->drop_table($table);
160 $dbman->create_table($table);
161 set_config('newcoursetable', $CFG->prefix.'enrol_database_test_courses', 'enrol_database');
162 set_config('newcoursefullname', 'fullname', 'enrol_database');
163 set_config('newcourseshortname', 'shortname', 'enrol_database');
164 set_config('newcourseidnumber', 'idnumber', 'enrol_database');
165 set_config('newcoursecategory', 'category', 'enrol_database');
167 // Create some test users and courses.
168 for ($i = 1; $i <= 4; $i++) {
169 self::$courses[$i] = $this->getDataGenerator()->create_course(array('fullname' => 'Test course '.$i, 'shortname' => 'tc'.$i, 'idnumber' => 'courseid'.$i));
172 for ($i = 1; $i <= 10; $i++) {
173 self::$users[$i] = $this->getDataGenerator()->create_user(array('username' => 'username'.$i, 'idnumber' => 'userid'.$i, 'email' => 'user'.$i.'@example.com'));
176 foreach (get_all_roles() as $role) {
177 self::$roles[$role->shortname] = $role;
181 protected function cleanup_enrol_database() {
182 global $DB;
184 $dbman = $DB->get_manager();
185 $table = new \xmldb_table('enrol_database_test_enrols');
186 $dbman->drop_table($table);
187 $table = new \xmldb_table('enrol_database_test_courses');
188 $dbman->drop_table($table);
190 self::$courses = null;
191 self::$users = null;
192 self::$roles = null;
194 ini_set('error_log', $this->oldlog);
197 protected function reset_enrol_database() {
198 global $DB;
200 $DB->delete_records('enrol_database_test_enrols', array());
201 $DB->delete_records('enrol_database_test_courses', array());
203 $plugin = enrol_get_plugin('database');
204 $instances = $DB->get_records('enrol', array('enrol' => 'database'));
205 foreach($instances as $instance) {
206 $plugin->delete_instance($instance);
210 protected function assertIsEnrolled($userindex, $courseindex, $status=null, $rolename = null) {
211 global $DB;
212 $dbinstance = $DB->get_record('enrol', array('courseid' => self::$courses[$courseindex]->id, 'enrol' => 'database'), '*', MUST_EXIST);
214 $conditions = array('enrolid' => $dbinstance->id, 'userid' => self::$users[$userindex]->id);
215 if ($status !== null) {
216 $conditions['status'] = $status;
218 $this->assertTrue($DB->record_exists('user_enrolments', $conditions));
220 $this->assertHasRoleAssignment($userindex, $courseindex, $rolename);
223 protected function assertHasRoleAssignment($userindex, $courseindex, $rolename = null) {
224 global $DB;
225 $dbinstance = $DB->get_record('enrol', array('courseid' => self::$courses[$courseindex]->id, 'enrol' => 'database'), '*', MUST_EXIST);
227 $coursecontext = \context_course::instance(self::$courses[$courseindex]->id);
228 if ($rolename === false) {
229 $this->assertFalse($DB->record_exists('role_assignments', array('component' => 'enrol_database', 'itemid' => $dbinstance->id, 'userid' => self::$users[$userindex]->id, 'contextid' => $coursecontext->id)));
230 } else if ($rolename !== null) {
231 $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)));
235 protected function assertIsNotEnrolled($userindex, $courseindex) {
236 global $DB;
237 if (!$dbinstance = $DB->get_record('enrol', array('courseid' => self::$courses[$courseindex]->id, 'enrol' => 'database'))) {
238 return;
240 $this->assertFalse($DB->record_exists('user_enrolments', array('enrolid' => $dbinstance->id, 'userid' => self::$users[$userindex]->id)));
243 public function test_sync_user_enrolments(): void {
244 global $DB;
246 $this->init_enrol_database();
248 $this->resetAfterTest(false);
249 $this->preventResetByRollback();
251 $plugin = enrol_get_plugin('database');
253 // Test basic enrol sync for one user after login.
255 $this->reset_enrol_database();
256 $plugin->set_config('localcoursefield', 'idnumber');
257 $plugin->set_config('localuserfield', 'idnumber');
258 $plugin->set_config('localrolefield', 'shortname');
260 $plugin->set_config('defaultrole', self::$roles['student']->id);
262 $DB->insert_record('enrol_database_test_enrols', array('userid' => 'userid1', 'courseid' => 'courseid1', 'roleid' => 'student'));
263 $DB->insert_record('enrol_database_test_enrols', array('userid' => 'userid1', 'courseid' => 'courseid2', 'roleid' => 'teacher'));
264 $DB->insert_record('enrol_database_test_enrols', array('userid' => 'userid2', 'courseid' => 'courseid1', 'roleid' => null));
265 $DB->insert_record('enrol_database_test_enrols', array('userid' => 'userid4', 'courseid' => 'courseid4', 'roleid' => 'editingteacher', 'otheruser' => '1'));
266 $DB->insert_record('enrol_database_test_enrols', array('userid' => 'xxxxxxx', 'courseid' => 'courseid1', 'roleid' => 'student')); // Bogus record to be ignored.
267 $DB->insert_record('enrol_database_test_enrols', array('userid' => 'userid1', 'courseid' => 'xxxxxxxxx', 'roleid' => 'student')); // Bogus record to be ignored.
269 $this->assertEquals(0, $DB->count_records('user_enrolments', array()));
270 $this->assertEquals(0, $DB->count_records('enrol', array('enrol' => 'database')));
271 $this->assertEquals(0, $DB->count_records('role_assignments', array('component' => 'enrol_database')));
273 $plugin->sync_user_enrolments(self::$users[1]);
274 $this->assertEquals(2, $DB->count_records('user_enrolments', array()));
275 $this->assertEquals(2, $DB->count_records('enrol', array('enrol' => 'database')));
276 $this->assertEquals(2, $DB->count_records('role_assignments', array('component' => 'enrol_database')));
277 $this->assertIsEnrolled(1, 1, ENROL_USER_ACTIVE, 'student');
278 $this->assertIsEnrolled(1, 2, ENROL_USER_ACTIVE, 'teacher');
280 // Make sure there are no errors or changes on the next login.
282 $plugin->sync_user_enrolments(self::$users[1]);
283 $this->assertEquals(2, $DB->count_records('user_enrolments', array()));
284 $this->assertEquals(2, $DB->count_records('enrol', array('enrol' => 'database')));
285 $this->assertEquals(2, $DB->count_records('role_assignments', array('component' => 'enrol_database')));
286 $this->assertIsEnrolled(1, 1, ENROL_USER_ACTIVE, 'student');
287 $this->assertIsEnrolled(1, 2, ENROL_USER_ACTIVE, 'teacher');
289 $plugin->sync_user_enrolments(self::$users[2]);
290 $this->assertEquals(3, $DB->count_records('user_enrolments', array()));
291 $this->assertEquals(2, $DB->count_records('enrol', array('enrol' => 'database')));
292 $this->assertEquals(3, $DB->count_records('role_assignments', array('component' => 'enrol_database')));
293 $this->assertIsEnrolled(1, 1, ENROL_USER_ACTIVE, 'student');
294 $this->assertIsEnrolled(1, 2, ENROL_USER_ACTIVE, 'teacher');
295 $this->assertIsEnrolled(2, 1, ENROL_USER_ACTIVE, 'student');
297 $plugin->sync_user_enrolments(self::$users[4]);
298 $this->assertEquals(3, $DB->count_records('user_enrolments', array()));
299 $this->assertEquals(3, $DB->count_records('enrol', array('enrol' => 'database')));
300 $this->assertEquals(4, $DB->count_records('role_assignments', array('component' => 'enrol_database')));
301 $this->assertIsEnrolled(1, 1, ENROL_USER_ACTIVE, 'student');
302 $this->assertIsEnrolled(1, 2, ENROL_USER_ACTIVE, 'teacher');
303 $this->assertIsEnrolled(2, 1, ENROL_USER_ACTIVE, 'student');
304 $this->assertIsNotEnrolled(4, 4);
305 $this->assertHasRoleAssignment(4, 4, 'editingteacher');
307 // Enrolment removals.
309 $DB->delete_records('enrol_database_test_enrols', array('userid' => 'userid1', 'courseid' => 'courseid1', 'roleid' => 'student'));
310 $plugin->set_config('unenrolaction', ENROL_EXT_REMOVED_KEEP);
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 $plugin->set_config('unenrolaction', ENROL_EXT_REMOVED_SUSPEND);
320 $plugin->sync_user_enrolments(self::$users[1]);
321 $this->assertEquals(3, $DB->count_records('user_enrolments', array()));
322 $this->assertEquals(3, $DB->count_records('enrol', array('enrol' => 'database')));
323 $this->assertEquals(4, $DB->count_records('role_assignments', array('component' => 'enrol_database')));
324 $this->assertIsEnrolled(1, 1, ENROL_USER_SUSPENDED, 'student');
325 $this->assertIsEnrolled(1, 2, ENROL_USER_ACTIVE, 'teacher');
327 $DB->insert_record('enrol_database_test_enrols', array('userid' => 'userid1', 'courseid' => 'courseid1', 'roleid' => 'student'));
328 $plugin->sync_user_enrolments(self::$users[1]);
329 $this->assertEquals(3, $DB->count_records('user_enrolments', array()));
330 $this->assertEquals(3, $DB->count_records('enrol', array('enrol' => 'database')));
331 $this->assertEquals(4, $DB->count_records('role_assignments', array('component' => 'enrol_database')));
332 $this->assertIsEnrolled(1, 1, ENROL_USER_ACTIVE, 'student');
333 $this->assertIsEnrolled(1, 2, ENROL_USER_ACTIVE, 'teacher');
336 $DB->delete_records('enrol_database_test_enrols', array('userid' => 'userid1', 'courseid' => 'courseid1', 'roleid' => 'student'));
337 $plugin->set_config('unenrolaction', ENROL_EXT_REMOVED_SUSPENDNOROLES);
338 $plugin->sync_user_enrolments(self::$users[1]);
339 $this->assertEquals(3, $DB->count_records('user_enrolments', array()));
340 $this->assertEquals(3, $DB->count_records('enrol', array('enrol' => 'database')));
341 $this->assertEquals(3, $DB->count_records('role_assignments', array('component' => 'enrol_database')));
342 $this->assertIsEnrolled(1, 1, ENROL_USER_SUSPENDED, false);
343 $this->assertIsEnrolled(1, 2, ENROL_USER_ACTIVE, 'teacher');
345 $DB->insert_record('enrol_database_test_enrols', array('userid' => 'userid1', 'courseid' => 'courseid1', 'roleid' => 'student'));
346 $plugin->sync_user_enrolments(self::$users[1]);
347 $this->assertEquals(3, $DB->count_records('user_enrolments', array()));
348 $this->assertEquals(3, $DB->count_records('enrol', array('enrol' => 'database')));
349 $this->assertEquals(4, $DB->count_records('role_assignments', array('component' => 'enrol_database')));
350 $this->assertIsEnrolled(1, 1, ENROL_USER_ACTIVE, 'student');
351 $this->assertIsEnrolled(1, 2, ENROL_USER_ACTIVE, 'teacher');
354 $DB->delete_records('enrol_database_test_enrols', array('userid' => 'userid1', 'courseid' => 'courseid1', 'roleid' => 'student'));
355 $plugin->set_config('unenrolaction', ENROL_EXT_REMOVED_UNENROL);
356 $plugin->sync_user_enrolments(self::$users[1]);
357 $this->assertEquals(2, $DB->count_records('user_enrolments', array()));
358 $this->assertEquals(3, $DB->count_records('enrol', array('enrol' => 'database')));
359 $this->assertEquals(3, $DB->count_records('role_assignments', array('component' => 'enrol_database')));
360 $this->assertIsNotEnrolled(1, 1);
361 $this->assertIsEnrolled(1, 2, ENROL_USER_ACTIVE, 'teacher');
363 $DB->delete_records('enrol_database_test_enrols', array('userid' => 'userid4', 'courseid' => 'courseid4', 'roleid' => 'editingteacher'));
364 $plugin->set_config('unenrolaction', ENROL_EXT_REMOVED_SUSPENDNOROLES);
365 $plugin->sync_user_enrolments(self::$users[4]);
366 $this->assertEquals(2, $DB->count_records('user_enrolments', array()));
367 $this->assertEquals(3, $DB->count_records('enrol', array('enrol' => 'database')));
368 $this->assertEquals(2, $DB->count_records('role_assignments', array('component' => 'enrol_database')));
369 $this->assertIsNotEnrolled(4, 4);
370 $this->assertHasRoleAssignment(4, 4, false);
372 // Test all other mapping options.
374 $this->reset_enrol_database();
376 $this->assertEquals(0, $DB->count_records('user_enrolments', array()));
377 $this->assertEquals(0, $DB->count_records('enrol', array('enrol' => 'database')));
378 $this->assertEquals(0, $DB->count_records('role_assignments', array('component' => 'enrol_database')));
380 $plugin->set_config('localcoursefield', 'id');
381 $plugin->set_config('localuserfield', 'id');
382 $plugin->set_config('localrolefield', 'id');
384 $DB->insert_record('enrol_database_test_enrols', array('userid' => self::$users[1]->id, 'courseid' => self::$courses[1]->id, 'roleid' => self::$roles['student']->id));
385 $DB->insert_record('enrol_database_test_enrols', array('userid' => self::$users[1]->id, 'courseid' => self::$courses[2]->id, 'roleid' => self::$roles['teacher']->id));
386 $DB->insert_record('enrol_database_test_enrols', array('userid' => self::$users[2]->id, 'courseid' => self::$courses[1]->id, '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', 'shortname');
398 $plugin->set_config('localuserfield', 'email');
399 $plugin->set_config('localrolefield', 'id');
401 $DB->insert_record('enrol_database_test_enrols', array('userid' => self::$users[1]->email, 'courseid' => self::$courses[1]->shortname, 'roleid' => self::$roles['student']->id));
402 $DB->insert_record('enrol_database_test_enrols', array('userid' => self::$users[1]->email, 'courseid' => self::$courses[2]->shortname, 'roleid' => self::$roles['teacher']->id));
403 $DB->insert_record('enrol_database_test_enrols', array('userid' => self::$users[2]->email, 'courseid' => self::$courses[1]->shortname, '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');
413 $this->reset_enrol_database();
414 $plugin->set_config('localcoursefield', 'id');
415 $plugin->set_config('localuserfield', 'username');
416 $plugin->set_config('localrolefield', 'id');
418 $DB->insert_record('enrol_database_test_enrols', array('userid' => self::$users[1]->username, 'courseid' => self::$courses[1]->id, 'roleid' => self::$roles['student']->id));
419 $DB->insert_record('enrol_database_test_enrols', array('userid' => self::$users[1]->username, 'courseid' => self::$courses[2]->id, 'roleid' => self::$roles['teacher']->id));
420 $DB->insert_record('enrol_database_test_enrols', array('userid' => self::$users[2]->username, 'courseid' => self::$courses[1]->id, 'roleid' => self::$roles['student']->id));
422 $plugin->sync_user_enrolments(self::$users[1]);
423 $this->assertEquals(2, $DB->count_records('user_enrolments', array()));
424 $this->assertEquals(2, $DB->count_records('enrol', array('enrol' => 'database')));
425 $this->assertEquals(2, $DB->count_records('role_assignments', array('component' => 'enrol_database')));
426 $this->assertIsEnrolled(1, 1, ENROL_USER_ACTIVE, 'student');
427 $this->assertIsEnrolled(1, 2, ENROL_USER_ACTIVE, 'teacher');
431 * @depends test_sync_user_enrolments
433 public function test_sync_users(): void {
434 global $DB;
436 $this->resetAfterTest(false);
437 $this->preventResetByRollback();
438 $this->reset_enrol_database();
440 $plugin = enrol_get_plugin('database');
442 $trace = new \null_progress_trace();
444 // Test basic enrol sync for one user after login.
446 $plugin->set_config('localcoursefield', 'idnumber');
447 $plugin->set_config('localuserfield', 'idnumber');
448 $plugin->set_config('localrolefield', 'shortname');
450 $DB->insert_record('enrol_database_test_enrols', array('userid' => 'userid1', 'courseid' => 'courseid1', 'roleid' => 'student'));
451 $DB->insert_record('enrol_database_test_enrols', array('userid' => 'userid1', 'courseid' => 'courseid2', 'roleid' => 'editingteacher'));
452 $DB->insert_record('enrol_database_test_enrols', array('userid' => 'userid2', 'courseid' => 'courseid1', 'roleid' => 'student'));
453 $DB->insert_record('enrol_database_test_enrols', array('userid' => 'userid4', 'courseid' => 'courseid4', 'roleid' => 'editingteacher', 'otheruser' => '1'));
454 $DB->insert_record('enrol_database_test_enrols', array('userid' => 'xxxxxxx', 'courseid' => 'courseid1', 'roleid' => 'student')); // Bogus record to be ignored.
455 $DB->insert_record('enrol_database_test_enrols', array('userid' => 'userid1', 'courseid' => 'xxxxxxxxx', 'roleid' => 'student')); // Bogus record to be ignored.
456 $this->assertEquals(0, $DB->count_records('user_enrolments', array()));
457 $this->assertEquals(0, $DB->count_records('enrol', array('enrol' => 'database')));
458 $this->assertEquals(0, $DB->count_records('role_assignments', array('component' => 'enrol_database')));
460 $plugin->sync_enrolments($trace);
461 $this->assertEquals(3, $DB->count_records('user_enrolments', array()));
462 $this->assertEquals(3, $DB->count_records('enrol', array('enrol' => 'database')));
463 $this->assertEquals(4, $DB->count_records('role_assignments', array('component' => 'enrol_database')));
464 $this->assertIsEnrolled(1, 1, ENROL_USER_ACTIVE, 'student');
465 $this->assertIsEnrolled(1, 2, ENROL_USER_ACTIVE, 'editingteacher');
466 $this->assertIsEnrolled(2, 1, ENROL_USER_ACTIVE, 'student');
467 $this->assertIsNotEnrolled(4, 4);
468 $this->assertHasRoleAssignment(4, 4, 'editingteacher');
470 $plugin->set_config('defaultrole', self::$roles['teacher']->id);
471 $DB->insert_record('enrol_database_test_enrols', array('userid' => 'userid3', 'courseid' => 'courseid3'));
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 // Test different unenrolment options.
486 $DB->delete_records('enrol_database_test_enrols', array('userid' => 'userid1', 'courseid' => 'courseid1', 'roleid' => 'student'));
487 $plugin->set_config('unenrolaction', ENROL_EXT_REMOVED_KEEP);
488 $plugin->sync_enrolments($trace);
489 $this->assertEquals(4, $DB->count_records('user_enrolments', array()));
490 $this->assertEquals(4, $DB->count_records('enrol', array('enrol' => 'database')));
491 $this->assertEquals(5, $DB->count_records('role_assignments', array('component' => 'enrol_database')));
492 $this->assertIsEnrolled(1, 1, ENROL_USER_ACTIVE, 'student');
493 $this->assertIsEnrolled(1, 2, ENROL_USER_ACTIVE, 'editingteacher');
494 $this->assertIsEnrolled(2, 1, ENROL_USER_ACTIVE, 'student');
495 $this->assertIsNotEnrolled(4, 4);
496 $this->assertHasRoleAssignment(4, 4, 'editingteacher');
497 $this->assertIsEnrolled(3, 3, ENROL_USER_ACTIVE, 'teacher');
500 $plugin->set_config('unenrolaction', ENROL_EXT_REMOVED_SUSPEND);
501 $plugin->sync_enrolments($trace);
502 $this->assertEquals(4, $DB->count_records('user_enrolments', array()));
503 $this->assertEquals(4, $DB->count_records('enrol', array('enrol' => 'database')));
504 $this->assertEquals(5, $DB->count_records('role_assignments', array('component' => 'enrol_database')));
505 $this->assertIsEnrolled(1, 1, ENROL_USER_SUSPENDED, 'student');
506 $this->assertIsEnrolled(1, 2, ENROL_USER_ACTIVE, 'editingteacher');
507 $this->assertIsEnrolled(2, 1, ENROL_USER_ACTIVE, 'student');
508 $this->assertIsNotEnrolled(4, 4);
509 $this->assertHasRoleAssignment(4, 4, 'editingteacher');
510 $this->assertIsEnrolled(3, 3, ENROL_USER_ACTIVE, 'teacher');
512 $DB->insert_record('enrol_database_test_enrols', array('userid' => 'userid1', 'courseid' => 'courseid1', 'roleid' => 'student'));
513 $plugin->sync_enrolments($trace);
514 $this->assertEquals(4, $DB->count_records('user_enrolments', array()));
515 $this->assertEquals(4, $DB->count_records('enrol', array('enrol' => 'database')));
516 $this->assertEquals(5, $DB->count_records('role_assignments', array('component' => 'enrol_database')));
517 $this->assertIsEnrolled(1, 1, ENROL_USER_ACTIVE, 'student');
518 $this->assertIsEnrolled(1, 2, ENROL_USER_ACTIVE, 'editingteacher');
519 $this->assertIsEnrolled(2, 1, ENROL_USER_ACTIVE, 'student');
520 $this->assertIsNotEnrolled(4, 4);
521 $this->assertHasRoleAssignment(4, 4, 'editingteacher');
522 $this->assertIsEnrolled(3, 3, ENROL_USER_ACTIVE, 'teacher');
525 $DB->delete_records('enrol_database_test_enrols', array('userid' => 'userid1', 'courseid' => 'courseid1', 'roleid' => 'student'));
526 $plugin->set_config('unenrolaction', ENROL_EXT_REMOVED_SUSPENDNOROLES);
527 $plugin->sync_enrolments($trace);
528 $this->assertEquals(4, $DB->count_records('user_enrolments', array()));
529 $this->assertEquals(4, $DB->count_records('enrol', array('enrol' => 'database')));
530 $this->assertEquals(4, $DB->count_records('role_assignments', array('component' => 'enrol_database')));
531 $this->assertIsEnrolled(1, 1, ENROL_USER_SUSPENDED, false);
532 $this->assertIsEnrolled(1, 2, ENROL_USER_ACTIVE, 'editingteacher');
533 $this->assertIsEnrolled(2, 1, ENROL_USER_ACTIVE, 'student');
534 $this->assertIsNotEnrolled(4, 4);
535 $this->assertHasRoleAssignment(4, 4, 'editingteacher');
536 $this->assertIsEnrolled(3, 3, ENROL_USER_ACTIVE, 'teacher');
538 $DB->insert_record('enrol_database_test_enrols', array('userid' => 'userid1', 'courseid' => 'courseid1', 'roleid' => 'student'));
539 $plugin->sync_enrolments($trace);
540 $this->assertEquals(4, $DB->count_records('user_enrolments', array()));
541 $this->assertEquals(4, $DB->count_records('enrol', array('enrol' => 'database')));
542 $this->assertEquals(5, $DB->count_records('role_assignments', array('component' => 'enrol_database')));
543 $this->assertIsEnrolled(1, 1, ENROL_USER_ACTIVE, 'student');
544 $this->assertIsEnrolled(1, 2, ENROL_USER_ACTIVE, 'editingteacher');
545 $this->assertIsEnrolled(2, 1, ENROL_USER_ACTIVE, 'student');
546 $this->assertIsNotEnrolled(4, 4);
547 $this->assertHasRoleAssignment(4, 4, 'editingteacher');
548 $this->assertIsEnrolled(3, 3, ENROL_USER_ACTIVE, 'teacher');
551 $DB->delete_records('enrol_database_test_enrols', array('userid' => 'userid1', 'courseid' => 'courseid1', 'roleid' => 'student'));
552 $plugin->set_config('unenrolaction', ENROL_EXT_REMOVED_UNENROL);
553 $plugin->sync_enrolments($trace);
554 $this->assertEquals(3, $DB->count_records('user_enrolments', array()));
555 $this->assertEquals(4, $DB->count_records('enrol', array('enrol' => 'database')));
556 $this->assertEquals(4, $DB->count_records('role_assignments', array('component' => 'enrol_database')));
557 $this->assertIsNotEnrolled(1, 1);
558 $this->assertIsEnrolled(1, 2, ENROL_USER_ACTIVE, 'editingteacher');
559 $this->assertIsEnrolled(2, 1, ENROL_USER_ACTIVE, 'student');
560 $this->assertIsNotEnrolled(4, 4);
561 $this->assertHasRoleAssignment(4, 4, 'editingteacher');
562 $this->assertIsEnrolled(3, 3, ENROL_USER_ACTIVE, 'teacher');
564 $DB->insert_record('enrol_database_test_enrols', array('userid' => 'userid1', 'courseid' => 'courseid1', 'roleid' => 'student'));
565 $DB->insert_record('enrol_database_test_enrols', array('userid' => 'userid1', 'courseid' => 'courseid1', 'roleid' => 'teacher'));
566 $plugin->sync_enrolments($trace);
567 $this->assertEquals(4, $DB->count_records('user_enrolments', array()));
568 $this->assertEquals(4, $DB->count_records('enrol', array('enrol' => 'database')));
569 $this->assertEquals(6, $DB->count_records('role_assignments', array('component' => 'enrol_database')));
570 $this->assertIsEnrolled(1, 1, ENROL_USER_ACTIVE, 'student');
571 $this->assertIsEnrolled(1, 1, ENROL_USER_ACTIVE, 'teacher');
572 $this->assertIsEnrolled(1, 2, ENROL_USER_ACTIVE, 'editingteacher');
573 $this->assertIsEnrolled(2, 1, ENROL_USER_ACTIVE, 'student');
574 $this->assertIsNotEnrolled(4, 4);
575 $this->assertHasRoleAssignment(4, 4, 'editingteacher');
576 $this->assertIsEnrolled(3, 3, ENROL_USER_ACTIVE, 'teacher');
578 $DB->delete_records('enrol_database_test_enrols', array('userid' => 'userid1', 'courseid' => 'courseid1', 'roleid' => 'teacher'));
579 $plugin->sync_enrolments($trace);
580 $this->assertEquals(4, $DB->count_records('user_enrolments', array()));
581 $this->assertEquals(4, $DB->count_records('enrol', array('enrol' => 'database')));
582 $this->assertEquals(5, $DB->count_records('role_assignments', array('component' => 'enrol_database')));
583 $this->assertIsEnrolled(1, 1, ENROL_USER_ACTIVE, 'student');
584 $this->assertIsEnrolled(1, 2, ENROL_USER_ACTIVE, 'editingteacher');
585 $this->assertIsEnrolled(2, 1, ENROL_USER_ACTIVE, 'student');
586 $this->assertIsNotEnrolled(4, 4);
587 $this->assertHasRoleAssignment(4, 4, 'editingteacher');
588 $this->assertIsEnrolled(3, 3, ENROL_USER_ACTIVE, 'teacher');
591 // Test all other mapping options.
593 $this->reset_enrol_database();
595 $this->assertEquals(0, $DB->count_records('user_enrolments', array()));
596 $this->assertEquals(0, $DB->count_records('enrol', array('enrol' => 'database')));
597 $this->assertEquals(0, $DB->count_records('role_assignments', array('component' => 'enrol_database')));
599 $plugin->set_config('localcoursefield', 'id');
600 $plugin->set_config('localuserfield', 'id');
601 $plugin->set_config('localrolefield', 'id');
603 $DB->insert_record('enrol_database_test_enrols', array('userid' => self::$users[1]->id, 'courseid' => self::$courses[1]->id, 'roleid' => self::$roles['student']->id));
604 $DB->insert_record('enrol_database_test_enrols', array('userid' => self::$users[1]->id, 'courseid' => self::$courses[2]->id, 'roleid' => self::$roles['teacher']->id));
605 $DB->insert_record('enrol_database_test_enrols', array('userid' => self::$users[2]->id, 'courseid' => self::$courses[1]->id, 'roleid' => self::$roles['student']->id));
607 $plugin->sync_enrolments($trace);
608 $this->assertEquals(3, $DB->count_records('user_enrolments', array()));
609 $this->assertEquals(2, $DB->count_records('enrol', array('enrol' => 'database')));
610 $this->assertEquals(3, $DB->count_records('role_assignments', array('component' => 'enrol_database')));
611 $this->assertIsEnrolled(1, 1, ENROL_USER_ACTIVE, 'student');
612 $this->assertIsEnrolled(1, 2, ENROL_USER_ACTIVE, 'teacher');
613 $this->assertIsEnrolled(2, 1, ENROL_USER_ACTIVE, 'student');
616 $this->reset_enrol_database();
617 $plugin->set_config('localcoursefield', 'shortname');
618 $plugin->set_config('localuserfield', 'email');
619 $plugin->set_config('localrolefield', 'id');
621 $DB->insert_record('enrol_database_test_enrols', array('userid' => self::$users[1]->email, 'courseid' => self::$courses[1]->shortname, 'roleid' => self::$roles['student']->id));
622 $DB->insert_record('enrol_database_test_enrols', array('userid' => self::$users[1]->email, 'courseid' => self::$courses[2]->shortname, 'roleid' => self::$roles['teacher']->id));
623 $DB->insert_record('enrol_database_test_enrols', array('userid' => self::$users[2]->email, 'courseid' => self::$courses[1]->shortname, 'roleid' => self::$roles['student']->id));
625 $plugin->sync_enrolments($trace);
626 $this->assertEquals(3, $DB->count_records('user_enrolments', array()));
627 $this->assertEquals(2, $DB->count_records('enrol', array('enrol' => 'database')));
628 $this->assertEquals(3, $DB->count_records('role_assignments', array('component' => 'enrol_database')));
629 $this->assertIsEnrolled(1, 1, ENROL_USER_ACTIVE, 'student');
630 $this->assertIsEnrolled(1, 2, ENROL_USER_ACTIVE, 'teacher');
631 $this->assertIsEnrolled(2, 1, ENROL_USER_ACTIVE, 'student');
634 $this->reset_enrol_database();
635 $plugin->set_config('localcoursefield', 'id');
636 $plugin->set_config('localuserfield', 'username');
637 $plugin->set_config('localrolefield', 'id');
639 $DB->insert_record('enrol_database_test_enrols', array('userid' => self::$users[1]->username, 'courseid' => self::$courses[1]->id, 'roleid' => self::$roles['student']->id));
640 $DB->insert_record('enrol_database_test_enrols', array('userid' => self::$users[1]->username, 'courseid' => self::$courses[2]->id, 'roleid' => self::$roles['teacher']->id));
641 $DB->insert_record('enrol_database_test_enrols', array('userid' => self::$users[2]->username, 'courseid' => self::$courses[1]->id, 'roleid' => self::$roles['student']->id));
643 $plugin->sync_enrolments($trace);
644 $this->assertEquals(3, $DB->count_records('user_enrolments', array()));
645 $this->assertEquals(2, $DB->count_records('enrol', array('enrol' => 'database')));
646 $this->assertEquals(3, $DB->count_records('role_assignments', array('component' => 'enrol_database')));
647 $this->assertIsEnrolled(1, 1, ENROL_USER_ACTIVE, 'student');
648 $this->assertIsEnrolled(1, 2, ENROL_USER_ACTIVE, 'teacher');
649 $this->assertIsEnrolled(2, 1, ENROL_USER_ACTIVE, 'student');
652 // Test sync of one course only.
654 $this->reset_enrol_database();
656 $DB->insert_record('enrol_database_test_enrols', array('userid' => self::$users[1]->username, 'courseid' => self::$courses[1]->id, 'roleid' => self::$roles['student']->id));
657 $DB->insert_record('enrol_database_test_enrols', array('userid' => self::$users[1]->username, 'courseid' => self::$courses[2]->id, 'roleid' => self::$roles['teacher']->id));
658 $DB->insert_record('enrol_database_test_enrols', array('userid' => self::$users[2]->username, 'courseid' => self::$courses[1]->id, 'roleid' => self::$roles['student']->id));
660 $this->assertEquals(0, $DB->count_records('user_enrolments', array()));
661 $this->assertEquals(0, $DB->count_records('enrol', array('enrol' => 'database')));
662 $this->assertEquals(0, $DB->count_records('role_assignments', array('component' => 'enrol_database')));
664 $plugin->sync_enrolments($trace, self::$courses[3]->id);
665 $this->assertEquals(0, $DB->count_records('user_enrolments', array()));
666 $this->assertEquals(1, $DB->count_records('enrol', array('enrol' => 'database')));
667 $this->assertEquals(0, $DB->count_records('role_assignments', array('component' => 'enrol_database')));
669 $plugin->sync_enrolments($trace, self::$courses[1]->id);
670 $this->assertEquals(2, $DB->count_records('user_enrolments', array()));
671 $this->assertEquals(2, $DB->count_records('enrol', array('enrol' => 'database')));
672 $this->assertEquals(2, $DB->count_records('role_assignments', array('component' => 'enrol_database')));
673 $this->assertIsEnrolled(1, 1, ENROL_USER_ACTIVE, 'student');
674 $this->assertIsEnrolled(2, 1, ENROL_USER_ACTIVE, 'student');
676 $plugin->sync_enrolments($trace, self::$courses[2]->id);
677 $this->assertEquals(3, $DB->count_records('user_enrolments', array()));
678 $this->assertEquals(3, $DB->count_records('enrol', array('enrol' => 'database')));
679 $this->assertEquals(3, $DB->count_records('role_assignments', array('component' => 'enrol_database')));
680 $this->assertIsEnrolled(1, 1, ENROL_USER_ACTIVE, 'student');
681 $this->assertIsEnrolled(1, 2, ENROL_USER_ACTIVE, 'teacher');
682 $this->assertIsEnrolled(2, 1, ENROL_USER_ACTIVE, 'student');
685 $plugin->set_config('unenrolaction', ENROL_EXT_REMOVED_UNENROL);
687 $DB->delete_records('enrol_database_test_enrols', array());
689 $plugin->sync_enrolments($trace, self::$courses[1]->id);
690 $this->assertEquals(1, $DB->count_records('user_enrolments', array()));
691 $this->assertEquals(3, $DB->count_records('enrol', array('enrol' => 'database')));
692 $this->assertEquals(1, $DB->count_records('role_assignments', array('component' => 'enrol_database')));
693 $this->assertIsEnrolled(1, 2, ENROL_USER_ACTIVE, 'teacher');
695 $plugin->sync_enrolments($trace, self::$courses[2]->id);
696 $this->assertEquals(0, $DB->count_records('user_enrolments', array()));
697 $this->assertEquals(3, $DB->count_records('enrol', array('enrol' => 'database')));
698 $this->assertEquals(0, $DB->count_records('role_assignments', array('component' => 'enrol_database')));
702 * @depends test_sync_users
704 public function test_sync_courses(): void {
705 global $DB;
707 $this->resetAfterTest(true);
708 $this->preventResetByRollback();
709 $this->reset_enrol_database();
711 $plugin = enrol_get_plugin('database');
713 $trace = new \null_progress_trace();
715 $plugin->set_config('localcategoryfield', 'id');
716 $coursecat = $this->getDataGenerator()->create_category(array('name' => 'Test category 1', 'idnumber' => 'tcid1'));
717 $defcat = $DB->get_record('course_categories', array('id' => $plugin->get_config('defaultcategory')));
719 $course1 = array('fullname' => 'New course 1', 'shortname' => 'nc1', 'idnumber' => 'ncid1', 'category' => $coursecat->id);
720 $course2 = array('fullname' => 'New course 2', 'shortname' => 'nc2', 'idnumber' => 'ncid2', 'category' => null);
721 // Duplicate records are to be ignored.
722 $course3 = array('fullname' => 'New course 3', 'shortname' => 'xx', 'idnumber' => 'yy2', 'category' => $defcat->id);
723 $course4 = array('fullname' => 'New course 4', 'shortname' => 'xx', 'idnumber' => 'yy3', 'category' => $defcat->id);
724 $course5 = array('fullname' => 'New course 5', 'shortname' => 'xx1', 'idnumber' => 'yy', 'category' => $defcat->id);
725 $course6 = array('fullname' => 'New course 6', 'shortname' => 'xx2', 'idnumber' => 'yy', 'category' => $defcat->id);
727 $DB->insert_record('enrol_database_test_courses', $course1);
728 $DB->insert_record('enrol_database_test_courses', $course2);
729 $DB->insert_record('enrol_database_test_courses', $course3);
730 $DB->insert_record('enrol_database_test_courses', $course4);
731 $DB->insert_record('enrol_database_test_courses', $course5);
732 $DB->insert_record('enrol_database_test_courses', $course6);
734 $this->assertEquals(1+count(self::$courses), $DB->count_records('course'));
736 $plugin->sync_courses($trace);
738 $this->assertEquals(4+1+count(self::$courses), $DB->count_records('course'));
740 $this->assertTrue($DB->record_exists('course', $course1));
741 $course2['category'] = $defcat->id;
742 $this->assertTrue($DB->record_exists('course', $course2));
745 // People should NOT push duplicates there because the results are UNDEFINED! But anyway skip the duplicates.
747 $this->assertEquals(1, $DB->count_records('course', array('idnumber' => 'yy')));
748 $this->assertEquals(1, $DB->count_records('course', array('shortname' => 'xx')));
750 // Check default number of sections matches with the created course sections.
752 $recordcourse1 = $DB->get_record('course', $course1);
753 $courseconfig = get_config('moodlecourse');
754 $numsections = $DB->count_records('course_sections', array('course' => $recordcourse1->id));
755 // To compare numsections we have to add topic 0 to default numsections.
756 $this->assertEquals(($courseconfig->numsections + 1), $numsections);
758 // Test category mapping via idnumber.
760 $plugin->set_config('localcategoryfield', 'idnumber');
761 $course7 = array('fullname' => 'New course 7', 'shortname' => 'nc7', 'idnumber' => 'ncid7', 'category' => 'tcid1');
762 $DB->insert_record('enrol_database_test_courses', $course7);
763 $plugin->sync_courses($trace);
765 $this->assertEquals(1+4+1+count(self::$courses), $DB->count_records('course'));
766 $this->assertTrue($DB->record_exists('course', $course1));
767 $this->assertTrue($DB->record_exists('course', $course2));
768 $course7['category'] = $coursecat->id;
769 $this->assertTrue($DB->record_exists('course', $course7));
772 // Test course template.
774 $template = $this->getDataGenerator()->create_course(array('numsections' => 666, 'shortname' => 'crstempl'));
775 $plugin->set_config('templatecourse', 'crstempl');
777 $course8 = array('fullname' => 'New course 8', 'shortname' => 'nc8', 'idnumber' => 'ncid8', 'category' => null);
778 $DB->insert_record('enrol_database_test_courses', $course8);
779 $plugin->sync_courses($trace);
781 $this->assertEquals(2+1+4+1+count(self::$courses), $DB->count_records('course'));
782 $course8['category'] = $defcat->id;
783 $record = $DB->get_record('course', $course8);
784 $this->assertFalse(empty($record));
785 $this->assertEquals(666, course_get_format($record)->get_last_section_number());
787 // Test invalid category.
789 $course9 = array('fullname' => 'New course 9', 'shortname' => 'nc9', 'idnumber' => 'ncid9', 'category' => 'xxxxxxx');
790 $DB->insert_record('enrol_database_test_courses', $course9);
791 $plugin->sync_courses($trace);
792 $this->assertEquals(2+1+4+1+count(self::$courses), $DB->count_records('course'));
793 $this->assertFalse($DB->record_exists('course', array('idnumber' => 'ncid9')));
796 // Test when categories not specified.
798 $plugin->set_config('newcoursecategory', '');
799 $plugin->sync_courses($trace);
800 $this->assertEquals(1+2+1+4+1+count(self::$courses), $DB->count_records('course'));
801 $this->assertTrue($DB->record_exists('course', array('idnumber' => 'ncid9')));
803 // Final cleanup - remove extra tables, fixtures and caches.
804 $this->cleanup_enrol_database();
808 * Test syncing courses with start and end dates.
810 * @covers \enrol_database_plugin::sync_courses
812 public function test_sync_courses_start_end_dates(): void {
813 global $DB;
815 $this->resetAfterTest();
816 $this->preventResetByRollback();
817 $this->init_enrol_database();
819 $courseconfig = get_config('moodlecourse');
820 $nextyear = (int) date('Y') + 1;
821 $prev = (int) date('Y') - 1;
823 $midnightstartdate = usergetmidnight(time());
824 $midnightenddate = usergetmidnight(time()) + $courseconfig->courseduration;
826 $plugin = enrol_get_plugin('database');
828 $trace = new \null_progress_trace();
830 $course1 = ['fullname' => 'C1', 'shortname' => 'c1', 'idnumber' => 'c1', 'startdate' => 0,
831 'enddate' => 0];
832 $course2 = ['fullname' => 'C2', 'shortname' => 'c2', 'idnumber' => 'c2', 'startdate' => null,
833 'enddate' => null];
834 // This course won't be created. Broken start date.
835 $course3 = ['fullname' => 'C3', 'shortname' => 'c3', 'idnumber' => 'c3', 'startdate' => 'not date',
836 'enddate' => 0];
837 // This course won't be created. Broken end date.
838 $course4 = ['fullname' => 'C4', 'shortname' => 'c4', 'idnumber' => 'c4', 'startdate' => 0,
839 'enddate' => 'not date'];
840 // This course won't be created. Start date after end date.
841 $course5 = ['fullname' => 'C5', 'shortname' => 'c5', 'idnumber' => 'c5', 'startdate' => '12.05.2024',
842 'enddate' => '12.05.2021'];
843 $course6 = ['fullname' => 'C6', 'shortname' => 'c6', 'idnumber' => 'c6', 'startdate' => '2024-05-22',
844 'enddate' => '2027-05-12'];
845 $course7 = ['fullname' => 'C7', 'shortname' => 'c7', 'idnumber' => 'c7', 'startdate' => null,
846 'enddate' => '12.05.' . $nextyear];
847 $course8 = ['fullname' => 'C8', 'shortname' => 'c8', 'idnumber' => 'c8', 'startdate' => '12.05.2024',
848 'enddate' => null];
849 // This course won't be created. Start date is not set, but it should be set to date after end date.
850 $course9 = ['fullname' => 'C9', 'shortname' => 'c9', 'idnumber' => 'c9', 'startdate' => null,
851 'enddate' => '12.05.' . $prev];
853 $DB->insert_record('enrol_database_test_courses', $course1);
854 $DB->insert_record('enrol_database_test_courses', $course2);
855 $DB->insert_record('enrol_database_test_courses', $course3);
856 $DB->insert_record('enrol_database_test_courses', $course4);
857 $DB->insert_record('enrol_database_test_courses', $course5);
858 $DB->insert_record('enrol_database_test_courses', $course6);
859 $DB->insert_record('enrol_database_test_courses', $course7);
860 $DB->insert_record('enrol_database_test_courses', $course8);
861 $DB->insert_record('enrol_database_test_courses', $course9);
863 $plugin->set_config('newcoursestartdate', 'startdate');
864 $plugin->set_config('newcourseenddate', 'enddate');
866 $plugin->sync_courses($trace);
868 // Course 3, course 4, course 5 and course 9 should not be created.
869 $this->assertTrue($DB->record_exists('course', ['shortname' => $course1['shortname']]));
870 $this->assertTrue($DB->record_exists('course', ['shortname' => $course2['shortname']]));
871 $this->assertFalse($DB->record_exists('course', ['shortname' => $course3['shortname']]));
872 $this->assertFalse($DB->record_exists('course', ['shortname' => $course4['shortname']]));
873 $this->assertFalse($DB->record_exists('course', ['shortname' => $course5['shortname']]));
874 $this->assertTrue($DB->record_exists('course', ['shortname' => $course6['shortname']]));
875 $this->assertTrue($DB->record_exists('course', ['shortname' => $course7['shortname']]));
876 $this->assertTrue($DB->record_exists('course', ['shortname' => $course8['shortname']]));
877 $this->assertFalse($DB->record_exists('course', ['shortname' => $course9['shortname']]));
879 // Check dates for created courses.
880 $this->assertEquals($midnightstartdate, $DB->get_field('course', 'startdate', ['shortname' => $course1['shortname']]));
881 $this->assertEquals($midnightenddate, $DB->get_field('course', 'enddate', ['shortname' => $course1['shortname']]));
883 $this->assertEquals($midnightstartdate, $DB->get_field('course', 'startdate', ['shortname' => $course2['shortname']]));
884 $this->assertEquals($midnightenddate, $DB->get_field('course', 'enddate', ['shortname' => $course2['shortname']]));
886 $this->assertEquals(strtotime('22.05.2024'), $DB->get_field('course', 'startdate', ['shortname' => $course6['shortname']]));
887 $this->assertEquals(strtotime('12.05.2027'), $DB->get_field('course', 'enddate', ['shortname' => $course6['shortname']]));
889 $this->assertEquals($midnightstartdate, $DB->get_field('course', 'startdate', ['shortname' => $course7['shortname']]));
890 $expected = strtotime('12.05.' . $nextyear);
891 $this->assertEquals($expected, $DB->get_field('course', 'enddate', ['shortname' => $course7['shortname']]));
893 $this->assertEquals(strtotime('12.05.2024'), $DB->get_field('course', 'startdate', ['shortname' => $course8['shortname']]));
894 $expected = strtotime('12.05.2024') + $courseconfig->courseduration;
895 $this->assertEquals($expected, $DB->get_field('course', 'enddate', ['shortname' => $course8['shortname']]));
897 // Push course with dates as timestamp.
898 $course10 = ['fullname' => 'C10', 'shortname' => 'c10', 'idnumber' => 'c10', 'startdate' => 1810051200,
899 'enddate' => 1810051211];
900 $DB->insert_record('enrol_database_test_courses', $course10);
902 $plugin->sync_courses($trace);
904 $this->assertTrue($DB->record_exists('course', ['shortname' => $course10['shortname']]));
905 $this->assertEquals(1810051200, $DB->get_field('course', 'startdate', ['shortname' => $course10['shortname']]));
906 $this->assertEquals(1810051211, $DB->get_field('course', 'enddate', ['shortname' => $course10['shortname']]));
908 // Push course with broken dates, but delete dates from plugin configuration before syncing.
909 $course11 = ['fullname' => 'C11', 'shortname' => 'c11', 'idnumber' => 'c11', 'startdate' => 'not date',
910 'enddate' => 'not date'];
911 $DB->insert_record('enrol_database_test_courses', $course11);
913 $plugin->set_config('newcoursestartdate', '');
914 $plugin->set_config('newcourseenddate', '');
915 $plugin->sync_courses($trace);
917 $this->assertTrue($DB->record_exists('course', ['shortname' => $course11['shortname']]));
918 $this->assertEquals($midnightstartdate, $DB->get_field('course', 'startdate', ['shortname' => $course11['shortname']]));
919 $this->assertEquals($midnightenddate, $DB->get_field('course', 'enddate', ['shortname' => $course11['shortname']]));
921 // Push courses with correct dates, but set date configuration to not existing date fields.
922 $course12 = ['fullname' => 'C12', 'shortname' => 'c12', 'idnumber' => 'c12', 'startdate' => '2024-05-22',
923 'enddate' => '2027-05-12'];
924 $DB->insert_record('enrol_database_test_courses', $course11);
926 $plugin->set_config('newcoursestartdate', 'startdate');
927 $plugin->set_config('newcourseenddate', 'ed');
928 $plugin->sync_courses($trace);
930 // Course should not be synced to prevent setting up incorrect dates.
931 $this->assertFalse($DB->record_exists('course', ['shortname' => $course12['shortname']]));
933 $course13 = ['fullname' => 'C13', 'shortname' => 'c13', 'idnumber' => 'c13', 'startdate' => '2024-05-22',
934 'enddate' => '2027-05-12'];
935 $DB->insert_record('enrol_database_test_courses', $course11);
937 $plugin->set_config('newcoursestartdate', 'sd');
938 $plugin->set_config('newcourseenddate', 'enddate');
939 $plugin->sync_courses($trace);
941 // Course should not be synced to prevent setting up incorrect dates.
942 $this->assertFalse($DB->record_exists('course', ['shortname' => $course13['shortname']]));
944 $this->cleanup_enrol_database();