Search moodle.org's
Developer Documentation

See Release Notes

  • Bug fixes for general core bugs in 4.3.x will end 7 October 2024 (12 months).
  • Bug fixes for security issues in 4.3.x will end 21 April 2025 (18 months).
  • PHP version: minimum PHP 8.0.0 Note: minimum PHP version has increased since Moodle 4.1. PHP 8.2.x is supported too.

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

   1  <?php
   2  // This file is part of Moodle - http://moodle.org/
   3  //
   4  // Moodle is free software: you can redistribute it and/or modify
   5  // it under the terms of the GNU General Public License as published by
   6  // the Free Software Foundation, either version 3 of the License, or
   7  // (at your option) any later version.
   8  //
   9  // Moodle is distributed in the hope that it will be useful,
  10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12  // GNU General Public License for more details.
  13  //
  14  // You should have received a copy of the GNU General Public License
  15  // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
  16  
  17  /**
  18   * Test non-plugin enrollib parts.
  19   *
  20   * @package    core_enrol
  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  
  29  /**
  30   * Test non-plugin enrollib parts.
  31   *
  32   * @package    core
  33   * @category   phpunit
  34   * @copyright  2012 Petr Skoda {@link http://skodak.org}
  35   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  36   */
  37  class enrollib_test extends advanced_testcase {
  38  
  39      public function test_enrol_get_all_users_courses() {
  40          global $DB, $CFG;
  41  
  42          $this->resetAfterTest();
  43  
  44          $studentrole = $DB->get_record('role', array('shortname'=>'student'));
  45          $this->assertNotEmpty($studentrole);
  46          $teacherrole = $DB->get_record('role', array('shortname'=>'teacher'));
  47          $this->assertNotEmpty($teacherrole);
  48  
  49          $admin = get_admin();
  50          $user1 = $this->getDataGenerator()->create_user();
  51          $user2 = $this->getDataGenerator()->create_user();
  52          $user3 = $this->getDataGenerator()->create_user();
  53          $user4 = $this->getDataGenerator()->create_user();
  54          $user5 = $this->getDataGenerator()->create_user();
  55  
  56          $category1 = $this->getDataGenerator()->create_category(array('visible'=>0));
  57          $category2 = $this->getDataGenerator()->create_category();
  58  
  59          $course1 = $this->getDataGenerator()->create_course(array(
  60              'shortname' => 'Z',
  61              'idnumber' => '123',
  62              'category' => $category1->id,
  63          ));
  64          $course2 = $this->getDataGenerator()->create_course(array(
  65              'shortname' => 'X',
  66              'idnumber' => '789',
  67              'category' => $category2->id,
  68          ));
  69          $course3 = $this->getDataGenerator()->create_course(array(
  70              'shortname' => 'Y',
  71              'idnumber' => '456',
  72              'category' => $category2->id,
  73              'visible' => 0,
  74          ));
  75          $course4 = $this->getDataGenerator()->create_course(array(
  76              'shortname' => 'W',
  77              'category' => $category2->id,
  78          ));
  79  
  80          $maninstance1 = $DB->get_record('enrol', array('courseid'=>$course1->id, 'enrol'=>'manual'), '*', MUST_EXIST);
  81          $DB->set_field('enrol', 'status', ENROL_INSTANCE_DISABLED, array('id'=>$maninstance1->id));
  82          $maninstance1 = $DB->get_record('enrol', array('courseid'=>$course1->id, 'enrol'=>'manual'), '*', MUST_EXIST);
  83          $maninstance2 = $DB->get_record('enrol', array('courseid'=>$course2->id, 'enrol'=>'manual'), '*', MUST_EXIST);
  84          $maninstance3 = $DB->get_record('enrol', array('courseid'=>$course3->id, 'enrol'=>'manual'), '*', MUST_EXIST);
  85          $maninstance4 = $DB->get_record('enrol', array('courseid'=>$course4->id, 'enrol'=>'manual'), '*', MUST_EXIST);
  86  
  87          $manual = enrol_get_plugin('manual');
  88          $this->assertNotEmpty($manual);
  89  
  90          $manual->enrol_user($maninstance1, $user1->id, $teacherrole->id);
  91          $manual->enrol_user($maninstance1, $user2->id, $studentrole->id);
  92          $manual->enrol_user($maninstance1, $user4->id, $teacherrole->id, 0, 0, ENROL_USER_SUSPENDED);
  93          $manual->enrol_user($maninstance1, $admin->id, $studentrole->id);
  94  
  95          $manual->enrol_user($maninstance2, $user1->id);
  96          $manual->enrol_user($maninstance2, $user2->id);
  97          $manual->enrol_user($maninstance2, $user3->id, 0, 1, time()+(60*60));
  98  
  99          $manual->enrol_user($maninstance3, $user1->id);
 100          $manual->enrol_user($maninstance3, $user2->id);
 101          $manual->enrol_user($maninstance3, $user3->id, 0, 1, time()-(60*60));
 102          $manual->enrol_user($maninstance3, $user4->id, 0, 0, 0, ENROL_USER_SUSPENDED);
 103  
 104  
 105          $courses = enrol_get_all_users_courses($CFG->siteguest);
 106          $this->assertSame(array(), $courses);
 107  
 108          $courses = enrol_get_all_users_courses(0);
 109          $this->assertSame(array(), $courses);
 110  
 111          // Results are sorted by visibility, sortorder by default (in our case order of creation)
 112  
 113          $courses = enrol_get_all_users_courses($admin->id);
 114          $this->assertCount(1, $courses);
 115          $this->assertEquals(array($course1->id), array_keys($courses));
 116  
 117          $courses = enrol_get_all_users_courses($admin->id, true);
 118          $this->assertCount(0, $courses);
 119          $this->assertEquals(array(), array_keys($courses));
 120  
 121          $courses = enrol_get_all_users_courses($user1->id);
 122          $this->assertCount(3, $courses);
 123          $this->assertEquals(array($course2->id, $course1->id, $course3->id), array_keys($courses));
 124  
 125          $courses = enrol_get_all_users_courses($user1->id, true);
 126          $this->assertCount(2, $courses);
 127          $this->assertEquals(array($course2->id, $course3->id), array_keys($courses));
 128  
 129          $courses = enrol_get_all_users_courses($user2->id);
 130          $this->assertCount(3, $courses);
 131          $this->assertEquals(array($course2->id, $course1->id, $course3->id), array_keys($courses));
 132  
 133          $courses = enrol_get_all_users_courses($user2->id, true);
 134          $this->assertCount(2, $courses);
 135          $this->assertEquals(array($course2->id, $course3->id), array_keys($courses));
 136  
 137          $courses = enrol_get_all_users_courses($user3->id);
 138          $this->assertCount(2, $courses);
 139          $this->assertEquals(array($course2->id, $course3->id), array_keys($courses));
 140  
 141          $courses = enrol_get_all_users_courses($user3->id, true);
 142          $this->assertCount(1, $courses);
 143          $this->assertEquals(array($course2->id), array_keys($courses));
 144  
 145          $courses = enrol_get_all_users_courses($user4->id);
 146          $this->assertCount(2, $courses);
 147          $this->assertEquals(array($course1->id, $course3->id), array_keys($courses));
 148  
 149          $courses = enrol_get_all_users_courses($user4->id, true);
 150          $this->assertCount(0, $courses);
 151          $this->assertEquals(array(), array_keys($courses));
 152  
 153          // Make sure sorting and columns work.
 154  
 155          $basefields = array('id', 'category', 'sortorder', 'shortname', 'fullname', 'idnumber',
 156              'startdate', 'visible', 'groupmode', 'groupmodeforce', 'defaultgroupingid');
 157  
 158          $courses = enrol_get_all_users_courses($user2->id, true);
 159          $course = reset($courses);
 160          context_helper::preload_from_record($course);
 161          $course = (array)$course;
 162          $this->assertEqualsCanonicalizing($basefields, array_keys($course));
 163  
 164          $courses = enrol_get_all_users_courses($user2->id, false, 'timecreated');
 165          $course = reset($courses);
 166          $this->assertTrue(property_exists($course, 'timecreated'));
 167  
 168          $courses = enrol_get_all_users_courses($user2->id, false, null, 'id DESC');
 169          $this->assertEquals(array($course2->id, $course3->id, $course1->id), array_keys($courses));
 170  
 171          // Make sure that implicit sorting defined in navsortmycoursessort is respected.
 172  
 173          $CFG->navsortmycoursessort = 'shortname';
 174  
 175          $courses = enrol_get_all_users_courses($user1->id);
 176          $this->assertEquals(array($course2->id, $course3->id, $course1->id), array_keys($courses));
 177  
 178          // But still the explicit sorting takes precedence over the implicit one.
 179  
 180          $courses = enrol_get_all_users_courses($user1->id, false, null, 'shortname DESC');
 181          $this->assertEquals(array($course2->id, $course1->id, $course3->id), array_keys($courses));
 182  
 183          // Make sure that implicit visibility sorting defined in navsortmycourseshiddenlast is respected for all course sortings.
 184  
 185          $CFG->navsortmycoursessort = 'sortorder';
 186          $CFG->navsortmycourseshiddenlast = true;
 187          $courses = enrol_get_all_users_courses($user1->id);
 188          $this->assertEquals(array($course2->id, $course1->id, $course3->id), array_keys($courses));
 189  
 190          $CFG->navsortmycoursessort = 'sortorder';
 191          $CFG->navsortmycourseshiddenlast = false;
 192          $courses = enrol_get_all_users_courses($user1->id);
 193          $this->assertEquals(array($course1->id, $course3->id, $course2->id), array_keys($courses));
 194  
 195          $CFG->navsortmycoursessort = 'fullname';
 196          $CFG->navsortmycourseshiddenlast = true;
 197          $courses = enrol_get_all_users_courses($user1->id);
 198          $this->assertEquals(array($course2->id, $course1->id, $course3->id), array_keys($courses));
 199  
 200          $CFG->navsortmycoursessort = 'fullname';
 201          $CFG->navsortmycourseshiddenlast = false;
 202          $courses = enrol_get_all_users_courses($user1->id);
 203          $this->assertEquals(array($course1->id, $course2->id, $course3->id), array_keys($courses));
 204  
 205          $CFG->navsortmycoursessort = 'shortname';
 206          $CFG->navsortmycourseshiddenlast = true;
 207          $courses = enrol_get_all_users_courses($user1->id);
 208          $this->assertEquals(array($course2->id, $course3->id, $course1->id), array_keys($courses));
 209  
 210          $CFG->navsortmycoursessort = 'shortname';
 211          $CFG->navsortmycourseshiddenlast = false;
 212          $courses = enrol_get_all_users_courses($user1->id);
 213          $this->assertEquals(array($course2->id, $course3->id, $course1->id), array_keys($courses));
 214  
 215          $CFG->navsortmycoursessort = 'idnumber';
 216          $CFG->navsortmycourseshiddenlast = true;
 217          $courses = enrol_get_all_users_courses($user1->id);
 218          $this->assertEquals(array($course2->id, $course1->id, $course3->id), array_keys($courses));
 219  
 220          $CFG->navsortmycoursessort = 'idnumber';
 221          $CFG->navsortmycourseshiddenlast = false;
 222          $courses = enrol_get_all_users_courses($user1->id);
 223          $this->assertEquals(array($course1->id, $course3->id, $course2->id), array_keys($courses));
 224  
 225          // But still the explicit visibility sorting takes precedence over the implicit one.
 226  
 227          $courses = enrol_get_all_users_courses($user1->id, false, null, 'visible DESC, shortname DESC');
 228          $this->assertEquals(array($course2->id, $course1->id, $course3->id), array_keys($courses));
 229      }
 230  
 231      /**
 232       * Test enrol_course_delete() without passing a user id. When a value for user id is not present, the method
 233       * should delete all enrolment related data in the course.
 234       */
 235      public function test_enrol_course_delete_without_userid() {
 236          global $DB;
 237  
 238          $this->resetAfterTest();
 239  
 240          // Create users.
 241          $user1 = $this->getDataGenerator()->create_user();
 242          $user2 = $this->getDataGenerator()->create_user();
 243          // Create a course.
 244          $course = $this->getDataGenerator()->create_course();
 245          $coursecontext = context_course::instance($course->id);
 246  
 247          $studentrole = $DB->get_record('role', ['shortname' => 'student']);
 248  
 249          $manual = enrol_get_plugin('manual');
 250          $manualinstance = $DB->get_record('enrol', ['courseid' => $course->id, 'enrol' => 'manual'], '*', MUST_EXIST);
 251          // Enrol user1 as a student in the course using manual enrolment.
 252          $manual->enrol_user($manualinstance, $user1->id, $studentrole->id);
 253  
 254          $self = enrol_get_plugin('self');
 255          $selfinstance = $DB->get_record('enrol', ['courseid' => $course->id, 'enrol' => 'self'], '*', MUST_EXIST);
 256          $self->update_status($selfinstance, ENROL_INSTANCE_ENABLED);
 257          // Enrol user2 as a student in the course using self enrolment.
 258          $self->enrol_user($selfinstance, $user2->id, $studentrole->id);
 259  
 260          // Delete all enrolment related records in the course.
 261          enrol_course_delete($course);
 262  
 263          // The course enrolment of user1 should not exists.
 264          $user1enrolment = $DB->get_record('user_enrolments',
 265              ['enrolid' => $manualinstance->id, 'userid' => $user1->id]);
 266          $this->assertFalse($user1enrolment);
 267  
 268          // The role assignment of user1 should not exists.
 269          $user1roleassignment = $DB->get_record('role_assignments',
 270              ['roleid' => $studentrole->id, 'userid'=> $user1->id, 'contextid' => $coursecontext->id]
 271          );
 272          $this->assertFalse($user1roleassignment);
 273  
 274          // The course enrolment of user2 should not exists.
 275          $user2enrolment = $DB->get_record('user_enrolments',
 276              ['enrolid' => $selfinstance->id, 'userid' => $user2->id]);
 277          $this->assertFalse($user2enrolment);
 278  
 279          // The role assignment of user2 should not exists.
 280          $user2roleassignment = $DB->get_record('role_assignments',
 281              ['roleid' => $studentrole->id, 'userid'=> $user2->id, 'contextid' => $coursecontext->id]);
 282          $this->assertFalse($user2roleassignment);
 283  
 284          // All existing course enrolment instances should not exists.
 285          $enrolmentinstances = enrol_get_instances($course->id, false);
 286          $this->assertCount(0, $enrolmentinstances);
 287      }
 288  
 289      /**
 290       * Test enrol_course_delete() when user id is present.
 291       * When a value for user id is present, the method should make sure the user has the proper capability to
 292       * un-enrol users before removing the enrolment data. If the capabilities are missing the data should not be removed.
 293       *
 294       * @dataProvider enrol_course_delete_with_userid_provider
 295       * @param array $excludedcapabilities The capabilities that should be excluded from the user's role
 296       * @param bool $expected The expected results
 297       */
 298      public function test_enrol_course_delete_with_userid($excludedcapabilities, $expected) {
 299          global $DB;
 300  
 301          $this->resetAfterTest();
 302          // Create users.
 303          $user1 = $this->getDataGenerator()->create_user();
 304          $user2 = $this->getDataGenerator()->create_user();
 305          $user3 = $this->getDataGenerator()->create_user();
 306          // Create a course.
 307          $course = $this->getDataGenerator()->create_course();
 308          $coursecontext = context_course::instance($course->id);
 309  
 310          $studentrole = $DB->get_record('role', ['shortname' => 'student']);
 311          $editingteacherrole = $DB->get_record('role', ['shortname' => 'editingteacher']);
 312  
 313          $manual = enrol_get_plugin('manual');
 314          $manualinstance = $DB->get_record('enrol', ['courseid' => $course->id, 'enrol' => 'manual'],
 315              '*', MUST_EXIST);
 316          // Enrol user1 as a student in the course using manual enrolment.
 317          $manual->enrol_user($manualinstance, $user1->id, $studentrole->id);
 318          // Enrol user3 as an editing teacher in the course using manual enrolment.
 319          // By default, the editing teacher role has the capability to un-enroll users which have been enrolled using
 320          // the existing enrolment methods.
 321          $manual->enrol_user($manualinstance, $user3->id, $editingteacherrole->id);
 322  
 323          $self = enrol_get_plugin('self');
 324          $selfinstance = $DB->get_record('enrol', ['courseid' => $course->id, 'enrol' => 'self'],
 325              '*', MUST_EXIST);
 326          $self->update_status($selfinstance, ENROL_INSTANCE_ENABLED);
 327          // Enrol user2 as a student in the course using self enrolment.
 328          $self->enrol_user($selfinstance, $user2->id, $studentrole->id);
 329  
 330          foreach($excludedcapabilities as $capability) {
 331              // Un-assign the given capability from the editing teacher role.
 332              unassign_capability($capability, $editingteacherrole->id);
 333          }
 334  
 335          // Delete only enrolment related records in the course where user3 has the required capability.
 336          enrol_course_delete($course, $user3->id);
 337  
 338          // Check the existence of the course enrolment of user1.
 339          $user1enrolmentexists = (bool) $DB->count_records('user_enrolments',
 340              ['enrolid' => $manualinstance->id, 'userid' => $user1->id]);
 341          $this->assertEquals($expected['User 1 course enrolment exists'], $user1enrolmentexists);
 342  
 343          // Check the existence of the role assignment of user1 in the course.
 344          $user1roleassignmentexists = (bool) $DB->count_records('role_assignments',
 345              ['roleid' => $studentrole->id, 'userid' => $user1->id, 'contextid' => $coursecontext->id]);
 346          $this->assertEquals($expected['User 1 role assignment exists'], $user1roleassignmentexists);
 347  
 348          // Check the existence of the course enrolment of user2.
 349          $user2enrolmentexists = (bool) $DB->count_records('user_enrolments',
 350              ['enrolid' => $selfinstance->id, 'userid' => $user2->id]);
 351          $this->assertEquals($expected['User 2 course enrolment exists'], $user2enrolmentexists);
 352  
 353          // Check the existence of the role assignment of user2 in the course.
 354          $user2roleassignmentexists = (bool) $DB->count_records('role_assignments',
 355              ['roleid' => $studentrole->id, 'userid' => $user2->id, 'contextid' => $coursecontext->id]);
 356          $this->assertEquals($expected['User 2 role assignment exists'], $user2roleassignmentexists);
 357  
 358          // Check the existence of the course enrolment of user3.
 359          $user3enrolmentexists = (bool) $DB->count_records('user_enrolments',
 360              ['enrolid' => $manualinstance->id, 'userid' => $user3->id]);
 361          $this->assertEquals($expected['User 3 course enrolment exists'], $user3enrolmentexists);
 362  
 363          // Check the existence of the role assignment of user3 in the course.
 364          $user3roleassignmentexists = (bool) $DB->count_records('role_assignments',
 365              ['roleid' => $editingteacherrole->id, 'userid' => $user3->id, 'contextid' => $coursecontext->id]);
 366          $this->assertEquals($expected['User 3 role assignment exists'], $user3roleassignmentexists);
 367  
 368          // Check the existence of the manual enrolment instance in the course.
 369          $manualinstance = (bool) $DB->count_records('enrol', ['enrol' => 'manual', 'courseid' => $course->id]);
 370          $this->assertEquals($expected['Manual course enrolment instance exists'], $manualinstance);
 371  
 372          // Check existence of the self enrolment instance in the course.
 373          $selfinstance = (bool) $DB->count_records('enrol', ['enrol' => 'self', 'courseid' => $course->id]);
 374          $this->assertEquals($expected['Self course enrolment instance exists'], $selfinstance);
 375      }
 376  
 377      /**
 378       * Data provider for test_enrol_course_delete_with_userid().
 379       *
 380       * @return array
 381       */
 382      public function enrol_course_delete_with_userid_provider() {
 383          return [
 384              'The teacher can un-enrol users in a course' =>
 385                  [
 386                      'excludedcapabilities' => [],
 387                      'results' => [
 388                          // Whether certain enrolment related data still exists in the course after the deletion.
 389                          // When the user has the capabilities to un-enrol users and the enrolment plugins allow manual
 390                          // unenerolment than all course enrolment data should be removed.
 391                          'Manual course enrolment instance exists' => false,
 392                          'Self course enrolment instance exists' => false,
 393                          'User 1 course enrolment exists' => false,
 394                          'User 1 role assignment exists' => false,
 395                          'User 2 course enrolment exists' => false,
 396                          'User 2 role assignment exists' => false,
 397                          'User 3 course enrolment exists' => false,
 398                          'User 3 role assignment exists' => false
 399                      ],
 400                  ],
 401              'The teacher cannot un-enrol self enrolled users'  =>
 402                  [
 403                      'excludedcapabilities' => [
 404                          // Exclude the following capabilities for the editing teacher.
 405                          'enrol/self:unenrol'
 406                      ],
 407                      'results' => [
 408                          // When the user does not have the capabilities to un-enrol self enrolled users, the data
 409                          // related to this enrolment method should not be removed. Everything else should be removed.
 410                          'Manual course enrolment instance exists' => false,
 411                          'Self course enrolment instance exists' => true,
 412                          'User 1 course enrolment exists' => false,
 413                          'User 1 role assignment exists' => false,
 414                          'User 2 course enrolment exists' => true,
 415                          'User 2 role assignment exists' => true,
 416                          'User 3 course enrolment exists' => false,
 417                          'User 3 role assignment exists' => false
 418                      ],
 419                  ],
 420              'The teacher cannot un-enrol self and manually enrolled users' =>
 421                  [
 422                      'excludedcapabilities' => [
 423                          // Exclude the following capabilities for the editing teacher.
 424                          'enrol/manual:unenrol',
 425                          'enrol/self:unenrol'
 426                      ],
 427                      'results' => [
 428                          // When the user does not have the capabilities to un-enrol self and manually enrolled users,
 429                          // the data related to these enrolment methods should not be removed.
 430                          'Manual course enrolment instance exists' => true,
 431                          'Self course enrolment instance exists' => true,
 432                          'User 1 course enrolment exists' => true,
 433                          'User 1 role assignment exists' => true,
 434                          'User 2 course enrolment exists' => true,
 435                          'User 2 role assignment exists' => true,
 436                          'User 3 course enrolment exists' => true,
 437                          'User 3 role assignment exists' => true
 438                      ],
 439                  ],
 440          ];
 441      }
 442  
 443  
 444      public function test_enrol_user_sees_own_courses() {
 445          global $DB, $CFG;
 446  
 447          $this->resetAfterTest();
 448  
 449          $studentrole = $DB->get_record('role', array('shortname'=>'student'));
 450          $this->assertNotEmpty($studentrole);
 451          $teacherrole = $DB->get_record('role', array('shortname'=>'teacher'));
 452          $this->assertNotEmpty($teacherrole);
 453  
 454          $admin = get_admin();
 455          $user1 = $this->getDataGenerator()->create_user();
 456          $user2 = $this->getDataGenerator()->create_user();
 457          $user3 = $this->getDataGenerator()->create_user();
 458          $user4 = $this->getDataGenerator()->create_user();
 459          $user5 = $this->getDataGenerator()->create_user();
 460          $user6 = $this->getDataGenerator()->create_user();
 461  
 462          $category1 = $this->getDataGenerator()->create_category(array('visible'=>0));
 463          $category2 = $this->getDataGenerator()->create_category();
 464          $course1 = $this->getDataGenerator()->create_course(array('category'=>$category1->id));
 465          $course2 = $this->getDataGenerator()->create_course(array('category'=>$category2->id));
 466          $course3 = $this->getDataGenerator()->create_course(array('category'=>$category2->id, 'visible'=>0));
 467          $course4 = $this->getDataGenerator()->create_course(array('category'=>$category2->id));
 468  
 469          $maninstance1 = $DB->get_record('enrol', array('courseid'=>$course1->id, 'enrol'=>'manual'), '*', MUST_EXIST);
 470          $DB->set_field('enrol', 'status', ENROL_INSTANCE_DISABLED, array('id'=>$maninstance1->id));
 471          $maninstance1 = $DB->get_record('enrol', array('courseid'=>$course1->id, 'enrol'=>'manual'), '*', MUST_EXIST);
 472          $maninstance2 = $DB->get_record('enrol', array('courseid'=>$course2->id, 'enrol'=>'manual'), '*', MUST_EXIST);
 473          $maninstance3 = $DB->get_record('enrol', array('courseid'=>$course3->id, 'enrol'=>'manual'), '*', MUST_EXIST);
 474          $maninstance4 = $DB->get_record('enrol', array('courseid'=>$course4->id, 'enrol'=>'manual'), '*', MUST_EXIST);
 475  
 476          $manual = enrol_get_plugin('manual');
 477          $this->assertNotEmpty($manual);
 478  
 479          $manual->enrol_user($maninstance1, $admin->id, $studentrole->id);
 480  
 481          $manual->enrol_user($maninstance3, $user1->id, $teacherrole->id);
 482  
 483          $manual->enrol_user($maninstance2, $user2->id, $studentrole->id);
 484  
 485          $manual->enrol_user($maninstance1, $user3->id, $studentrole->id, 1, time()+(60*60));
 486          $manual->enrol_user($maninstance2, $user3->id, 0, 1, time()-(60*60));
 487          $manual->enrol_user($maninstance3, $user2->id, $studentrole->id);
 488          $manual->enrol_user($maninstance4, $user2->id, 0, 0, 0, ENROL_USER_SUSPENDED);
 489  
 490          $manual->enrol_user($maninstance1, $user4->id, $teacherrole->id, 0, 0, ENROL_USER_SUSPENDED);
 491          $manual->enrol_user($maninstance3, $user4->id, 0, 0, 0, ENROL_USER_SUSPENDED);
 492  
 493  
 494          $this->assertFalse(enrol_user_sees_own_courses($CFG->siteguest));
 495          $this->assertFalse(enrol_user_sees_own_courses(0));
 496          $this->assertFalse(enrol_user_sees_own_courses($admin));
 497          $this->assertFalse(enrol_user_sees_own_courses(-222)); // Nonexistent user.
 498  
 499          $this->assertTrue(enrol_user_sees_own_courses($user1));
 500          $this->assertTrue(enrol_user_sees_own_courses($user2->id));
 501          $this->assertFalse(enrol_user_sees_own_courses($user3->id));
 502          $this->assertFalse(enrol_user_sees_own_courses($user4));
 503          $this->assertFalse(enrol_user_sees_own_courses($user5));
 504  
 505          $this->setAdminUser();
 506          $this->assertFalse(enrol_user_sees_own_courses());
 507  
 508          $this->setGuestUser();
 509          $this->assertFalse(enrol_user_sees_own_courses());
 510  
 511          $this->setUser(0);
 512          $this->assertFalse(enrol_user_sees_own_courses());
 513  
 514          $this->setUser($user1);
 515          $this->assertTrue(enrol_user_sees_own_courses());
 516  
 517          $this->setUser($user2);
 518          $this->assertTrue(enrol_user_sees_own_courses());
 519  
 520          $this->setUser($user3);
 521          $this->assertFalse(enrol_user_sees_own_courses());
 522  
 523          $this->setUser($user4);
 524          $this->assertFalse(enrol_user_sees_own_courses());
 525  
 526          $this->setUser($user5);
 527          $this->assertFalse(enrol_user_sees_own_courses());
 528  
 529          $user1 = $DB->get_record('user', array('id'=>$user1->id));
 530          $this->setUser($user1);
 531          $reads = $DB->perf_get_reads();
 532          $this->assertTrue(enrol_user_sees_own_courses());
 533          $this->assertGreaterThan($reads, $DB->perf_get_reads());
 534  
 535          $user1 = $DB->get_record('user', array('id'=>$user1->id));
 536          $this->setUser($user1);
 537          require_login($course3);
 538          $reads = $DB->perf_get_reads();
 539          $this->assertTrue(enrol_user_sees_own_courses());
 540          $this->assertEquals($reads, $DB->perf_get_reads());
 541      }
 542  
 543      public function test_enrol_get_shared_courses() {
 544          $this->resetAfterTest();
 545  
 546          $user1 = $this->getDataGenerator()->create_user();
 547          $user2 = $this->getDataGenerator()->create_user();
 548          $user3 = $this->getDataGenerator()->create_user();
 549  
 550          $course1 = $this->getDataGenerator()->create_course();
 551          $this->getDataGenerator()->enrol_user($user1->id, $course1->id);
 552          $this->getDataGenerator()->enrol_user($user2->id, $course1->id);
 553  
 554          $course2 = $this->getDataGenerator()->create_course();
 555          $this->getDataGenerator()->enrol_user($user1->id, $course2->id);
 556  
 557          // Test that user1 and user2 have courses in common.
 558          $this->assertTrue(enrol_get_shared_courses($user1, $user2, false, true));
 559          // Test that user1 and user3 have no courses in common.
 560          $this->assertFalse(enrol_get_shared_courses($user1, $user3, false, true));
 561  
 562          // Test retrieving the courses in common.
 563          $sharedcourses = enrol_get_shared_courses($user1, $user2, true);
 564  
 565          // Only should be one shared course.
 566          $this->assertCount(1, $sharedcourses);
 567          $sharedcourse = array_shift($sharedcourses);
 568          // It should be course 1.
 569          $this->assertEquals($sharedcourse->id, $course1->id);
 570      }
 571  
 572      public function test_enrol_get_shared_courses_different_methods() {
 573          global $DB, $CFG;
 574  
 575          require_once($CFG->dirroot . '/enrol/self/externallib.php');
 576  
 577          $this->resetAfterTest();
 578  
 579          $user1 = $this->getDataGenerator()->create_user();
 580          $user2 = $this->getDataGenerator()->create_user();
 581          $user3 = $this->getDataGenerator()->create_user();
 582  
 583          $course1 = $this->getDataGenerator()->create_course();
 584  
 585          // Enrol user1 and user2 in course1 with a different enrolment methode.
 586          // Add self enrolment method for course1.
 587          $selfplugin = enrol_get_plugin('self');
 588          $this->assertNotEmpty($selfplugin);
 589  
 590          $studentrole = $DB->get_record('role', array('shortname' => 'student'));
 591          $this->assertNotEmpty($studentrole);
 592  
 593          $instance1id = $selfplugin->add_instance($course1, array('status' => ENROL_INSTANCE_ENABLED,
 594                                                                   'name' => 'Test instance 1',
 595                                                                   'customint6' => 1,
 596                                                                   'roleid' => $studentrole->id));
 597  
 598          $instance1 = $DB->get_record('enrol', array('id' => $instance1id), '*', MUST_EXIST);
 599  
 600          self::setUser($user2);
 601          // Self enrol me (user2).
 602          $result = enrol_self_external::enrol_user($course1->id);
 603  
 604          // Enrol user1 manually.
 605          $this->getDataGenerator()->enrol_user($user1->id, $course1->id, null, 'manual');
 606  
 607          $course2 = $this->getDataGenerator()->create_course();
 608          $this->getDataGenerator()->enrol_user($user1->id, $course2->id);
 609  
 610          $course3 = $this->getDataGenerator()->create_course();
 611          $this->getDataGenerator()->enrol_user($user2->id, $course3->id);
 612  
 613          // Test that user1 and user2 have courses in common.
 614          $this->assertTrue(enrol_get_shared_courses($user1, $user2, false, true));
 615          // Test that user1 and user3 have no courses in common.
 616          $this->assertFalse(enrol_get_shared_courses($user1, $user3, false, true));
 617  
 618          // Test retrieving the courses in common.
 619          $sharedcourses = enrol_get_shared_courses($user1, $user2, true);
 620  
 621          // Only should be one shared course.
 622          $this->assertCount(1, $sharedcourses);
 623          $sharedcourse = array_shift($sharedcourses);
 624          // It should be course 1.
 625          $this->assertEquals($sharedcourse->id, $course1->id);
 626      }
 627  
 628      /**
 629       * Test user enrolment created event.
 630       */
 631      public function test_user_enrolment_created_event() {
 632          global $DB;
 633  
 634          $this->resetAfterTest();
 635  
 636          $studentrole = $DB->get_record('role', array('shortname'=>'student'));
 637          $this->assertNotEmpty($studentrole);
 638  
 639          $admin = get_admin();
 640  
 641          $course1 = $this->getDataGenerator()->create_course();
 642  
 643          $maninstance1 = $DB->get_record('enrol', array('courseid'=>$course1->id, 'enrol'=>'manual'), '*', MUST_EXIST);
 644  
 645          $manual = enrol_get_plugin('manual');
 646          $this->assertNotEmpty($manual);
 647  
 648          // Enrol user and capture event.
 649          $sink = $this->redirectEvents();
 650          $manual->enrol_user($maninstance1, $admin->id, $studentrole->id);
 651          $events = $sink->get_events();
 652          $sink->close();
 653          $event = array_shift($events);
 654  
 655          $dbuserenrolled = $DB->get_record('user_enrolments', array('userid' => $admin->id));
 656          $this->assertInstanceOf('\core\event\user_enrolment_created', $event);
 657          $this->assertEquals($dbuserenrolled->id, $event->objectid);
 658          $this->assertEquals(context_course::instance($course1->id), $event->get_context());
 659          $this->assertEventContextNotUsed($event);
 660      }
 661  
 662      /**
 663       * Test user_enrolment_deleted event.
 664       */
 665      public function test_user_enrolment_deleted_event() {
 666          global $DB;
 667  
 668          $this->resetAfterTest(true);
 669  
 670          $manualplugin = enrol_get_plugin('manual');
 671          $user = $this->getDataGenerator()->create_user();
 672          $course = $this->getDataGenerator()->create_course();
 673          $student = $DB->get_record('role', array('shortname' => 'student'));
 674  
 675          $enrol = $DB->get_record('enrol', array('courseid' => $course->id, 'enrol' => 'manual'), '*', MUST_EXIST);
 676  
 677          // Enrol user.
 678          $manualplugin->enrol_user($enrol, $user->id, $student->id);
 679  
 680          // Get the user enrolment information, used to validate legacy event data.
 681          $dbuserenrolled = $DB->get_record('user_enrolments', array('userid' => $user->id));
 682  
 683          // Unenrol user and capture event.
 684          $sink = $this->redirectEvents();
 685          $manualplugin->unenrol_user($enrol, $user->id);
 686          $events = $sink->get_events();
 687          $sink->close();
 688          $event = array_pop($events);
 689  
 690          // Validate the event.
 691          $this->assertInstanceOf('\core\event\user_enrolment_deleted', $event);
 692          $this->assertEquals(context_course::instance($course->id), $event->get_context());
 693          $this->assertEventContextNotUsed($event);
 694      }
 695  
 696      /**
 697       * Test enrol_instance_created, enrol_instance_updated and enrol_instance_deleted events.
 698       */
 699      public function test_instance_events() {
 700          global $DB;
 701  
 702          $this->resetAfterTest(true);
 703  
 704          $selfplugin = enrol_get_plugin('self');
 705          $studentrole = $DB->get_record('role', array('shortname' => 'student'));
 706  
 707          $course = $this->getDataGenerator()->create_course();
 708  
 709          // Creating enrol instance.
 710          $sink = $this->redirectEvents();
 711          $instanceid = $selfplugin->add_instance($course, array('status' => ENROL_INSTANCE_ENABLED,
 712                                                                  'name' => 'Test instance 1',
 713                                                                  'customint6' => 1,
 714                                                                  'roleid' => $studentrole->id));
 715          $events = $sink->get_events();
 716          $sink->close();
 717  
 718          $this->assertCount(1, $events);
 719          $event = array_pop($events);
 720          $this->assertInstanceOf('\core\event\enrol_instance_created', $event);
 721          $this->assertEquals(context_course::instance($course->id), $event->get_context());
 722          $this->assertEquals('self', $event->other['enrol']);
 723          $this->assertEventContextNotUsed($event);
 724  
 725          // Updating enrol instance.
 726          $instance = $DB->get_record('enrol', array('id' => $instanceid));
 727          $sink = $this->redirectEvents();
 728          $selfplugin->update_status($instance, ENROL_INSTANCE_DISABLED);
 729  
 730          $events = $sink->get_events();
 731          $sink->close();
 732  
 733          $this->assertCount(1, $events);
 734          $event = array_pop($events);
 735          $this->assertInstanceOf('\core\event\enrol_instance_updated', $event);
 736          $this->assertEquals(context_course::instance($course->id), $event->get_context());
 737          $this->assertEquals('self', $event->other['enrol']);
 738          $this->assertEventContextNotUsed($event);
 739  
 740          // Deleting enrol instance.
 741          $instance = $DB->get_record('enrol', array('id' => $instanceid));
 742          $sink = $this->redirectEvents();
 743          $selfplugin->delete_instance($instance);
 744  
 745          $events = $sink->get_events();
 746          $sink->close();
 747  
 748          $this->assertCount(1, $events);
 749          $event = array_pop($events);
 750          $this->assertInstanceOf('\core\event\enrol_instance_deleted', $event);
 751          $this->assertEquals(context_course::instance($course->id), $event->get_context());
 752          $this->assertEquals('self', $event->other['enrol']);
 753          $this->assertEventContextNotUsed($event);
 754      }
 755  
 756      /**
 757       * Confirms that timemodified field was updated after modification of user enrollment
 758       */
 759      public function test_enrollment_update_timemodified() {
 760          global $DB;
 761  
 762          $this->resetAfterTest(true);
 763          $datagen = $this->getDataGenerator();
 764  
 765          /** @var enrol_manual_plugin $manualplugin */
 766          $manualplugin = enrol_get_plugin('manual');
 767          $this->assertNotNull($manualplugin);
 768  
 769          $studentroleid = $DB->get_field('role', 'id', ['shortname' => 'student'], MUST_EXIST);
 770          $course = $datagen->create_course();
 771          $user = $datagen->create_user();
 772  
 773          $instanceid = null;
 774          $instances = enrol_get_instances($course->id, true);
 775          foreach ($instances as $inst) {
 776              if ($inst->enrol == 'manual') {
 777                  $instanceid = (int)$inst->id;
 778                  break;
 779              }
 780          }
 781          if (empty($instanceid)) {
 782              $instanceid = $manualplugin->add_default_instance($course);
 783              if (empty($instanceid)) {
 784                  $instanceid = $manualplugin->add_instance($course);
 785              }
 786          }
 787          $this->assertNotNull($instanceid);
 788  
 789          $instance = $DB->get_record('enrol', ['id' => $instanceid], '*', MUST_EXIST);
 790          $manualplugin->enrol_user($instance, $user->id, $studentroleid, 0, 0, ENROL_USER_ACTIVE);
 791          $userenrolorig = (int)$DB->get_field(
 792              'user_enrolments',
 793              'timemodified',
 794              ['enrolid' => $instance->id, 'userid' => $user->id],
 795              MUST_EXIST
 796          );
 797          $this->waitForSecond();
 798          $this->waitForSecond();
 799          $manualplugin->update_user_enrol($instance, $user->id, ENROL_USER_SUSPENDED);
 800          $userenrolpost = (int)$DB->get_field(
 801              'user_enrolments',
 802              'timemodified',
 803              ['enrolid' => $instance->id, 'userid' => $user->id],
 804              MUST_EXIST
 805          );
 806  
 807          $this->assertGreaterThan($userenrolorig, $userenrolpost);
 808      }
 809  
 810      /**
 811       * Test to confirm that enrol_get_my_courses only return the courses that
 812       * the logged in user is enrolled in.
 813       */
 814      public function test_enrol_get_my_courses_only_enrolled_courses() {
 815          $user = $this->getDataGenerator()->create_user();
 816          $course1 = $this->getDataGenerator()->create_course();
 817          $course2 = $this->getDataGenerator()->create_course();
 818          $course3 = $this->getDataGenerator()->create_course();
 819          $course4 = $this->getDataGenerator()->create_course();
 820  
 821          $this->getDataGenerator()->enrol_user($user->id, $course1->id);
 822          $this->getDataGenerator()->enrol_user($user->id, $course2->id);
 823          $this->getDataGenerator()->enrol_user($user->id, $course3->id);
 824          $this->resetAfterTest(true);
 825          $this->setUser($user);
 826  
 827          // By default this function should return all of the courses the user
 828          // is enrolled in.
 829          $courses = enrol_get_my_courses();
 830  
 831          $this->assertCount(3, $courses);
 832          $this->assertEquals($course1->id, $courses[$course1->id]->id);
 833          $this->assertEquals($course2->id, $courses[$course2->id]->id);
 834          $this->assertEquals($course3->id, $courses[$course3->id]->id);
 835  
 836          // If a set of course ids are provided then the result set will only contain
 837          // these courses.
 838          $courseids = [$course1->id, $course2->id];
 839          $courses = enrol_get_my_courses(['id'], 'visible DESC,sortorder ASC', 0, $courseids);
 840  
 841          $this->assertCount(2, $courses);
 842          $this->assertEquals($course1->id, $courses[$course1->id]->id);
 843          $this->assertEquals($course2->id, $courses[$course2->id]->id);
 844  
 845          // If the course ids list contains any ids for courses the user isn't enrolled in
 846          // then they will be ignored (in this case $course4).
 847          $courseids = [$course1->id, $course2->id, $course4->id];
 848          $courses = enrol_get_my_courses(['id'], 'visible DESC,sortorder ASC', 0, $courseids);
 849  
 850          $this->assertCount(2, $courses);
 851          $this->assertEquals($course1->id, $courses[$course1->id]->id);
 852          $this->assertEquals($course2->id, $courses[$course2->id]->id);
 853      }
 854  
 855      /**
 856       * Tests the enrol_get_my_courses function when using the $includehidden parameter, which
 857       * should remove any courses hidden from the user's timeline
 858       *
 859       * @throws coding_exception
 860       * @throws dml_exception
 861       */
 862      public function test_enrol_get_my_courses_include_hidden() {
 863          global $DB, $CFG;
 864  
 865          $this->resetAfterTest(true);
 866  
 867          // Create test user and 4 courses, two of which have guest access enabled.
 868          $user = $this->getDataGenerator()->create_user();
 869          $course1 = $this->getDataGenerator()->create_course(
 870              (object)array('shortname' => 'X',
 871                  'enrol_guest_status_0' => ENROL_INSTANCE_DISABLED,
 872                  'enrol_guest_password_0' => ''));
 873          $course2 = $this->getDataGenerator()->create_course(
 874              (object)array('shortname' => 'Z',
 875                  'enrol_guest_status_0' => ENROL_INSTANCE_ENABLED,
 876                  'enrol_guest_password_0' => ''));
 877          $course3 = $this->getDataGenerator()->create_course(
 878              (object)array('shortname' => 'Y',
 879                  'enrol_guest_status_0' => ENROL_INSTANCE_ENABLED,
 880                  'enrol_guest_password_0' => 'frog'));
 881          $course4 = $this->getDataGenerator()->create_course(
 882              (object)array('shortname' => 'W',
 883                  'enrol_guest_status_0' => ENROL_INSTANCE_DISABLED,
 884                  'enrol_guest_password_0' => ''));
 885  
 886          // User is enrolled in first course.
 887          $this->getDataGenerator()->enrol_user($user->id, $course1->id);
 888          $this->getDataGenerator()->enrol_user($user->id, $course2->id);
 889          $this->getDataGenerator()->enrol_user($user->id, $course3->id);
 890          $this->getDataGenerator()->enrol_user($user->id, $course4->id);
 891  
 892          // Check enrol_get_my_courses basic use (without include hidden provided).
 893          $this->setUser($user);
 894          $courses = enrol_get_my_courses();
 895          $this->assertEquals([$course4->id, $course3->id, $course2->id, $course1->id], array_keys($courses));
 896  
 897          // Hide a course.
 898          set_user_preference('block_myoverview_hidden_course_' . $course3->id, true);
 899  
 900          // Hidden course shouldn't be returned.
 901          $courses = enrol_get_my_courses(null, null, 0, [], false, 0, [$course3->id]);
 902          $this->assertEquals([$course4->id, $course2->id, $course1->id], array_keys($courses));
 903  
 904          // Offset should take into account hidden course.
 905          $courses = enrol_get_my_courses(null, null, 0, [], false, 2, [$course3->id]);
 906          $this->assertEquals([$course1->id], array_keys($courses));
 907      }
 908  
 909      /**
 910       * Tests the enrol_get_my_courses function when using the $allaccessible parameter, which
 911       * includes a wider range of courses (enrolled courses + other accessible ones).
 912       */
 913      public function test_enrol_get_my_courses_all_accessible() {
 914          global $DB, $CFG;
 915  
 916          $this->resetAfterTest(true);
 917  
 918          // Create test user and 4 courses, two of which have guest access enabled.
 919          $user = $this->getDataGenerator()->create_user();
 920          $course1 = $this->getDataGenerator()->create_course(
 921                  (object)array('shortname' => 'X',
 922                  'enrol_guest_status_0' => ENROL_INSTANCE_DISABLED,
 923                  'enrol_guest_password_0' => ''));
 924          $course2 = $this->getDataGenerator()->create_course(
 925                  (object)array('shortname' => 'Z',
 926                  'enrol_guest_status_0' => ENROL_INSTANCE_ENABLED,
 927                  'enrol_guest_password_0' => ''));
 928          $course3 = $this->getDataGenerator()->create_course(
 929                  (object)array('shortname' => 'Y',
 930                  'enrol_guest_status_0' => ENROL_INSTANCE_ENABLED,
 931                  'enrol_guest_password_0' => 'frog'));
 932          $course4 = $this->getDataGenerator()->create_course(
 933                  (object)array('shortname' => 'W',
 934                  'enrol_guest_status_0' => ENROL_INSTANCE_DISABLED,
 935                  'enrol_guest_password_0' => ''));
 936  
 937          // User is enrolled in first course.
 938          $this->getDataGenerator()->enrol_user($user->id, $course1->id);
 939  
 940          // Check enrol_get_my_courses basic use (without all accessible).
 941          $this->setUser($user);
 942          $courses = enrol_get_my_courses();
 943          $this->assertEquals([$course1->id], array_keys($courses));
 944  
 945          // Turn on all accessible, now they can access the second course too.
 946          $courses = enrol_get_my_courses(null, 'id', 0, [], true);
 947          $this->assertEquals([$course1->id, $course2->id], array_keys($courses));
 948  
 949          // Log in as guest to third course.
 950          load_temp_course_role(context_course::instance($course3->id), $CFG->guestroleid);
 951          $courses = enrol_get_my_courses(null, 'id', 0, [], true);
 952          $this->assertEquals([$course1->id, $course2->id, $course3->id], array_keys($courses));
 953  
 954          // Check fields parameter still works. Fields default (certain base fields).
 955          $this->assertObjectHasAttribute('id', $courses[$course3->id]);
 956          $this->assertObjectHasAttribute('shortname', $courses[$course3->id]);
 957          $this->assertObjectNotHasAttribute('summary', $courses[$course3->id]);
 958  
 959          // Specified fields (one, string).
 960          $courses = enrol_get_my_courses('summary', 'id', 0, [], true);
 961          $this->assertObjectHasAttribute('id', $courses[$course3->id]);
 962          $this->assertObjectHasAttribute('shortname', $courses[$course3->id]);
 963          $this->assertObjectHasAttribute('summary', $courses[$course3->id]);
 964          $this->assertObjectNotHasAttribute('summaryformat', $courses[$course3->id]);
 965  
 966          // Specified fields (two, string).
 967          $courses = enrol_get_my_courses('summary, summaryformat', 'id', 0, [], true);
 968          $this->assertObjectHasAttribute('summary', $courses[$course3->id]);
 969          $this->assertObjectHasAttribute('summaryformat', $courses[$course3->id]);
 970  
 971          // Specified fields (two, array).
 972          $courses = enrol_get_my_courses(['summary', 'summaryformat'], 'id', 0, [], true);
 973          $this->assertObjectHasAttribute('summary', $courses[$course3->id]);
 974          $this->assertObjectHasAttribute('summaryformat', $courses[$course3->id]);
 975  
 976          // By default, courses are ordered by sortorder - which by default is most recent first.
 977          $courses = enrol_get_my_courses(null, null, 0, [], true);
 978          $this->assertEquals([$course3->id, $course2->id, $course1->id], array_keys($courses));
 979  
 980          // Make sure that implicit sorting defined in navsortmycoursessort is respected.
 981          $CFG->navsortmycoursessort = 'shortname';
 982          $courses = enrol_get_my_courses(null, null, 0, [], true);
 983          $this->assertEquals([$course1->id, $course3->id, $course2->id], array_keys($courses));
 984  
 985          // But still the explicit sorting takes precedence over the implicit one.
 986          $courses = enrol_get_my_courses(null, 'shortname DESC', 0, [], true);
 987          $this->assertEquals([$course2->id, $course3->id, $course1->id], array_keys($courses));
 988  
 989          // Check filter parameter still works.
 990          $courses = enrol_get_my_courses(null, 'id', 0, [$course2->id, $course3->id, $course4->id], true);
 991          $this->assertEquals([$course2->id, $course3->id], array_keys($courses));
 992  
 993          // Check limit parameter.
 994          $courses = enrol_get_my_courses(null, 'id', 2, [], true);
 995          $this->assertEquals([$course1->id, $course2->id], array_keys($courses));
 996  
 997          // Now try access for a different user who has manager role at system level.
 998          $manager = $this->getDataGenerator()->create_user();
 999          $managerroleid = $DB->get_field('role', 'id', ['shortname' => 'manager']);
1000          role_assign($managerroleid, $manager->id, \context_system::instance()->id);
1001          $this->setUser($manager);
1002  
1003          // With default get enrolled, they don't have any courses.
1004          $courses = enrol_get_my_courses();
1005          $this->assertCount(0, $courses);
1006  
1007          // But with all accessible, they have 4 because they have moodle/course:view everywhere.
1008          $courses = enrol_get_my_courses(null, 'id', 0, [], true);
1009          $this->assertEquals([$course1->id, $course2->id, $course3->id, $course4->id],
1010                  array_keys($courses));
1011  
1012          // If we prohibit manager from course:view on course 1 though...
1013          assign_capability('moodle/course:view', CAP_PROHIBIT, $managerroleid,
1014                  \context_course::instance($course1->id));
1015          $courses = enrol_get_my_courses(null, 'id', 0, [], true);
1016          $this->assertEquals([$course2->id, $course3->id, $course4->id], array_keys($courses));
1017  
1018          // Check for admin user, which has a slightly different query.
1019          $this->setAdminUser();
1020          $courses = enrol_get_my_courses(null, 'id', 0, [], true);
1021          $this->assertEquals([$course1->id, $course2->id, $course3->id, $course4->id], array_keys($courses));
1022      }
1023  
1024      /**
1025       * Data provider for {@see test_enrol_get_my_courses_by_time}
1026       *
1027       * @return array
1028       */
1029      public function enrol_get_my_courses_by_time_provider(): array {
1030          return [
1031              'No start or end time' =>
1032                  [null, null, true],
1033              'Start time now, no end time' =>
1034                  [0, null, true],
1035              'Start time now, end time in the future' =>
1036                  [0, MINSECS, true],
1037              'Start time in the past, no end time' =>
1038                  [-MINSECS, null, true],
1039              'Start time in the past, end time in the future' =>
1040                  [-MINSECS, MINSECS, true],
1041              'Start time in the past, end time in the past' =>
1042                  [-DAYSECS, -HOURSECS, false],
1043              'Start time in the future' =>
1044                  [MINSECS, null, false],
1045          ];
1046      }
1047  
1048      /**
1049       * Test that expected course enrolments are returned when they have timestart / timeend specified
1050       *
1051       * @param int|null $timestartoffset Null for 0, otherwise offset from current time
1052       * @param int|null $timeendoffset Null for 0, otherwise offset from current time
1053       * @param bool $expectreturn
1054       *
1055       * @dataProvider enrol_get_my_courses_by_time_provider
1056       */
1057      public function test_enrol_get_my_courses_by_time(?int $timestartoffset, ?int $timeendoffset, bool $expectreturn): void {
1058          $this->resetAfterTest();
1059  
1060          $time = time();
1061          $timestart = $timestartoffset === null ? 0 : $time + $timestartoffset;
1062          $timeend = $timeendoffset === null ? 0 : $time + $timeendoffset;
1063  
1064          $course = $this->getDataGenerator()->create_course();
1065          $user = $this->getDataGenerator()->create_and_enrol($course, 'student', null, 'manual', $timestart, $timeend);
1066          $this->setUser($user);
1067  
1068          $courses = enrol_get_my_courses();
1069          if ($expectreturn) {
1070              $this->assertCount(1, $courses);
1071              $this->assertEquals($course->id, reset($courses)->id);
1072          } else {
1073              $this->assertEmpty($courses);
1074          }
1075      }
1076  
1077      /**
1078       * test_course_users
1079       *
1080       * @return void
1081       */
1082      public function test_course_users() {
1083          $this->resetAfterTest();
1084  
1085          $user1 = $this->getDataGenerator()->create_user();
1086          $user2 = $this->getDataGenerator()->create_user();
1087          $course1 = $this->getDataGenerator()->create_course();
1088          $course2 = $this->getDataGenerator()->create_course();
1089  
1090          $this->getDataGenerator()->enrol_user($user1->id, $course1->id);
1091          $this->getDataGenerator()->enrol_user($user2->id, $course1->id);
1092          $this->getDataGenerator()->enrol_user($user1->id, $course2->id);
1093  
1094          $this->assertCount(2, enrol_get_course_users($course1->id));
1095          $this->assertCount(2, enrol_get_course_users($course1->id, true));
1096  
1097          $this->assertCount(1, enrol_get_course_users($course1->id, true, array($user1->id)));
1098  
1099          $this->assertCount(2, enrol_get_course_users(false, false, array($user1->id)));
1100  
1101          $instances = enrol_get_instances($course1->id, true);
1102          $manualinstance = reset($instances);
1103  
1104          $manualplugin = enrol_get_plugin('manual');
1105          $manualplugin->update_user_enrol($manualinstance, $user1->id, ENROL_USER_SUSPENDED);
1106          $this->assertCount(2, enrol_get_course_users($course1->id, false));
1107          $this->assertCount(1, enrol_get_course_users($course1->id, true));
1108      }
1109  
1110      /**
1111       * test_course_users in groups
1112       *
1113       * @covers \enrol_get_course_users()
1114       * @return void
1115       */
1116      public function test_course_users_in_groups() {
1117          $this->resetAfterTest();
1118  
1119          $user1 = $this->getDataGenerator()->create_user();
1120          $user2 = $this->getDataGenerator()->create_user();
1121          $user3 = $this->getDataGenerator()->create_user();
1122          $course = $this->getDataGenerator()->create_course();
1123          $group1 = $this->getDataGenerator()->create_group(['courseid' => $course->id]);
1124          $group2 = $this->getDataGenerator()->create_group(['courseid' => $course->id]);
1125  
1126          $this->getDataGenerator()->enrol_user($user1->id, $course->id);
1127          $this->getDataGenerator()->enrol_user($user2->id, $course->id);
1128          $this->getDataGenerator()->enrol_user($user3->id, $course->id);
1129  
1130          $this->getDataGenerator()->create_group_member(['groupid' => $group1->id, 'userid' => $user1->id]);
1131          $this->getDataGenerator()->create_group_member(['groupid' => $group2->id, 'userid' => $user1->id]);
1132          $this->getDataGenerator()->create_group_member(['groupid' => $group2->id, 'userid' => $user2->id]);
1133  
1134          $this->assertCount(3, enrol_get_course_users($course->id));
1135          $this->assertCount(1, enrol_get_course_users($course->id, false, [], [], [$group1->id]));
1136          $this->assertCount(2, enrol_get_course_users($course->id, false, [], [], [$group2->id]));
1137  
1138          $instances = enrol_get_instances($course->id, true);
1139          $manualinstance = reset($instances);
1140  
1141          $manualplugin = enrol_get_plugin('manual');
1142          $manualplugin->update_user_enrol($manualinstance, $user1->id, ENROL_USER_SUSPENDED);
1143          $this->assertCount(2, enrol_get_course_users($course->id, false, [], [], [$group2->id]));
1144          $this->assertCount(1, enrol_get_course_users($course->id, true, [], [], [$group2->id]));
1145      }
1146  
1147      /**
1148       * Test count of enrolled users
1149       *
1150       * @return void
1151       */
1152      public function test_count_enrolled_users() {
1153          global $DB;
1154  
1155          $this->resetAfterTest(true);
1156  
1157          $course = $this->getDataGenerator()->create_course();
1158          $context = \context_course::instance($course->id);
1159  
1160          $user1 = $this->getDataGenerator()->create_user();
1161          $user2 = $this->getDataGenerator()->create_user();
1162  
1163          $studentrole = $DB->get_record('role', ['shortname' => 'student']);
1164  
1165          // Add each user to the manual enrolment instance.
1166          $manual = enrol_get_plugin('manual');
1167  
1168          $manualinstance = $DB->get_record('enrol', ['courseid' => $course->id, 'enrol' => 'manual'], '*', MUST_EXIST);
1169  
1170          $manual->enrol_user($manualinstance, $user1->id, $studentrole->id);
1171          $manual->enrol_user($manualinstance, $user2->id, $studentrole->id);
1172  
1173          $this->assertEquals(2, count_enrolled_users($context));
1174  
1175          // Create a self enrolment instance, enrol first user only.
1176          $self = enrol_get_plugin('self');
1177  
1178          $selfid = $self->add_instance($course,
1179              ['status' => ENROL_INSTANCE_ENABLED, 'name' => 'Self', 'customint6' => 1, 'roleid' => $studentrole->id]);
1180          $selfinstance = $DB->get_record('enrol', ['id' => $selfid], '*', MUST_EXIST);
1181  
1182          $self->enrol_user($selfinstance, $user1->id, $studentrole->id);
1183  
1184          // There are still only two distinct users.
1185          $this->assertEquals(2, count_enrolled_users($context));
1186      }
1187  
1188      /**
1189       * Test cases for the test_enrol_get_my_courses_sort_by_last_access test.
1190       */
1191      public function get_enrol_get_my_courses_sort_by_last_access_test_cases() {
1192          $now = time();
1193  
1194          $enrolledcoursesdata = [
1195              ['shortname' => 'a', 'lastaccess' => $now - 2],
1196              ['shortname' => 'b', 'lastaccess' => $now - 1],
1197              ['shortname' => 'c', 'lastaccess' => $now],
1198              ['shortname' => 'd', 'lastaccess' => $now - 1],
1199              ['shortname' => 'e']
1200          ];
1201          $unenrolledcoursesdata = [
1202              ['shortname' => 'x', 'lastaccess' => $now - 2],
1203              ['shortname' => 'y', 'lastaccess' => $now - 1],
1204              ['shortname' => 'z', 'lastaccess' => $now]
1205          ];
1206  
1207          return [
1208              'empty set' => [
1209                  'enrolledcoursesdata' => [],
1210                  'unenrolledcoursesdata' => $unenrolledcoursesdata,
1211                  'sort' => 'ul.timeaccess asc',
1212                  'limit' => 0,
1213                  'offset' => 0,
1214                  'expectedcourses' => []
1215              ],
1216              'ul.timeaccess asc, shortname asc no limit or offset' => [
1217                  'enrolledcoursesdata' => $enrolledcoursesdata,
1218                  'unenrolledcoursesdata' => $unenrolledcoursesdata,
1219                  'sort' => 'ul.timeaccess asc, shortname asc',
1220                  'limit' => 0,
1221                  'offset' => 0,
1222                  'expectedcourses' => ['e', 'a', 'b', 'd', 'c']
1223              ],
1224              'ul.timeaccess asc, shortname asc with limit no offset' => [
1225                  'enrolledcoursesdata' => $enrolledcoursesdata,
1226                  'unenrolledcoursesdata' => $unenrolledcoursesdata,
1227                  'sort' => 'ul.timeaccess asc, shortname asc',
1228                  'limit' => 2,
1229                  'offset' => 0,
1230                  'expectedcourses' => ['e', 'a']
1231              ],
1232              'ul.timeaccess asc, shortname asc with limit and offset' => [
1233                  'enrolledcoursesdata' => $enrolledcoursesdata,
1234                  'unenrolledcoursesdata' => $unenrolledcoursesdata,
1235                  'sort' => 'ul.timeaccess asc, shortname asc',
1236                  'limit' => 2,
1237                  'offset' => 2,
1238                  'expectedcourses' => ['b', 'd']
1239              ],
1240              'ul.timeaccess asc, shortname asc with limit and offset beyond end of data set' => [
1241                  'enrolledcoursesdata' => $enrolledcoursesdata,
1242                  'unenrolledcoursesdata' => $unenrolledcoursesdata,
1243                  'sort' => 'ul.timeaccess asc, shortname asc',
1244                  'limit' => 2,
1245                  'offset' => 4,
1246                  'expectedcourses' => ['c']
1247              ],
1248              'ul.timeaccess desc, shortname asc no limit or offset' => [
1249                  'enrolledcoursesdata' => $enrolledcoursesdata,
1250                  'unenrolledcoursesdata' => $unenrolledcoursesdata,
1251                  'sort' => 'ul.timeaccess desc, shortname asc',
1252                  'limit' => 0,
1253                  'offset' => 0,
1254                  'expectedcourses' => ['c', 'b', 'd', 'a', 'e']
1255              ],
1256              'ul.timeaccess desc, shortname desc, no limit or offset' => [
1257                  'enrolledcoursesdata' => $enrolledcoursesdata,
1258                  'unenrolledcoursesdata' => $unenrolledcoursesdata,
1259                  'sort' => 'ul.timeaccess desc, shortname desc',
1260                  'limit' => 0,
1261                  'offset' => 0,
1262                  'expectedcourses' => ['c', 'd', 'b', 'a', 'e']
1263              ],
1264              'ul.timeaccess asc, shortname desc, no limit or offset' => [
1265                  'enrolledcoursesdata' => $enrolledcoursesdata,
1266                  'unenrolledcoursesdata' => $unenrolledcoursesdata,
1267                  'sort' => 'ul.timeaccess asc, shortname desc',
1268                  'limit' => 0,
1269                  'offset' => 0,
1270                  'expectedcourses' => ['e', 'a', 'd', 'b', 'c']
1271              ],
1272              'shortname asc, no limit or offset' => [
1273                  'enrolledcoursesdata' => $enrolledcoursesdata,
1274                  'unenrolledcoursesdata' => $unenrolledcoursesdata,
1275                  'sort' => 'shortname asc',
1276                  'limit' => 0,
1277                  'offset' => 0,
1278                  'expectedcourses' => ['a', 'b', 'c', 'd', 'e']
1279              ],
1280              'shortname desc, no limit or offset' => [
1281                  'enrolledcoursesdata' => $enrolledcoursesdata,
1282                  'unenrolledcoursesdata' => $unenrolledcoursesdata,
1283                  'sort' => 'shortname desc',
1284                  'limit' => 0,
1285                  'offset' => 0,
1286                  'expectedcourses' => ['e', 'd', 'c', 'b', 'a']
1287              ],
1288          ];
1289      }
1290  
1291      /**
1292       * Test the get_enrolled_courses_by_timeline_classification function.
1293       *
1294       * @dataProvider get_enrol_get_my_courses_sort_by_last_access_test_cases()
1295       * @param array $enrolledcoursesdata Courses to create and enrol the user in
1296       * @param array $unenrolledcoursesdata Courses to create nut not enrol the user in
1297       * @param string $sort Sort string for the enrol function
1298       * @param int $limit Maximum number of results
1299       * @param int $offset Offset the courses result set by this amount
1300       * @param array $expectedcourses Expected courses in result
1301       */
1302      public function test_enrol_get_my_courses_sort_by_last_access(
1303          $enrolledcoursesdata,
1304          $unenrolledcoursesdata,
1305          $sort,
1306          $limit,
1307          $offset,
1308          $expectedcourses
1309      ) {
1310          global $DB, $CFG;
1311  
1312          $this->resetAfterTest();
1313          $generator = $this->getDataGenerator();
1314          $student = $generator->create_user();
1315          $lastaccessrecords = [];
1316  
1317          foreach ($enrolledcoursesdata as $coursedata) {
1318              $lastaccess = null;
1319  
1320              if (isset($coursedata['lastaccess'])) {
1321                  $lastaccess = $coursedata['lastaccess'];
1322                  unset($coursedata['lastaccess']);
1323              }
1324  
1325              $course = $generator->create_course($coursedata);
1326              $generator->enrol_user($student->id, $course->id, 'student');
1327  
1328              if (!is_null($lastaccess)) {
1329                  $lastaccessrecords[] = [
1330                      'userid' => $student->id,
1331                      'courseid' => $course->id,
1332                      'timeaccess' => $lastaccess
1333                  ];
1334              }
1335          }
1336  
1337          foreach ($unenrolledcoursesdata as $coursedata) {
1338              $lastaccess = null;
1339  
1340              if (isset($coursedata['lastaccess'])) {
1341                  $lastaccess = $coursedata['lastaccess'];
1342                  unset($coursedata['lastaccess']);
1343              }
1344  
1345              $course = $generator->create_course($coursedata);
1346  
1347              if (!is_null($lastaccess)) {
1348                  $lastaccessrecords[] = [
1349                      'userid' => $student->id,
1350                      'courseid' => $course->id,
1351                      'timeaccess' => $lastaccess
1352                  ];
1353              }
1354          }
1355  
1356          if (!empty($lastaccessrecords)) {
1357              $DB->insert_records('user_lastaccess', $lastaccessrecords);
1358          }
1359  
1360          $this->setUser($student);
1361  
1362          $result = enrol_get_my_courses('shortname', $sort, $limit, [], false, $offset);
1363          $actual = array_map(function($course) {
1364              return $course->shortname;
1365          }, array_values($result));
1366  
1367          $this->assertEquals($expectedcourses, $actual);
1368      }
1369  
1370      /**
1371       * Test enrol_get_course_users_roles function.
1372       *
1373       * @return void
1374       */
1375      public function test_enrol_get_course_users_roles() {
1376          global $DB;
1377  
1378          $this->resetAfterTest();
1379  
1380          $user1 = $this->getDataGenerator()->create_user();
1381          $user2 = $this->getDataGenerator()->create_user();
1382          $course = $this->getDataGenerator()->create_course();
1383          $context = context_course::instance($course->id);
1384  
1385          $roles = array();
1386          $roles['student'] = $DB->get_field('role', 'id', array('shortname' => 'student'), MUST_EXIST);
1387          $roles['teacher'] = $DB->get_field('role', 'id', array('shortname' => 'teacher'), MUST_EXIST);
1388  
1389          $manual = enrol_get_plugin('manual');
1390          $this->assertNotEmpty($manual);
1391  
1392          $enrol = $DB->get_record('enrol', array('courseid' => $course->id, 'enrol' => 'manual'), '*', MUST_EXIST);
1393  
1394          // Test without enrolments.
1395          $this->assertEmpty(enrol_get_course_users_roles($course->id));
1396  
1397          // Test with 1 user, 1 role.
1398          $manual->enrol_user($enrol, $user1->id, $roles['student']);
1399          $return = enrol_get_course_users_roles($course->id);
1400          $this->assertArrayHasKey($user1->id, $return);
1401          $this->assertArrayHasKey($roles['student'], $return[$user1->id]);
1402          $this->assertArrayNotHasKey($roles['teacher'], $return[$user1->id]);
1403  
1404          // Test with 1 user, 2 role.
1405          $manual->enrol_user($enrol, $user1->id, $roles['teacher']);
1406          $return = enrol_get_course_users_roles($course->id);
1407          $this->assertArrayHasKey($user1->id, $return);
1408          $this->assertArrayHasKey($roles['student'], $return[$user1->id]);
1409          $this->assertArrayHasKey($roles['teacher'], $return[$user1->id]);
1410  
1411          // Test with another user, 1 role.
1412          $manual->enrol_user($enrol, $user2->id, $roles['student']);
1413          $return = enrol_get_course_users_roles($course->id);
1414          $this->assertArrayHasKey($user1->id, $return);
1415          $this->assertArrayHasKey($roles['student'], $return[$user1->id]);
1416          $this->assertArrayHasKey($roles['teacher'], $return[$user1->id]);
1417          $this->assertArrayHasKey($user2->id, $return);
1418          $this->assertArrayHasKey($roles['student'], $return[$user2->id]);
1419          $this->assertArrayNotHasKey($roles['teacher'], $return[$user2->id]);
1420      }
1421  
1422      /**
1423       * Test enrol_calculate_duration function
1424       */
1425      public function test_enrol_calculate_duration() {
1426          // Start time 07/01/2019 @ 12:00am (UTC).
1427          $timestart = 1561939200;
1428          // End time 07/05/2019 @ 12:00am (UTC).
1429          $timeend = 1562284800;
1430          $duration = enrol_calculate_duration($timestart, $timeend);
1431          $durationinday = $duration / DAYSECS;
1432          $this->assertEquals(4, $durationinday);
1433  
1434          // End time 07/10/2019 @ 12:00am (UTC).
1435          $timeend = 1562716800;
1436          $duration = enrol_calculate_duration($timestart, $timeend);
1437          $durationinday = $duration / DAYSECS;
1438          $this->assertEquals(9, $durationinday);
1439      }
1440  
1441      /**
1442       * Test get_enrolled_with_capabilities_join cannotmatchanyrows attribute.
1443       *
1444       * @dataProvider get_enrolled_with_capabilities_join_cannotmatchanyrows_data()
1445       * @param string $capability the tested capability
1446       * @param bool $useprohibit if the capability must be assigned to prohibit
1447       * @param int $expectedmatch expected cannotmatchanyrows value
1448       * @param int $expectedcount expceted count value
1449       */
1450      public function test_get_enrolled_with_capabilities_join_cannotmatchanyrows(
1451          string $capability,
1452          bool $useprohibit,
1453          int $expectedmatch,
1454          int $expectedcount
1455      ) {
1456          global $DB, $CFG;
1457  
1458          $this->resetAfterTest();
1459  
1460          $course = $this->getDataGenerator()->create_course();
1461          $context = context_course::instance($course->id);
1462  
1463          $roleid = $CFG->defaultuserroleid;
1464  
1465          // Override capability if necessary.
1466          if ($useprohibit && $capability) {
1467              assign_capability($capability, CAP_PROHIBIT, $roleid, $context);
1468          }
1469  
1470          // Check if we must enrol or not.
1471          $this->getDataGenerator()->create_and_enrol($course, 'editingteacher');
1472  
1473          $join = get_enrolled_with_capabilities_join($context, '', $capability);
1474  
1475          // Execute query.
1476          $sql = "SELECT COUNT(DISTINCT u.id)
1477                    FROM {user} u {$join->joins}
1478                   WHERE {$join->wheres}";
1479          $countrecords = $DB->count_records_sql($sql, $join->params);
1480  
1481          // Validate cannotmatchanyrows.
1482          $this->assertEquals($expectedmatch, $join->cannotmatchanyrows);
1483          $this->assertEquals($expectedcount, $countrecords);
1484      }
1485  
1486      /**
1487       * Data provider for test_get_enrolled_with_capabilities_join_cannotmatchanyrows
1488       *
1489       * @return @array of testing scenarios
1490       */
1491      public function get_enrolled_with_capabilities_join_cannotmatchanyrows_data() {
1492          return [
1493              'no prohibits, no capability' => [
1494                  'capability' => '',
1495                  'useprohibit' => false,
1496                  'expectedmatch' => 0,
1497                  'expectedcount' => 1,
1498              ],
1499              'no prohibits with capability' => [
1500                  'capability' => 'moodle/course:manageactivities',
1501                  'useprohibit' => false,
1502                  'expectedmatch' => 0,
1503                  'expectedcount' => 1,
1504              ],
1505              'prohibits with capability' => [
1506                  'capability' => 'moodle/course:manageactivities',
1507                  'useprohibit' => true,
1508                  'expectedmatch' => 1,
1509                  'expectedcount' => 0,
1510              ],
1511          ];
1512      }
1513  
1514      /**
1515       * Test last_time_enrolments_synced not recorded with "force" option for enrol_check_plugins.
1516       * @covers ::enrol_check_plugins
1517       */
1518      public function test_enrol_check_plugins_with_forced_option() {
1519          $this->resetAfterTest();
1520          $user = $this->getDataGenerator()->create_user();
1521  
1522          $this->assertNull(get_user_preferences('last_time_enrolments_synced', null, $user));
1523          enrol_check_plugins($user);
1524          $this->assertNull(get_user_preferences('last_time_enrolments_synced', null, $user));
1525      }
1526  
1527      /**
1528       * Data provided for test_enrol_check_plugins_with_empty_config_value test.
1529       * @return array
1530       */
1531      public function empty_config_data_provider(): array {
1532          return [
1533              [0],
1534              ["0"],
1535              [false],
1536              [''],
1537              ['string'],
1538          ];
1539      }
1540  
1541      /**
1542       * Test that empty 'enrolments_sync_interval' is treated as forced option for enrol_check_plugins.
1543       *
1544       * @dataProvider empty_config_data_provider
1545       * @covers ::enrol_check_plugins
1546       *
1547       * @param mixed $config Config value.
1548       */
1549      public function test_enrol_check_plugins_with_empty_config_value($config) {
1550          global $CFG;
1551  
1552          $this->resetAfterTest();
1553          $CFG->enrolments_sync_interval = $config;
1554          $user = $this->getDataGenerator()->create_user();
1555  
1556          $this->assertNull(get_user_preferences('last_time_enrolments_synced', null, $user));
1557          enrol_check_plugins($user, false);
1558          $this->assertNull(get_user_preferences('last_time_enrolments_synced', null, $user));
1559      }
1560  
1561      /**
1562       * Test last_time_enrolments_synced is recorded without "force" option for enrol_check_plugins.
1563       * @covers ::enrol_check_plugins
1564       */
1565      public function test_last_time_enrolments_synced_is_set_if_not_forced() {
1566          $this->resetAfterTest();
1567          $user = $this->getDataGenerator()->create_user();
1568  
1569          $this->assertNull(get_user_preferences('last_time_enrolments_synced', null, $user));
1570  
1571          enrol_check_plugins($user, false);
1572          $firstrun = get_user_preferences('last_time_enrolments_synced', null, $user);
1573          $this->assertNotNull($firstrun);
1574          sleep(1);
1575  
1576          enrol_check_plugins($user, false);
1577          $secondrun = get_user_preferences('last_time_enrolments_synced', null, $user);
1578          $this->assertNotNull($secondrun);
1579          $this->assertTrue((int)$secondrun == (int)$firstrun);
1580      }
1581  
1582      /**
1583       * Test last_time_enrolments_synced is recorded correctly without "force" option for enrol_check_plugins.
1584       * @covers ::enrol_check_plugins
1585       */
1586      public function test_last_time_enrolments_synced_is_set_if_not_forced_if_have_not_passed_interval() {
1587          global $CFG;
1588  
1589          $this->resetAfterTest();
1590          $CFG->enrolments_sync_interval = 1;
1591          $user = $this->getDataGenerator()->create_user();
1592  
1593          $this->assertNull(get_user_preferences('last_time_enrolments_synced', null, $user));
1594  
1595          enrol_check_plugins($user, false);
1596          $firstrun = get_user_preferences('last_time_enrolments_synced', null, $user);
1597          $this->assertNotNull($firstrun);
1598          sleep(2);
1599  
1600          enrol_check_plugins($user, false);
1601          $secondrun = get_user_preferences('last_time_enrolments_synced', null, $user);
1602          $this->assertNotNull($secondrun);
1603          $this->assertTrue((int)$secondrun > (int)$firstrun);
1604      }
1605  
1606      /**
1607       * Test enrol_selfenrol_available function behavior.
1608       *
1609       * @covers ::enrol_selfenrol_available
1610       */
1611      public function test_enrol_selfenrol_available() {
1612          global $DB, $CFG;
1613  
1614          $this->resetAfterTest();
1615          $this->preventResetByRollback(); // Messaging does not like transactions...
1616  
1617          $selfplugin = enrol_get_plugin('self');
1618  
1619          $user1 = $this->getDataGenerator()->create_user();
1620          $user2 = $this->getDataGenerator()->create_user();
1621  
1622          $studentrole = $DB->get_record('role', ['shortname' => 'student'], '*', MUST_EXIST);
1623          $course = $this->getDataGenerator()->create_course();
1624          $cohort1 = $this->getDataGenerator()->create_cohort();
1625          $cohort2 = $this->getDataGenerator()->create_cohort();
1626  
1627          // New enrolments are allowed and enrolment instance is enabled.
1628          $instance = $DB->get_record('enrol', ['courseid' => $course->id, 'enrol' => 'self'], '*', MUST_EXIST);
1629          $instance->customint6 = 1;
1630          $DB->update_record('enrol', $instance);
1631          $selfplugin->update_status($instance, ENROL_INSTANCE_ENABLED);
1632          $this->setUser($user1);
1633          $this->assertTrue(enrol_selfenrol_available($course->id));
1634          $this->setGuestUser();
1635          $this->assertTrue(enrol_selfenrol_available($course->id));
1636  
1637          $canntenrolerror = get_string('canntenrol', 'enrol_self');
1638  
1639          // New enrolments are not allowed, but enrolment instance is enabled.
1640          $instance->customint6 = 0;
1641          $DB->update_record('enrol', $instance);
1642          $this->setUser($user1);
1643          $this->assertFalse(enrol_selfenrol_available($course->id));
1644          $this->setGuestUser();
1645          $this->assertFalse(enrol_selfenrol_available($course->id));
1646  
1647          // New enrolments are allowed, but enrolment instance is disabled.
1648          $instance->customint6 = 1;
1649          $DB->update_record('enrol', $instance);
1650          $selfplugin->update_status($instance, ENROL_INSTANCE_DISABLED);
1651          $this->setUser($user1);
1652          $this->assertFalse(enrol_selfenrol_available($course->id));
1653          $this->setGuestUser();
1654          $this->assertFalse(enrol_selfenrol_available($course->id));
1655  
1656          // New enrolments are not allowed and enrolment instance is disabled.
1657          $instance->customint6 = 0;
1658          $DB->update_record('enrol', $instance);
1659          $this->setUser($user1);
1660          $this->assertFalse(enrol_selfenrol_available($course->id));
1661          $this->setGuestUser();
1662          $this->assertFalse(enrol_selfenrol_available($course->id));
1663  
1664          // Enable enrolment instance for the rest of the tests.
1665          $selfplugin->update_status($instance, ENROL_INSTANCE_ENABLED);
1666  
1667          // Enrol start date is in future.
1668          $instance->customint6 = 1;
1669          $instance->enrolstartdate = time() + 60;
1670          $DB->update_record('enrol', $instance);
1671          $error = get_string('canntenrolearly', 'enrol_self', userdate($instance->enrolstartdate));
1672          $this->setUser($user1);
1673          $this->assertFalse(enrol_selfenrol_available($course->id));
1674          $this->setGuestUser();
1675          $this->assertFalse(enrol_selfenrol_available($course->id));
1676  
1677          // Enrol start date is in past.
1678          $instance->enrolstartdate = time() - 60;
1679          $DB->update_record('enrol', $instance);
1680          $this->setUser($user1);
1681          $this->assertTrue(enrol_selfenrol_available($course->id));
1682          $this->setGuestUser();
1683          $this->assertTrue(enrol_selfenrol_available($course->id));
1684  
1685          // Enrol end date is in future.
1686          $instance->enrolstartdate = 0;
1687          $instance->enrolenddate = time() + 60;
1688          $DB->update_record('enrol', $instance);
1689          $this->setUser($user1);
1690          $this->assertTrue(enrol_selfenrol_available($course->id));
1691          $this->setGuestUser();
1692          $this->assertTrue(enrol_selfenrol_available($course->id));
1693  
1694          // Enrol end date is in past.
1695          $instance->enrolenddate = time() - 60;
1696          $DB->update_record('enrol', $instance);
1697          $error = get_string('canntenrollate', 'enrol_self', userdate($instance->enrolenddate));
1698          $this->setUser($user1);
1699          $this->assertFalse(enrol_selfenrol_available($course->id));
1700          $this->setGuestUser();
1701          $this->assertFalse(enrol_selfenrol_available($course->id));
1702  
1703          // Maximum enrolments reached.
1704          $instance->customint3 = 1;
1705          $instance->enrolenddate = 0;
1706          $DB->update_record('enrol', $instance);
1707          $selfplugin->enrol_user($instance, $user2->id, $studentrole->id);
1708          $error = get_string('maxenrolledreached', 'enrol_self');
1709          $this->setUser($user1);
1710          $this->assertFalse(enrol_selfenrol_available($course->id));
1711          $this->setGuestUser();
1712          $this->assertFalse(enrol_selfenrol_available($course->id));
1713  
1714          // Maximum enrolments not reached.
1715          $instance->customint3 = 3;
1716          $DB->update_record('enrol', $instance);
1717          $this->setUser($user1);
1718          $this->assertTrue(enrol_selfenrol_available($course->id));
1719          $this->setGuestUser();
1720          $this->assertTrue(enrol_selfenrol_available($course->id));
1721  
1722          require_once("$CFG->dirroot/cohort/lib.php");
1723          cohort_add_member($cohort1->id, $user2->id);
1724  
1725          // Cohort test.
1726          $instance->customint5 = $cohort1->id;
1727          $DB->update_record('enrol', $instance);
1728          $error = get_string('cohortnonmemberinfo', 'enrol_self', $cohort1->name);
1729          $this->setUser($user1);
1730          $this->assertFalse(enrol_selfenrol_available($course->id));
1731          $this->setGuestUser();
1732          $this->assertFalse(enrol_selfenrol_available($course->id));
1733          $this->setUser($user2);
1734          $this->assertFalse(enrol_selfenrol_available($course->id));
1735      }
1736  }