Search moodle.org's
Developer Documentation

See Release Notes

  • Bug fixes for general core bugs in 3.11.x will end 14 Nov 2022 (12 months plus 6 months extension).
  • Bug fixes for security issues in 3.11.x will end 13 Nov 2023 (18 months plus 12 months extension).
  • PHP version: minimum PHP 7.3.0 Note: minimum PHP version has increased since Moodle 3.10. PHP 7.4.x is supported too.

Differences Between: [Versions 310 and 311] [Versions 39 and 311]

   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.
  13  //
  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/>.
  16  
  17  namespace enrol_database;
  18  
  19  /**
  20   * External database enrolment sync tests
  21   *
  22   * This also tests adodb drivers that are matching
  23   * our four supported Moodle database drivers.
  24   *
  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
  29   */
  30  class sync_test extends \advanced_testcase {
  31      protected static $courses = array();
  32      protected static $users = array();
  33      protected static $roles = array();
  34  
  35      /** @var string Original error log */
  36      protected $oldlog;
  37  
  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);
  46          }
  47      }
  48  
  49      protected function init_enrol_database() {
  50          global $DB, $CFG;
  51  
  52          // Discard error logs from AdoDB.
  53          $this->oldlog = ini_get('error_log');
  54          ini_set('error_log', "$CFG->dataroot/testlog.log");
  55  
  56          $dbman = $DB->get_manager();
  57  
  58          set_config('dbencoding', 'utf-8', 'enrol_database');
  59  
  60          set_config('dbhost', $CFG->dbhost, 'enrol_database');
  61          set_config('dbuser', $CFG->dbuser, 'enrol_database');
  62          set_config('dbpass', $CFG->dbpass, 'enrol_database');
  63          set_config('dbname', $CFG->dbname, 'enrol_database');
  64  
  65          if (!empty($CFG->dboptions['dbport'])) {
  66              set_config('dbhost', $CFG->dbhost.':'.$CFG->dboptions['dbport'], 'enrol_database');
  67          }
  68  
  69          switch ($DB->get_dbfamily()) {
  70  
  71              case 'mysql':
  72                  set_config('dbtype', 'mysqli', 'enrol_database');
  73                  set_config('dbsetupsql', "SET NAMES 'UTF-8'", 'enrol_database');
  74                  set_config('dbsybasequoting', '0', 'enrol_database');
  75                  if (!empty($CFG->dboptions['dbsocket'])) {
  76                      $dbsocket = $CFG->dboptions['dbsocket'];
  77                      if ((strpos($dbsocket, '/') === false and strpos($dbsocket, '\\') === false)) {
  78                          $dbsocket = ini_get('mysqli.default_socket');
  79                      }
  80                      set_config('dbtype', 'mysqli://'.rawurlencode($CFG->dbuser).':'.rawurlencode($CFG->dbpass).'@'.rawurlencode($CFG->dbhost).'/'.rawurlencode($CFG->dbname).'?socket='.rawurlencode($dbsocket), 'enrol_database');
  81                  }
  82                  break;
  83  
  84              case 'oracle':
  85                  set_config('dbtype', 'oci8po', 'enrol_database');
  86                  set_config('dbsybasequoting', '1', 'enrol_database');
  87                  break;
  88  
  89              case 'postgres':
  90                  set_config('dbtype', 'postgres7', 'enrol_database');
  91                  $setupsql = "SET NAMES 'UTF-8'";
  92                  if (!empty($CFG->dboptions['dbschema'])) {
  93                      $setupsql .= "; SET search_path = '".$CFG->dboptions['dbschema']."'";
  94                  }
  95                  set_config('dbsetupsql', $setupsql, 'enrol_database');
  96                  set_config('dbsybasequoting', '0', 'enrol_database');
  97                  if (!empty($CFG->dboptions['dbsocket']) and ($CFG->dbhost === 'localhost' or $CFG->dbhost === '127.0.0.1')) {
  98                      if (strpos($CFG->dboptions['dbsocket'], '/') !== false) {
  99                          $socket = $CFG->dboptions['dbsocket'];
 100                          if (!empty($CFG->dboptions['dbport'])) {
 101                              $socket .= ':' . $CFG->dboptions['dbport'];
 102                          }
 103                          set_config('dbhost', $socket, 'enrol_database');
 104                      } else {
 105                        set_config('dbhost', '', 'enrol_database');
 106                      }
 107                  }
 108                  break;
 109  
 110              case 'mssql':
 111                  set_config('dbtype', 'mssqlnative', 'enrol_database');
 112                  set_config('dbsybasequoting', '1', 'enrol_database');
 113  
 114                  // The native sqlsrv driver uses a comma as separator between host and port.
 115                  $dbhost = $CFG->dbhost;
 116                  if (!empty($dboptions['dbport'])) {
 117                      $dbhost .= ',' . $dboptions['dbport'];
 118                  }
 119                  set_config('dbhost', $dbhost, 'enrol_database');
 120                  break;
 121  
 122              default:
 123                  throw new exception('Unknown database driver '.get_class($DB));
 124          }
 125  
 126          // NOTE: It is stongly discouraged to create new tables in advanced_testcase classes,
 127          //       but there is no other simple way to test ext database enrol sync, so let's
 128          //       disable transactions are try to cleanup after the tests.
 129  
 130          $table = new \xmldb_table('enrol_database_test_enrols');
 131          $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
 132          $table->add_field('courseid', XMLDB_TYPE_CHAR, '255', null, null, null);
 133          $table->add_field('userid', XMLDB_TYPE_CHAR, '255', null, null, null);
 134          $table->add_field('roleid', XMLDB_TYPE_CHAR, '255', null, null, null);
 135          $table->add_field('otheruser', XMLDB_TYPE_CHAR, '1', null, XMLDB_NOTNULL, null, '0');
 136          $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
 137          if ($dbman->table_exists($table)) {
 138              $dbman->drop_table($table);
 139          }
 140          $dbman->create_table($table);
 141          set_config('remoteenroltable', $CFG->prefix.'enrol_database_test_enrols', 'enrol_database');
 142          set_config('remotecoursefield', 'courseid', 'enrol_database');
 143          set_config('remoteuserfield', 'userid', 'enrol_database');
 144          set_config('remoterolefield', 'roleid', 'enrol_database');
 145          set_config('remoteotheruserfield', 'otheruser', 'enrol_database');
 146  
 147          $table = new \xmldb_table('enrol_database_test_courses');
 148          $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
 149          $table->add_field('fullname', XMLDB_TYPE_CHAR, '255', null, null, null);
 150          $table->add_field('shortname', XMLDB_TYPE_CHAR, '255', null, null, null);
 151          $table->add_field('idnumber', XMLDB_TYPE_CHAR, '255', null, null, null);
 152          $table->add_field('category', XMLDB_TYPE_CHAR, '255', null, null, null);
 153          $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
 154          if ($dbman->table_exists($table)) {
 155              $dbman->drop_table($table);
 156          }
 157          $dbman->create_table($table);
 158          set_config('newcoursetable', $CFG->prefix.'enrol_database_test_courses', 'enrol_database');
 159          set_config('newcoursefullname', 'fullname', 'enrol_database');
 160          set_config('newcourseshortname', 'shortname', 'enrol_database');
 161          set_config('newcourseidnumber', 'idnumber', 'enrol_database');
 162          set_config('newcoursecategory', 'category', 'enrol_database');
 163  
 164          // Create some test users and courses.
 165          for ($i = 1; $i <= 4; $i++) {
 166              self::$courses[$i] = $this->getDataGenerator()->create_course(array('fullname' => 'Test course '.$i, 'shortname' => 'tc'.$i, 'idnumber' => 'courseid'.$i));
 167          }
 168  
 169          for ($i = 1; $i <= 10; $i++) {
 170              self::$users[$i] = $this->getDataGenerator()->create_user(array('username' => 'username'.$i, 'idnumber' => 'userid'.$i, 'email' => 'user'.$i.'@example.com'));
 171          }
 172  
 173          foreach (get_all_roles() as $role) {
 174              self::$roles[$role->shortname] = $role;
 175          }
 176      }
 177  
 178      protected function cleanup_enrol_database() {
 179          global $DB;
 180  
 181          $dbman = $DB->get_manager();
 182          $table = new \xmldb_table('enrol_database_test_enrols');
 183          $dbman->drop_table($table);
 184          $table = new \xmldb_table('enrol_database_test_courses');
 185          $dbman->drop_table($table);
 186  
 187          self::$courses = null;
 188          self::$users = null;
 189          self::$roles = null;
 190  
 191          ini_set('error_log', $this->oldlog);
 192      }
 193  
 194      protected function reset_enrol_database() {
 195          global $DB;
 196  
 197          $DB->delete_records('enrol_database_test_enrols', array());
 198          $DB->delete_records('enrol_database_test_courses', array());
 199  
 200          $plugin = enrol_get_plugin('database');
 201          $instances = $DB->get_records('enrol', array('enrol' => 'database'));
 202          foreach($instances as $instance) {
 203              $plugin->delete_instance($instance);
 204          }
 205      }
 206  
 207      protected function assertIsEnrolled($userindex, $courseindex, $status=null, $rolename = null) {
 208          global $DB;
 209          $dbinstance = $DB->get_record('enrol', array('courseid' => self::$courses[$courseindex]->id, 'enrol' => 'database'), '*', MUST_EXIST);
 210  
 211          $conditions = array('enrolid' => $dbinstance->id, 'userid' => self::$users[$userindex]->id);
 212          if ($status !== null) {
 213              $conditions['status'] = $status;
 214          }
 215          $this->assertTrue($DB->record_exists('user_enrolments', $conditions));
 216  
 217          $this->assertHasRoleAssignment($userindex, $courseindex, $rolename);
 218      }
 219  
 220      protected function assertHasRoleAssignment($userindex, $courseindex, $rolename = null) {
 221          global $DB;
 222          $dbinstance = $DB->get_record('enrol', array('courseid' => self::$courses[$courseindex]->id, 'enrol' => 'database'), '*', MUST_EXIST);
 223  
 224          $coursecontext = \context_course::instance(self::$courses[$courseindex]->id);
 225          if ($rolename === false) {
 226              $this->assertFalse($DB->record_exists('role_assignments', array('component' => 'enrol_database', 'itemid' => $dbinstance->id, 'userid' => self::$users[$userindex]->id, 'contextid' => $coursecontext->id)));
 227          } else if ($rolename !== null) {
 228              $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)));
 229          }
 230      }
 231  
 232      protected function assertIsNotEnrolled($userindex, $courseindex) {
 233          global $DB;
 234          if (!$dbinstance = $DB->get_record('enrol', array('courseid' => self::$courses[$courseindex]->id, 'enrol' => 'database'))) {
 235              return;
 236          }
 237          $this->assertFalse($DB->record_exists('user_enrolments', array('enrolid' => $dbinstance->id, 'userid' => self::$users[$userindex]->id)));
 238      }
 239  
 240      public function test_sync_user_enrolments() {
 241          global $DB;
 242  
 243          $this->init_enrol_database();
 244  
 245          $this->resetAfterTest(false);
 246          $this->preventResetByRollback();
 247  
 248          $plugin = enrol_get_plugin('database');
 249  
 250          // Test basic enrol sync for one user after login.
 251  
 252          $this->reset_enrol_database();
 253          $plugin->set_config('localcoursefield', 'idnumber');
 254          $plugin->set_config('localuserfield', 'idnumber');
 255          $plugin->set_config('localrolefield', 'shortname');
 256  
 257          $plugin->set_config('defaultrole', self::$roles['student']->id);
 258  
 259          $DB->insert_record('enrol_database_test_enrols', array('userid' => 'userid1', 'courseid' => 'courseid1', 'roleid' => 'student'));
 260          $DB->insert_record('enrol_database_test_enrols', array('userid' => 'userid1', 'courseid' => 'courseid2', 'roleid' => 'teacher'));
 261          $DB->insert_record('enrol_database_test_enrols', array('userid' => 'userid2', 'courseid' => 'courseid1', 'roleid' => null));
 262          $DB->insert_record('enrol_database_test_enrols', array('userid' => 'userid4', 'courseid' => 'courseid4', 'roleid' => 'editingteacher', 'otheruser' => '1'));
 263          $DB->insert_record('enrol_database_test_enrols', array('userid' => 'xxxxxxx', 'courseid' => 'courseid1', 'roleid' => 'student')); // Bogus record to be ignored.
 264          $DB->insert_record('enrol_database_test_enrols', array('userid' => 'userid1', 'courseid' => 'xxxxxxxxx', 'roleid' => 'student')); // Bogus record to be ignored.
 265  
 266          $this->assertEquals(0, $DB->count_records('user_enrolments', array()));
 267          $this->assertEquals(0, $DB->count_records('enrol', array('enrol' => 'database')));
 268          $this->assertEquals(0, $DB->count_records('role_assignments', array('component' => 'enrol_database')));
 269  
 270          $plugin->sync_user_enrolments(self::$users[1]);
 271          $this->assertEquals(2, $DB->count_records('user_enrolments', array()));
 272          $this->assertEquals(2, $DB->count_records('enrol', array('enrol' => 'database')));
 273          $this->assertEquals(2, $DB->count_records('role_assignments', array('component' => 'enrol_database')));
 274          $this->assertIsEnrolled(1, 1, ENROL_USER_ACTIVE, 'student');
 275          $this->assertIsEnrolled(1, 2, ENROL_USER_ACTIVE, 'teacher');
 276  
 277          // Make sure there are no errors or changes on the next login.
 278  
 279          $plugin->sync_user_enrolments(self::$users[1]);
 280          $this->assertEquals(2, $DB->count_records('user_enrolments', array()));
 281          $this->assertEquals(2, $DB->count_records('enrol', array('enrol' => 'database')));
 282          $this->assertEquals(2, $DB->count_records('role_assignments', array('component' => 'enrol_database')));
 283          $this->assertIsEnrolled(1, 1, ENROL_USER_ACTIVE, 'student');
 284          $this->assertIsEnrolled(1, 2, ENROL_USER_ACTIVE, 'teacher');
 285  
 286          $plugin->sync_user_enrolments(self::$users[2]);
 287          $this->assertEquals(3, $DB->count_records('user_enrolments', array()));
 288          $this->assertEquals(2, $DB->count_records('enrol', array('enrol' => 'database')));
 289          $this->assertEquals(3, $DB->count_records('role_assignments', array('component' => 'enrol_database')));
 290          $this->assertIsEnrolled(1, 1, ENROL_USER_ACTIVE, 'student');
 291          $this->assertIsEnrolled(1, 2, ENROL_USER_ACTIVE, 'teacher');
 292          $this->assertIsEnrolled(2, 1, ENROL_USER_ACTIVE, 'student');
 293  
 294          $plugin->sync_user_enrolments(self::$users[4]);
 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');
 300          $this->assertIsEnrolled(2, 1, ENROL_USER_ACTIVE, 'student');
 301          $this->assertIsNotEnrolled(4, 4);
 302          $this->assertHasRoleAssignment(4, 4, 'editingteacher');
 303  
 304          // Enrolment removals.
 305  
 306          $DB->delete_records('enrol_database_test_enrols', array('userid' => 'userid1', 'courseid' => 'courseid1', 'roleid' => 'student'));
 307          $plugin->set_config('unenrolaction', ENROL_EXT_REMOVED_KEEP);
 308          $plugin->sync_user_enrolments(self::$users[1]);
 309          $this->assertEquals(3, $DB->count_records('user_enrolments', array()));
 310          $this->assertEquals(3, $DB->count_records('enrol', array('enrol' => 'database')));
 311          $this->assertEquals(4, $DB->count_records('role_assignments', array('component' => 'enrol_database')));
 312          $this->assertIsEnrolled(1, 1, ENROL_USER_ACTIVE, 'student');
 313          $this->assertIsEnrolled(1, 2, ENROL_USER_ACTIVE, 'teacher');
 314  
 315  
 316          $plugin->set_config('unenrolaction', ENROL_EXT_REMOVED_SUSPEND);
 317          $plugin->sync_user_enrolments(self::$users[1]);
 318          $this->assertEquals(3, $DB->count_records('user_enrolments', array()));
 319          $this->assertEquals(3, $DB->count_records('enrol', array('enrol' => 'database')));
 320          $this->assertEquals(4, $DB->count_records('role_assignments', array('component' => 'enrol_database')));
 321          $this->assertIsEnrolled(1, 1, ENROL_USER_SUSPENDED, 'student');
 322          $this->assertIsEnrolled(1, 2, ENROL_USER_ACTIVE, 'teacher');
 323  
 324          $DB->insert_record('enrol_database_test_enrols', array('userid' => 'userid1', 'courseid' => 'courseid1', 'roleid' => 'student'));
 325          $plugin->sync_user_enrolments(self::$users[1]);
 326          $this->assertEquals(3, $DB->count_records('user_enrolments', array()));
 327          $this->assertEquals(3, $DB->count_records('enrol', array('enrol' => 'database')));
 328          $this->assertEquals(4, $DB->count_records('role_assignments', array('component' => 'enrol_database')));
 329          $this->assertIsEnrolled(1, 1, ENROL_USER_ACTIVE, 'student');
 330          $this->assertIsEnrolled(1, 2, ENROL_USER_ACTIVE, 'teacher');
 331  
 332  
 333          $DB->delete_records('enrol_database_test_enrols', array('userid' => 'userid1', 'courseid' => 'courseid1', 'roleid' => 'student'));
 334          $plugin->set_config('unenrolaction', ENROL_EXT_REMOVED_SUSPENDNOROLES);
 335          $plugin->sync_user_enrolments(self::$users[1]);
 336          $this->assertEquals(3, $DB->count_records('user_enrolments', array()));
 337          $this->assertEquals(3, $DB->count_records('enrol', array('enrol' => 'database')));
 338          $this->assertEquals(3, $DB->count_records('role_assignments', array('component' => 'enrol_database')));
 339          $this->assertIsEnrolled(1, 1, ENROL_USER_SUSPENDED, false);
 340          $this->assertIsEnrolled(1, 2, ENROL_USER_ACTIVE, 'teacher');
 341  
 342          $DB->insert_record('enrol_database_test_enrols', array('userid' => 'userid1', 'courseid' => 'courseid1', 'roleid' => 'student'));
 343          $plugin->sync_user_enrolments(self::$users[1]);
 344          $this->assertEquals(3, $DB->count_records('user_enrolments', array()));
 345          $this->assertEquals(3, $DB->count_records('enrol', array('enrol' => 'database')));
 346          $this->assertEquals(4, $DB->count_records('role_assignments', array('component' => 'enrol_database')));
 347          $this->assertIsEnrolled(1, 1, ENROL_USER_ACTIVE, 'student');
 348          $this->assertIsEnrolled(1, 2, ENROL_USER_ACTIVE, 'teacher');
 349  
 350  
 351          $DB->delete_records('enrol_database_test_enrols', array('userid' => 'userid1', 'courseid' => 'courseid1', 'roleid' => 'student'));
 352          $plugin->set_config('unenrolaction', ENROL_EXT_REMOVED_UNENROL);
 353          $plugin->sync_user_enrolments(self::$users[1]);
 354          $this->assertEquals(2, $DB->count_records('user_enrolments', array()));
 355          $this->assertEquals(3, $DB->count_records('enrol', array('enrol' => 'database')));
 356          $this->assertEquals(3, $DB->count_records('role_assignments', array('component' => 'enrol_database')));
 357          $this->assertIsNotEnrolled(1, 1);
 358          $this->assertIsEnrolled(1, 2, ENROL_USER_ACTIVE, 'teacher');
 359  
 360          $DB->delete_records('enrol_database_test_enrols', array('userid' => 'userid4', 'courseid' => 'courseid4', 'roleid' => 'editingteacher'));
 361          $plugin->set_config('unenrolaction', ENROL_EXT_REMOVED_SUSPENDNOROLES);
 362          $plugin->sync_user_enrolments(self::$users[4]);
 363          $this->assertEquals(2, $DB->count_records('user_enrolments', array()));
 364          $this->assertEquals(3, $DB->count_records('enrol', array('enrol' => 'database')));
 365          $this->assertEquals(2, $DB->count_records('role_assignments', array('component' => 'enrol_database')));
 366          $this->assertIsNotEnrolled(4, 4);
 367          $this->assertHasRoleAssignment(4, 4, false);
 368  
 369          // Test all other mapping options.
 370  
 371          $this->reset_enrol_database();
 372  
 373          $this->assertEquals(0, $DB->count_records('user_enrolments', array()));
 374          $this->assertEquals(0, $DB->count_records('enrol', array('enrol' => 'database')));
 375          $this->assertEquals(0, $DB->count_records('role_assignments', array('component' => 'enrol_database')));
 376  
 377          $plugin->set_config('localcoursefield', 'id');
 378          $plugin->set_config('localuserfield', 'id');
 379          $plugin->set_config('localrolefield', 'id');
 380  
 381          $DB->insert_record('enrol_database_test_enrols', array('userid' => self::$users[1]->id, 'courseid' => self::$courses[1]->id, 'roleid' => self::$roles['student']->id));
 382          $DB->insert_record('enrol_database_test_enrols', array('userid' => self::$users[1]->id, 'courseid' => self::$courses[2]->id, 'roleid' => self::$roles['teacher']->id));
 383          $DB->insert_record('enrol_database_test_enrols', array('userid' => self::$users[2]->id, 'courseid' => self::$courses[1]->id, 'roleid' => self::$roles['student']->id));
 384  
 385          $plugin->sync_user_enrolments(self::$users[1]);
 386          $this->assertEquals(2, $DB->count_records('user_enrolments', array()));
 387          $this->assertEquals(2, $DB->count_records('enrol', array('enrol' => 'database')));
 388          $this->assertEquals(2, $DB->count_records('role_assignments', array('component' => 'enrol_database')));
 389          $this->assertIsEnrolled(1, 1, ENROL_USER_ACTIVE, 'student');
 390          $this->assertIsEnrolled(1, 2, ENROL_USER_ACTIVE, 'teacher');
 391  
 392  
 393          $this->reset_enrol_database();
 394          $plugin->set_config('localcoursefield', 'shortname');
 395          $plugin->set_config('localuserfield', 'email');
 396          $plugin->set_config('localrolefield', 'id');
 397  
 398          $DB->insert_record('enrol_database_test_enrols', array('userid' => self::$users[1]->email, 'courseid' => self::$courses[1]->shortname, 'roleid' => self::$roles['student']->id));
 399          $DB->insert_record('enrol_database_test_enrols', array('userid' => self::$users[1]->email, 'courseid' => self::$courses[2]->shortname, 'roleid' => self::$roles['teacher']->id));
 400          $DB->insert_record('enrol_database_test_enrols', array('userid' => self::$users[2]->email, 'courseid' => self::$courses[1]->shortname, 'roleid' => self::$roles['student']->id));
 401  
 402          $plugin->sync_user_enrolments(self::$users[1]);
 403          $this->assertEquals(2, $DB->count_records('user_enrolments', array()));
 404          $this->assertEquals(2, $DB->count_records('enrol', array('enrol' => 'database')));
 405          $this->assertEquals(2, $DB->count_records('role_assignments', array('component' => 'enrol_database')));
 406          $this->assertIsEnrolled(1, 1, ENROL_USER_ACTIVE, 'student');
 407          $this->assertIsEnrolled(1, 2, ENROL_USER_ACTIVE, 'teacher');
 408  
 409  
 410          $this->reset_enrol_database();
 411          $plugin->set_config('localcoursefield', 'id');
 412          $plugin->set_config('localuserfield', 'username');
 413          $plugin->set_config('localrolefield', 'id');
 414  
 415          $DB->insert_record('enrol_database_test_enrols', array('userid' => self::$users[1]->username, 'courseid' => self::$courses[1]->id, 'roleid' => self::$roles['student']->id));
 416          $DB->insert_record('enrol_database_test_enrols', array('userid' => self::$users[1]->username, 'courseid' => self::$courses[2]->id, 'roleid' => self::$roles['teacher']->id));
 417          $DB->insert_record('enrol_database_test_enrols', array('userid' => self::$users[2]->username, 'courseid' => self::$courses[1]->id, 'roleid' => self::$roles['student']->id));
 418  
 419          $plugin->sync_user_enrolments(self::$users[1]);
 420          $this->assertEquals(2, $DB->count_records('user_enrolments', array()));
 421          $this->assertEquals(2, $DB->count_records('enrol', array('enrol' => 'database')));
 422          $this->assertEquals(2, $DB->count_records('role_assignments', array('component' => 'enrol_database')));
 423          $this->assertIsEnrolled(1, 1, ENROL_USER_ACTIVE, 'student');
 424          $this->assertIsEnrolled(1, 2, ENROL_USER_ACTIVE, 'teacher');
 425      }
 426  
 427      /**
 428       * @depends test_sync_user_enrolments
 429       */
 430      public function test_sync_users() {
 431          global $DB;
 432  
 433          $this->resetAfterTest(false);
 434          $this->preventResetByRollback();
 435          $this->reset_enrol_database();
 436  
 437          $plugin = enrol_get_plugin('database');
 438  
 439          $trace = new \null_progress_trace();
 440  
 441          // Test basic enrol sync for one user after login.
 442  
 443          $this->reset_enrol_database();
 444          $plugin->set_config('localcoursefield', 'idnumber');
 445          $plugin->set_config('localuserfield', 'idnumber');
 446          $plugin->set_config('localrolefield', 'shortname');
 447  
 448          $DB->insert_record('enrol_database_test_enrols', array('userid' => 'userid1', 'courseid' => 'courseid1', 'roleid' => 'student'));
 449          $DB->insert_record('enrol_database_test_enrols', array('userid' => 'userid1', 'courseid' => 'courseid2', 'roleid' => 'editingteacher'));
 450          $DB->insert_record('enrol_database_test_enrols', array('userid' => 'userid2', 'courseid' => 'courseid1', 'roleid' => 'student'));
 451          $DB->insert_record('enrol_database_test_enrols', array('userid' => 'userid4', 'courseid' => 'courseid4', 'roleid' => 'editingteacher', 'otheruser' => '1'));
 452          $DB->insert_record('enrol_database_test_enrols', array('userid' => 'xxxxxxx', 'courseid' => 'courseid1', 'roleid' => 'student')); // Bogus record to be ignored.
 453          $DB->insert_record('enrol_database_test_enrols', array('userid' => 'userid1', 'courseid' => 'xxxxxxxxx', 'roleid' => 'student')); // Bogus record to be ignored.
 454          $this->assertEquals(0, $DB->count_records('user_enrolments', array()));
 455          $this->assertEquals(0, $DB->count_records('enrol', array('enrol' => 'database')));
 456          $this->assertEquals(0, $DB->count_records('role_assignments', array('component' => 'enrol_database')));
 457  
 458          $plugin->sync_enrolments($trace);
 459          $this->assertEquals(3, $DB->count_records('user_enrolments', array()));
 460          $this->assertEquals(3, $DB->count_records('enrol', array('enrol' => 'database')));
 461          $this->assertEquals(4, $DB->count_records('role_assignments', array('component' => 'enrol_database')));
 462          $this->assertIsEnrolled(1, 1, ENROL_USER_ACTIVE, 'student');
 463          $this->assertIsEnrolled(1, 2, ENROL_USER_ACTIVE, 'editingteacher');
 464          $this->assertIsEnrolled(2, 1, ENROL_USER_ACTIVE, 'student');
 465          $this->assertIsNotEnrolled(4, 4);
 466          $this->assertHasRoleAssignment(4, 4, 'editingteacher');
 467  
 468          $plugin->set_config('defaultrole', self::$roles['teacher']->id);
 469          $DB->insert_record('enrol_database_test_enrols', array('userid' => 'userid3', 'courseid' => 'courseid3'));
 470          $plugin->sync_enrolments($trace);
 471          $this->assertEquals(4, $DB->count_records('user_enrolments', array()));
 472          $this->assertEquals(4, $DB->count_records('enrol', array('enrol' => 'database')));
 473          $this->assertEquals(5, $DB->count_records('role_assignments', array('component' => 'enrol_database')));
 474          $this->assertIsEnrolled(1, 1, ENROL_USER_ACTIVE, 'student');
 475          $this->assertIsEnrolled(1, 2, ENROL_USER_ACTIVE, 'editingteacher');
 476          $this->assertIsEnrolled(2, 1, ENROL_USER_ACTIVE, 'student');
 477          $this->assertIsNotEnrolled(4, 4);
 478          $this->assertHasRoleAssignment(4, 4, 'editingteacher');
 479          $this->assertIsEnrolled(3, 3, ENROL_USER_ACTIVE, 'teacher');
 480  
 481  
 482          // Test different unenrolment options.
 483  
 484          $DB->delete_records('enrol_database_test_enrols', array('userid' => 'userid1', 'courseid' => 'courseid1', 'roleid' => 'student'));
 485          $plugin->set_config('unenrolaction', ENROL_EXT_REMOVED_KEEP);
 486          $plugin->sync_enrolments($trace);
 487          $this->assertEquals(4, $DB->count_records('user_enrolments', array()));
 488          $this->assertEquals(4, $DB->count_records('enrol', array('enrol' => 'database')));
 489          $this->assertEquals(5, $DB->count_records('role_assignments', array('component' => 'enrol_database')));
 490          $this->assertIsEnrolled(1, 1, ENROL_USER_ACTIVE, 'student');
 491          $this->assertIsEnrolled(1, 2, ENROL_USER_ACTIVE, 'editingteacher');
 492          $this->assertIsEnrolled(2, 1, ENROL_USER_ACTIVE, 'student');
 493          $this->assertIsNotEnrolled(4, 4);
 494          $this->assertHasRoleAssignment(4, 4, 'editingteacher');
 495          $this->assertIsEnrolled(3, 3, ENROL_USER_ACTIVE, 'teacher');
 496  
 497  
 498          $plugin->set_config('unenrolaction', ENROL_EXT_REMOVED_SUSPEND);
 499          $plugin->sync_enrolments($trace);
 500          $this->assertEquals(4, $DB->count_records('user_enrolments', array()));
 501          $this->assertEquals(4, $DB->count_records('enrol', array('enrol' => 'database')));
 502          $this->assertEquals(5, $DB->count_records('role_assignments', array('component' => 'enrol_database')));
 503          $this->assertIsEnrolled(1, 1, ENROL_USER_SUSPENDED, 'student');
 504          $this->assertIsEnrolled(1, 2, ENROL_USER_ACTIVE, 'editingteacher');
 505          $this->assertIsEnrolled(2, 1, ENROL_USER_ACTIVE, 'student');
 506          $this->assertIsNotEnrolled(4, 4);
 507          $this->assertHasRoleAssignment(4, 4, 'editingteacher');
 508          $this->assertIsEnrolled(3, 3, ENROL_USER_ACTIVE, 'teacher');
 509  
 510          $DB->insert_record('enrol_database_test_enrols', array('userid' => 'userid1', 'courseid' => 'courseid1', 'roleid' => 'student'));
 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(5, $DB->count_records('role_assignments', array('component' => 'enrol_database')));
 515          $this->assertIsEnrolled(1, 1, ENROL_USER_ACTIVE, 'student');
 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');
 521  
 522  
 523          $DB->delete_records('enrol_database_test_enrols', array('userid' => 'userid1', 'courseid' => 'courseid1', 'roleid' => 'student'));
 524          $plugin->set_config('unenrolaction', ENROL_EXT_REMOVED_SUSPENDNOROLES);
 525          $plugin->sync_enrolments($trace);
 526          $this->assertEquals(4, $DB->count_records('user_enrolments', array()));
 527          $this->assertEquals(4, $DB->count_records('enrol', array('enrol' => 'database')));
 528          $this->assertEquals(4, $DB->count_records('role_assignments', array('component' => 'enrol_database')));
 529          $this->assertIsEnrolled(1, 1, ENROL_USER_SUSPENDED, false);
 530          $this->assertIsEnrolled(1, 2, ENROL_USER_ACTIVE, 'editingteacher');
 531          $this->assertIsEnrolled(2, 1, ENROL_USER_ACTIVE, 'student');
 532          $this->assertIsNotEnrolled(4, 4);
 533          $this->assertHasRoleAssignment(4, 4, 'editingteacher');
 534          $this->assertIsEnrolled(3, 3, ENROL_USER_ACTIVE, 'teacher');
 535  
 536          $DB->insert_record('enrol_database_test_enrols', array('userid' => 'userid1', 'courseid' => 'courseid1', 'roleid' => 'student'));
 537          $plugin->sync_enrolments($trace);
 538          $this->assertEquals(4, $DB->count_records('user_enrolments', array()));
 539          $this->assertEquals(4, $DB->count_records('enrol', array('enrol' => 'database')));
 540          $this->assertEquals(5, $DB->count_records('role_assignments', array('component' => 'enrol_database')));
 541          $this->assertIsEnrolled(1, 1, ENROL_USER_ACTIVE, 'student');
 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');
 547  
 548  
 549          $DB->delete_records('enrol_database_test_enrols', array('userid' => 'userid1', 'courseid' => 'courseid1', 'roleid' => 'student'));
 550          $plugin->set_config('unenrolaction', ENROL_EXT_REMOVED_UNENROL);
 551          $plugin->sync_enrolments($trace);
 552          $this->assertEquals(3, $DB->count_records('user_enrolments', array()));
 553          $this->assertEquals(4, $DB->count_records('enrol', array('enrol' => 'database')));
 554          $this->assertEquals(4, $DB->count_records('role_assignments', array('component' => 'enrol_database')));
 555          $this->assertIsNotEnrolled(1, 1);
 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');
 561  
 562          $DB->insert_record('enrol_database_test_enrols', array('userid' => 'userid1', 'courseid' => 'courseid1', 'roleid' => 'student'));
 563          $DB->insert_record('enrol_database_test_enrols', array('userid' => 'userid1', 'courseid' => 'courseid1', 'roleid' => 'teacher'));
 564          $plugin->sync_enrolments($trace);
 565          $this->assertEquals(4, $DB->count_records('user_enrolments', array()));
 566          $this->assertEquals(4, $DB->count_records('enrol', array('enrol' => 'database')));
 567          $this->assertEquals(6, $DB->count_records('role_assignments', array('component' => 'enrol_database')));
 568          $this->assertIsEnrolled(1, 1, ENROL_USER_ACTIVE, 'student');
 569          $this->assertIsEnrolled(1, 1, ENROL_USER_ACTIVE, 'teacher');
 570          $this->assertIsEnrolled(1, 2, ENROL_USER_ACTIVE, 'editingteacher');
 571          $this->assertIsEnrolled(2, 1, ENROL_USER_ACTIVE, 'student');
 572          $this->assertIsNotEnrolled(4, 4);
 573          $this->assertHasRoleAssignment(4, 4, 'editingteacher');
 574          $this->assertIsEnrolled(3, 3, ENROL_USER_ACTIVE, 'teacher');
 575  
 576          $DB->delete_records('enrol_database_test_enrols', array('userid' => 'userid1', 'courseid' => 'courseid1', 'roleid' => 'teacher'));
 577          $plugin->sync_enrolments($trace);
 578          $this->assertEquals(4, $DB->count_records('user_enrolments', array()));
 579          $this->assertEquals(4, $DB->count_records('enrol', array('enrol' => 'database')));
 580          $this->assertEquals(5, $DB->count_records('role_assignments', array('component' => 'enrol_database')));
 581          $this->assertIsEnrolled(1, 1, ENROL_USER_ACTIVE, 'student');
 582          $this->assertIsEnrolled(1, 2, ENROL_USER_ACTIVE, 'editingteacher');
 583          $this->assertIsEnrolled(2, 1, ENROL_USER_ACTIVE, 'student');
 584          $this->assertIsNotEnrolled(4, 4);
 585          $this->assertHasRoleAssignment(4, 4, 'editingteacher');
 586          $this->assertIsEnrolled(3, 3, ENROL_USER_ACTIVE, 'teacher');
 587  
 588  
 589          // Test all other mapping options.
 590  
 591          $this->reset_enrol_database();
 592  
 593          $this->assertEquals(0, $DB->count_records('user_enrolments', array()));
 594          $this->assertEquals(0, $DB->count_records('enrol', array('enrol' => 'database')));
 595          $this->assertEquals(0, $DB->count_records('role_assignments', array('component' => 'enrol_database')));
 596  
 597          $plugin->set_config('localcoursefield', 'id');
 598          $plugin->set_config('localuserfield', 'id');
 599          $plugin->set_config('localrolefield', 'id');
 600  
 601          $DB->insert_record('enrol_database_test_enrols', array('userid' => self::$users[1]->id, 'courseid' => self::$courses[1]->id, 'roleid' => self::$roles['student']->id));
 602          $DB->insert_record('enrol_database_test_enrols', array('userid' => self::$users[1]->id, 'courseid' => self::$courses[2]->id, 'roleid' => self::$roles['teacher']->id));
 603          $DB->insert_record('enrol_database_test_enrols', array('userid' => self::$users[2]->id, 'courseid' => self::$courses[1]->id, 'roleid' => self::$roles['student']->id));
 604  
 605          $plugin->sync_enrolments($trace);
 606          $this->assertEquals(3, $DB->count_records('user_enrolments', array()));
 607          $this->assertEquals(2, $DB->count_records('enrol', array('enrol' => 'database')));
 608          $this->assertEquals(3, $DB->count_records('role_assignments', array('component' => 'enrol_database')));
 609          $this->assertIsEnrolled(1, 1, ENROL_USER_ACTIVE, 'student');
 610          $this->assertIsEnrolled(1, 2, ENROL_USER_ACTIVE, 'teacher');
 611          $this->assertIsEnrolled(2, 1, ENROL_USER_ACTIVE, 'student');
 612  
 613  
 614          $this->reset_enrol_database();
 615          $plugin->set_config('localcoursefield', 'shortname');
 616          $plugin->set_config('localuserfield', 'email');
 617          $plugin->set_config('localrolefield', 'id');
 618  
 619          $DB->insert_record('enrol_database_test_enrols', array('userid' => self::$users[1]->email, 'courseid' => self::$courses[1]->shortname, 'roleid' => self::$roles['student']->id));
 620          $DB->insert_record('enrol_database_test_enrols', array('userid' => self::$users[1]->email, 'courseid' => self::$courses[2]->shortname, 'roleid' => self::$roles['teacher']->id));
 621          $DB->insert_record('enrol_database_test_enrols', array('userid' => self::$users[2]->email, 'courseid' => self::$courses[1]->shortname, 'roleid' => self::$roles['student']->id));
 622  
 623          $plugin->sync_enrolments($trace);
 624          $this->assertEquals(3, $DB->count_records('user_enrolments', array()));
 625          $this->assertEquals(2, $DB->count_records('enrol', array('enrol' => 'database')));
 626          $this->assertEquals(3, $DB->count_records('role_assignments', array('component' => 'enrol_database')));
 627          $this->assertIsEnrolled(1, 1, ENROL_USER_ACTIVE, 'student');
 628          $this->assertIsEnrolled(1, 2, ENROL_USER_ACTIVE, 'teacher');
 629          $this->assertIsEnrolled(2, 1, ENROL_USER_ACTIVE, 'student');
 630  
 631  
 632          $this->reset_enrol_database();
 633          $plugin->set_config('localcoursefield', 'id');
 634          $plugin->set_config('localuserfield', 'username');
 635          $plugin->set_config('localrolefield', 'id');
 636  
 637          $DB->insert_record('enrol_database_test_enrols', array('userid' => self::$users[1]->username, 'courseid' => self::$courses[1]->id, 'roleid' => self::$roles['student']->id));
 638          $DB->insert_record('enrol_database_test_enrols', array('userid' => self::$users[1]->username, 'courseid' => self::$courses[2]->id, 'roleid' => self::$roles['teacher']->id));
 639          $DB->insert_record('enrol_database_test_enrols', array('userid' => self::$users[2]->username, 'courseid' => self::$courses[1]->id, 'roleid' => self::$roles['student']->id));
 640  
 641          $plugin->sync_enrolments($trace);
 642          $this->assertEquals(3, $DB->count_records('user_enrolments', array()));
 643          $this->assertEquals(2, $DB->count_records('enrol', array('enrol' => 'database')));
 644          $this->assertEquals(3, $DB->count_records('role_assignments', array('component' => 'enrol_database')));
 645          $this->assertIsEnrolled(1, 1, ENROL_USER_ACTIVE, 'student');
 646          $this->assertIsEnrolled(1, 2, ENROL_USER_ACTIVE, 'teacher');
 647          $this->assertIsEnrolled(2, 1, ENROL_USER_ACTIVE, 'student');
 648  
 649  
 650          // Test sync of one course only.
 651  
 652          $this->reset_enrol_database();
 653  
 654          $DB->insert_record('enrol_database_test_enrols', array('userid' => self::$users[1]->username, 'courseid' => self::$courses[1]->id, 'roleid' => self::$roles['student']->id));
 655          $DB->insert_record('enrol_database_test_enrols', array('userid' => self::$users[1]->username, 'courseid' => self::$courses[2]->id, 'roleid' => self::$roles['teacher']->id));
 656          $DB->insert_record('enrol_database_test_enrols', array('userid' => self::$users[2]->username, 'courseid' => self::$courses[1]->id, 'roleid' => self::$roles['student']->id));
 657  
 658          $this->assertEquals(0, $DB->count_records('user_enrolments', array()));
 659          $this->assertEquals(0, $DB->count_records('enrol', array('enrol' => 'database')));
 660          $this->assertEquals(0, $DB->count_records('role_assignments', array('component' => 'enrol_database')));
 661  
 662          $plugin->sync_enrolments($trace, self::$courses[3]->id);
 663          $this->assertEquals(0, $DB->count_records('user_enrolments', array()));
 664          $this->assertEquals(1, $DB->count_records('enrol', array('enrol' => 'database')));
 665          $this->assertEquals(0, $DB->count_records('role_assignments', array('component' => 'enrol_database')));
 666  
 667          $plugin->sync_enrolments($trace, self::$courses[1]->id);
 668          $this->assertEquals(2, $DB->count_records('user_enrolments', array()));
 669          $this->assertEquals(2, $DB->count_records('enrol', array('enrol' => 'database')));
 670          $this->assertEquals(2, $DB->count_records('role_assignments', array('component' => 'enrol_database')));
 671          $this->assertIsEnrolled(1, 1, ENROL_USER_ACTIVE, 'student');
 672          $this->assertIsEnrolled(2, 1, ENROL_USER_ACTIVE, 'student');
 673  
 674          $plugin->sync_enrolments($trace, self::$courses[2]->id);
 675          $this->assertEquals(3, $DB->count_records('user_enrolments', array()));
 676          $this->assertEquals(3, $DB->count_records('enrol', array('enrol' => 'database')));
 677          $this->assertEquals(3, $DB->count_records('role_assignments', array('component' => 'enrol_database')));
 678          $this->assertIsEnrolled(1, 1, ENROL_USER_ACTIVE, 'student');
 679          $this->assertIsEnrolled(1, 2, ENROL_USER_ACTIVE, 'teacher');
 680          $this->assertIsEnrolled(2, 1, ENROL_USER_ACTIVE, 'student');
 681  
 682  
 683          $plugin->set_config('unenrolaction', ENROL_EXT_REMOVED_UNENROL);
 684  
 685          $DB->delete_records('enrol_database_test_enrols', array());
 686  
 687          $plugin->sync_enrolments($trace, self::$courses[1]->id);
 688          $this->assertEquals(1, $DB->count_records('user_enrolments', array()));
 689          $this->assertEquals(3, $DB->count_records('enrol', array('enrol' => 'database')));
 690          $this->assertEquals(1, $DB->count_records('role_assignments', array('component' => 'enrol_database')));
 691          $this->assertIsEnrolled(1, 2, ENROL_USER_ACTIVE, 'teacher');
 692  
 693          $plugin->sync_enrolments($trace, self::$courses[2]->id);
 694          $this->assertEquals(0, $DB->count_records('user_enrolments', array()));
 695          $this->assertEquals(3, $DB->count_records('enrol', array('enrol' => 'database')));
 696          $this->assertEquals(0, $DB->count_records('role_assignments', array('component' => 'enrol_database')));
 697      }
 698  
 699      /**
 700       * @depends test_sync_users
 701       */
 702      public function test_sync_courses() {
 703          global $DB;
 704  
 705          $this->resetAfterTest(true);
 706          $this->preventResetByRollback();
 707          $this->reset_enrol_database();
 708  
 709          $plugin = enrol_get_plugin('database');
 710  
 711          $trace = new \null_progress_trace();
 712  
 713          $plugin->set_config('localcategoryfield', 'id');
 714          $coursecat = $this->getDataGenerator()->create_category(array('name' => 'Test category 1', 'idnumber' => 'tcid1'));
 715          $defcat = $DB->get_record('course_categories', array('id' => $plugin->get_config('defaultcategory')));
 716  
 717          $course1 = array('fullname' => 'New course 1', 'shortname' => 'nc1', 'idnumber' => 'ncid1', 'category' => $coursecat->id);
 718          $course2 = array('fullname' => 'New course 2', 'shortname' => 'nc2', 'idnumber' => 'ncid2', 'category' => null);
 719          // Duplicate records are to be ignored.
 720          $course3 = array('fullname' => 'New course 3', 'shortname' => 'xx', 'idnumber' => 'yy2', 'category' => $defcat->id);
 721          $course4 = array('fullname' => 'New course 4', 'shortname' => 'xx', 'idnumber' => 'yy3', 'category' => $defcat->id);
 722          $course5 = array('fullname' => 'New course 5', 'shortname' => 'xx1', 'idnumber' => 'yy', 'category' => $defcat->id);
 723          $course6 = array('fullname' => 'New course 6', 'shortname' => 'xx2', 'idnumber' => 'yy', 'category' => $defcat->id);
 724  
 725          $DB->insert_record('enrol_database_test_courses', $course1);
 726          $DB->insert_record('enrol_database_test_courses', $course2);
 727          $DB->insert_record('enrol_database_test_courses', $course3);
 728          $DB->insert_record('enrol_database_test_courses', $course4);
 729          $DB->insert_record('enrol_database_test_courses', $course5);
 730          $DB->insert_record('enrol_database_test_courses', $course6);
 731  
 732          $this->assertEquals(1+count(self::$courses), $DB->count_records('course'));
 733  
 734          $plugin->sync_courses($trace);
 735  
 736          $this->assertEquals(4+1+count(self::$courses), $DB->count_records('course'));
 737  
 738          $this->assertTrue($DB->record_exists('course', $course1));
 739          $course2['category'] = $defcat->id;
 740          $this->assertTrue($DB->record_exists('course', $course2));
 741  
 742  
 743          // People should NOT push duplicates there because the results are UNDEFINED! But anyway skip the duplicates.
 744  
 745          $this->assertEquals(1, $DB->count_records('course', array('idnumber' => 'yy')));
 746          $this->assertEquals(1, $DB->count_records('course', array('shortname' => 'xx')));
 747  
 748          // Check default number of sections matches with the created course sections.
 749  
 750          $recordcourse1 = $DB->get_record('course', $course1);
 751          $courseconfig = get_config('moodlecourse');
 752          $numsections = $DB->count_records('course_sections', array('course' => $recordcourse1->id));
 753          // To compare numsections we have to add topic 0 to default numsections.
 754          $this->assertEquals(($courseconfig->numsections + 1), $numsections);
 755  
 756          // Test category mapping via idnumber.
 757  
 758          $plugin->set_config('localcategoryfield', 'idnumber');
 759          $course7 = array('fullname' => 'New course 7', 'shortname' => 'nc7', 'idnumber' => 'ncid7', 'category' => 'tcid1');
 760          $DB->insert_record('enrol_database_test_courses', $course7);
 761          $plugin->sync_courses($trace);
 762  
 763          $this->assertEquals(1+4+1+count(self::$courses), $DB->count_records('course'));
 764          $this->assertTrue($DB->record_exists('course', $course1));
 765          $this->assertTrue($DB->record_exists('course', $course2));
 766          $course7['category'] = $coursecat->id;
 767          $this->assertTrue($DB->record_exists('course', $course7));
 768  
 769  
 770          // Test course template.
 771  
 772          $template = $this->getDataGenerator()->create_course(array('numsections' => 666, 'shortname' => 'crstempl'));
 773          $plugin->set_config('templatecourse', 'crstempl');
 774  
 775          $course8 = array('fullname' => 'New course 8', 'shortname' => 'nc8', 'idnumber' => 'ncid8', 'category' => null);
 776          $DB->insert_record('enrol_database_test_courses', $course8);
 777          $plugin->sync_courses($trace);
 778  
 779          $this->assertEquals(2+1+4+1+count(self::$courses), $DB->count_records('course'));
 780          $course8['category'] = $defcat->id;
 781          $record = $DB->get_record('course', $course8);
 782          $this->assertFalse(empty($record));
 783          $this->assertEquals(666, course_get_format($record)->get_last_section_number());
 784  
 785          // Test invalid category.
 786  
 787          $course9 = array('fullname' => 'New course 9', 'shortname' => 'nc9', 'idnumber' => 'ncid9', 'category' => 'xxxxxxx');
 788          $DB->insert_record('enrol_database_test_courses', $course9);
 789          $plugin->sync_courses($trace);
 790          $this->assertEquals(2+1+4+1+count(self::$courses), $DB->count_records('course'));
 791          $this->assertFalse($DB->record_exists('course', array('idnumber' => 'ncid9')));
 792  
 793  
 794          // Test when categories not specified.
 795  
 796          $plugin->set_config('newcoursecategory', '');
 797          $plugin->sync_courses($trace);
 798          $this->assertEquals(1+2+1+4+1+count(self::$courses), $DB->count_records('course'));
 799          $this->assertTrue($DB->record_exists('course', array('idnumber' => 'ncid9')));
 800  
 801  
 802          // Final cleanup - remove extra tables, fixtures and caches.
 803          $this->cleanup_enrol_database();
 804      }
 805  }