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