Search moodle.org's
Developer Documentation

See Release Notes

  • Bug fixes for general core bugs in 3.10.x will end 8 November 2021 (12 months).
  • Bug fixes for security issues in 3.10.x will end 9 May 2022 (18 months).
  • PHP version: minimum PHP 7.2.0 Note: minimum PHP version has increased since Moodle 3.8. PHP 7.3.x and 7.4.x are supported too.

Differences Between: [Versions 310 and 311] [Versions 310 and 400] [Versions 310 and 401] [Versions 310 and 402] [Versions 310 and 403]

   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  /**
  18   * Meta enrolment sync functional test.
  19   *
  20   * @package    enrol_meta
  21   * @category   phpunit
  22   * @copyright  2013 Petr Skoda {@link http://skodak.org}
  23   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  24   */
  25  
  26  defined('MOODLE_INTERNAL') || die();
  27  
  28  global $CFG;
  29  
  30  class enrol_meta_plugin_testcase extends advanced_testcase {
  31  
  32      protected function enable_plugin() {
  33          $enabled = enrol_get_plugins(true);
  34          $enabled['meta'] = true;
  35          $enabled = array_keys($enabled);
  36          set_config('enrol_plugins_enabled', implode(',', $enabled));
  37      }
  38  
  39      protected function disable_plugin() {
  40          $enabled = enrol_get_plugins(true);
  41          unset($enabled['meta']);
  42          $enabled = array_keys($enabled);
  43          set_config('enrol_plugins_enabled', implode(',', $enabled));
  44      }
  45  
  46      protected function is_meta_enrolled($user, $enrol, $role = null) {
  47          global $DB;
  48  
  49          if (!$DB->record_exists('user_enrolments', array('enrolid'=>$enrol->id, 'userid'=>$user->id))) {
  50              return false;
  51          }
  52  
  53          if ($role === null) {
  54              return true;
  55          }
  56  
  57          return $this->has_role($user, $enrol, $role);
  58      }
  59  
  60      protected function has_role($user, $enrol, $role) {
  61          global $DB;
  62  
  63          $context = context_course::instance($enrol->courseid);
  64  
  65          if ($role === false) {
  66              if ($DB->record_exists('role_assignments', array('contextid'=>$context->id, 'userid'=>$user->id, 'component'=>'enrol_meta', 'itemid'=>$enrol->id))) {
  67                  return false;
  68              }
  69          } else if (!$DB->record_exists('role_assignments', array('contextid'=>$context->id, 'userid'=>$user->id, 'roleid'=>$role->id, 'component'=>'enrol_meta', 'itemid'=>$enrol->id))) {
  70              return false;
  71          }
  72  
  73          return true;
  74      }
  75  
  76      public function test_sync() {
  77          global $CFG, $DB;
  78  
  79          $this->resetAfterTest(true);
  80  
  81          $metalplugin = enrol_get_plugin('meta');
  82          $manplugin = enrol_get_plugin('manual');
  83  
  84          $user1 = $this->getDataGenerator()->create_user();
  85          $user2 = $this->getDataGenerator()->create_user();
  86          $user3 = $this->getDataGenerator()->create_user();
  87          $user4 = $this->getDataGenerator()->create_user();
  88          $user5 = $this->getDataGenerator()->create_user();
  89  
  90          $course1 = $this->getDataGenerator()->create_course();
  91          $course2 = $this->getDataGenerator()->create_course();
  92          $course3 = $this->getDataGenerator()->create_course();
  93          $course4 = $this->getDataGenerator()->create_course();
  94          $manual1 = $DB->get_record('enrol', array('courseid'=>$course1->id, 'enrol'=>'manual'), '*', MUST_EXIST);
  95          $manual2 = $DB->get_record('enrol', array('courseid'=>$course2->id, 'enrol'=>'manual'), '*', MUST_EXIST);
  96          $manual3 = $DB->get_record('enrol', array('courseid'=>$course3->id, 'enrol'=>'manual'), '*', MUST_EXIST);
  97          $manual4 = $DB->get_record('enrol', array('courseid'=>$course4->id, 'enrol'=>'manual'), '*', MUST_EXIST);
  98  
  99          $student = $DB->get_record('role', array('shortname'=>'student'));
 100          $teacher = $DB->get_record('role', array('shortname'=>'teacher'));
 101          $manager = $DB->get_record('role', array('shortname'=>'manager'));
 102  
 103          $this->disable_plugin();
 104  
 105          $this->getDataGenerator()->enrol_user($user1->id, $course1->id, $student->id);
 106          $this->getDataGenerator()->enrol_user($user2->id, $course1->id, $student->id);
 107          $this->getDataGenerator()->enrol_user($user3->id, $course1->id, 0);
 108          $this->getDataGenerator()->enrol_user($user4->id, $course1->id, $teacher->id);
 109          $this->getDataGenerator()->enrol_user($user5->id, $course1->id, $manager->id);
 110  
 111          $this->getDataGenerator()->enrol_user($user1->id, $course2->id, $student->id);
 112          $this->getDataGenerator()->enrol_user($user2->id, $course2->id, $teacher->id);
 113  
 114          $this->assertEquals(7, $DB->count_records('user_enrolments'));
 115          $this->assertEquals(6, $DB->count_records('role_assignments'));
 116  
 117          set_config('syncall', 0, 'enrol_meta');
 118          set_config('nosyncroleids', $manager->id, 'enrol_meta');
 119  
 120          require_once($CFG->dirroot.'/enrol/meta/locallib.php');
 121  
 122          enrol_meta_sync(null, false);
 123          $this->assertEquals(7, $DB->count_records('user_enrolments'));
 124          $this->assertEquals(6, $DB->count_records('role_assignments'));
 125  
 126          $this->enable_plugin();
 127          enrol_meta_sync(null, false);
 128          $this->assertEquals(7, $DB->count_records('user_enrolments'));
 129          $this->assertEquals(6, $DB->count_records('role_assignments'));
 130  
 131          // Disable the plugin to prevent add_instance from calling enrol_meta_sync.
 132          $this->disable_plugin();
 133          $e1 = $metalplugin->add_instance($course3, array('customint1'=>$course1->id));
 134          $e2 = $metalplugin->add_instance($course3, array('customint1'=>$course2->id));
 135          $e3 = $metalplugin->add_instance($course4, array('customint1'=>$course2->id));
 136          $enrol1 = $DB->get_record('enrol', array('id'=>$e1));
 137          $enrol2 = $DB->get_record('enrol', array('id'=>$e2));
 138          $enrol3 = $DB->get_record('enrol', array('id'=>$e3));
 139          $this->enable_plugin();
 140  
 141          enrol_meta_sync($course4->id, false);
 142          $this->assertEquals(9, $DB->count_records('user_enrolments'));
 143          $this->assertEquals(8, $DB->count_records('role_assignments'));
 144          $this->assertTrue($this->is_meta_enrolled($user1, $enrol3, $student));
 145          $this->assertTrue($this->is_meta_enrolled($user2, $enrol3, $teacher));
 146  
 147          enrol_meta_sync(null, false);
 148          $this->assertEquals(14, $DB->count_records('user_enrolments'));
 149          $this->assertEquals(13, $DB->count_records('role_assignments'));
 150  
 151          $this->assertTrue($this->is_meta_enrolled($user1, $enrol1, $student));
 152          $this->assertTrue($this->is_meta_enrolled($user2, $enrol1, $student));
 153          $this->assertFalse($this->is_meta_enrolled($user3, $enrol1));
 154          $this->assertTrue($this->is_meta_enrolled($user4, $enrol1, $teacher));
 155          $this->assertFalse($this->is_meta_enrolled($user5, $enrol1));
 156  
 157          $this->assertTrue($this->is_meta_enrolled($user1, $enrol2, $student));
 158          $this->assertTrue($this->is_meta_enrolled($user2, $enrol2, $teacher));
 159  
 160          $this->assertTrue($this->is_meta_enrolled($user1, $enrol3, $student));
 161          $this->assertTrue($this->is_meta_enrolled($user2, $enrol3, $teacher));
 162  
 163          set_config('syncall', 1, 'enrol_meta');
 164          enrol_meta_sync(null, false);
 165          $this->assertEquals(16, $DB->count_records('user_enrolments'));
 166          $this->assertEquals(13, $DB->count_records('role_assignments'));
 167  
 168          $this->assertTrue($this->is_meta_enrolled($user3, $enrol1, false));
 169          $this->assertTrue($this->is_meta_enrolled($user5, $enrol1, false));
 170  
 171          $this->assertEquals(16, $DB->count_records('user_enrolments', array('status'=>ENROL_USER_ACTIVE)));
 172          $this->disable_plugin();
 173          $manplugin->unenrol_user($manual1, $user1->id);
 174          $manplugin->unenrol_user($manual2, $user1->id);
 175  
 176          $this->assertEquals(14, $DB->count_records('user_enrolments'));
 177          $this->assertEquals(11, $DB->count_records('role_assignments'));
 178          $this->assertEquals(14, $DB->count_records('user_enrolments', array('status'=>ENROL_USER_ACTIVE)));
 179  
 180          $this->enable_plugin();
 181  
 182          set_config('unenrolaction', ENROL_EXT_REMOVED_SUSPEND, 'enrol_meta');
 183          enrol_meta_sync($course4->id, false);
 184          $this->assertEquals(14, $DB->count_records('user_enrolments'));
 185          $this->assertEquals(11, $DB->count_records('role_assignments'));
 186          $this->assertEquals(13, $DB->count_records('user_enrolments', array('status'=>ENROL_USER_ACTIVE)));
 187          $this->assertTrue($this->is_meta_enrolled($user1, $enrol3, $student));
 188          $this->assertTrue($DB->record_exists('user_enrolments', array('enrolid'=>$enrol3->id, 'status'=>ENROL_USER_SUSPENDED, 'userid'=>$user1->id)));
 189  
 190          enrol_meta_sync(null, false);
 191          $this->assertEquals(14, $DB->count_records('user_enrolments'));
 192          $this->assertEquals(11, $DB->count_records('role_assignments'));
 193          $this->assertEquals(11, $DB->count_records('user_enrolments', array('status'=>ENROL_USER_ACTIVE)));
 194          $this->assertTrue($this->is_meta_enrolled($user1, $enrol1, $student));
 195          $this->assertTrue($DB->record_exists('user_enrolments', array('enrolid'=>$enrol1->id, 'status'=>ENROL_USER_SUSPENDED, 'userid'=>$user1->id)));
 196          $this->assertTrue($this->is_meta_enrolled($user1, $enrol2, $student));
 197          $this->assertTrue($DB->record_exists('user_enrolments', array('enrolid'=>$enrol2->id, 'status'=>ENROL_USER_SUSPENDED, 'userid'=>$user1->id)));
 198  
 199          set_config('unenrolaction', ENROL_EXT_REMOVED_SUSPENDNOROLES, 'enrol_meta');
 200          enrol_meta_sync($course4->id, false);
 201          $this->assertEquals(14, $DB->count_records('user_enrolments'));
 202          $this->assertEquals(10, $DB->count_records('role_assignments'));
 203          $this->assertEquals(11, $DB->count_records('user_enrolments', array('status'=>ENROL_USER_ACTIVE)));
 204          $this->assertTrue($this->is_meta_enrolled($user1, $enrol3, false));
 205          $this->assertTrue($DB->record_exists('user_enrolments', array('enrolid'=>$enrol3->id, 'status'=>ENROL_USER_SUSPENDED, 'userid'=>$user1->id)));
 206  
 207          enrol_meta_sync(null, false);
 208          $this->assertEquals(14, $DB->count_records('user_enrolments'));
 209          $this->assertEquals(8, $DB->count_records('role_assignments'));
 210          $this->assertEquals(11, $DB->count_records('user_enrolments', array('status'=>ENROL_USER_ACTIVE)));
 211          $this->assertTrue($this->is_meta_enrolled($user1, $enrol1, false));
 212          $this->assertTrue($DB->record_exists('user_enrolments', array('enrolid'=>$enrol1->id, 'status'=>ENROL_USER_SUSPENDED, 'userid'=>$user1->id)));
 213          $this->assertTrue($this->is_meta_enrolled($user1, $enrol2, false));
 214          $this->assertTrue($DB->record_exists('user_enrolments', array('enrolid'=>$enrol2->id, 'status'=>ENROL_USER_SUSPENDED, 'userid'=>$user1->id)));
 215  
 216          set_config('unenrolaction', ENROL_EXT_REMOVED_UNENROL, 'enrol_meta');
 217          enrol_meta_sync($course4->id, false);
 218          $this->assertEquals(13, $DB->count_records('user_enrolments'));
 219          $this->assertEquals(8, $DB->count_records('role_assignments'));
 220          $this->assertEquals(11, $DB->count_records('user_enrolments', array('status'=>ENROL_USER_ACTIVE)));
 221          $this->assertFalse($this->is_meta_enrolled($user1, $enrol3));
 222  
 223          enrol_meta_sync(null, false);
 224          $this->assertEquals(11, $DB->count_records('user_enrolments'));
 225          $this->assertEquals(8, $DB->count_records('role_assignments'));
 226          $this->assertEquals(11, $DB->count_records('user_enrolments', array('status'=>ENROL_USER_ACTIVE)));
 227          $this->assertFalse($this->is_meta_enrolled($user1, $enrol1));
 228          $this->assertFalse($this->is_meta_enrolled($user1, $enrol2));
 229  
 230  
 231          // Now try sync triggered by events.
 232  
 233          set_config('syncall', 1, 'enrol_meta');
 234  
 235          $this->getDataGenerator()->enrol_user($user1->id, $course1->id, $student->id);
 236          $this->assertEquals(13, $DB->count_records('user_enrolments'));
 237          $this->assertEquals(10, $DB->count_records('role_assignments'));
 238          $this->assertEquals(13, $DB->count_records('user_enrolments', array('status'=>ENROL_USER_ACTIVE)));
 239          $this->assertTrue($this->is_meta_enrolled($user1, $enrol1, $student));
 240          enrol_meta_sync(null, false);
 241          $this->assertEquals(13, $DB->count_records('user_enrolments'));
 242          $this->assertEquals(10, $DB->count_records('role_assignments'));
 243          $this->assertEquals(13, $DB->count_records('user_enrolments', array('status'=>ENROL_USER_ACTIVE)));
 244          $this->assertTrue($this->is_meta_enrolled($user1, $enrol1, $student));
 245  
 246          $manplugin->unenrol_user($manual1, $user1->id);
 247          $this->assertEquals(11, $DB->count_records('user_enrolments'));
 248          $this->assertEquals(8, $DB->count_records('role_assignments'));
 249          $this->assertEquals(11, $DB->count_records('user_enrolments', array('status'=>ENROL_USER_ACTIVE)));
 250          $this->assertFalse($this->is_meta_enrolled($user1, $enrol1));
 251          enrol_meta_sync(null, false);
 252          $this->assertEquals(11, $DB->count_records('user_enrolments'));
 253          $this->assertEquals(8, $DB->count_records('role_assignments'));
 254          $this->assertEquals(11, $DB->count_records('user_enrolments', array('status'=>ENROL_USER_ACTIVE)));
 255          $this->assertFalse($this->is_meta_enrolled($user1, $enrol1));
 256  
 257          $this->getDataGenerator()->enrol_user($user1->id, $course1->id, 0);
 258          $this->assertEquals(13, $DB->count_records('user_enrolments'));
 259          $this->assertEquals(8, $DB->count_records('role_assignments'));
 260          $this->assertEquals(13, $DB->count_records('user_enrolments', array('status'=>ENROL_USER_ACTIVE)));
 261          $this->assertTrue($this->is_meta_enrolled($user1, $enrol1, false));
 262          enrol_meta_sync(null, false);
 263          $this->assertEquals(13, $DB->count_records('user_enrolments'));
 264          $this->assertEquals(8, $DB->count_records('role_assignments'));
 265          $this->assertEquals(13, $DB->count_records('user_enrolments', array('status'=>ENROL_USER_ACTIVE)));
 266          $this->assertTrue($this->is_meta_enrolled($user1, $enrol1, false));
 267  
 268          $manplugin->unenrol_user($manual1, $user1->id);
 269          $this->assertEquals(11, $DB->count_records('user_enrolments'));
 270          $this->assertEquals(8, $DB->count_records('role_assignments'));
 271          $this->assertEquals(11, $DB->count_records('user_enrolments', array('status'=>ENROL_USER_ACTIVE)));
 272          $this->assertFalse($this->is_meta_enrolled($user1, $enrol1));
 273          enrol_meta_sync(null, false);
 274          $this->assertEquals(11, $DB->count_records('user_enrolments'));
 275          $this->assertEquals(8, $DB->count_records('role_assignments'));
 276          $this->assertEquals(11, $DB->count_records('user_enrolments', array('status'=>ENROL_USER_ACTIVE)));
 277          $this->assertFalse($this->is_meta_enrolled($user1, $enrol1));
 278  
 279          set_config('syncall', 0, 'enrol_meta');
 280          enrol_meta_sync(null, false);
 281          $this->assertEquals(9, $DB->count_records('user_enrolments'));
 282          $this->assertEquals(8, $DB->count_records('role_assignments'));
 283          $this->assertEquals(9, $DB->count_records('user_enrolments', array('status'=>ENROL_USER_ACTIVE)));
 284          $this->assertFalse($this->is_meta_enrolled($user1, $enrol1));
 285  
 286          $this->getDataGenerator()->enrol_user($user1->id, $course1->id, 0);
 287          $this->assertEquals(10, $DB->count_records('user_enrolments'));
 288          $this->assertEquals(8, $DB->count_records('role_assignments'));
 289          $this->assertEquals(10, $DB->count_records('user_enrolments', array('status'=>ENROL_USER_ACTIVE)));
 290          $this->assertFalse($this->is_meta_enrolled($user1, $enrol1, $student));
 291          enrol_meta_sync(null, false);
 292          $this->assertEquals(10, $DB->count_records('user_enrolments'));
 293          $this->assertEquals(8, $DB->count_records('role_assignments'));
 294          $this->assertEquals(10, $DB->count_records('user_enrolments', array('status'=>ENROL_USER_ACTIVE)));
 295          $this->assertFalse($this->is_meta_enrolled($user1, $enrol1, $student));
 296  
 297          role_assign($teacher->id, $user1->id, context_course::instance($course1->id)->id);
 298          $this->assertEquals(11, $DB->count_records('user_enrolments'));
 299          $this->assertEquals(10, $DB->count_records('role_assignments'));
 300          $this->assertEquals(11, $DB->count_records('user_enrolments', array('status'=>ENROL_USER_ACTIVE)));
 301          $this->assertTrue($this->is_meta_enrolled($user1, $enrol1, $teacher));
 302          enrol_meta_sync(null, false);
 303          $this->assertEquals(11, $DB->count_records('user_enrolments'));
 304          $this->assertEquals(10, $DB->count_records('role_assignments'));
 305          $this->assertEquals(11, $DB->count_records('user_enrolments', array('status'=>ENROL_USER_ACTIVE)));
 306          $this->assertTrue($this->is_meta_enrolled($user1, $enrol1, $teacher));
 307  
 308          role_unassign($teacher->id, $user1->id, context_course::instance($course1->id)->id);
 309          $this->assertEquals(10, $DB->count_records('user_enrolments'));
 310          $this->assertEquals(8, $DB->count_records('role_assignments'));
 311          $this->assertEquals(10, $DB->count_records('user_enrolments', array('status'=>ENROL_USER_ACTIVE)));
 312          $this->assertFalse($this->is_meta_enrolled($user1, $enrol1, $student));
 313          enrol_meta_sync(null, false);
 314          $this->assertEquals(10, $DB->count_records('user_enrolments'));
 315          $this->assertEquals(8, $DB->count_records('role_assignments'));
 316          $this->assertEquals(10, $DB->count_records('user_enrolments', array('status'=>ENROL_USER_ACTIVE)));
 317          $this->assertFalse($this->is_meta_enrolled($user1, $enrol1, $student));
 318  
 319          $manplugin->unenrol_user($manual1, $user1->id);
 320          $this->assertEquals(9, $DB->count_records('user_enrolments'));
 321          $this->assertEquals(8, $DB->count_records('role_assignments'));
 322          $this->assertEquals(9, $DB->count_records('user_enrolments', array('status'=>ENROL_USER_ACTIVE)));
 323          $this->assertFalse($this->is_meta_enrolled($user1, $enrol1));
 324  
 325          set_config('syncall', 1, 'enrol_meta');
 326          set_config('unenrolaction', ENROL_EXT_REMOVED_SUSPEND, 'enrol_meta');
 327          enrol_meta_sync(null, false);
 328          $this->assertEquals(11, $DB->count_records('user_enrolments'));
 329          $this->assertEquals(8, $DB->count_records('role_assignments'));
 330          $this->assertEquals(11, $DB->count_records('user_enrolments', array('status'=>ENROL_USER_ACTIVE)));
 331  
 332          $this->getDataGenerator()->enrol_user($user1->id, $course1->id, $student->id);
 333          $this->assertEquals(13, $DB->count_records('user_enrolments'));
 334          $this->assertEquals(10, $DB->count_records('role_assignments'));
 335          $this->assertEquals(13, $DB->count_records('user_enrolments', array('status'=>ENROL_USER_ACTIVE)));
 336          $this->assertTrue($this->is_meta_enrolled($user1, $enrol1, $student));
 337          enrol_meta_sync(null, false);
 338          $this->assertEquals(13, $DB->count_records('user_enrolments'));
 339          $this->assertEquals(10, $DB->count_records('role_assignments'));
 340          $this->assertEquals(13, $DB->count_records('user_enrolments', array('status'=>ENROL_USER_ACTIVE)));
 341          $this->assertTrue($this->is_meta_enrolled($user1, $enrol1, $student));
 342  
 343          $manplugin->update_user_enrol($manual1, $user1->id, ENROL_USER_SUSPENDED);
 344          $this->assertEquals(13, $DB->count_records('user_enrolments'));
 345          $this->assertEquals(10, $DB->count_records('role_assignments'));
 346          $this->assertEquals(11, $DB->count_records('user_enrolments', array('status'=>ENROL_USER_ACTIVE)));
 347          $this->assertTrue($this->is_meta_enrolled($user1, $enrol1, $student));
 348          enrol_meta_sync(null, false);
 349          $this->assertEquals(13, $DB->count_records('user_enrolments'));
 350          $this->assertEquals(10, $DB->count_records('role_assignments'));
 351          $this->assertEquals(11, $DB->count_records('user_enrolments', array('status'=>ENROL_USER_ACTIVE)));
 352          $this->assertTrue($this->is_meta_enrolled($user1, $enrol1, $student));
 353  
 354          $manplugin->unenrol_user($manual1, $user1->id);
 355          $this->assertEquals(12, $DB->count_records('user_enrolments'));
 356          $this->assertEquals(9, $DB->count_records('role_assignments'));
 357          $this->assertEquals(11, $DB->count_records('user_enrolments', array('status'=>ENROL_USER_ACTIVE)));
 358          $this->assertTrue($this->is_meta_enrolled($user1, $enrol1, $student));
 359          enrol_meta_sync(null, false);
 360          $this->assertEquals(12, $DB->count_records('user_enrolments'));
 361          $this->assertEquals(9, $DB->count_records('role_assignments'));
 362          $this->assertEquals(11, $DB->count_records('user_enrolments', array('status'=>ENROL_USER_ACTIVE)));
 363          $this->assertTrue($this->is_meta_enrolled($user1, $enrol1, $student));
 364  
 365          $this->getDataGenerator()->enrol_user($user1->id, $course1->id, $student->id);
 366          $this->assertEquals(13, $DB->count_records('user_enrolments'));
 367          $this->assertEquals(10, $DB->count_records('role_assignments'));
 368          $this->assertEquals(13, $DB->count_records('user_enrolments', array('status'=>ENROL_USER_ACTIVE)));
 369          $this->assertTrue($this->is_meta_enrolled($user1, $enrol1, $student));
 370          enrol_meta_sync(null, false);
 371          $this->assertEquals(13, $DB->count_records('user_enrolments'));
 372          $this->assertEquals(10, $DB->count_records('role_assignments'));
 373          $this->assertEquals(13, $DB->count_records('user_enrolments', array('status'=>ENROL_USER_ACTIVE)));
 374          $this->assertTrue($this->is_meta_enrolled($user1, $enrol1, $student));
 375  
 376          set_config('syncall', 1, 'enrol_meta');
 377          set_config('unenrolaction', ENROL_EXT_REMOVED_SUSPENDNOROLES, 'enrol_meta');
 378          enrol_meta_sync(null, false);
 379          $this->assertEquals(13, $DB->count_records('user_enrolments'));
 380          $this->assertEquals(10, $DB->count_records('role_assignments'));
 381          $this->assertEquals(13, $DB->count_records('user_enrolments', array('status'=>ENROL_USER_ACTIVE)));
 382  
 383          $this->getDataGenerator()->enrol_user($user1->id, $course1->id, $student->id);
 384          $this->assertEquals(13, $DB->count_records('user_enrolments'));
 385          $this->assertEquals(10, $DB->count_records('role_assignments'));
 386          $this->assertEquals(13, $DB->count_records('user_enrolments', array('status'=>ENROL_USER_ACTIVE)));
 387          $this->assertTrue($this->is_meta_enrolled($user1, $enrol1, $student));
 388          enrol_meta_sync(null, false);
 389          $this->assertEquals(13, $DB->count_records('user_enrolments'));
 390          $this->assertEquals(10, $DB->count_records('role_assignments'));
 391          $this->assertEquals(13, $DB->count_records('user_enrolments', array('status'=>ENROL_USER_ACTIVE)));
 392          $this->assertTrue($this->is_meta_enrolled($user1, $enrol1, $student));
 393  
 394          $manplugin->unenrol_user($manual1, $user1->id);
 395          $this->assertEquals(12, $DB->count_records('user_enrolments'));
 396          $this->assertEquals(8, $DB->count_records('role_assignments'));
 397          $this->assertEquals(11, $DB->count_records('user_enrolments', array('status'=>ENROL_USER_ACTIVE)));
 398          $this->assertTrue($this->is_meta_enrolled($user1, $enrol1, false));
 399          enrol_meta_sync(null, false);
 400          $this->assertEquals(12, $DB->count_records('user_enrolments'));
 401          $this->assertEquals(8, $DB->count_records('role_assignments'));
 402          $this->assertEquals(11, $DB->count_records('user_enrolments', array('status'=>ENROL_USER_ACTIVE)));
 403          $this->assertTrue($this->is_meta_enrolled($user1, $enrol1, false));
 404  
 405          $this->getDataGenerator()->enrol_user($user1->id, $course1->id, $student->id);
 406          $this->assertEquals(13, $DB->count_records('user_enrolments'));
 407          $this->assertEquals(10, $DB->count_records('role_assignments'));
 408          $this->assertEquals(13, $DB->count_records('user_enrolments', array('status'=>ENROL_USER_ACTIVE)));
 409          $this->assertTrue($this->is_meta_enrolled($user1, $enrol1, $student));
 410          enrol_meta_sync(null, false);
 411          $this->assertEquals(13, $DB->count_records('user_enrolments'));
 412          $this->assertEquals(10, $DB->count_records('role_assignments'));
 413          $this->assertEquals(13, $DB->count_records('user_enrolments', array('status'=>ENROL_USER_ACTIVE)));
 414          $this->assertTrue($this->is_meta_enrolled($user1, $enrol1, $student));
 415  
 416  
 417          set_config('unenrolaction', ENROL_EXT_REMOVED_UNENROL, 'enrol_meta');
 418          enrol_meta_sync(null, false);
 419          $this->assertEquals(13, $DB->count_records('user_enrolments'));
 420          $this->assertEquals(10, $DB->count_records('role_assignments'));
 421          $this->assertEquals(13, $DB->count_records('user_enrolments', array('status'=>ENROL_USER_ACTIVE)));
 422  
 423          delete_course($course1, false);
 424          $this->assertEquals(3, $DB->count_records('user_enrolments'));
 425          $this->assertEquals(3, $DB->count_records('role_assignments'));
 426          $this->assertEquals(3, $DB->count_records('user_enrolments', array('status'=>ENROL_USER_ACTIVE)));
 427          enrol_meta_sync(null, false);
 428          $this->assertEquals(3, $DB->count_records('user_enrolments'));
 429          $this->assertEquals(3, $DB->count_records('role_assignments'));
 430          $this->assertEquals(3, $DB->count_records('user_enrolments', array('status'=>ENROL_USER_ACTIVE)));
 431  
 432          delete_course($course2, false);
 433          $this->assertEquals(0, $DB->count_records('user_enrolments'));
 434          $this->assertEquals(0, $DB->count_records('role_assignments'));
 435          $this->assertEquals(0, $DB->count_records('user_enrolments', array('status'=>ENROL_USER_ACTIVE)));
 436          enrol_meta_sync(null, false);
 437          $this->assertEquals(0, $DB->count_records('user_enrolments'));
 438          $this->assertEquals(0, $DB->count_records('role_assignments'));
 439          $this->assertEquals(0, $DB->count_records('user_enrolments', array('status'=>ENROL_USER_ACTIVE)));
 440  
 441          delete_course($course3, false);
 442          delete_course($course4, false);
 443  
 444      }
 445  
 446      public function test_add_to_group() {
 447          global $CFG, $DB;
 448  
 449          require_once($CFG->dirroot.'/group/lib.php');
 450  
 451          $this->resetAfterTest(true);
 452  
 453          $metalplugin = enrol_get_plugin('meta');
 454  
 455          $user1 = $this->getDataGenerator()->create_user();
 456          $user4 = $this->getDataGenerator()->create_user();
 457  
 458          $course1 = $this->getDataGenerator()->create_course();
 459          $course2 = $this->getDataGenerator()->create_course();
 460          $course3 = $this->getDataGenerator()->create_course();
 461          $manualenrol1 = $DB->get_record('enrol', array('courseid' => $course1->id, 'enrol' => 'manual'), '*', MUST_EXIST);
 462          $manualenrol2 = $DB->get_record('enrol', array('courseid' => $course2->id, 'enrol' => 'manual'), '*', MUST_EXIST);
 463  
 464          $student = $DB->get_record('role', array('shortname' => 'student'));
 465          $teacher = $DB->get_record('role', array('shortname' => 'teacher'));
 466  
 467          $id = groups_create_group((object)array('name' => 'Group 1 in course 3', 'courseid' => $course3->id));
 468          $group31 = $DB->get_record('groups', array('id' => $id), '*', MUST_EXIST);
 469          $id = groups_create_group((object)array('name' => 'Group 2 in course 4', 'courseid' => $course3->id));
 470          $group32 = $DB->get_record('groups', array('id' => $id), '*', MUST_EXIST);
 471  
 472          $this->enable_plugin();
 473  
 474          $e1 = $metalplugin->add_instance($course3, array('customint1' => $course1->id, 'customint2' => $group31->id));
 475          $e2 = $metalplugin->add_instance($course3, array('customint1' => $course2->id, 'customint2' => $group32->id));
 476  
 477          $this->getDataGenerator()->enrol_user($user1->id, $course1->id, $student->id);
 478          $this->getDataGenerator()->enrol_user($user4->id, $course1->id, $teacher->id);
 479  
 480          $this->getDataGenerator()->enrol_user($user1->id, $course2->id, $student->id);
 481  
 482          // Now make sure users are in the correct groups.
 483          $this->assertTrue(groups_is_member($group31->id, $user1->id));
 484          $this->assertTrue($DB->record_exists('groups_members', array('groupid' => $group31->id, 'userid' => $user1->id,
 485              'component' => 'enrol_meta', 'itemid' => $e1)));
 486          $this->assertTrue(groups_is_member($group32->id, $user1->id));
 487          $this->assertTrue($DB->record_exists('groups_members', array('groupid' => $group32->id, 'userid' => $user1->id,
 488              'component' => 'enrol_meta', 'itemid' => $e2)));
 489  
 490          $this->assertTrue(groups_is_member($group31->id, $user4->id));
 491          $this->assertTrue($DB->record_exists('groups_members', array('groupid' => $group31->id, 'userid' => $user4->id,
 492              'component' => 'enrol_meta', 'itemid' => $e1)));
 493  
 494          // Make sure everything is the same after sync.
 495          enrol_meta_sync(null, false);
 496          $this->assertTrue(groups_is_member($group31->id, $user1->id));
 497          $this->assertTrue($DB->record_exists('groups_members', array('groupid' => $group31->id, 'userid' => $user1->id,
 498              'component' => 'enrol_meta', 'itemid' => $e1)));
 499          $this->assertTrue(groups_is_member($group32->id, $user1->id));
 500          $this->assertTrue($DB->record_exists('groups_members', array('groupid' => $group32->id, 'userid' => $user1->id,
 501              'component' => 'enrol_meta', 'itemid' => $e2)));
 502  
 503          $this->assertTrue(groups_is_member($group31->id, $user4->id));
 504          $this->assertTrue($DB->record_exists('groups_members', array('groupid' => $group31->id, 'userid' => $user4->id,
 505              'component' => 'enrol_meta', 'itemid' => $e1)));
 506  
 507          set_config('unenrolaction', ENROL_EXT_REMOVED_UNENROL, 'enrol_meta');
 508  
 509          // When user 1 is unenrolled from course1, he is removed from group31 but still present in group32.
 510          enrol_get_plugin('manual')->unenrol_user($manualenrol1, $user1->id);
 511          $this->assertFalse(groups_is_member($group31->id, $user1->id));
 512          $this->assertTrue(groups_is_member($group32->id, $user1->id));
 513          $this->assertTrue(is_enrolled(context_course::instance($course3->id), $user1, '', true)); // He still has active enrolment.
 514          // And the same after sync.
 515          enrol_meta_sync(null, false);
 516          $this->assertFalse(groups_is_member($group31->id, $user1->id));
 517          $this->assertTrue(groups_is_member($group32->id, $user1->id));
 518          $this->assertTrue(is_enrolled(context_course::instance($course3->id), $user1, '', true));
 519  
 520          // Unenroll user1 from course2 and make sure he is completely unenrolled from course3.
 521          enrol_get_plugin('manual')->unenrol_user($manualenrol2, $user1->id);
 522          $this->assertFalse(groups_is_member($group32->id, $user1->id));
 523          $this->assertFalse(is_enrolled(context_course::instance($course3->id), $user1));
 524  
 525          set_config('unenrolaction', ENROL_EXT_REMOVED_SUSPENDNOROLES, 'enrol_meta');
 526  
 527          // When user is unenrolled in this case, he is still a member of a group (but enrolment is suspended).
 528          enrol_get_plugin('manual')->unenrol_user($manualenrol1, $user4->id);
 529          $this->assertTrue(groups_is_member($group31->id, $user4->id));
 530          $this->assertTrue(is_enrolled(context_course::instance($course3->id), $user4));
 531          $this->assertFalse(is_enrolled(context_course::instance($course3->id), $user4, '', true));
 532          enrol_meta_sync(null, false);
 533          $this->assertTrue(groups_is_member($group31->id, $user4->id));
 534          $this->assertTrue(is_enrolled(context_course::instance($course3->id), $user4));
 535          $this->assertFalse(is_enrolled(context_course::instance($course3->id), $user4, '', true));
 536      }
 537  
 538      /**
 539       * Enrol users from another course into a course where one of the members is already enrolled
 540       * and is a member of the same group.
 541       */
 542      public function test_add_to_group_with_member() {
 543          global $CFG, $DB;
 544  
 545          require_once($CFG->dirroot.'/group/lib.php');
 546  
 547          $this->resetAfterTest(true);
 548  
 549          $metalplugin = enrol_get_plugin('meta');
 550  
 551          $user1 = $this->getDataGenerator()->create_user();
 552          $user2 = $this->getDataGenerator()->create_user();
 553  
 554          $course1 = $this->getDataGenerator()->create_course();
 555          $course2 = $this->getDataGenerator()->create_course();
 556          $manualenrol1 = $DB->get_record('enrol', array('courseid' => $course1->id, 'enrol' => 'manual'), '*', MUST_EXIST);
 557          $manualenrol2 = $DB->get_record('enrol', array('courseid' => $course2->id, 'enrol' => 'manual'), '*', MUST_EXIST);
 558  
 559          $student = $DB->get_record('role', array('shortname' => 'student'));
 560  
 561          $groupid = groups_create_group((object)array('name' => 'Grp', 'courseid' => $course2->id));
 562  
 563          $this->enable_plugin();
 564          set_config('unenrolaction', ENROL_EXT_REMOVED_UNENROL, 'enrol_meta');
 565  
 566          // Manually enrol user1 to course2 and add him to group.
 567          // Manually enrol user2 to course2 but do not add him to the group.
 568          enrol_get_plugin('manual')->enrol_user($manualenrol2, $user1->id, $student->id);
 569          groups_add_member($groupid, $user1->id);
 570          enrol_get_plugin('manual')->enrol_user($manualenrol2, $user2->id, $student->id);
 571          $this->assertTrue(groups_is_member($groupid, $user1->id));
 572          $this->assertFalse(groups_is_member($groupid, $user2->id));
 573  
 574          // Add instance of meta enrolment in course2 linking to course1 and enrol both users in course1.
 575          $metalplugin->add_instance($course2, array('customint1' => $course1->id, 'customint2' => $groupid));
 576  
 577          enrol_get_plugin('manual')->enrol_user($manualenrol1, $user1->id, $student->id);
 578          enrol_get_plugin('manual')->enrol_user($manualenrol1, $user2->id, $student->id);
 579  
 580          // Both users now should be members of the group.
 581          $this->assertTrue(groups_is_member($groupid, $user1->id));
 582          $this->assertTrue(groups_is_member($groupid, $user2->id));
 583  
 584          // Ununerol both users from course1.
 585          enrol_get_plugin('manual')->unenrol_user($manualenrol1, $user1->id);
 586          enrol_get_plugin('manual')->unenrol_user($manualenrol1, $user2->id);
 587  
 588          // User1 should still be member of the group because he was added there manually. User2 should no longer be there.
 589          $this->assertTrue(groups_is_member($groupid, $user1->id));
 590          $this->assertFalse(groups_is_member($groupid, $user2->id));
 591  
 592          // Assert that everything is the same after sync.
 593          enrol_meta_sync();
 594  
 595          $this->assertTrue(groups_is_member($groupid, $user1->id));
 596          $this->assertFalse(groups_is_member($groupid, $user2->id));
 597  
 598      }
 599  
 600      /**
 601       * Test user_enrolment_created event.
 602       */
 603      public function test_user_enrolment_created_event() {
 604          global $DB;
 605  
 606          $this->resetAfterTest();
 607  
 608          $metaplugin = enrol_get_plugin('meta');
 609          $user1 = $this->getDataGenerator()->create_user();
 610          $course1 = $this->getDataGenerator()->create_course();
 611          $course2 = $this->getDataGenerator()->create_course();
 612          $student = $DB->get_record('role', array('shortname' => 'student'));
 613  
 614          $e1 = $metaplugin->add_instance($course2, array('customint1' => $course1->id));
 615          $enrol1 = $DB->get_record('enrol', array('id' => $e1));
 616  
 617          // Enrol user and capture event.
 618          $sink = $this->redirectEvents();
 619  
 620          $metaplugin->enrol_user($enrol1, $user1->id, $student->id);
 621          $events = $sink->get_events();
 622          $sink->close();
 623          $event = array_shift($events);
 624  
 625          // Test Event.
 626          $dbuserenrolled = $DB->get_record('user_enrolments', array('userid' => $user1->id));
 627          $this->assertInstanceOf('\core\event\user_enrolment_created', $event);
 628          $this->assertEquals($dbuserenrolled->id, $event->objectid);
 629          $this->assertEquals('user_enrolled', $event->get_legacy_eventname());
 630          $expectedlegacyeventdata = $dbuserenrolled;
 631          $expectedlegacyeventdata->enrol = 'meta';
 632          $expectedlegacyeventdata->courseid = $course2->id;
 633          $this->assertEventLegacyData($expectedlegacyeventdata, $event);
 634          $this->assertEventContextNotUsed($event);
 635      }
 636  
 637      /**
 638       * Test user_enrolment_deleted event.
 639       */
 640      public function test_user_enrolment_deleted_event() {
 641          global $DB;
 642  
 643          $this->resetAfterTest(true);
 644  
 645          $metalplugin = enrol_get_plugin('meta');
 646          $user1 = $this->getDataGenerator()->create_user();
 647          $course1 = $this->getDataGenerator()->create_course();
 648          $course2 = $this->getDataGenerator()->create_course();
 649          $student = $DB->get_record('role', array('shortname'=>'student'));
 650  
 651          $e1 = $metalplugin->add_instance($course2, array('customint1' => $course1->id));
 652          $enrol1 = $DB->get_record('enrol', array('id' => $e1));
 653  
 654          // Enrol user.
 655          $metalplugin->enrol_user($enrol1, $user1->id, $student->id);
 656          $this->assertEquals(1, $DB->count_records('user_enrolments'));
 657  
 658          // Unenrol user and capture event.
 659          $sink = $this->redirectEvents();
 660          $metalplugin->unenrol_user($enrol1, $user1->id);
 661          $events = $sink->get_events();
 662          $sink->close();
 663          $event = array_pop($events);
 664  
 665          $this->assertEquals(0, $DB->count_records('user_enrolments'));
 666          $this->assertInstanceOf('\core\event\user_enrolment_deleted', $event);
 667          $this->assertEquals('user_unenrolled', $event->get_legacy_eventname());
 668          $this->assertEventContextNotUsed($event);
 669      }
 670  
 671      /**
 672       * Test user_enrolment_updated event.
 673       */
 674      public function test_user_enrolment_updated_event() {
 675          global $DB;
 676  
 677          $this->resetAfterTest(true);
 678  
 679          $metalplugin = enrol_get_plugin('meta');
 680          $user1 = $this->getDataGenerator()->create_user();
 681          $course1 = $this->getDataGenerator()->create_course();
 682          $course2 = $this->getDataGenerator()->create_course();
 683          $student = $DB->get_record('role', array('shortname'=>'student'));
 684  
 685          $e1 = $metalplugin->add_instance($course2, array('customint1' => $course1->id));
 686          $enrol1 = $DB->get_record('enrol', array('id' => $e1));
 687  
 688          // Enrol user.
 689          $metalplugin->enrol_user($enrol1, $user1->id, $student->id);
 690          $this->assertEquals(1, $DB->count_records('user_enrolments'));
 691  
 692          // Updated enrolment for user and capture event.
 693          $sink = $this->redirectEvents();
 694          $metalplugin->update_user_enrol($enrol1, $user1->id, ENROL_USER_SUSPENDED, null, time());
 695          $events = $sink->get_events();
 696          $sink->close();
 697          $event = array_shift($events);
 698  
 699          // Test Event.
 700          $dbuserenrolled = $DB->get_record('user_enrolments', array('userid' => $user1->id));
 701          $this->assertInstanceOf('\core\event\user_enrolment_updated', $event);
 702          $this->assertEquals($dbuserenrolled->id, $event->objectid);
 703          $this->assertEquals('user_enrol_modified', $event->get_legacy_eventname());
 704          $expectedlegacyeventdata = $dbuserenrolled;
 705          $expectedlegacyeventdata->enrol = 'meta';
 706          $expectedlegacyeventdata->courseid = $course2->id;
 707          $url = new \moodle_url('/enrol/editenrolment.php', array('ue' => $event->objectid));
 708          $this->assertEquals($url, $event->get_url());
 709          $this->assertEventLegacyData($expectedlegacyeventdata, $event);
 710          $this->assertEventContextNotUsed($event);
 711      }
 712  
 713      /**
 714       * Test that a new group with the name of the course is created.
 715       */
 716      public function test_enrol_meta_create_new_group() {
 717          global $DB;
 718          $this->resetAfterTest();
 719          // Create two courses.
 720          $course = $this->getDataGenerator()->create_course(array('fullname' => 'Mathematics'));
 721          $course2 = $this->getDataGenerator()->create_course(array('fullname' => 'Physics'));
 722          $metacourse = $this->getDataGenerator()->create_course(array('fullname' => 'All sciences'));
 723          // Run the function.
 724          $groupid = enrol_meta_create_new_group($metacourse->id, $course->id);
 725          // Check the results.
 726          $group = $DB->get_record('groups', array('id' => $groupid));
 727          // The group name should match the course name.
 728          $this->assertEquals('Mathematics course', $group->name);
 729          // Group course id should match the course id.
 730          $this->assertEquals($metacourse->id, $group->courseid);
 731  
 732          // Create a group that will have the same name as the course.
 733          $groupdata = new stdClass();
 734          $groupdata->courseid = $metacourse->id;
 735          $groupdata->name = 'Physics course';
 736          groups_create_group($groupdata);
 737          // Create a group for the course 2 in metacourse.
 738          $groupid = enrol_meta_create_new_group($metacourse->id, $course2->id);
 739          $groupinfo = $DB->get_record('groups', array('id' => $groupid));
 740          // Check that the group name has been changed.
 741          $this->assertEquals('Physics course (2)', $groupinfo->name);
 742  
 743          // Create a group for the course 2 in metacourse.
 744          $groupid = enrol_meta_create_new_group($metacourse->id, $course2->id);
 745          $groupinfo = $DB->get_record('groups', array('id' => $groupid));
 746          // Check that the group name has been changed.
 747          $this->assertEquals('Physics course (3)', $groupinfo->name);
 748      }
 749  
 750      /**
 751       * Test that enrolment timestart-timeend is respected in meta course.
 752       */
 753      public function test_timeend() {
 754          global $CFG, $DB;
 755  
 756          $this->resetAfterTest(true);
 757  
 758          $timeinfuture = time() + DAYSECS;
 759          $timeinpast = time() - DAYSECS;
 760  
 761          $metalplugin = enrol_get_plugin('meta');
 762          $manplugin = enrol_get_plugin('manual');
 763  
 764          $user1 = $this->getDataGenerator()->create_user();
 765          $user2 = $this->getDataGenerator()->create_user();
 766          $user3 = $this->getDataGenerator()->create_user();
 767          $user4 = $this->getDataGenerator()->create_user();
 768          $user5 = $this->getDataGenerator()->create_user();
 769  
 770          $course1 = $this->getDataGenerator()->create_course();
 771          $course2 = $this->getDataGenerator()->create_course();
 772          $course3 = $this->getDataGenerator()->create_course();
 773          $manual1 = $DB->get_record('enrol', array('courseid' => $course1->id, 'enrol' => 'manual'), '*', MUST_EXIST);
 774  
 775          $student = $DB->get_record('role', array('shortname' => 'student'));
 776  
 777          $this->enable_plugin();
 778  
 779          // Create instance of enrol_meta in course2 when there are no enrolments present.
 780          $meta2id = $metalplugin->add_instance($course2, array('customint1' => $course1->id));
 781  
 782          $expectedenrolments = array(
 783              $user1->id => array(0, 0, ENROL_USER_ACTIVE),
 784              $user2->id => array($timeinpast, 0, ENROL_USER_ACTIVE),
 785              $user3->id => array(0, $timeinfuture, ENROL_USER_ACTIVE),
 786              $user4->id => array($timeinpast, $timeinfuture, ENROL_USER_ACTIVE),
 787              $user5->id => array(0, 0, ENROL_USER_SUSPENDED),
 788          );
 789          foreach ($expectedenrolments as $userid => $data) {
 790              $expectedenrolments[$userid] = (object)(array('userid' => $userid) +
 791                      array_combine(array('timestart', 'timeend', 'status'), $data));
 792          }
 793  
 794          // Enrol users manually in course 1.
 795          foreach ($expectedenrolments as $e) {
 796              $manplugin->enrol_user($manual1, $e->userid, $student->id, $e->timestart, $e->timeend, $e->status);
 797          }
 798  
 799          $enrolments = $DB->get_records('user_enrolments', array('enrolid' => $manual1->id), 'userid', 'userid, timestart, timeend, status');
 800          $this->assertEquals($expectedenrolments, $enrolments);
 801  
 802          // Make sure that the same enrolments are now present in course2 under meta enrolment.
 803          $enrolments = $DB->get_records('user_enrolments', array('enrolid' => $meta2id), '', 'userid, timestart, timeend, status');
 804          $this->assertEquals($expectedenrolments, $enrolments);
 805  
 806          // Create instance of enrol_meta in course3 and run sync.
 807          $meta3id = $metalplugin->add_instance($course3, array('customint1' => $course1->id));
 808          enrol_meta_sync($course3->id);
 809  
 810          // Make sure that the same enrolments are now present in course3 under meta enrolment.
 811          $enrolments = $DB->get_records('user_enrolments', array('enrolid' => $meta3id), '', 'userid, timestart, timeend, status');
 812          $this->assertEquals($expectedenrolments, $enrolments);
 813  
 814          // Update some of the manual enrolments.
 815          $expectedenrolments[$user2->id]->timestart = $timeinpast - 60;
 816          $expectedenrolments[$user3->id]->timeend = $timeinfuture + 60;
 817          $expectedenrolments[$user4->id]->status = ENROL_USER_SUSPENDED;
 818          $expectedenrolments[$user5->id]->status = ENROL_USER_ACTIVE;
 819          foreach ($expectedenrolments as $e) {
 820              $manplugin->update_user_enrol($manual1, $e->userid, $e->status, $e->timestart, $e->timeend);
 821          }
 822  
 823          // Make sure meta courses are also updated.
 824          $enrolments = $DB->get_records('user_enrolments', array('enrolid' => $meta2id), '', 'userid, timestart, timeend, status');
 825          $this->assertEquals($expectedenrolments, $enrolments);
 826          $enrolments = $DB->get_records('user_enrolments', array('enrolid' => $meta3id), '', 'userid, timestart, timeend, status');
 827          $this->assertEquals($expectedenrolments, $enrolments);
 828  
 829          // Test meta sync. Imagine events are not working.
 830          $sink = $this->redirectEvents();
 831          $expectedenrolments[$user2->id]->timestart = $timeinpast;
 832          $expectedenrolments[$user3->id]->timeend = $timeinfuture;
 833          $expectedenrolments[$user4->id]->status = ENROL_USER_ACTIVE;
 834          $expectedenrolments[$user5->id]->status = ENROL_USER_SUSPENDED;
 835          foreach ($expectedenrolments as $e) {
 836              $manplugin->update_user_enrol($manual1, $e->userid, $e->status, $e->timestart, $e->timeend);
 837          }
 838  
 839          // Make sure meta courses are updated only for the course that was synced.
 840          enrol_meta_sync($course3->id);
 841  
 842          $enrolments = $DB->get_records('user_enrolments', array('enrolid' => $meta2id), '', 'userid, timestart, timeend, status');
 843          $this->assertNotEquals($expectedenrolments, $enrolments);
 844  
 845          $enrolments = $DB->get_records('user_enrolments', array('enrolid' => $meta3id), '', 'userid, timestart, timeend, status');
 846          $this->assertEquals($expectedenrolments, $enrolments);
 847  
 848          $sink->close();
 849  
 850          // Disable manual enrolment in course1 and make sure all user enrolments in course2 are suspended.
 851          $manplugin->update_status($manual1, ENROL_INSTANCE_DISABLED);
 852          $allsuspendedenrolemnts = array_combine(array_keys($expectedenrolments), array_fill(0, 5, ENROL_USER_SUSPENDED));
 853          $enrolmentstatuses = $DB->get_records_menu('user_enrolments', array('enrolid' => $meta2id), '', 'userid, status');
 854          $this->assertEquals($allsuspendedenrolemnts, $enrolmentstatuses);
 855  
 856          $manplugin->update_status($manual1, ENROL_INSTANCE_ENABLED);
 857          $enrolments = $DB->get_records('user_enrolments', array('enrolid' => $meta2id), '', 'userid, timestart, timeend, status');
 858          $this->assertEquals($expectedenrolments, $enrolments);
 859  
 860          // Disable events and repeat the same for course3 (testing sync):
 861          $sink = $this->redirectEvents();
 862          $manplugin->update_status($manual1, ENROL_INSTANCE_DISABLED);
 863          enrol_meta_sync($course3->id);
 864          $enrolmentstatuses = $DB->get_records_menu('user_enrolments', array('enrolid' => $meta3id), '', 'userid, status');
 865          $this->assertEquals($allsuspendedenrolemnts, $enrolmentstatuses);
 866  
 867          $manplugin->update_status($manual1, ENROL_INSTANCE_ENABLED);
 868          enrol_meta_sync($course3->id);
 869          $enrolments = $DB->get_records('user_enrolments', array('enrolid' => $meta3id), '', 'userid, timestart, timeend, status');
 870          $this->assertEquals($expectedenrolments, $enrolments);
 871          $sink->close();
 872      }
 873  
 874      /**
 875       * Test for getting user enrolment actions.
 876       */
 877      public function test_get_user_enrolment_actions() {
 878          global $CFG, $PAGE;
 879          $this->resetAfterTest();
 880  
 881          // Set page URL to prevent debugging messages.
 882          $PAGE->set_url('/enrol/editinstance.php');
 883  
 884          $pluginname = 'meta';
 885  
 886          // Only enable the meta enrol plugin.
 887          $CFG->enrol_plugins_enabled = $pluginname;
 888  
 889          $generator = $this->getDataGenerator();
 890  
 891          // Get the enrol plugin.
 892          $plugin = enrol_get_plugin($pluginname);
 893  
 894          // Create a course.
 895          $course = $generator->create_course();
 896          // Enable this enrol plugin for the course.
 897          $plugin->add_instance($course);
 898  
 899          // Create a student.
 900          $student = $generator->create_user();
 901          // Enrol the student to the course.
 902          $generator->enrol_user($student->id, $course->id, 'student', $pluginname);
 903  
 904          // Teachers don't have enrol/meta:unenrol capability by default. Login as admin for simplicity.
 905          $this->setAdminUser();
 906          require_once($CFG->dirroot . '/enrol/locallib.php');
 907          $manager = new course_enrolment_manager($PAGE, $course);
 908  
 909          $userenrolments = $manager->get_user_enrolments($student->id);
 910          $this->assertCount(1, $userenrolments);
 911  
 912          $ue = reset($userenrolments);
 913          $actions = $plugin->get_user_enrolment_actions($manager, $ue);
 914          // Meta-link enrolment has no enrol actions for active students.
 915          $this->assertCount(0, $actions);
 916  
 917          // Enrol actions for a suspended student.
 918          // Suspend the student.
 919          $ue->status = ENROL_USER_SUSPENDED;
 920  
 921          $actions = $plugin->get_user_enrolment_actions($manager, $ue);
 922          // Meta-link enrolment has enrol actions for suspended students -- unenrol.
 923          $this->assertCount(1, $actions);
 924      }
 925  
 926      /**
 927       * Test how data for instance editing is validated.
 928       */
 929      public function test_edit_instance_validation() {
 930          global $DB;
 931  
 932          $this->resetAfterTest();
 933  
 934          $metaplugin = enrol_get_plugin('meta');
 935  
 936          // A course with meta enrolment.
 937          $course = $this->getDataGenerator()->create_course();
 938          $coursecontext = context_course::instance($course->id);
 939  
 940          // Create a meta enrolment instance.
 941          $instance = (object)$metaplugin->get_instance_defaults();
 942          $instance->id       = null;
 943          $instance->courseid = $course->id;
 944          $instance->status   = ENROL_INSTANCE_ENABLED;
 945          // Emulate the form data.
 946          $data = [
 947              'customint1' => 0,
 948              'customint2' => 0
 949          ];
 950          // Test when no valid 'customint1' field (meta courses links) is provided.
 951          $errors = $metaplugin->edit_instance_validation($data, [], $instance, $coursecontext);
 952          // We're going to check the string contents of the errors returned as this is the only way
 953          // to differentiate the errors produced by the 'edit_instance_validation()' method somehow.
 954          // The method always returns what the edit instance form expects and this is an array of form fields
 955          // with the corresponding errors messages.
 956          $this->assertEquals('Required', $errors['customint1']);
 957  
 958          // Test when 'customint1' contains an unknown course.
 959          // Fetch the max course id from the courses table and increment it to get
 960          // the course id which surely doesn't exist.
 961          $maxid = $DB->get_field_sql('SELECT MAX(id) FROM {course}');
 962          // Use the same instance as before but set another data.
 963          $data = [
 964              'customint1' => [$maxid + 1],
 965              'customint2' => 0
 966          ];
 967          $errors = $metaplugin->edit_instance_validation($data, [], $instance, $coursecontext);
 968          $this->assertEquals('You are trying to use an invalid course ID', $errors['customint1']);
 969  
 970          // Test when 'customint1' field already contains courses meta linked with the current one.
 971          $metacourse1 = $this->getDataGenerator()->create_course();
 972          $metaplugin->add_instance($course, array('customint1' => $metacourse1->id));
 973          // Use the same instance as before but set another data.
 974          $data = [
 975              'customint1' => [$metacourse1->id],
 976              'customint2' => 0
 977          ];
 978          $errors = $metaplugin->edit_instance_validation($data, [], $instance, $coursecontext);
 979          $this->assertEquals('You are trying to use an invalid course ID', $errors['customint1']);
 980  
 981          // Test when a course is set as a not visible and a user doesn't have the capability to use it here.
 982          $metacourse2record = new stdClass();
 983          $metacourse2record->visible = 0;
 984          $metacourse2 = $this->getDataGenerator()->create_course($metacourse2record);
 985          $metacourse2context = context_course::instance($metacourse2->id);
 986  
 987          $user = $this->getDataGenerator()->create_user();
 988          $teacherrole = $DB->get_record('role', array('shortname' => 'teacher'));
 989          role_assign($teacherrole->id, $user->id, $metacourse2context->id);
 990          unassign_capability('moodle/course:viewhiddencourses', $teacherrole->id);
 991          $this->setUser($user);
 992  
 993          // Use the same instance as before but set another data.
 994          $data = [
 995              'customint1' => [$metacourse2->id],
 996              'customint2' => 0
 997          ];
 998          $errors = $metaplugin->edit_instance_validation($data, [], $instance, $coursecontext);
 999          $this->assertEquals('Sorry, but you do not currently have permissions to do that (moodle/course:viewhiddencourses).',
1000              $errors['customint1']);
1001  
1002          // Revert some changes from the last assertion to reuse the course.
1003          $metacourse2->visible = 1;
1004          $DB->update_record('course', $metacourse2);
1005          assign_capability('moodle/course:viewhiddencourses', CAP_ALLOW,
1006              $teacherrole->id, context_course::instance($metacourse2->id));
1007  
1008          // Test with no 'enrol/meta:selectaslinked' capability.
1009          unassign_capability('enrol/meta:selectaslinked', $teacherrole->id);
1010          $errors = $metaplugin->edit_instance_validation($data, [], $instance, $coursecontext);
1011          $this->assertEquals('Sorry, but you do not currently have permissions to do that (enrol/meta:selectaslinked).',
1012              $errors['customint1']);
1013  
1014          // Back to admin user to regain the capabilities quickly.
1015          $this->setAdminUser();
1016  
1017          // Test when meta course id is the site id.
1018          $site = $DB->get_record('course', ['id' => SITEID]);
1019          // Use the same instance as before but set another data.
1020          $data = [
1021              'customint1' => [$site->id],
1022              'customint2' => 0
1023          ];
1024          $errors = $metaplugin->edit_instance_validation($data, [], $instance, $coursecontext);
1025          $this->assertEquals('You are trying to use an invalid course ID', $errors['customint1']);
1026  
1027          // Test when meta course id is id of the current course.
1028          // Use the same instance as before but set another data.
1029          $data = [
1030              'customint1' => [$course->id],
1031              'customint2' => 0
1032          ];
1033          $errors = $metaplugin->edit_instance_validation($data, [], $instance, $coursecontext);
1034          $this->assertEquals('You are trying to use an invalid course ID', $errors['customint1']);
1035  
1036          // Test with the 'customint2' field set (which is groups).
1037          // Prepare some groups data.
1038          $this->getDataGenerator()->create_group(array('courseid' => $course->id));
1039          $this->getDataGenerator()->create_group(array('courseid' => $course->id));
1040          $groups = [];
1041          foreach (groups_get_all_groups($course->id) as $group) {
1042              $groups[$group->id] = format_string($group->name, true, array('context' => $coursecontext));
1043          }
1044  
1045          // Use the same instance as before but set another data.
1046          // Use a non-existing group id.
1047          if (!$maxid = $DB->get_field_sql('SELECT MAX(id) FROM {groups}')) {
1048              $maxid = 0;
1049          }
1050          $data = [
1051              'customint1' => [$metacourse2->id],
1052              'customint2' => [$maxid + 1]
1053          ];
1054          $errors = $metaplugin->edit_instance_validation($data, [], $instance, $coursecontext);
1055          $this->assertArrayHasKey('customint2', $errors);
1056  
1057          // Test with valid data.
1058          reset($groups);
1059          $validgroup = key($groups);
1060          $data = [
1061              'customint1' => [$metacourse2->id],
1062              'customint2' => $validgroup
1063          ];
1064          $errors = $metaplugin->edit_instance_validation($data, [], $instance, $coursecontext);
1065          $this->assertArrayNotHasKey('customint1', $errors);
1066          $this->assertArrayNotHasKey('customint2', $errors);
1067      }
1068  }