Search moodle.org's
Developer Documentation

  • 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 37 and 311] [Versions 38 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  }