Search moodle.org's
Developer Documentation

See Release Notes
Long Term Support Release

  • Bug fixes for general core bugs in 4.1.x will end 13 November 2023 (12 months).
  • Bug fixes for security issues in 4.1.x will end 10 November 2025 (36 months).
  • PHP version: minimum PHP 7.4.0 Note: minimum PHP version has increased since Moodle 4.0. PHP 8.0.x is supported too.

Differences Between: [Versions 310 and 401] [Versions 39 and 401] [Versions 401 and 402] [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  namespace core_enrol;
  18  
  19  use context_course;
  20  use course_enrolment_manager;
  21  
  22  /**
  23   * Test course_enrolment_manager parts.
  24   *
  25   * @package    core_enrol
  26   * @category   test
  27   * @copyright  2016 Ruslan Kabalin, Lancaster University
  28   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  29   * @covers     \course_enrolment_manager
  30   */
  31  class course_enrolment_manager_test extends \advanced_testcase {
  32      /**
  33       * The course used in tests.
  34       * @var stdClass
  35       */
  36      private $course = null;
  37      /**
  38       * List of users used in tests.
  39       * @var array
  40       */
  41      private $users = array();
  42      /**
  43       * List of groups used in tests.
  44       * @var array
  45       */
  46      private $groups = array();
  47  
  48      /**
  49       * Tests set up
  50       */
  51      protected function setUp(): void {
  52          global $CFG;
  53          require_once($CFG->dirroot . '/enrol/locallib.php');
  54          $this->setAdminUser();
  55  
  56          $users = array();
  57          $groups = array();
  58          // Create the course and the users.
  59          $course = $this->getDataGenerator()->create_course();
  60          $users['user0'] = $this->getDataGenerator()->create_user(
  61                  array('username' => 'user0', 'firstname' => 'user0')); // A user without group.
  62          $users['user1'] = $this->getDataGenerator()->create_user(
  63                  array('username' => 'user1', 'firstname' => 'user1')); // User for group 1.
  64          $users['user21'] = $this->getDataGenerator()->create_user(
  65                  array('username' => 'user21', 'firstname' => 'user21')); // Two users for group 2.
  66          $users['user22'] = $this->getDataGenerator()->create_user(
  67                  array('username' => 'user22', 'firstname' => 'user22'));
  68          $users['userall'] = $this->getDataGenerator()->create_user(
  69                  array('username' => 'userall', 'firstname' => 'userall')); // A user in all groups.
  70          $users['usertch'] = $this->getDataGenerator()->create_user(
  71                  array('username' => 'usertch', 'firstname' => 'usertch')); // A user with teacher role.
  72  
  73          // Enrol the users in the course.
  74          $this->getDataGenerator()->enrol_user($users['user0']->id, $course->id, 'student'); // Student.
  75          $this->getDataGenerator()->enrol_user($users['user1']->id, $course->id, 'student'); // Student.
  76          $this->getDataGenerator()->enrol_user($users['user21']->id, $course->id, 'student'); // Student.
  77          $this->getDataGenerator()->enrol_user($users['user22']->id, $course->id, 'student', 'manual', 0, 0, ENROL_USER_SUSPENDED); // Suspended student.
  78          $this->getDataGenerator()->enrol_user($users['userall']->id, $course->id, 'student'); // Student.
  79          $this->getDataGenerator()->enrol_user($users['usertch']->id, $course->id, 'editingteacher'); // Teacher.
  80  
  81          // Create 2 groups.
  82          $groups['group1'] = $this->getDataGenerator()->create_group(array('courseid' => $course->id));
  83          $groups['group2'] = $this->getDataGenerator()->create_group(array('courseid' => $course->id));
  84  
  85          // Add the users to the groups.
  86          $this->getDataGenerator()->create_group_member(
  87                  array('groupid' => $groups['group1']->id, 'userid' => $users['user1']->id));
  88          $this->getDataGenerator()->create_group_member(
  89                  array('groupid' => $groups['group2']->id, 'userid' => $users['user21']->id));
  90          $this->getDataGenerator()->create_group_member(
  91                  array('groupid' => $groups['group2']->id, 'userid' => $users['user22']->id));
  92          $this->getDataGenerator()->create_group_member(
  93                  array('groupid' => $groups['group1']->id, 'userid' => $users['userall']->id));
  94          $this->getDataGenerator()->create_group_member(
  95                  array('groupid' => $groups['group2']->id, 'userid' => $users['userall']->id));
  96  
  97          // Make setup data accessible from test methods.
  98          $this->course = $course;
  99          $this->users = $users;
 100          $this->groups = $groups;
 101  
 102          // Make sample users and not enroll to any course.
 103          $this->getDataGenerator()->create_user([
 104                  'username' => 'testapiuser1',
 105                  'firstname' => 'testapiuser 1'
 106          ]);
 107          $this->getDataGenerator()->create_user([
 108                  'username' => 'testapiuser2',
 109                  'firstname' => 'testapiuser 2'
 110          ]);
 111          $this->getDataGenerator()->create_user([
 112                  'username' => 'testapiuser3',
 113                  'firstname' => 'testapiuser 3'
 114          ]);
 115      }
 116  
 117      /**
 118       * Verify get_total_users() returned number of users expected in every situation.
 119       */
 120      public function test_get_total_users() {
 121          global $PAGE;
 122  
 123          $this->resetAfterTest();
 124  
 125          // All users filtering.
 126          $manager = new course_enrolment_manager($PAGE, $this->course);
 127          $totalusers = $manager->get_total_users();
 128          $this->assertEquals(6, $totalusers, 'All users must be returned when no filtering is applied.');
 129  
 130          // Student role filtering.
 131          $manager = new course_enrolment_manager($PAGE, $this->course, null, 5);
 132          $totalusers = $manager->get_total_users();
 133          $this->assertEquals(5, $totalusers, 'Only students must be returned when student role filtering is applied.');
 134  
 135          // Teacher role filtering.
 136          $manager = new course_enrolment_manager($PAGE, $this->course, null, 3);
 137          $totalusers = $manager->get_total_users();
 138          $this->assertEquals(1, $totalusers, 'Only teacher must be returned when teacher role filtering is applied.');
 139  
 140          // Search user filtering.
 141          $manager = new course_enrolment_manager($PAGE, $this->course, null, 0, 'userall');
 142          $totalusers = $manager->get_total_users();
 143          $this->assertEquals(1, $totalusers, 'Only searchable user must be returned when search filtering is applied.');
 144  
 145          // Group 1 filtering.
 146          $manager = new course_enrolment_manager($PAGE, $this->course, null, 0, '', $this->groups['group1']->id);
 147          $totalusers = $manager->get_total_users();
 148          $this->assertEquals(2, $totalusers, 'Only group members must be returned when group filtering is applied.');
 149  
 150          // Group 2 filtering.
 151          $manager = new course_enrolment_manager($PAGE, $this->course, null, 0, '', $this->groups['group2']->id);
 152          $totalusers = $manager->get_total_users();
 153          $this->assertEquals(3, $totalusers, 'Only group members must be returned when group filtering is applied.');
 154  
 155          // 'No groups' filtering.
 156          $manager = new course_enrolment_manager($PAGE, $this->course, null, 0, '', -1);
 157          $totalusers = $manager->get_total_users();
 158          $this->assertEquals(2, $totalusers, 'Only non-group members must be returned when \'no groups\' filtering is applied.');
 159  
 160          // Active users filtering.
 161          $manager = new course_enrolment_manager($PAGE, $this->course, null, 0, '', 0, ENROL_USER_ACTIVE);
 162          $totalusers = $manager->get_total_users();
 163          $this->assertEquals(5, $totalusers, 'Only active users must be returned when active users filtering is applied.');
 164  
 165          // Suspended users filtering.
 166          $manager = new course_enrolment_manager($PAGE, $this->course, null, 0, '', 0, ENROL_USER_SUSPENDED);
 167          $totalusers = $manager->get_total_users();
 168          $this->assertEquals(1, $totalusers, 'Only suspended users must be returned when suspended users filtering is applied.');
 169      }
 170  
 171      /**
 172       * Verify get_users() returned number of users expected in every situation.
 173       */
 174      public function test_get_users() {
 175          global $PAGE;
 176  
 177          $this->resetAfterTest();
 178  
 179          // All users filtering.
 180          $manager = new course_enrolment_manager($PAGE, $this->course);
 181          $users = $manager->get_users('id');
 182          $this->assertCount(6, $users,  'All users must be returned when no filtering is applied.');
 183          $this->assertArrayHasKey($this->users['user0']->id, $users);
 184          $this->assertArrayHasKey($this->users['user1']->id, $users);
 185          $this->assertArrayHasKey($this->users['user21']->id, $users);
 186          $this->assertArrayHasKey($this->users['user22']->id, $users);
 187          $this->assertArrayHasKey($this->users['userall']->id, $users);
 188          $this->assertArrayHasKey($this->users['usertch']->id, $users);
 189  
 190          // Student role filtering.
 191          $manager = new course_enrolment_manager($PAGE, $this->course, null, 5);
 192          $users = $manager->get_users('id');
 193          $this->assertCount(5, $users, 'Only students must be returned when student role filtering is applied.');
 194          $this->assertArrayHasKey($this->users['user0']->id, $users);
 195          $this->assertArrayHasKey($this->users['user1']->id, $users);
 196          $this->assertArrayHasKey($this->users['user21']->id, $users);
 197          $this->assertArrayHasKey($this->users['user22']->id, $users);
 198          $this->assertArrayHasKey($this->users['userall']->id, $users);
 199  
 200          // Teacher role filtering.
 201          $manager = new course_enrolment_manager($PAGE, $this->course, null, 3);
 202          $users = $manager->get_users('id');
 203          $this->assertCount(1, $users, 'Only teacher must be returned when teacher role filtering is applied.');
 204          $this->assertArrayHasKey($this->users['usertch']->id, $users);
 205  
 206          // Search user filtering.
 207          $manager = new course_enrolment_manager($PAGE, $this->course, null, 0, 'userall');
 208          $users = $manager->get_users('id');
 209          $this->assertCount(1, $users, 'Only searchable user must be returned when search filtering is applied.');
 210          $this->assertArrayHasKey($this->users['userall']->id, $users);
 211  
 212          // Group 1 filtering.
 213          $manager = new course_enrolment_manager($PAGE, $this->course, null, 0, '', $this->groups['group1']->id);
 214          $users = $manager->get_users('id');
 215          $this->assertCount(2, $users, 'Only group members must be returned when group filtering is applied.');
 216          $this->assertArrayHasKey($this->users['user1']->id, $users);
 217          $this->assertArrayHasKey($this->users['userall']->id, $users);
 218  
 219          // Group 2 filtering.
 220          $manager = new course_enrolment_manager($PAGE, $this->course, null, 0, '', $this->groups['group2']->id);
 221          $users = $manager->get_users('id');
 222          $this->assertCount(3, $users, 'Only group members must be returned when group filtering is applied.');
 223          $this->assertArrayHasKey($this->users['user21']->id, $users);
 224          $this->assertArrayHasKey($this->users['user22']->id, $users);
 225          $this->assertArrayHasKey($this->users['userall']->id, $users);
 226  
 227          // 'No groups' filtering.
 228          $manager = new course_enrolment_manager($PAGE, $this->course, null, 0, '', -1);
 229          $users = $manager->get_users('id');
 230          $this->assertCount(2, $users, 'Only non-group members must be returned when \'no groups\' filtering is applied.');
 231          $this->assertArrayHasKey($this->users['user0']->id, $users);
 232          $this->assertArrayHasKey($this->users['usertch']->id, $users);
 233  
 234          // Active users filtering.
 235          $manager = new course_enrolment_manager($PAGE, $this->course, null, 0, '', 0, ENROL_USER_ACTIVE);
 236          $users = $manager->get_users('id');
 237          $this->assertCount(5, $users, 'Only active users must be returned when active users filtering is applied.');
 238          $this->assertArrayHasKey($this->users['user0']->id, $users);
 239          $this->assertArrayHasKey($this->users['user1']->id, $users);
 240          $this->assertArrayHasKey($this->users['user21']->id, $users);
 241          $this->assertArrayHasKey($this->users['userall']->id, $users);
 242          $this->assertArrayHasKey($this->users['usertch']->id, $users);
 243  
 244          // Suspended users filtering.
 245          $manager = new course_enrolment_manager($PAGE, $this->course, null, 0, '', 0, ENROL_USER_SUSPENDED);
 246          $users = $manager->get_users('id');
 247          $this->assertCount(1, $users, 'Only suspended users must be returned when suspended users filtering is applied.');
 248          $this->assertArrayHasKey($this->users['user22']->id, $users);
 249      }
 250  
 251      /**
 252       * Sets up a custom profile field and the showuseridentity option, and creates a test user
 253       * with suitable values set.
 254       *
 255       * @return stdClass Test user
 256       */
 257      protected function setup_for_user_identity_tests(): \stdClass {
 258          // Configure extra fields to include one normal user field and one profile field, and
 259          // set the values for a new test user.
 260          $generator = $this->getDataGenerator();
 261          $generator->create_custom_profile_field(['datatype' => 'text',
 262                  'shortname' => 'researchtopic', 'name' => 'Research topic']);
 263          set_config('showuseridentity', 'email,department,profile_field_researchtopic');
 264          return $generator->create_user(
 265                  ['username' => 'newuser', 'department' => 'Amphibian studies', 'email' => 'x@x.org',
 266                          'profile_field_researchtopic' => 'Frogs', 'imagealt' => 'Smart suit']);
 267      }
 268  
 269      /**
 270       * Checks that the get_users function returns the correct user fields.
 271       */
 272      public function test_get_users_fields() {
 273          global $PAGE;
 274  
 275          $this->resetAfterTest();
 276          $newuser = $this->setup_for_user_identity_tests();
 277  
 278          // Enrol the user in test course.
 279          $this->getDataGenerator()->enrol_user($newuser->id, $this->course->id, 'student');
 280  
 281          // Get all users and fish out the one we're interested in.
 282          $manager = new course_enrolment_manager($PAGE, $this->course);
 283          $users = $manager->get_users('id');
 284          $user = $users[$newuser->id];
 285  
 286          // Should include core required fields...
 287          $this->assertEquals($newuser->id, $user->id);
 288  
 289          // ...And the ones specified in showuseridentity (one of which is also needed for user pics).
 290          $this->assertEquals('Amphibian studies', $user->department);
 291          $this->assertEquals('Frogs', $user->profile_field_researchtopic);
 292          $this->assertEquals('x@x.org', $user->email);
 293  
 294          // And the ones necessary for user pics.
 295          $this->assertEquals('Smart suit', $user->imagealt);
 296  
 297          // But not some random other field like city.
 298          $this->assertObjectNotHasAttribute('city', $user);
 299      }
 300  
 301      /**
 302       * Checks that the get_other_users function returns the correct user fields.
 303       */
 304      public function test_get_other_users_fields() {
 305          global $PAGE, $DB;
 306  
 307          $this->resetAfterTest();
 308  
 309          // Configure extra fields to include one normal user field and one profile field, and
 310          // set the values for a new test user.
 311          $newuser = $this->setup_for_user_identity_tests();
 312          $context = \context_course::instance($this->course->id);
 313          role_assign($DB->get_field('role', 'id', ['shortname' => 'manager']), $newuser->id, $context->id);
 314  
 315          // Get the 'other' (role but not enrolled) users and fish out the one we're interested in.
 316          $manager = new course_enrolment_manager($PAGE, $this->course);
 317          $users = array_values($manager->get_other_users('id'));
 318          $user = $users[0];
 319  
 320          // Should include core required fields...
 321          $this->assertEquals($newuser->id, $user->id);
 322  
 323          // ...And the ones specified in showuseridentity (one of which is also needed for user pics).
 324          $this->assertEquals('Amphibian studies', $user->department);
 325          $this->assertEquals('Frogs', $user->profile_field_researchtopic);
 326          $this->assertEquals('x@x.org', $user->email);
 327  
 328          // And the ones necessary for user pics.
 329          $this->assertEquals('Smart suit', $user->imagealt);
 330  
 331          // But not some random other field like city.
 332          $this->assertObjectNotHasAttribute('city', $user);
 333      }
 334  
 335      /**
 336       * Checks that the get_potential_users function returns the correct user fields.
 337       */
 338      public function test_get_potential_users_fields() {
 339          global $PAGE;
 340  
 341          $this->resetAfterTest();
 342  
 343          // Configure extra fields to include one normal user field and one profile field, and
 344          // set the values for a new test user.
 345          $newuser = $this->setup_for_user_identity_tests();
 346  
 347          // Get the 'potential' (not enrolled) users and fish out the one we're interested in.
 348          $manager = new course_enrolment_manager($PAGE, $this->course);
 349          foreach (enrol_get_instances($this->course->id, true) as $enrolinstance) {
 350              if ($enrolinstance->enrol === 'manual') {
 351                  $enrolid = $enrolinstance->id;
 352              }
 353          }
 354          $users = array_values($manager->get_potential_users($enrolid));
 355          $user = $users[0][$newuser->id];
 356  
 357          // Should include core required fields...
 358          $this->assertEquals($newuser->id, $user->id);
 359  
 360          // ...And the ones specified in showuseridentity (one of which is also needed for user pics).
 361          $this->assertEquals('Amphibian studies', $user->department);
 362          $this->assertEquals('Frogs', $user->profile_field_researchtopic);
 363          $this->assertEquals('x@x.org', $user->email);
 364  
 365          // And the ones necessary for user pics.
 366          $this->assertEquals('Smart suit', $user->imagealt);
 367  
 368          // But not some random other field like city.
 369          $this->assertObjectNotHasAttribute('city', $user);
 370      }
 371  
 372      /**
 373       * Test get_potential_users without returnexactcount param.
 374       *
 375       * @dataProvider search_users_provider
 376       *
 377       * @param int $perpage Number of users per page.
 378       * @param bool $returnexactcount Return the exact count or not.
 379       * @param int $expectedusers Expected number of users return.
 380       * @param int $expectedtotalusers Expected total of users in database.
 381       * @param bool $expectedmoreusers Expected for more users return or not.
 382       */
 383      public function test_get_potential_users($perpage, $returnexactcount, $expectedusers, $expectedtotalusers, $expectedmoreusers) {
 384          global $DB, $PAGE;
 385          $this->resetAfterTest();
 386          $this->setAdminUser();
 387  
 388          $enrol = $DB->get_record('enrol', array('courseid' => $this->course->id, 'enrol' => 'manual'));
 389          $manager = new course_enrolment_manager($PAGE, $this->course);
 390          $users = $manager->get_potential_users($enrol->id,
 391                  'testapiuser',
 392                  true,
 393                  0,
 394                  $perpage,
 395                  0,
 396                  $returnexactcount);
 397  
 398          $this->assertCount($expectedusers, $users['users']);
 399          $this->assertEquals($expectedmoreusers, $users['moreusers']);
 400          if ($returnexactcount) {
 401              $this->assertArrayHasKey('totalusers', $users);
 402              $this->assertEquals($expectedtotalusers, $users['totalusers']);
 403          } else {
 404              $this->assertArrayNotHasKey('totalusers', $users);
 405          }
 406      }
 407  
 408      /**
 409       * Tests get_potential_users when the search term includes a custom field.
 410       */
 411      public function test_get_potential_users_search_fields() {
 412          global $PAGE;
 413  
 414          $this->resetAfterTest();
 415  
 416          // Configure extra fields to include one normal user field and one profile field, and
 417          // set the values for a new test user.
 418          $newuser = $this->setup_for_user_identity_tests();
 419  
 420          // Set up the enrolment manager.
 421          $manager = new course_enrolment_manager($PAGE, $this->course);
 422          foreach (enrol_get_instances($this->course->id, true) as $enrolinstance) {
 423              if ($enrolinstance->enrol === 'manual') {
 424                  $enrolid = $enrolinstance->id;
 425              }
 426          }
 427  
 428          // Search for text included in a 'standard' (user table) identity field.
 429          $users = array_values($manager->get_potential_users($enrolid, 'Amphibian studies'));
 430          $this->assertEquals([$newuser->id], array_keys($users[0]));
 431  
 432          // And for text included in a custom field.
 433          $users = array_values($manager->get_potential_users($enrolid, 'Frogs'));
 434          $this->assertEquals([$newuser->id], array_keys($users[0]));
 435  
 436          // With partial matches.
 437          $users = array_values($manager->get_potential_users($enrolid, 'Amphibian'));
 438          $this->assertEquals([$newuser->id], array_keys($users[0]));
 439          $users = array_values($manager->get_potential_users($enrolid, 'Fro'));
 440          $this->assertEquals([$newuser->id], array_keys($users[0]));
 441  
 442          // With partial in-the-middle matches.
 443          $users = array_values($manager->get_potential_users($enrolid, 'phibian'));
 444          $this->assertEquals([], array_keys($users[0]));
 445          $users = array_values($manager->get_potential_users($enrolid, 'rog'));
 446          $this->assertEquals([], array_keys($users[0]));
 447          $users = array_values($manager->get_potential_users($enrolid, 'phibian', true));
 448          $this->assertEquals([$newuser->id], array_keys($users[0]));
 449          $users = array_values($manager->get_potential_users($enrolid, 'rog', true));
 450          $this->assertEquals([$newuser->id], array_keys($users[0]));
 451  
 452          // If the current user doesn't have access to identity fields then these searches won't work.
 453          $this->setUser($this->getDataGenerator()->create_user());
 454          $users = array_values($manager->get_potential_users($enrolid, 'Amphibian studies'));
 455          $this->assertEquals([], array_keys($users[0]));
 456          $users = array_values($manager->get_potential_users($enrolid, 'Frogs'));
 457          $this->assertEquals([], array_keys($users[0]));
 458  
 459          // Search for username field (there is special handling for this one field).
 460          set_config('showuseridentity', 'username');
 461          $this->setAdminUser();
 462          $users = array_values($manager->get_potential_users($enrolid, 'newuse'));
 463          $this->assertEquals([$newuser->id], array_keys($users[0]));
 464      }
 465  
 466      /**
 467       * Test search_other_users with returnexactcount param.
 468       *
 469       * @dataProvider search_users_provider
 470       *
 471       * @param int $perpage Number of users per page.
 472       * @param bool $returnexactcount Return the exact count or not.
 473       * @param int $expectedusers Expected number of users return.
 474       * @param int $expectedtotalusers Expected total of users in database.
 475       * @param bool $expectedmoreusers Expected for more users return or not.
 476       */
 477      public function test_search_other_users($perpage, $returnexactcount, $expectedusers, $expectedtotalusers, $expectedmoreusers) {
 478          global $PAGE;
 479          $this->resetAfterTest();
 480          $this->setAdminUser();
 481  
 482          $manager = new course_enrolment_manager($PAGE, $this->course);
 483          $users = $manager->search_other_users(
 484                  'testapiuser',
 485                  true,
 486                  0,
 487                  $perpage,
 488                  $returnexactcount);
 489  
 490          $this->assertCount($expectedusers, $users['users']);
 491          $this->assertEquals($expectedmoreusers, $users['moreusers']);
 492          if ($returnexactcount) {
 493              $this->assertArrayHasKey('totalusers', $users);
 494              $this->assertEquals($expectedtotalusers, $users['totalusers']);
 495          } else {
 496              $this->assertArrayNotHasKey('totalusers', $users);
 497          }
 498      }
 499  
 500      /**
 501       * Test case for test_get_potential_users, test_search_other_users and test_search_users tests.
 502       *
 503       * @return array Dataset
 504       */
 505      public function search_users_provider() {
 506          return [
 507                  [2, false, 2, 3, true],
 508                  [5, false, 3, 3, false],
 509                  [2, true, 2, 3, true],
 510                  [5, true, 3, 3, false]
 511          ];
 512      }
 513  
 514      /**
 515       * Test search_users function.
 516       *
 517       * @dataProvider search_users_provider
 518       *
 519       * @param int $perpage Number of users per page.
 520       * @param bool $returnexactcount Return the exact count or not.
 521       * @param int $expectedusers Expected number of users return.
 522       * @param int $expectedtotalusers Expected total of users in database.
 523       * @param bool $expectedmoreusers Expected for more users return or not.
 524       */
 525      public function test_search_users($perpage, $returnexactcount, $expectedusers, $expectedtotalusers, $expectedmoreusers) {
 526          global $PAGE;
 527          $this->resetAfterTest();
 528  
 529          $this->getDataGenerator()->create_and_enrol($this->course, 'student', ['firstname' => 'sutest 1']);
 530          $this->getDataGenerator()->create_and_enrol($this->course, 'student', ['firstname' => 'sutest 2']);
 531          $this->getDataGenerator()->create_and_enrol($this->course, 'student', ['firstname' => 'sutest 3']);
 532  
 533          $manager = new course_enrolment_manager($PAGE, $this->course);
 534          $users = $manager->search_users(
 535              'sutest',
 536              true,
 537              0,
 538              $perpage,
 539              $returnexactcount
 540          );
 541  
 542          $this->assertCount($expectedusers, $users['users']);
 543          $this->assertEquals($expectedmoreusers, $users['moreusers']);
 544          if ($returnexactcount) {
 545              $this->assertArrayHasKey('totalusers', $users);
 546              $this->assertEquals($expectedtotalusers, $users['totalusers']);
 547          } else {
 548              $this->assertArrayNotHasKey('totalusers', $users);
 549          }
 550      }
 551  
 552      /**
 553       * Test that search_users observes course group mode restrictions correctly
 554       */
 555      public function test_search_users_course_groupmode(): void {
 556          global $DB, $PAGE;
 557  
 558          $this->resetAfterTest();
 559  
 560          $teacher = $this->getDataGenerator()->create_and_enrol($this->course, 'teacher');
 561          $this->getDataGenerator()->create_group_member(['groupid' => $this->groups['group1']->id, 'userid' => $teacher->id]);
 562          $this->setUser($teacher);
 563  
 564          $users = (new course_enrolment_manager($PAGE, $this->course))->search_users('', false, 0, 25, true);
 565          $this->assertEqualsCanonicalizing([
 566              $teacher->username,
 567              $this->users['user0']->username,
 568              $this->users['user1']->username,
 569              $this->users['user21']->username,
 570              $this->users['user22']->username,
 571              $this->users['userall']->username,
 572              $this->users['usertch']->username,
 573          ], array_column($users['users'], 'username'));
 574          $this->assertEquals(7, $users['totalusers']);
 575  
 576          // Switch course to separate groups.
 577          $this->course->groupmode = SEPARATEGROUPS;
 578          update_course($this->course);
 579  
 580          $users = (new course_enrolment_manager($PAGE, $this->course))->search_users('', false, 0, 25, true);
 581          $this->assertEqualsCanonicalizing([
 582              $teacher->username,
 583              $this->users['user1']->username,
 584              $this->users['userall']->username,
 585          ], array_column($users['users'], 'username'));
 586          $this->assertEquals(3, $users['totalusers']);
 587  
 588          // Allow teacher to access all groups.
 589          $roleid = $DB->get_field('role', 'id', ['shortname' => 'teacher']);
 590          assign_capability('moodle/site:accessallgroups', CAP_ALLOW, $roleid, context_course::instance($this->course->id)->id);
 591  
 592          $users = (new course_enrolment_manager($PAGE, $this->course))->search_users('', false, 0, 25, true);
 593          $this->assertEqualsCanonicalizing([
 594              $teacher->username,
 595              $this->users['user0']->username,
 596              $this->users['user1']->username,
 597              $this->users['user21']->username,
 598              $this->users['user22']->username,
 599              $this->users['userall']->username,
 600              $this->users['usertch']->username,
 601          ], array_column($users['users'], 'username'));
 602          $this->assertEquals(7, $users['totalusers']);
 603      }
 604  }