Search moodle.org's
Developer Documentation

  • Bug fixes for general core bugs in 3.11.x will end 9 May 2022 (12 months).
  • Bug fixes for security issues in 3.11.x will end 14 November 2022 (18 months).
  • 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 35 and 311] [Versions 36 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  /**
      18   * Self enrolment plugin tests.
      19   *
      20   * @package    enrol_self
      21   * @category   phpunit
      22   * @copyright  2012 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  require_once($CFG->dirroot.'/enrol/self/lib.php');
      30  require_once($CFG->dirroot.'/enrol/self/locallib.php');
      31  
      32  class enrol_self_testcase extends advanced_testcase {
      33  
      34      public function test_basics() {
      35          $this->assertTrue(enrol_is_enabled('self'));
      36          $plugin = enrol_get_plugin('self');
      37          $this->assertInstanceOf('enrol_self_plugin', $plugin);
      38          $this->assertEquals(1, get_config('enrol_self', 'defaultenrol'));
      39          $this->assertEquals(ENROL_EXT_REMOVED_KEEP, get_config('enrol_self', 'expiredaction'));
      40      }
      41  
      42      public function test_sync_nothing() {
      43          global $SITE;
      44  
      45          $selfplugin = enrol_get_plugin('self');
      46  
      47          $trace = new null_progress_trace();
      48  
      49          // Just make sure the sync does not throw any errors when nothing to do.
      50          $selfplugin->sync($trace, null);
      51          $selfplugin->sync($trace, $SITE->id);
      52      }
      53  
      54      public function test_longtimnosee() {
      55          global $DB;
      56          $this->resetAfterTest();
      57  
      58          $selfplugin = enrol_get_plugin('self');
      59          $manualplugin = enrol_get_plugin('manual');
      60          $this->assertNotEmpty($manualplugin);
      61  
      62          $now = time();
      63  
      64          $trace = new progress_trace_buffer(new text_progress_trace(), false);
      65  
      66          // Prepare some data.
      67  
      68          $studentrole = $DB->get_record('role', array('shortname'=>'student'));
      69          $this->assertNotEmpty($studentrole);
      70          $teacherrole = $DB->get_record('role', array('shortname'=>'teacher'));
      71          $this->assertNotEmpty($teacherrole);
      72  
      73          $record = array('firstaccess'=>$now-60*60*24*800);
      74          $record['lastaccess'] = $now-60*60*24*100;
      75          $user1 = $this->getDataGenerator()->create_user($record);
      76          $record['lastaccess'] = $now-60*60*24*10;
      77          $user2 = $this->getDataGenerator()->create_user($record);
      78          $record['lastaccess'] = $now-60*60*24*1;
      79          $user3 = $this->getDataGenerator()->create_user($record);
      80          $record['lastaccess'] = $now-10;
      81          $user4 = $this->getDataGenerator()->create_user($record);
      82  
      83          $course1 = $this->getDataGenerator()->create_course();
      84          $course2 = $this->getDataGenerator()->create_course();
      85          $course3 = $this->getDataGenerator()->create_course();
      86          $context1 = context_course::instance($course1->id);
      87          $context2 = context_course::instance($course2->id);
      88          $context3 = context_course::instance($course3->id);
      89  
      90          $this->assertEquals(3, $DB->count_records('enrol', array('enrol'=>'self')));
      91          $instance1 = $DB->get_record('enrol', array('courseid'=>$course1->id, 'enrol'=>'self'), '*', MUST_EXIST);
      92          $instance2 = $DB->get_record('enrol', array('courseid'=>$course2->id, 'enrol'=>'self'), '*', MUST_EXIST);
      93          $instance3 = $DB->get_record('enrol', array('courseid'=>$course3->id, 'enrol'=>'self'), '*', MUST_EXIST);
      94          $id = $selfplugin->add_instance($course3, array('status'=>ENROL_INSTANCE_ENABLED, 'roleid'=>$teacherrole->id));
      95          $instance3b = $DB->get_record('enrol', array('id'=>$id), '*', MUST_EXIST);
      96          unset($id);
      97  
      98          $this->assertEquals($studentrole->id, $instance1->roleid);
      99          $instance1->customint2 = 60*60*24*14;
     100          $DB->update_record('enrol', $instance1);
     101          $selfplugin->enrol_user($instance1, $user1->id, $studentrole->id);
     102          $selfplugin->enrol_user($instance1, $user2->id, $studentrole->id);
     103          $selfplugin->enrol_user($instance1, $user3->id, $studentrole->id);
     104          $this->assertEquals(3, $DB->count_records('user_enrolments'));
     105          $DB->insert_record('user_lastaccess', array('userid'=>$user2->id, 'courseid'=>$course1->id, 'timeaccess'=>$now-60*60*24*20));
     106          $DB->insert_record('user_lastaccess', array('userid'=>$user3->id, 'courseid'=>$course1->id, 'timeaccess'=>$now-60*60*24*2));
     107          $DB->insert_record('user_lastaccess', array('userid'=>$user4->id, 'courseid'=>$course1->id, 'timeaccess'=>$now-60));
     108  
     109          $this->assertEquals($studentrole->id, $instance3->roleid);
     110          $instance3->customint2 = 60*60*24*50;
     111          $DB->update_record('enrol', $instance3);
     112          $selfplugin->enrol_user($instance3, $user1->id, $studentrole->id);
     113          $selfplugin->enrol_user($instance3, $user2->id, $studentrole->id);
     114          $selfplugin->enrol_user($instance3, $user3->id, $studentrole->id);
     115          $selfplugin->enrol_user($instance3b, $user1->id, $teacherrole->id);
     116          $selfplugin->enrol_user($instance3b, $user4->id, $teacherrole->id);
     117          $this->assertEquals(8, $DB->count_records('user_enrolments'));
     118          $DB->insert_record('user_lastaccess', array('userid'=>$user2->id, 'courseid'=>$course3->id, 'timeaccess'=>$now-60*60*24*11));
     119          $DB->insert_record('user_lastaccess', array('userid'=>$user3->id, 'courseid'=>$course3->id, 'timeaccess'=>$now-60*60*24*200));
     120          $DB->insert_record('user_lastaccess', array('userid'=>$user4->id, 'courseid'=>$course3->id, 'timeaccess'=>$now-60*60*24*200));
     121  
     122          $maninstance2 = $DB->get_record('enrol', array('courseid'=>$course2->id, 'enrol'=>'manual'), '*', MUST_EXIST);
     123          $maninstance3 = $DB->get_record('enrol', array('courseid'=>$course3->id, 'enrol'=>'manual'), '*', MUST_EXIST);
     124  
     125          $manualplugin->enrol_user($maninstance2, $user1->id, $studentrole->id);
     126          $manualplugin->enrol_user($maninstance3, $user1->id, $teacherrole->id);
     127  
     128          $this->assertEquals(10, $DB->count_records('user_enrolments'));
     129          $this->assertEquals(9, $DB->count_records('role_assignments'));
     130          $this->assertEquals(7, $DB->count_records('role_assignments', array('roleid'=>$studentrole->id)));
     131          $this->assertEquals(2, $DB->count_records('role_assignments', array('roleid'=>$teacherrole->id)));
     132  
     133          // Execute sync - this is the same thing used from cron.
     134  
     135          $selfplugin->sync($trace, $course2->id);
     136          $output = $trace->get_buffer();
     137          $trace->reset_buffer();
     138          $this->assertEquals(10, $DB->count_records('user_enrolments'));
     139          $this->assertStringContainsString('No expired enrol_self enrolments detected', $output);
     140          $this->assertTrue($DB->record_exists('user_enrolments', array('enrolid'=>$instance1->id, 'userid'=>$user1->id)));
     141          $this->assertTrue($DB->record_exists('user_enrolments', array('enrolid'=>$instance1->id, 'userid'=>$user2->id)));
     142          $this->assertTrue($DB->record_exists('user_enrolments', array('enrolid'=>$instance3->id, 'userid'=>$user1->id)));
     143          $this->assertTrue($DB->record_exists('user_enrolments', array('enrolid'=>$instance3->id, 'userid'=>$user3->id)));
     144  
     145          $selfplugin->sync($trace, null);
     146          $output = $trace->get_buffer();
     147          $trace->reset_buffer();
     148          $this->assertEquals(6, $DB->count_records('user_enrolments'));
     149          $this->assertFalse($DB->record_exists('user_enrolments', array('enrolid'=>$instance1->id, 'userid'=>$user1->id)));
     150          $this->assertFalse($DB->record_exists('user_enrolments', array('enrolid'=>$instance1->id, 'userid'=>$user2->id)));
     151          $this->assertFalse($DB->record_exists('user_enrolments', array('enrolid'=>$instance3->id, 'userid'=>$user1->id)));
     152          $this->assertFalse($DB->record_exists('user_enrolments', array('enrolid'=>$instance3->id, 'userid'=>$user3->id)));
     153          $this->assertStringContainsString('unenrolling user ' . $user1->id . ' from course ' . $course1->id .
     154              ' as they did not log in for at least 14 days', $output);
     155          $this->assertStringContainsString('unenrolling user ' . $user1->id . ' from course ' . $course3->id .
     156              ' as they did not log in for at least 50 days', $output);
     157          $this->assertStringContainsString('unenrolling user ' . $user2->id . ' from course ' . $course1->id .
     158              ' as they did not access the course for at least 14 days', $output);
     159          $this->assertStringContainsString('unenrolling user ' . $user3->id . ' from course ' . $course3->id .
     160              ' as they did not access the course for at least 50 days', $output);
     161          $this->assertStringNotContainsString('unenrolling user ' . $user4->id, $output);
     162  
     163          $this->assertEquals(6, $DB->count_records('role_assignments'));
     164          $this->assertEquals(4, $DB->count_records('role_assignments', array('roleid'=>$studentrole->id)));
     165          $this->assertEquals(2, $DB->count_records('role_assignments', array('roleid'=>$teacherrole->id)));
     166      }
     167  
     168      public function test_expired() {
     169          global $DB;
     170          $this->resetAfterTest();
     171  
     172          $selfplugin = enrol_get_plugin('self');
     173          $manualplugin = enrol_get_plugin('manual');
     174          $this->assertNotEmpty($manualplugin);
     175  
     176          $now = time();
     177  
     178          $trace = new null_progress_trace();
     179  
     180          // Prepare some data.
     181  
     182          $studentrole = $DB->get_record('role', array('shortname'=>'student'));
     183          $this->assertNotEmpty($studentrole);
     184          $teacherrole = $DB->get_record('role', array('shortname'=>'teacher'));
     185          $this->assertNotEmpty($teacherrole);
     186          $managerrole = $DB->get_record('role', array('shortname'=>'manager'));
     187          $this->assertNotEmpty($managerrole);
     188  
     189          $user1 = $this->getDataGenerator()->create_user();
     190          $user2 = $this->getDataGenerator()->create_user();
     191          $user3 = $this->getDataGenerator()->create_user();
     192          $user4 = $this->getDataGenerator()->create_user();
     193  
     194          $course1 = $this->getDataGenerator()->create_course();
     195          $course2 = $this->getDataGenerator()->create_course();
     196          $course3 = $this->getDataGenerator()->create_course();
     197          $context1 = context_course::instance($course1->id);
     198          $context2 = context_course::instance($course2->id);
     199          $context3 = context_course::instance($course3->id);
     200  
     201          $this->assertEquals(3, $DB->count_records('enrol', array('enrol'=>'self')));
     202          $instance1 = $DB->get_record('enrol', array('courseid'=>$course1->id, 'enrol'=>'self'), '*', MUST_EXIST);
     203          $this->assertEquals($studentrole->id, $instance1->roleid);
     204          $instance2 = $DB->get_record('enrol', array('courseid'=>$course2->id, 'enrol'=>'self'), '*', MUST_EXIST);
     205          $this->assertEquals($studentrole->id, $instance2->roleid);
     206          $instance3 = $DB->get_record('enrol', array('courseid'=>$course3->id, 'enrol'=>'self'), '*', MUST_EXIST);
     207          $this->assertEquals($studentrole->id, $instance3->roleid);
     208          $id = $selfplugin->add_instance($course3, array('status'=>ENROL_INSTANCE_ENABLED, 'roleid'=>$teacherrole->id));
     209          $instance3b = $DB->get_record('enrol', array('id'=>$id), '*', MUST_EXIST);
     210          $this->assertEquals($teacherrole->id, $instance3b->roleid);
     211          unset($id);
     212  
     213          $maninstance2 = $DB->get_record('enrol', array('courseid'=>$course2->id, 'enrol'=>'manual'), '*', MUST_EXIST);
     214          $maninstance3 = $DB->get_record('enrol', array('courseid'=>$course3->id, 'enrol'=>'manual'), '*', MUST_EXIST);
     215  
     216          $manualplugin->enrol_user($maninstance2, $user1->id, $studentrole->id);
     217          $manualplugin->enrol_user($maninstance3, $user1->id, $teacherrole->id);
     218  
     219          $this->assertEquals(2, $DB->count_records('user_enrolments'));
     220          $this->assertEquals(2, $DB->count_records('role_assignments'));
     221          $this->assertEquals(1, $DB->count_records('role_assignments', array('roleid'=>$studentrole->id)));
     222          $this->assertEquals(1, $DB->count_records('role_assignments', array('roleid'=>$teacherrole->id)));
     223  
     224          $selfplugin->enrol_user($instance1, $user1->id, $studentrole->id);
     225          $selfplugin->enrol_user($instance1, $user2->id, $studentrole->id);
     226          $selfplugin->enrol_user($instance1, $user3->id, $studentrole->id, 0, $now-60);
     227  
     228          $selfplugin->enrol_user($instance3, $user1->id, $studentrole->id, 0, 0);
     229          $selfplugin->enrol_user($instance3, $user2->id, $studentrole->id, 0, $now-60*60);
     230          $selfplugin->enrol_user($instance3, $user3->id, $studentrole->id, 0, $now+60*60);
     231          $selfplugin->enrol_user($instance3b, $user1->id, $teacherrole->id, $now-60*60*24*7, $now-60);
     232          $selfplugin->enrol_user($instance3b, $user4->id, $teacherrole->id);
     233  
     234          role_assign($managerrole->id, $user3->id, $context1->id);
     235  
     236          $this->assertEquals(10, $DB->count_records('user_enrolments'));
     237          $this->assertEquals(10, $DB->count_records('role_assignments'));
     238          $this->assertEquals(7, $DB->count_records('role_assignments', array('roleid'=>$studentrole->id)));
     239          $this->assertEquals(2, $DB->count_records('role_assignments', array('roleid'=>$teacherrole->id)));
     240  
     241          // Execute tests.
     242  
     243          $this->assertEquals(ENROL_EXT_REMOVED_KEEP, $selfplugin->get_config('expiredaction'));
     244          $selfplugin->sync($trace, null);
     245          $this->assertEquals(10, $DB->count_records('user_enrolments'));
     246          $this->assertEquals(10, $DB->count_records('role_assignments'));
     247  
     248  
     249          $selfplugin->set_config('expiredaction', ENROL_EXT_REMOVED_SUSPENDNOROLES);
     250          $selfplugin->sync($trace, $course2->id);
     251          $this->assertEquals(10, $DB->count_records('user_enrolments'));
     252          $this->assertEquals(10, $DB->count_records('role_assignments'));
     253  
     254          $selfplugin->sync($trace, null);
     255          $this->assertEquals(10, $DB->count_records('user_enrolments'));
     256          $this->assertEquals(7, $DB->count_records('role_assignments'));
     257          $this->assertEquals(5, $DB->count_records('role_assignments', array('roleid'=>$studentrole->id)));
     258          $this->assertEquals(1, $DB->count_records('role_assignments', array('roleid'=>$teacherrole->id)));
     259          $this->assertFalse($DB->record_exists('role_assignments', array('contextid'=>$context1->id, 'userid'=>$user3->id, 'roleid'=>$studentrole->id)));
     260          $this->assertFalse($DB->record_exists('role_assignments', array('contextid'=>$context3->id, 'userid'=>$user2->id, 'roleid'=>$studentrole->id)));
     261          $this->assertFalse($DB->record_exists('role_assignments', array('contextid'=>$context3->id, 'userid'=>$user1->id, 'roleid'=>$teacherrole->id)));
     262          $this->assertTrue($DB->record_exists('role_assignments', array('contextid'=>$context3->id, 'userid'=>$user1->id, 'roleid'=>$studentrole->id)));
     263  
     264  
     265          $selfplugin->set_config('expiredaction', ENROL_EXT_REMOVED_UNENROL);
     266  
     267          role_assign($studentrole->id, $user3->id, $context1->id);
     268          role_assign($studentrole->id, $user2->id, $context3->id);
     269          role_assign($teacherrole->id, $user1->id, $context3->id);
     270          $this->assertEquals(10, $DB->count_records('user_enrolments'));
     271          $this->assertEquals(10, $DB->count_records('role_assignments'));
     272          $this->assertEquals(7, $DB->count_records('role_assignments', array('roleid'=>$studentrole->id)));
     273          $this->assertEquals(2, $DB->count_records('role_assignments', array('roleid'=>$teacherrole->id)));
     274  
     275          $selfplugin->sync($trace, null);
     276          $this->assertEquals(7, $DB->count_records('user_enrolments'));
     277          $this->assertFalse($DB->record_exists('user_enrolments', array('enrolid'=>$instance1->id, 'userid'=>$user3->id)));
     278          $this->assertFalse($DB->record_exists('user_enrolments', array('enrolid'=>$instance3->id, 'userid'=>$user2->id)));
     279          $this->assertFalse($DB->record_exists('user_enrolments', array('enrolid'=>$instance3b->id, 'userid'=>$user1->id)));
     280          $this->assertEquals(6, $DB->count_records('role_assignments'));
     281          $this->assertEquals(5, $DB->count_records('role_assignments', array('roleid'=>$studentrole->id)));
     282          $this->assertEquals(1, $DB->count_records('role_assignments', array('roleid'=>$teacherrole->id)));
     283      }
     284  
     285      public function test_send_expiry_notifications() {
     286          global $DB, $CFG;
     287          $this->resetAfterTest();
     288          $this->preventResetByRollback(); // Messaging does not like transactions...
     289  
     290          /** @var $selfplugin enrol_self_plugin */
     291          $selfplugin = enrol_get_plugin('self');
     292          /** @var $manualplugin enrol_manual_plugin */
     293          $manualplugin = enrol_get_plugin('manual');
     294          $now = time();
     295          $admin = get_admin();
     296  
     297          $trace = new null_progress_trace();
     298  
     299          // Note: hopefully nobody executes the unit tests the last second before midnight...
     300  
     301          $selfplugin->set_config('expirynotifylast', $now - 60*60*24);
     302          $selfplugin->set_config('expirynotifyhour', 0);
     303  
     304          $studentrole = $DB->get_record('role', array('shortname'=>'student'));
     305          $this->assertNotEmpty($studentrole);
     306          $editingteacherrole = $DB->get_record('role', array('shortname'=>'editingteacher'));
     307          $this->assertNotEmpty($editingteacherrole);
     308          $managerrole = $DB->get_record('role', array('shortname'=>'manager'));
     309          $this->assertNotEmpty($managerrole);
     310  
     311          $user1 = $this->getDataGenerator()->create_user(array('lastname'=>'xuser1'));
     312          $user2 = $this->getDataGenerator()->create_user(array('lastname'=>'xuser2'));
     313          $user3 = $this->getDataGenerator()->create_user(array('lastname'=>'xuser3'));
     314          $user4 = $this->getDataGenerator()->create_user(array('lastname'=>'xuser4'));
     315          $user5 = $this->getDataGenerator()->create_user(array('lastname'=>'xuser5'));
     316          $user6 = $this->getDataGenerator()->create_user(array('lastname'=>'xuser6'));
     317          $user7 = $this->getDataGenerator()->create_user(array('lastname'=>'xuser6'));
     318          $user8 = $this->getDataGenerator()->create_user(array('lastname'=>'xuser6'));
     319  
     320          $course1 = $this->getDataGenerator()->create_course(array('fullname'=>'xcourse1'));
     321          $course2 = $this->getDataGenerator()->create_course(array('fullname'=>'xcourse2'));
     322          $course3 = $this->getDataGenerator()->create_course(array('fullname'=>'xcourse3'));
     323          $course4 = $this->getDataGenerator()->create_course(array('fullname'=>'xcourse4'));
     324  
     325          $this->assertEquals(4, $DB->count_records('enrol', array('enrol'=>'manual')));
     326          $this->assertEquals(4, $DB->count_records('enrol', array('enrol'=>'self')));
     327  
     328          $maninstance1 = $DB->get_record('enrol', array('courseid'=>$course1->id, 'enrol'=>'manual'), '*', MUST_EXIST);
     329          $instance1 = $DB->get_record('enrol', array('courseid'=>$course1->id, 'enrol'=>'self'), '*', MUST_EXIST);
     330          $instance1->expirythreshold = 60*60*24*4;
     331          $instance1->expirynotify    = 1;
     332          $instance1->notifyall       = 1;
     333          $instance1->status          = ENROL_INSTANCE_ENABLED;
     334          $DB->update_record('enrol', $instance1);
     335  
     336          $maninstance2 = $DB->get_record('enrol', array('courseid'=>$course2->id, 'enrol'=>'manual'), '*', MUST_EXIST);
     337          $instance2 = $DB->get_record('enrol', array('courseid'=>$course2->id, 'enrol'=>'self'), '*', MUST_EXIST);
     338          $instance2->expirythreshold = 60*60*24*1;
     339          $instance2->expirynotify    = 1;
     340          $instance2->notifyall       = 1;
     341          $instance2->status          = ENROL_INSTANCE_ENABLED;
     342          $DB->update_record('enrol', $instance2);
     343  
     344          $maninstance3 = $DB->get_record('enrol', array('courseid'=>$course3->id, 'enrol'=>'manual'), '*', MUST_EXIST);
     345          $instance3 = $DB->get_record('enrol', array('courseid'=>$course3->id, 'enrol'=>'self'), '*', MUST_EXIST);
     346          $instance3->expirythreshold = 60*60*24*1;
     347          $instance3->expirynotify    = 1;
     348          $instance3->notifyall       = 0;
     349          $instance3->status          = ENROL_INSTANCE_ENABLED;
     350          $DB->update_record('enrol', $instance3);
     351  
     352          $maninstance4 = $DB->get_record('enrol', array('courseid'=>$course4->id, 'enrol'=>'manual'), '*', MUST_EXIST);
     353          $instance4 = $DB->get_record('enrol', array('courseid'=>$course4->id, 'enrol'=>'self'), '*', MUST_EXIST);
     354          $instance4->expirythreshold = 60*60*24*1;
     355          $instance4->expirynotify    = 0;
     356          $instance4->notifyall       = 0;
     357          $instance4->status          = ENROL_INSTANCE_ENABLED;
     358          $DB->update_record('enrol', $instance4);
     359  
     360          $selfplugin->enrol_user($instance1, $user1->id, $studentrole->id, 0, $now + 60*60*24*1, ENROL_USER_SUSPENDED); // Suspended users are not notified.
     361          $selfplugin->enrol_user($instance1, $user2->id, $studentrole->id, 0, $now + 60*60*24*5);                       // Above threshold are not notified.
     362          $selfplugin->enrol_user($instance1, $user3->id, $studentrole->id, 0, $now + 60*60*24*3 + 60*60);               // Less than one day after threshold - should be notified.
     363          $selfplugin->enrol_user($instance1, $user4->id, $studentrole->id, 0, $now + 60*60*24*4 - 60*3);                // Less than one day after threshold - should be notified.
     364          $selfplugin->enrol_user($instance1, $user5->id, $studentrole->id, 0, $now + 60*60);                            // Should have been already notified.
     365          $selfplugin->enrol_user($instance1, $user6->id, $studentrole->id, 0, $now - 60);                               // Already expired.
     366          $manualplugin->enrol_user($maninstance1, $user7->id, $editingteacherrole->id);
     367          $manualplugin->enrol_user($maninstance1, $user8->id, $managerrole->id);                                        // Highest role --> enroller.
     368  
     369          $selfplugin->enrol_user($instance2, $user1->id, $studentrole->id);
     370          $selfplugin->enrol_user($instance2, $user2->id, $studentrole->id, 0, $now + 60*60*24*1 + 60*3);                // Above threshold are not notified.
     371          $selfplugin->enrol_user($instance2, $user3->id, $studentrole->id, 0, $now + 60*60*24*1 - 60*60);               // Less than one day after threshold - should be notified.
     372  
     373          $manualplugin->enrol_user($maninstance3, $user1->id, $editingteacherrole->id);
     374          $selfplugin->enrol_user($instance3, $user2->id, $studentrole->id, 0, $now + 60*60*24*1 + 60);                  // Above threshold are not notified.
     375          $selfplugin->enrol_user($instance3, $user3->id, $studentrole->id, 0, $now + 60*60*24*1 - 60*60);               // Less than one day after threshold - should be notified.
     376  
     377          $manualplugin->enrol_user($maninstance4, $user4->id, $editingteacherrole->id);
     378          $selfplugin->enrol_user($instance4, $user5->id, $studentrole->id, 0, $now + 60*60*24*1 + 60);
     379          $selfplugin->enrol_user($instance4, $user6->id, $studentrole->id, 0, $now + 60*60*24*1 - 60*60);
     380  
     381          // The notification is sent out in fixed order first individual users,
     382          // then summary per course by enrolid, user lastname, etc.
     383          $this->assertGreaterThan($instance1->id, $instance2->id);
     384          $this->assertGreaterThan($instance2->id, $instance3->id);
     385  
     386          $sink = $this->redirectMessages();
     387  
     388          $selfplugin->send_expiry_notifications($trace);
     389  
     390          $messages = $sink->get_messages();
     391  
     392          $this->assertEquals(2+1 + 1+1 + 1 + 0, count($messages));
     393  
     394          // First individual notifications from course1.
     395          $this->assertEquals($user3->id, $messages[0]->useridto);
     396          $this->assertEquals($user8->id, $messages[0]->useridfrom);
     397          $this->assertStringContainsString('xcourse1', $messages[0]->fullmessagehtml);
     398  
     399          $this->assertEquals($user4->id, $messages[1]->useridto);
     400          $this->assertEquals($user8->id, $messages[1]->useridfrom);
     401          $this->assertStringContainsString('xcourse1', $messages[1]->fullmessagehtml);
     402  
     403          // Then summary for course1.
     404          $this->assertEquals($user8->id, $messages[2]->useridto);
     405          $this->assertEquals($admin->id, $messages[2]->useridfrom);
     406          $this->assertStringContainsString('xcourse1', $messages[2]->fullmessagehtml);
     407          $this->assertStringNotContainsString('xuser1', $messages[2]->fullmessagehtml);
     408          $this->assertStringNotContainsString('xuser2', $messages[2]->fullmessagehtml);
     409          $this->assertStringContainsString('xuser3', $messages[2]->fullmessagehtml);
     410          $this->assertStringContainsString('xuser4', $messages[2]->fullmessagehtml);
     411          $this->assertStringContainsString('xuser5', $messages[2]->fullmessagehtml);
     412          $this->assertStringNotContainsString('xuser6', $messages[2]->fullmessagehtml);
     413  
     414          // First individual notifications from course2.
     415          $this->assertEquals($user3->id, $messages[3]->useridto);
     416          $this->assertEquals($admin->id, $messages[3]->useridfrom);
     417          $this->assertStringContainsString('xcourse2', $messages[3]->fullmessagehtml);
     418  
     419          // Then summary for course2.
     420          $this->assertEquals($admin->id, $messages[4]->useridto);
     421          $this->assertEquals($admin->id, $messages[4]->useridfrom);
     422          $this->assertStringContainsString('xcourse2', $messages[4]->fullmessagehtml);
     423          $this->assertStringNotContainsString('xuser1', $messages[4]->fullmessagehtml);
     424          $this->assertStringNotContainsString('xuser2', $messages[4]->fullmessagehtml);
     425          $this->assertStringContainsString('xuser3', $messages[4]->fullmessagehtml);
     426          $this->assertStringNotContainsString('xuser4', $messages[4]->fullmessagehtml);
     427          $this->assertStringNotContainsString('xuser5', $messages[4]->fullmessagehtml);
     428          $this->assertStringNotContainsString('xuser6', $messages[4]->fullmessagehtml);
     429  
     430          // Only summary in course3.
     431          $this->assertEquals($user1->id, $messages[5]->useridto);
     432          $this->assertEquals($admin->id, $messages[5]->useridfrom);
     433          $this->assertStringContainsString('xcourse3', $messages[5]->fullmessagehtml);
     434          $this->assertStringNotContainsString('xuser1', $messages[5]->fullmessagehtml);
     435          $this->assertStringNotContainsString('xuser2', $messages[5]->fullmessagehtml);
     436          $this->assertStringContainsString('xuser3', $messages[5]->fullmessagehtml);
     437          $this->assertStringNotContainsString('xuser4', $messages[5]->fullmessagehtml);
     438          $this->assertStringNotContainsString('xuser5', $messages[5]->fullmessagehtml);
     439          $this->assertStringNotContainsString('xuser6', $messages[5]->fullmessagehtml);
     440  
     441  
     442          // Make sure that notifications are not repeated.
     443          $sink->clear();
     444  
     445          $selfplugin->send_expiry_notifications($trace);
     446          $this->assertEquals(0, $sink->count());
     447  
     448          // use invalid notification hour to verify that before the hour the notifications are not sent.
     449          $selfplugin->set_config('expirynotifylast', time() - 60*60*24);
     450          $selfplugin->set_config('expirynotifyhour', '24');
     451  
     452          $selfplugin->send_expiry_notifications($trace);
     453          $this->assertEquals(0, $sink->count());
     454  
     455          $selfplugin->set_config('expirynotifyhour', '0');
     456          $selfplugin->send_expiry_notifications($trace);
     457          $this->assertEquals(6, $sink->count());
     458      }
     459  
     460      public function test_show_enrolme_link() {
     461          global $DB, $CFG;
     462          $this->resetAfterTest();
     463          $this->preventResetByRollback(); // Messaging does not like transactions...
     464  
     465          /** @var $selfplugin enrol_self_plugin */
     466          $selfplugin = enrol_get_plugin('self');
     467  
     468          $user1 = $this->getDataGenerator()->create_user();
     469          $user2 = $this->getDataGenerator()->create_user();
     470  
     471          $studentrole = $DB->get_record('role', array('shortname'=>'student'));
     472          $this->assertNotEmpty($studentrole);
     473  
     474          $course1 = $this->getDataGenerator()->create_course();
     475          $course2 = $this->getDataGenerator()->create_course();
     476          $course3 = $this->getDataGenerator()->create_course();
     477          $course4 = $this->getDataGenerator()->create_course();
     478          $course5 = $this->getDataGenerator()->create_course();
     479          $course6 = $this->getDataGenerator()->create_course();
     480          $course7 = $this->getDataGenerator()->create_course();
     481          $course8 = $this->getDataGenerator()->create_course();
     482          $course9 = $this->getDataGenerator()->create_course();
     483          $course10 = $this->getDataGenerator()->create_course();
     484          $course11 = $this->getDataGenerator()->create_course();
     485  
     486          $cohort1 = $this->getDataGenerator()->create_cohort();
     487          $cohort2 = $this->getDataGenerator()->create_cohort();
     488  
     489          // New enrolments are allowed and enrolment instance is enabled.
     490          $instance1 = $DB->get_record('enrol', array('courseid'=>$course1->id, 'enrol'=>'self'), '*', MUST_EXIST);
     491          $instance1->customint6 = 1;
     492          $DB->update_record('enrol', $instance1);
     493          $selfplugin->update_status($instance1, ENROL_INSTANCE_ENABLED);
     494  
     495          // New enrolments are not allowed, but enrolment instance is enabled.
     496          $instance2 = $DB->get_record('enrol', array('courseid'=>$course2->id, 'enrol'=>'self'), '*', MUST_EXIST);
     497          $instance2->customint6 = 0;
     498          $DB->update_record('enrol', $instance2);
     499          $selfplugin->update_status($instance2, ENROL_INSTANCE_ENABLED);
     500  
     501          // New enrolments are allowed , but enrolment instance is disabled.
     502          $instance3 = $DB->get_record('enrol', array('courseid'=>$course3->id, 'enrol'=>'self'), '*', MUST_EXIST);
     503          $instance3->customint6 = 1;
     504          $DB->update_record('enrol', $instance3);
     505          $selfplugin->update_status($instance3, ENROL_INSTANCE_DISABLED);
     506  
     507          // New enrolments are not allowed and enrolment instance is disabled.
     508          $instance4 = $DB->get_record('enrol', array('courseid'=>$course4->id, 'enrol'=>'self'), '*', MUST_EXIST);
     509          $instance4->customint6 = 0;
     510          $DB->update_record('enrol', $instance4);
     511          $selfplugin->update_status($instance4, ENROL_INSTANCE_DISABLED);
     512  
     513          // Cohort member test.
     514          $instance5 = $DB->get_record('enrol', array('courseid'=>$course5->id, 'enrol'=>'self'), '*', MUST_EXIST);
     515          $instance5->customint6 = 1;
     516          $instance5->customint5 = $cohort1->id;
     517          $DB->update_record('enrol', $instance1);
     518          $selfplugin->update_status($instance5, ENROL_INSTANCE_ENABLED);
     519  
     520          $id = $selfplugin->add_instance($course5, $selfplugin->get_instance_defaults());
     521          $instance6 = $DB->get_record('enrol', array('id'=>$id), '*', MUST_EXIST);
     522          $instance6->customint6 = 1;
     523          $instance6->customint5 = $cohort2->id;
     524          $DB->update_record('enrol', $instance1);
     525          $selfplugin->update_status($instance6, ENROL_INSTANCE_ENABLED);
     526  
     527          // Enrol start date is in future.
     528          $instance7 = $DB->get_record('enrol', array('courseid'=>$course6->id, 'enrol'=>'self'), '*', MUST_EXIST);
     529          $instance7->customint6 = 1;
     530          $instance7->enrolstartdate = time() + 60;
     531          $DB->update_record('enrol', $instance7);
     532          $selfplugin->update_status($instance7, ENROL_INSTANCE_ENABLED);
     533  
     534          // Enrol start date is in past.
     535          $instance8 = $DB->get_record('enrol', array('courseid'=>$course7->id, 'enrol'=>'self'), '*', MUST_EXIST);
     536          $instance8->customint6 = 1;
     537          $instance8->enrolstartdate = time() - 60;
     538          $DB->update_record('enrol', $instance8);
     539          $selfplugin->update_status($instance8, ENROL_INSTANCE_ENABLED);
     540  
     541          // Enrol end date is in future.
     542          $instance9 = $DB->get_record('enrol', array('courseid'=>$course8->id, 'enrol'=>'self'), '*', MUST_EXIST);
     543          $instance9->customint6 = 1;
     544          $instance9->enrolenddate = time() + 60;
     545          $DB->update_record('enrol', $instance9);
     546          $selfplugin->update_status($instance9, ENROL_INSTANCE_ENABLED);
     547  
     548          // Enrol end date is in past.
     549          $instance10 = $DB->get_record('enrol', array('courseid'=>$course9->id, 'enrol'=>'self'), '*', MUST_EXIST);
     550          $instance10->customint6 = 1;
     551          $instance10->enrolenddate = time() - 60;
     552          $DB->update_record('enrol', $instance10);
     553          $selfplugin->update_status($instance10, ENROL_INSTANCE_ENABLED);
     554  
     555          // Maximum enrolments reached.
     556          $instance11 = $DB->get_record('enrol', array('courseid'=>$course10->id, 'enrol'=>'self'), '*', MUST_EXIST);
     557          $instance11->customint6 = 1;
     558          $instance11->customint3 = 1;
     559          $DB->update_record('enrol', $instance11);
     560          $selfplugin->update_status($instance11, ENROL_INSTANCE_ENABLED);
     561          $selfplugin->enrol_user($instance11, $user2->id, $studentrole->id);
     562  
     563          // Maximum enrolments not reached.
     564          $instance12 = $DB->get_record('enrol', array('courseid'=>$course11->id, 'enrol'=>'self'), '*', MUST_EXIST);
     565          $instance12->customint6 = 1;
     566          $instance12->customint3 = 1;
     567          $DB->update_record('enrol', $instance12);
     568          $selfplugin->update_status($instance12, ENROL_INSTANCE_ENABLED);
     569  
     570          $this->setUser($user1);
     571          $this->assertTrue($selfplugin->show_enrolme_link($instance1));
     572          $this->assertFalse($selfplugin->show_enrolme_link($instance2));
     573          $this->assertFalse($selfplugin->show_enrolme_link($instance3));
     574          $this->assertFalse($selfplugin->show_enrolme_link($instance4));
     575          $this->assertFalse($selfplugin->show_enrolme_link($instance7));
     576          $this->assertTrue($selfplugin->show_enrolme_link($instance8));
     577          $this->assertTrue($selfplugin->show_enrolme_link($instance9));
     578          $this->assertFalse($selfplugin->show_enrolme_link($instance10));
     579          $this->assertFalse($selfplugin->show_enrolme_link($instance11));
     580          $this->assertTrue($selfplugin->show_enrolme_link($instance12));
     581  
     582          require_once("$CFG->dirroot/cohort/lib.php");
     583          cohort_add_member($cohort1->id, $user1->id);
     584  
     585          $this->assertTrue($selfplugin->show_enrolme_link($instance5));
     586          $this->assertFalse($selfplugin->show_enrolme_link($instance6));
     587      }
     588  
     589      /**
     590       * This will check user enrolment only, rest has been tested in test_show_enrolme_link.
     591       */
     592      public function test_can_self_enrol() {
     593          global $DB, $CFG, $OUTPUT;
     594          $this->resetAfterTest();
     595          $this->preventResetByRollback();
     596  
     597          $selfplugin = enrol_get_plugin('self');
     598  
     599          $expectederrorstring = get_string('canntenrol', 'enrol_self');
     600  
     601          $user1 = $this->getDataGenerator()->create_user();
     602          $user2 = $this->getDataGenerator()->create_user();
     603          $guest = $DB->get_record('user', array('id' => $CFG->siteguest));
     604  
     605          $studentrole = $DB->get_record('role', array('shortname'=>'student'));
     606          $this->assertNotEmpty($studentrole);
     607          $editingteacherrole = $DB->get_record('role', array('shortname'=>'editingteacher'));
     608          $this->assertNotEmpty($editingteacherrole);
     609  
     610          $course1 = $this->getDataGenerator()->create_course();
     611  
     612          $instance1 = $DB->get_record('enrol', array('courseid'=>$course1->id, 'enrol'=>'self'), '*', MUST_EXIST);
     613          $instance1->customint6 = 1;
     614          $DB->update_record('enrol', $instance1);
     615          $selfplugin->update_status($instance1, ENROL_INSTANCE_ENABLED);
     616          $selfplugin->enrol_user($instance1, $user2->id, $editingteacherrole->id);
     617  
     618          $this->setUser($guest);
     619          $this->assertStringContainsString(get_string('noguestaccess', 'enrol'),
     620                  $selfplugin->can_self_enrol($instance1, true));
     621  
     622          $this->setUser($user1);
     623          $this->assertTrue($selfplugin->can_self_enrol($instance1, true));
     624  
     625          // Active enroled user.
     626          $this->setUser($user2);
     627          $selfplugin->enrol_user($instance1, $user1->id, $studentrole->id);
     628          $this->setUser($user1);
     629          $this->assertSame($expectederrorstring, $selfplugin->can_self_enrol($instance1, true));
     630      }
     631  
     632      /**
     633       * Test enrol_self_check_group_enrolment_key
     634       */
     635      public function test_enrol_self_check_group_enrolment_key() {
     636          global $DB;
     637          self::resetAfterTest(true);
     638  
     639          // Test in course with groups.
     640          $course = self::getDataGenerator()->create_course(array('groupmode' => SEPARATEGROUPS, 'groupmodeforce' => 1));
     641  
     642          $group1 = $this->getDataGenerator()->create_group(array('courseid' => $course->id));
     643          $group2 = $this->getDataGenerator()->create_group(array('courseid' => $course->id, 'enrolmentkey' => 'thepassword'));
     644  
     645          $result = enrol_self_check_group_enrolment_key($course->id, 'invalidpassword');
     646          $this->assertFalse($result);
     647  
     648          $result = enrol_self_check_group_enrolment_key($course->id, 'thepassword');
     649          $this->assertTrue($result);
     650  
     651          // Test disabling group options.
     652          $course->groupmode = NOGROUPS;
     653          $course->groupmodeforce = 0;
     654          $DB->update_record('course', $course);
     655  
     656          $result = enrol_self_check_group_enrolment_key($course->id, 'invalidpassword');
     657          $this->assertFalse($result);
     658  
     659          $result = enrol_self_check_group_enrolment_key($course->id, 'thepassword');
     660          $this->assertTrue($result);
     661  
     662          // Test without groups.
     663          $othercourse = self::getDataGenerator()->create_course();
     664          $result = enrol_self_check_group_enrolment_key($othercourse->id, 'thepassword');
     665          $this->assertFalse($result);
     666  
     667      }
     668  
     669      /**
     670       * Test get_welcome_email_contact().
     671       */
     672      public function test_get_welcome_email_contact() {
     673          global $DB;
     674          self::resetAfterTest(true);
     675  
     676          $user1 = $this->getDataGenerator()->create_user(['lastname' => 'Marsh']);
     677          $user2 = $this->getDataGenerator()->create_user(['lastname' => 'Victoria']);
     678          $user3 = $this->getDataGenerator()->create_user(['lastname' => 'Burch']);
     679          $user4 = $this->getDataGenerator()->create_user(['lastname' => 'Cartman']);
     680          $noreplyuser = core_user::get_noreply_user();
     681  
     682          $course1 = $this->getDataGenerator()->create_course();
     683          $context = context_course::instance($course1->id);
     684  
     685          // Get editing teacher role.
     686          $editingteacherrole = $DB->get_record('role', ['shortname' => 'editingteacher']);
     687          $this->assertNotEmpty($editingteacherrole);
     688  
     689          // Enable self enrolment plugin and set to send email from course contact.
     690          $selfplugin = enrol_get_plugin('self');
     691          $instance1 = $DB->get_record('enrol', ['courseid' => $course1->id, 'enrol' => 'self'], '*', MUST_EXIST);
     692          $instance1->customint6 = 1;
     693          $instance1->customint4 = ENROL_SEND_EMAIL_FROM_COURSE_CONTACT;
     694          $DB->update_record('enrol', $instance1);
     695          $selfplugin->update_status($instance1, ENROL_INSTANCE_ENABLED);
     696  
     697          // We do not have a teacher enrolled at this point, so it should send as no reply user.
     698          $contact = $selfplugin->get_welcome_email_contact(ENROL_SEND_EMAIL_FROM_COURSE_CONTACT, $context);
     699          $this->assertEquals($noreplyuser, $contact);
     700  
     701          // By default, course contact is assigned to teacher role.
     702          // Enrol a teacher, now it should send emails from teacher email's address.
     703          $selfplugin->enrol_user($instance1, $user1->id, $editingteacherrole->id);
     704  
     705          // We should get the teacher email.
     706          $contact = $selfplugin->get_welcome_email_contact(ENROL_SEND_EMAIL_FROM_COURSE_CONTACT, $context);
     707          $this->assertEquals($user1->username, $contact->username);
     708          $this->assertEquals($user1->email, $contact->email);
     709  
     710          // Now let's enrol another teacher.
     711          $selfplugin->enrol_user($instance1, $user2->id, $editingteacherrole->id);
     712          $contact = $selfplugin->get_welcome_email_contact(ENROL_SEND_EMAIL_FROM_COURSE_CONTACT, $context);
     713          $this->assertEquals($user1->username, $contact->username);
     714          $this->assertEquals($user1->email, $contact->email);
     715  
     716          // Get manager role, and enrol user as manager.
     717          $managerrole = $DB->get_record('role', ['shortname' => 'manager']);
     718          $this->assertNotEmpty($managerrole);
     719          $instance1->customint4 = ENROL_SEND_EMAIL_FROM_KEY_HOLDER;
     720          $DB->update_record('enrol', $instance1);
     721          $selfplugin->enrol_user($instance1, $user3->id, $managerrole->id);
     722  
     723          // Give manager role holdkey capability.
     724          assign_capability('enrol/self:holdkey', CAP_ALLOW, $managerrole->id, $context);
     725  
     726          // We should get the manager email contact.
     727          $contact = $selfplugin->get_welcome_email_contact(ENROL_SEND_EMAIL_FROM_KEY_HOLDER, $context);
     728          $this->assertEquals($user3->username, $contact->username);
     729          $this->assertEquals($user3->email, $contact->email);
     730  
     731          // Now let's enrol another manager.
     732          $selfplugin->enrol_user($instance1, $user4->id, $managerrole->id);
     733          $contact = $selfplugin->get_welcome_email_contact(ENROL_SEND_EMAIL_FROM_KEY_HOLDER, $context);
     734          $this->assertEquals($user3->username, $contact->username);
     735          $this->assertEquals($user3->email, $contact->email);
     736  
     737          $instance1->customint4 = ENROL_SEND_EMAIL_FROM_NOREPLY;
     738          $DB->update_record('enrol', $instance1);
     739  
     740          $contact = $selfplugin->get_welcome_email_contact(ENROL_SEND_EMAIL_FROM_NOREPLY, $context);
     741          $this->assertEquals($noreplyuser, $contact);
     742      }
     743  
     744      /**
     745       * Test for getting user enrolment actions.
     746       */
     747      public function test_get_user_enrolment_actions() {
     748          global $CFG, $DB, $PAGE;
     749          $this->resetAfterTest();
     750  
     751          // Set page URL to prevent debugging messages.
     752          $PAGE->set_url('/enrol/editinstance.php');
     753  
     754          $pluginname = 'self';
     755  
     756          // Only enable the self enrol plugin.
     757          $CFG->enrol_plugins_enabled = $pluginname;
     758  
     759          $generator = $this->getDataGenerator();
     760  
     761          // Get the enrol plugin.
     762          $plugin = enrol_get_plugin($pluginname);
     763  
     764          // Create a course.
     765          $course = $generator->create_course();
     766  
     767          // Create a teacher.
     768          $teacher = $generator->create_user();
     769          // Enrol the teacher to the course.
     770          $enrolresult = $generator->enrol_user($teacher->id, $course->id, 'editingteacher', $pluginname);
     771          $this->assertTrue($enrolresult);
     772          // Create a student.
     773          $student = $generator->create_user();
     774          // Enrol the student to the course.
     775          $enrolresult = $generator->enrol_user($student->id, $course->id, 'student', $pluginname);
     776          $this->assertTrue($enrolresult);
     777  
     778          // Login as the teacher.
     779          $this->setUser($teacher);
     780          require_once($CFG->dirroot . '/enrol/locallib.php');
     781          $manager = new course_enrolment_manager($PAGE, $course);
     782          $userenrolments = $manager->get_user_enrolments($student->id);
     783          $this->assertCount(1, $userenrolments);
     784  
     785          $ue = reset($userenrolments);
     786          $actions = $plugin->get_user_enrolment_actions($manager, $ue);
     787          // Self enrol has 2 enrol actions -- edit and unenrol.
     788          $this->assertCount(2, $actions);
     789      }
     790  }