Search moodle.org's
Developer Documentation

See Release Notes

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

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

   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;
  18  
  19  use core_group\visibility;
  20  
  21  /**
  22   * Unit tests for lib/grouplib.php
  23   *
  24   * @package    core
  25   * @copyright  2007 onwards Martin Dougiamas (http://dougiamas.com)
  26   * @author     Andrew Nicols
  27   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  28   */
  29  class grouplib_test extends \advanced_testcase {
  30  
  31      public function test_groups_get_group_by_idnumber() {
  32          $this->resetAfterTest(true);
  33  
  34          $generator = $this->getDataGenerator();
  35  
  36          // Create a course category and course.
  37          $cat = $generator->create_category(array('parent' => 0));
  38          $course = $generator->create_course(array('category' => $cat->id));
  39  
  40          $idnumber1 = 'idnumber1';
  41          $idnumber2 = 'idnumber2';
  42  
  43          /*
  44           * Test with an empty and a null idnumber.
  45           */
  46          // An empty idnumber should always return a false value.
  47          $this->assertFalse(groups_get_group_by_idnumber($course->id, ''));
  48          $this->assertFalse(groups_get_group_by_idnumber($course->id, null));
  49  
  50          // Even when a group exists which also has an empty idnumber.
  51          $generator->create_group(array('courseid' => $course->id));
  52          $this->assertFalse(groups_get_group_by_idnumber($course->id, ''));
  53          $this->assertFalse(groups_get_group_by_idnumber($course->id, null));
  54  
  55          /*
  56           * Test with a valid idnumber.
  57           */
  58          // There is no matching idnumber at present.
  59          $this->assertFalse(groups_get_group_by_idnumber($course->id, $idnumber1));
  60  
  61          // We should now have a valid group returned by the idnumber search.
  62          $group = $generator->create_group(array('courseid' => $course->id, 'idnumber' => $idnumber1));
  63          $this->assertEquals($group, groups_get_group_by_idnumber($course->id, $idnumber1));
  64  
  65          // An empty idnumber should still return false.
  66          $this->assertFalse(groups_get_group_by_idnumber($course->id, ''));
  67          $this->assertFalse(groups_get_group_by_idnumber($course->id, null));
  68  
  69          /*
  70           * Test with another idnumber.
  71           */
  72          // There is no matching idnumber at present.
  73          $this->assertFalse(groups_get_group_by_idnumber($course->id, $idnumber2));
  74  
  75          // We should now have a valid group returned by the idnumber search.
  76          $group = $generator->create_group(array('courseid' => $course->id, 'idnumber' => $idnumber2));
  77          $this->assertEquals($group, groups_get_group_by_idnumber($course->id, $idnumber2));
  78  
  79          /*
  80           * Group idnumbers are unique within a course so test that we don't
  81           * retrieve groups for the first course.
  82           */
  83  
  84          // Create a second course.
  85          $course = $generator->create_course(array('category' => $cat->id));
  86  
  87          // An empty idnumber should always return a false value.
  88          $this->assertFalse(groups_get_group_by_idnumber($course->id, ''));
  89          $this->assertFalse(groups_get_group_by_idnumber($course->id, null));
  90  
  91          // Our existing idnumbers shouldn't be returned here as we're in a different course.
  92          $this->assertFalse(groups_get_group_by_idnumber($course->id, $idnumber1));
  93          $this->assertFalse(groups_get_group_by_idnumber($course->id, $idnumber2));
  94  
  95          // We should be able to reuse the idnumbers again since this is a different course.
  96          $group = $generator->create_group(array('courseid' => $course->id, 'idnumber' => $idnumber1));
  97          $this->assertEquals($group, groups_get_group_by_idnumber($course->id, $idnumber1));
  98  
  99          $group = $generator->create_group(array('courseid' => $course->id, 'idnumber' => $idnumber2));
 100          $this->assertEquals($group, groups_get_group_by_idnumber($course->id, $idnumber2));
 101      }
 102  
 103      public function test_groups_get_grouping_by_idnumber() {
 104          $this->resetAfterTest(true);
 105  
 106          $generator = $this->getDataGenerator();
 107  
 108          // Create a course category and course.
 109          $cat = $generator->create_category(array('parent' => 0));
 110          $course = $generator->create_course(array('category' => $cat->id));
 111  
 112          $idnumber1 = 'idnumber1';
 113          $idnumber2 = 'idnumber2';
 114  
 115          /*
 116           * Test with an empty and a null idnumber.
 117           */
 118          // An empty idnumber should always return a false value.
 119          $this->assertFalse(groups_get_grouping_by_idnumber($course->id, ''));
 120          $this->assertFalse(groups_get_grouping_by_idnumber($course->id, null));
 121  
 122          // Even when a grouping exists which also has an empty idnumber.
 123          $generator->create_grouping(array('courseid' => $course->id));
 124          $this->assertFalse(groups_get_grouping_by_idnumber($course->id, ''));
 125          $this->assertFalse(groups_get_grouping_by_idnumber($course->id, null));
 126  
 127          /*
 128           * Test with a valid idnumber
 129           */
 130          // There is no matching idnumber at present.
 131          $this->assertFalse(groups_get_grouping_by_idnumber($course->id, $idnumber1));
 132  
 133          // We should now have a valid group returned by the idnumber search.
 134          $grouping = $generator->create_grouping(array('courseid' => $course->id, 'idnumber' => $idnumber1));
 135          $this->assertEquals($grouping, groups_get_grouping_by_idnumber($course->id, $idnumber1));
 136  
 137          // An empty idnumber should still return false.
 138          $this->assertFalse(groups_get_grouping_by_idnumber($course->id, ''));
 139          $this->assertFalse(groups_get_grouping_by_idnumber($course->id, null));
 140  
 141          /*
 142           * Test with another idnumber.
 143           */
 144          // There is no matching idnumber at present.
 145          $this->assertFalse(groups_get_grouping_by_idnumber($course->id, $idnumber2));
 146  
 147          // We should now have a valid grouping returned by the idnumber search.
 148          $grouping = $generator->create_grouping(array('courseid' => $course->id, 'idnumber' => $idnumber2));
 149          $this->assertEquals($grouping, groups_get_grouping_by_idnumber($course->id, $idnumber2));
 150  
 151          /*
 152           * Grouping idnumbers are unique within a course so test that we don't
 153           * retrieve groupings for the first course.
 154           */
 155  
 156          // Create a second course.
 157          $course = $generator->create_course(array('category' => $cat->id));
 158  
 159          // An empty idnumber should always return a false value.
 160          $this->assertFalse(groups_get_grouping_by_idnumber($course->id, ''));
 161          $this->assertFalse(groups_get_grouping_by_idnumber($course->id, null));
 162  
 163          // Our existing idnumbers shouldn't be returned here as we're in a different course.
 164          $this->assertFalse(groups_get_grouping_by_idnumber($course->id, $idnumber1));
 165          $this->assertFalse(groups_get_grouping_by_idnumber($course->id, $idnumber2));
 166  
 167          // We should be able to reuse the idnumbers again since this is a different course.
 168          $grouping = $generator->create_grouping(array('courseid' => $course->id, 'idnumber' => $idnumber1));
 169          $this->assertEquals($grouping, groups_get_grouping_by_idnumber($course->id, $idnumber1));
 170  
 171          $grouping = $generator->create_grouping(array('courseid' => $course->id, 'idnumber' => $idnumber2));
 172          $this->assertEquals($grouping, groups_get_grouping_by_idnumber($course->id, $idnumber2));
 173      }
 174  
 175      public function test_groups_get_members_ids_sql() {
 176          global $DB;
 177  
 178          $this->resetAfterTest(true);
 179  
 180          $generator = $this->getDataGenerator();
 181  
 182          $course = $generator->create_course();
 183          $coursecontext = \context_course::instance($course->id);
 184          $student1 = $generator->create_user();
 185          $student2 = $generator->create_user();
 186          $plugin = enrol_get_plugin('manual');
 187          $role = $DB->get_record('role', array('shortname' => 'student'));
 188          $group = $generator->create_group(array('courseid' => $course->id));
 189          $instance = $DB->get_record('enrol', array(
 190                  'courseid' => $course->id,
 191                  'enrol' => 'manual',
 192          ));
 193  
 194          $this->assertNotEquals($instance, false);
 195  
 196          // Enrol users in the course.
 197          $plugin->enrol_user($instance, $student1->id, $role->id);
 198          $plugin->enrol_user($instance, $student2->id, $role->id);
 199  
 200          list($sql, $params) = groups_get_members_ids_sql($group->id);
 201  
 202          // Test an empty group.
 203          $users = $DB->get_records_sql($sql, $params);
 204          $this->assertFalse(array_key_exists($student1->id, $users));
 205  
 206          // Test with a group member.
 207          groups_add_member($group->id, $student1->id);
 208          $users = $DB->get_records_sql($sql, $params);
 209          $this->assertTrue(array_key_exists($student1->id, $users));
 210      }
 211  
 212      public function test_groups_get_members_ids_sql_multiple_groups() {
 213          global $DB;
 214  
 215          $this->resetAfterTest(true);
 216  
 217          $generator = $this->getDataGenerator();
 218  
 219          $course = $generator->create_course();
 220          $student1 = $generator->create_user();
 221          $student2 = $generator->create_user();
 222          $plugin = enrol_get_plugin('manual');
 223          $role = $DB->get_record('role', array('shortname' => 'student'));
 224          $group1 = $generator->create_group(array('courseid' => $course->id));
 225          $group2 = $generator->create_group(array('courseid' => $course->id));
 226          $groupids = [
 227              $group1->id,
 228              $group2->id,
 229          ];
 230          $instance = $DB->get_record('enrol', array(
 231                  'courseid' => $course->id,
 232                  'enrol' => 'manual',
 233          ));
 234  
 235          $this->assertNotEquals($instance, false);
 236  
 237          // Enrol users in the course.
 238          $plugin->enrol_user($instance, $student1->id, $role->id);
 239          $plugin->enrol_user($instance, $student2->id, $role->id);
 240  
 241          list($sql, $params) = groups_get_members_ids_sql($groupids);
 242  
 243          // Test an empty group.
 244          $users = $DB->get_records_sql($sql, $params);
 245          $this->assertFalse(array_key_exists($student1->id, $users));
 246  
 247          // Test with a member of one of the two group.
 248          groups_add_member($group1->id, $student1->id);
 249          $users = $DB->get_records_sql($sql, $params);
 250          $this->assertTrue(array_key_exists($student1->id, $users));
 251  
 252          // Test with members of two groups.
 253          groups_add_member($group2->id, $student2->id);
 254          $users = $DB->get_records_sql($sql, $params);
 255          $this->assertTrue(array_key_exists($student1->id, $users));
 256          $this->assertTrue(array_key_exists($student2->id, $users));
 257      }
 258  
 259      public function test_groups_get_members_ids_sql_multiple_groups_join_types() {
 260          global $DB;
 261  
 262          $this->resetAfterTest(true);
 263  
 264          $generator = $this->getDataGenerator();
 265  
 266          $course = $generator->create_course();
 267          $student1 = $generator->create_user();
 268          $student2 = $generator->create_user();
 269          $student3 = $generator->create_user();
 270          $student4 = $generator->create_user();
 271          $student5 = $generator->create_user();
 272          $student6 = $generator->create_user();
 273          $plugin = enrol_get_plugin('manual');
 274          $role = $DB->get_record('role', array('shortname' => 'student'));
 275          $group1 = $generator->create_group(array('courseid' => $course->id));
 276          $group2 = $generator->create_group(array('courseid' => $course->id));
 277          $group3 = $generator->create_group(array('courseid' => $course->id));
 278          // Only groups 1 and 2 specified in SQL (group 3 helps cover the None case).
 279          $groupids = [
 280              $group1->id,
 281              $group2->id,
 282          ];
 283          $instance = $DB->get_record('enrol', array(
 284                  'courseid' => $course->id,
 285                  'enrol' => 'manual',
 286          ));
 287  
 288          $this->assertNotEquals($instance, false);
 289  
 290          // Enrol users in the course.
 291          $plugin->enrol_user($instance, $student1->id, $role->id);
 292          $plugin->enrol_user($instance, $student2->id, $role->id);
 293          $plugin->enrol_user($instance, $student3->id, $role->id);
 294          $plugin->enrol_user($instance, $student4->id, $role->id);
 295          $plugin->enrol_user($instance, $student5->id, $role->id);
 296          $plugin->enrol_user($instance, $student6->id, $role->id);
 297  
 298          // Generate SQL with the different groups join types for members of group1 and group2.
 299          list($sqlany, $paramsany) = groups_get_members_ids_sql($groupids, null, GROUPS_JOIN_ANY);
 300          list($sqlall, $paramsall) = groups_get_members_ids_sql($groupids, null, GROUPS_JOIN_ALL);
 301          list($sqlnone, $paramsnone) = groups_get_members_ids_sql($groupids, null, GROUPS_JOIN_NONE);
 302  
 303          // Any - Test empty groups, no matches.
 304          $users = $DB->get_records_sql($sqlany, $paramsany);
 305          $this->assertFalse(array_key_exists($student1->id, $users));
 306          $this->assertFalse(array_key_exists($student2->id, $users));
 307          $this->assertFalse(array_key_exists($student3->id, $users));
 308          $this->assertFalse(array_key_exists($student4->id, $users));
 309          $this->assertFalse(array_key_exists($student5->id, $users));
 310          $this->assertFalse(array_key_exists($student6->id, $users));
 311  
 312          // All - Test empty groups, no matches.
 313          $users = $DB->get_records_sql($sqlall, $paramsall);
 314          $this->assertFalse(array_key_exists($student1->id, $users));
 315          $this->assertFalse(array_key_exists($student2->id, $users));
 316          $this->assertFalse(array_key_exists($student3->id, $users));
 317          $this->assertFalse(array_key_exists($student4->id, $users));
 318          $this->assertFalse(array_key_exists($student5->id, $users));
 319          $this->assertFalse(array_key_exists($student6->id, $users));
 320  
 321          // None - Test empty groups, all match.
 322          $users = $DB->get_records_sql($sqlnone, $paramsnone);
 323          $this->assertTrue(array_key_exists($student1->id, $users));
 324          $this->assertTrue(array_key_exists($student2->id, $users));
 325          $this->assertTrue(array_key_exists($student3->id, $users));
 326          $this->assertTrue(array_key_exists($student4->id, $users));
 327          $this->assertTrue(array_key_exists($student5->id, $users));
 328          $this->assertTrue(array_key_exists($student6->id, $users));
 329  
 330          // Assign various group member combinations.
 331          groups_add_member($group1->id, $student1->id);
 332          groups_add_member($group1->id, $student2->id);
 333          groups_add_member($group1->id, $student3->id);
 334          groups_add_member($group2->id, $student2->id);
 335          groups_add_member($group2->id, $student3->id);
 336          groups_add_member($group2->id, $student4->id);
 337          groups_add_member($group3->id, $student5->id);
 338  
 339          // Any - Test students in one or both of groups 1 and 2 matched.
 340          $users = $DB->get_records_sql($sqlany, $paramsany);
 341          $this->assertTrue(array_key_exists($student1->id, $users));
 342          $this->assertTrue(array_key_exists($student2->id, $users));
 343          $this->assertTrue(array_key_exists($student3->id, $users));
 344          $this->assertTrue(array_key_exists($student4->id, $users));
 345          $this->assertFalse(array_key_exists($student5->id, $users));
 346          $this->assertFalse(array_key_exists($student6->id, $users));
 347  
 348          // All - Test only students in both groups 1 and 2 matched.
 349          $users = $DB->get_records_sql($sqlall, $paramsall);
 350          $this->assertTrue(array_key_exists($student2->id, $users));
 351          $this->assertTrue(array_key_exists($student3->id, $users));
 352          $this->assertFalse(array_key_exists($student1->id, $users));
 353          $this->assertFalse(array_key_exists($student4->id, $users));
 354          $this->assertFalse(array_key_exists($student5->id, $users));
 355          $this->assertFalse(array_key_exists($student6->id, $users));
 356  
 357          // None - Test only students not in group 1 or 2 matched.
 358          $users = $DB->get_records_sql($sqlnone, $paramsnone);
 359          $this->assertTrue(array_key_exists($student5->id, $users));
 360          $this->assertTrue(array_key_exists($student6->id, $users));
 361          $this->assertFalse(array_key_exists($student1->id, $users));
 362          $this->assertFalse(array_key_exists($student2->id, $users));
 363          $this->assertFalse(array_key_exists($student3->id, $users));
 364          $this->assertFalse(array_key_exists($student4->id, $users));
 365      }
 366  
 367      public function test_groups_get_members_ids_sql_valid_context() {
 368          global $DB;
 369  
 370          $this->resetAfterTest(true);
 371  
 372          $generator = $this->getDataGenerator();
 373  
 374          $course = $generator->create_course();
 375          $coursecontext = \context_course::instance($course->id);
 376          $student1 = $generator->create_user();
 377          $student2 = $generator->create_user();
 378          $plugin = enrol_get_plugin('manual');
 379          $role = $DB->get_record('role', array('shortname' => 'student'));
 380          $group = $generator->create_group(array('courseid' => $course->id));
 381          $instance = $DB->get_record('enrol', array(
 382                  'courseid' => $course->id,
 383                  'enrol' => 'manual',
 384          ));
 385  
 386          $this->assertNotEquals($instance, false);
 387  
 388          // Enrol users in the course.
 389          $plugin->enrol_user($instance, $student1->id, $role->id);
 390          $plugin->enrol_user($instance, $student2->id, $role->id);
 391  
 392          // Add student1 to the group.
 393          groups_add_member($group->id, $student1->id);
 394  
 395          // Test with members at any group and with a valid $context.
 396          list($sql, $params) = groups_get_members_ids_sql(USERSWITHOUTGROUP, $coursecontext);
 397          $users = $DB->get_records_sql($sql, $params);
 398          $this->assertFalse(array_key_exists($student1->id, $users));
 399          $this->assertTrue(array_key_exists($student2->id, $users));
 400      }
 401  
 402      public function test_groups_get_members_ids_sql_empty_context() {
 403          global $DB;
 404  
 405          $this->resetAfterTest(true);
 406  
 407          $generator = $this->getDataGenerator();
 408  
 409          $course = $generator->create_course();
 410          $coursecontext = \context_course::instance($course->id);
 411          $student1 = $generator->create_user();
 412          $student2 = $generator->create_user();
 413          $plugin = enrol_get_plugin('manual');
 414          $role = $DB->get_record('role', array('shortname' => 'student'));
 415          $group = $generator->create_group(array('courseid' => $course->id));
 416          $instance = $DB->get_record('enrol', array(
 417                  'courseid' => $course->id,
 418                  'enrol' => 'manual',
 419          ));
 420  
 421          $this->assertNotEquals($instance, false);
 422  
 423          // Enrol users in the course.
 424          $plugin->enrol_user($instance, $student1->id, $role->id);
 425          $plugin->enrol_user($instance, $student2->id, $role->id);
 426  
 427          // Add student1 to the group.
 428          groups_add_member($group->id, $student1->id);
 429  
 430          // Test with members at any group and without the $context.
 431          $this->expectException('coding_exception');
 432          list($sql, $params) = groups_get_members_ids_sql(USERSWITHOUTGROUP);
 433      }
 434  
 435      public function test_groups_get_members_ids_sql_invalid_context() {
 436          global $DB;
 437  
 438          $this->resetAfterTest(true);
 439  
 440          $generator = $this->getDataGenerator();
 441  
 442          $course = $generator->create_course();
 443          $coursecontext = \context_course::instance($course->id);
 444          $student1 = $generator->create_user();
 445          $student2 = $generator->create_user();
 446          $plugin = enrol_get_plugin('manual');
 447          $role = $DB->get_record('role', array('shortname' => 'student'));
 448          $group = $generator->create_group(array('courseid' => $course->id));
 449          $instance = $DB->get_record('enrol', array(
 450                  'courseid' => $course->id,
 451                  'enrol' => 'manual',
 452          ));
 453  
 454          $this->assertNotEquals($instance, false);
 455  
 456          // Enrol users in the course.
 457          $plugin->enrol_user($instance, $student1->id, $role->id);
 458          $plugin->enrol_user($instance, $student2->id, $role->id);
 459  
 460          // Add student1 to the group.
 461          groups_add_member($group->id, $student1->id);
 462  
 463          // Test with members at any group and with an invalid $context.
 464          $syscontext = \context_system::instance();
 465          $this->expectException('coding_exception');
 466          list($sql, $params) = groups_get_members_ids_sql(USERSWITHOUTGROUP, $syscontext);
 467      }
 468  
 469      /**
 470       * Test retrieving users with concatenated group names from a course
 471       */
 472      public function test_groups_get_names_concat_sql(): void {
 473          global $DB;
 474  
 475          $this->resetAfterTest();
 476  
 477          // Create a course containing two groups.
 478          $course = $this->getDataGenerator()->create_course();
 479          $group1 = $this->getDataGenerator()->create_group(['courseid' => $course->id]);
 480          $group2 = $this->getDataGenerator()->create_group(['courseid' => $course->id]);
 481  
 482          // Create first user, add them to group 1 and group 2.
 483          $user1 = $this->getDataGenerator()->create_and_enrol($course, 'student');
 484          $this->getDataGenerator()->create_group_member(['userid' => $user1->id, 'groupid' => $group1->id]);
 485          $this->getDataGenerator()->create_group_member(['userid' => $user1->id, 'groupid' => $group2->id]);
 486  
 487          // Create second user, add them to group 1 only.
 488          $user2 = $this->getDataGenerator()->create_and_enrol($course, 'student');
 489          $this->getDataGenerator()->create_group_member(['userid' => $user2->id, 'groupid' => $group1->id]);
 490  
 491          // Call our method, and assertion.
 492          [$sql, $params] = groups_get_names_concat_sql($course->id);
 493          $records = $DB->get_records_sql($sql, $params);
 494  
 495          $this->assertEqualsCanonicalizing([
 496              (object) [
 497                  'userid' => $user1->id,
 498                  'groupnames' => "{$group1->name}, {$group2->name}",
 499              ],
 500              (object) [
 501                  'userid' => $user2->id,
 502                  'groupnames' => $group1->name,
 503              ],
 504          ], $records);
 505      }
 506  
 507      public function test_groups_get_group_by_name() {
 508          $this->resetAfterTest(true);
 509  
 510          $generator = $this->getDataGenerator();
 511  
 512          // Create a course category and course.
 513          $cat = $generator->create_category(array('parent' => 0));
 514          $course = $generator->create_course(array('category' => $cat->id));
 515  
 516          $name1 = 'Name 1';
 517          $name2 = 'Name 2';
 518  
 519          // Test with an empty and a null idnumber.
 520          $this->assertFalse(groups_get_group_by_name($course->id, ''));
 521          $this->assertFalse(groups_get_group_by_name($course->id, null));
 522  
 523          // Even when a group exists.
 524          $generator->create_group(array('courseid' => $course->id));
 525          $this->assertFalse(groups_get_group_by_name($course->id, ''));
 526          $this->assertFalse(groups_get_group_by_name($course->id, null));
 527  
 528          // Test with a valid name, but one that doesn't exist yet.
 529          $this->assertFalse(groups_get_group_by_name($course->id, $name1));
 530          $this->assertFalse(groups_get_group_by_name($course->id, $name2));
 531  
 532          // We should now have a valid group returned by the name search.
 533          $group1 = $generator->create_group(array('courseid' => $course->id, 'name' => $name1));
 534          $this->assertEquals($group1->id, groups_get_group_by_name($course->id, $name1));
 535          $this->assertFalse(groups_get_group_by_name($course->id, $name2));
 536  
 537          // We should now have a two valid groups returned by the name search.
 538          $group2 = $generator->create_group(array('courseid' => $course->id, 'name' => $name2));
 539          $this->assertEquals($group1->id, groups_get_group_by_name($course->id, $name1));
 540          $this->assertEquals($group2->id, groups_get_group_by_name($course->id, $name2));
 541  
 542          // Delete a group.
 543          $this->assertTrue(groups_delete_group($group1));
 544          $this->assertFalse(groups_get_group_by_name($course->id, $name1));
 545          $this->assertEquals($group2->id, groups_get_group_by_name($course->id, $name2));
 546  
 547          /*
 548           * Group idnumbers are unique within a course so test that we don't
 549           * retrieve groups for the first course.
 550           */
 551  
 552          // Create a second course.
 553          $course = $generator->create_course(array('category' => $cat->id));
 554  
 555          // An empty name should always return a false value.
 556          $this->assertFalse(groups_get_group_by_name($course->id, ''));
 557          $this->assertFalse(groups_get_group_by_name($course->id, null));
 558  
 559          // Our existing names shouldn't be returned here as we're in a different course.
 560          $this->assertFalse(groups_get_group_by_name($course->id, $name1));
 561          $this->assertFalse(groups_get_group_by_name($course->id, $name2));
 562  
 563          // We should be able to reuse the idnumbers again since this is a different course.
 564          $group1 = $generator->create_group(array('courseid' => $course->id, 'name' => $name1));
 565          $this->assertEquals($group1->id, groups_get_group_by_name($course->id, $name1));
 566  
 567          $group2 = $generator->create_group(array('courseid' => $course->id, 'name' => $name2));
 568          $this->assertEquals($group2->id, groups_get_group_by_name($course->id, $name2));
 569      }
 570  
 571      public function test_groups_get_grouping() {
 572          $this->resetAfterTest(true);
 573  
 574          $generator = $this->getDataGenerator();
 575  
 576          // Create a course category and course.
 577          $cat = $generator->create_category(array('parent' => 0));
 578          $course = $generator->create_course(array('category' => $cat->id));
 579  
 580          $name1 = 'Grouping 1';
 581          $name2 = 'Grouping 2';
 582  
 583          // Test with an empty and a null idnumber.
 584          $this->assertFalse(groups_get_grouping_by_name($course->id, ''));
 585          $this->assertFalse(groups_get_grouping_by_name($course->id, null));
 586  
 587          // Even when a group exists.
 588          $generator->create_group(array('courseid' => $course->id));
 589          $this->assertFalse(groups_get_grouping_by_name($course->id, ''));
 590          $this->assertFalse(groups_get_grouping_by_name($course->id, null));
 591  
 592          // Test with a valid name, but one that doesn't exist yet.
 593          $this->assertFalse(groups_get_grouping_by_name($course->id, $name1));
 594          $this->assertFalse(groups_get_grouping_by_name($course->id, $name2));
 595  
 596          // We should now have a valid group returned by the name search.
 597          $group1 = $generator->create_grouping(array('courseid' => $course->id, 'name' => $name1));
 598          $this->assertEquals($group1->id, groups_get_grouping_by_name($course->id, $name1));
 599          $this->assertFalse(groups_get_grouping_by_name($course->id, $name2));
 600  
 601          // We should now have a two valid groups returned by the name search.
 602          $group2 = $generator->create_grouping(array('courseid' => $course->id, 'name' => $name2));
 603          $this->assertEquals($group1->id, groups_get_grouping_by_name($course->id, $name1));
 604          $this->assertEquals($group2->id, groups_get_grouping_by_name($course->id, $name2));
 605  
 606          // Delete a group.
 607          $this->assertTrue(groups_delete_grouping($group1));
 608          $this->assertFalse(groups_get_grouping_by_name($course->id, $name1));
 609          $this->assertEquals($group2->id, groups_get_grouping_by_name($course->id, $name2));
 610  
 611          /*
 612           * Group idnumbers are unique within a course so test that we don't
 613           * retrieve groups for the first course.
 614           */
 615  
 616          // Create a second course.
 617          $course = $generator->create_course(array('category' => $cat->id));
 618  
 619          // An empty name should always return a false value.
 620          $this->assertFalse(groups_get_grouping_by_name($course->id, ''));
 621          $this->assertFalse(groups_get_grouping_by_name($course->id, null));
 622  
 623          // Our existing names shouldn't be returned here as we're in a different course.
 624          $this->assertFalse(groups_get_grouping_by_name($course->id, $name1));
 625          $this->assertFalse(groups_get_grouping_by_name($course->id, $name2));
 626  
 627          // We should be able to reuse the idnumbers again since this is a different course.
 628          $group1 = $generator->create_grouping(array('courseid' => $course->id, 'name' => $name1));
 629          $this->assertEquals($group1->id, groups_get_grouping_by_name($course->id, $name1));
 630  
 631          $group2 = $generator->create_grouping(array('courseid' => $course->id, 'name' => $name2));
 632          $this->assertEquals($group2->id, groups_get_grouping_by_name($course->id, $name2));
 633      }
 634  
 635      public function test_groups_get_course_data() {
 636          $this->resetAfterTest(true);
 637  
 638          $generator = $this->getDataGenerator();
 639  
 640          // Create a course category and course.
 641          $cat = $generator->create_category(array('parent' => 0));
 642          $course = $generator->create_course(array('category' => $cat->id));
 643          $grouping1 = $generator->create_grouping(array('courseid' => $course->id, 'name' => 'Grouping 1'));
 644          $grouping2 = $generator->create_grouping(array('courseid' => $course->id, 'name' => 'Grouping 2'));
 645          $group1 = $generator->create_group(array('courseid' => $course->id, 'name' => 'Group 1'));
 646          $group2 = $generator->create_group(array('courseid' => $course->id, 'name' => 'Group 2'));
 647          $group3 = $generator->create_group(array('courseid' => $course->id, 'name' => 'Group 3'));
 648          $group4 = $generator->create_group(array('courseid' => $course->id, 'name' => 'Group 4'));
 649  
 650          // Assign the groups to groupings.
 651          $this->assertTrue(groups_assign_grouping($grouping1->id, $group1->id));
 652          $this->assertTrue(groups_assign_grouping($grouping1->id, $group2->id));
 653          $this->assertTrue(groups_assign_grouping($grouping2->id, $group3->id));
 654          $this->assertTrue(groups_assign_grouping($grouping2->id, $group4->id));
 655  
 656          // Get the data.
 657          $data = groups_get_course_data($course->id);
 658          $this->assertInstanceOf('stdClass', $data);
 659          $this->assertObjectHasAttribute('groups', $data);
 660          $this->assertObjectHasAttribute('groupings', $data);
 661          $this->assertObjectHasAttribute('mappings', $data);
 662  
 663          // Test we have the expected items returns.
 664          $this->assertCount(4, $data->groups);
 665          $this->assertCount(2, $data->groupings);
 666          $this->assertCount(4, $data->mappings);
 667  
 668          // Check we have the expected groups.
 669          $this->assertArrayHasKey($group1->id, $data->groups);
 670          $this->assertArrayHasKey($group2->id, $data->groups);
 671          $this->assertArrayHasKey($group3->id, $data->groups);
 672          $this->assertArrayHasKey($group4->id, $data->groups);
 673  
 674          // Test a group-id is mapped correctly.
 675          $this->assertSame($group3->name, $data->groups[$group3->id]->name);
 676  
 677          // Check we have the expected number of groupings.
 678          $this->assertArrayHasKey($grouping1->id, $data->groupings);
 679          $this->assertArrayHasKey($grouping2->id, $data->groupings);
 680  
 681          // Test a grouping-id is mapped correctly.
 682          $this->assertEquals($grouping2->name, $data->groupings[$grouping2->id]->name);
 683  
 684          // Test that all of the mappings are correct.
 685          $grouping1maps = 0;
 686          $grouping2maps = 0;
 687          $group1maps = 0;
 688          $group2maps = 0;
 689          $group3maps = 0;
 690          $group4maps = 0;
 691          foreach ($data->mappings as $mapping) {
 692              if ($mapping->groupingid === $grouping1->id) {
 693                  $grouping1maps++;
 694                  $this->assertContainsEquals($mapping->groupid, array($group1->id, $group2->id));
 695              } else if ($mapping->groupingid === $grouping2->id) {
 696                  $grouping2maps++;
 697                  $this->assertContainsEquals($mapping->groupid, array($group3->id, $group4->id));
 698              } else {
 699                  $this->fail('Unexpected groupingid');
 700              }
 701              switch ($mapping->groupid) {
 702                  case $group1->id : $group1maps++; break;
 703                  case $group2->id : $group2maps++; break;
 704                  case $group3->id : $group3maps++; break;
 705                  case $group4->id : $group4maps++; break;
 706              }
 707          }
 708          $this->assertEquals(2, $grouping1maps);
 709          $this->assertEquals(2, $grouping2maps);
 710          $this->assertEquals(1, $group1maps);
 711          $this->assertEquals(1, $group2maps);
 712          $this->assertEquals(1, $group3maps);
 713          $this->assertEquals(1, $group4maps);
 714  
 715          // Test the groups_get_all_groups which uses this functionality.
 716          $groups  = groups_get_all_groups($course->id);
 717          $this->assertCount(4, $groups);
 718          $this->assertArrayHasKey($group1->id, $groups);
 719          $this->assertArrayHasKey($group2->id, $groups);
 720          $this->assertArrayHasKey($group3->id, $groups);
 721          $this->assertArrayHasKey($group4->id, $groups);
 722  
 723          $groups  = groups_get_all_groups($course->id, null, $grouping1->id);
 724          $this->assertCount(2, $groups);
 725          $this->assertArrayHasKey($group1->id, $groups);
 726          $this->assertArrayHasKey($group2->id, $groups);
 727          $this->assertArrayNotHasKey($group3->id, $groups);
 728          $this->assertArrayNotHasKey($group4->id, $groups);
 729  
 730          $groups  = groups_get_all_groups($course->id, null, $grouping2->id);
 731          $this->assertCount(2, $groups);
 732          $this->assertArrayNotHasKey($group1->id, $groups);
 733          $this->assertArrayNotHasKey($group2->id, $groups);
 734          $this->assertArrayHasKey($group3->id, $groups);
 735          $this->assertArrayHasKey($group4->id, $groups);
 736  
 737          // Test this function using an alternate column for the result index
 738          $groups  = groups_get_all_groups($course->id, null, $grouping2->id, 'g.name, g.id');
 739          $this->assertCount(2, $groups);
 740          $this->assertArrayNotHasKey($group3->id, $groups);
 741          $this->assertArrayHasKey($group3->name, $groups);
 742          $this->assertEquals($group3->id, $groups[$group3->name]->id);
 743      }
 744  
 745      /**
 746       * Tests for groups_group_visible.
 747       */
 748      public function test_groups_group_visible() {
 749          global $CFG, $DB;
 750  
 751          $generator = $this->getDataGenerator();
 752          $this->resetAfterTest();
 753          $this->setAdminUser();
 754  
 755          // Create a course category, course and groups.
 756          $cat = $generator->create_category(array('parent' => 0));
 757          $course = $generator->create_course(array('category' => $cat->id));
 758          $coursecontext = \context_course::instance($course->id);
 759          $group1 = $generator->create_group(array('courseid' => $course->id, 'name' => 'Group 1'));
 760          $group2 = $generator->create_group(array('courseid' => $course->id, 'name' => 'Group 2'));
 761          $group3 = $generator->create_group(array('courseid' => $course->id, 'name' => 'Group 3'));
 762          $group4 = $generator->create_group(array('courseid' => $course->id, 'name' => 'Group 4'));
 763  
 764          // Create cm.
 765          $assign = $generator->create_module("assign", array('course' => $course->id));
 766          $cm = get_coursemodule_from_instance("assign", $assign->id);
 767  
 768          // Create users.
 769          $user1 = $generator->create_user();
 770          $user2 = $generator->create_user();
 771          $user3 = $generator->create_user();
 772  
 773          // Enrol users into the course.
 774          $generator->enrol_user($user1->id, $course->id);
 775          $generator->enrol_user($user2->id, $course->id);
 776  
 777          // Assign groups.
 778          groups_add_member($group1, $user2);
 779  
 780          // Give capability at course level to the user to access all groups.
 781          $role = $DB->get_field("role", "id", array("shortname" => "manager"));
 782          $generator->enrol_user($user3->id, $course->id, $role);
 783          // Make sure the user has the capability.
 784          assign_capability('moodle/site:accessallgroups', CAP_ALLOW, $role, $coursecontext->id);
 785  
 786          // No groups , not forced.
 787          $result = groups_group_visible($group1->id, $course, null, $user1->id);
 788          $this->assertTrue($result);
 789          $result = groups_group_visible(0, $course, null, $user1->id);
 790          $this->assertTrue($result); // Requesting all groups.
 791  
 792          $result = groups_group_visible($group1->id, $course, $cm, $user1->id);
 793          $this->assertTrue($result); // Cm with no groups.
 794  
 795          $cm->groupmode = SEPARATEGROUPS;
 796          $result = groups_group_visible($group1->id, $course, $cm, $user1->id);
 797          $this->assertFalse($result); // Cm with separate groups.
 798          $result = groups_group_visible($group1->id, $course, $cm, $user2->id);
 799          $this->assertTrue($result); // Cm with separate groups.
 800  
 801          $cm->groupmode = VISIBLEGROUPS;
 802          $result = groups_group_visible($group1->id, $course, $cm, $user1->id);
 803          $this->assertTrue($result); // Cm with visible groups.
 804  
 805          // No groups, forced.
 806          $course->groupmode = NOGROUPS;
 807          $course->groupmodeforce = true;
 808          update_course($course);
 809          $result = groups_group_visible($group1->id, $course, null, $user1->id);
 810          $this->assertTrue($result);
 811          $result = groups_group_visible(0, $course, null, $user1->id);
 812          $this->assertTrue($result); // Requesting all groups.
 813  
 814          $result = groups_group_visible($group1->id, $course, $cm, $user1->id);
 815          $this->assertTrue($result); // Cm with no groups.
 816  
 817          $cm->groupmode = SEPARATEGROUPS;
 818          $result = groups_group_visible($group1->id, $course, $cm, $user1->id);
 819          $this->assertTrue($result); // Cm with separate groups.
 820          $result = groups_group_visible($group1->id, $course, $cm, $user2->id);
 821          $this->assertTrue($result); // Cm with separate groups.
 822  
 823          $cm->groupmode = SEPARATEGROUPS;
 824          $result = groups_group_visible($group1->id, $course, $cm, $user1->id);
 825          $this->assertTrue($result); // Cm with visible groups.
 826  
 827          // Visible groups, forced.
 828          $course->groupmode = VISIBLEGROUPS;
 829          $course->groupmodeforce = true;
 830          update_course($course);
 831          $result = groups_group_visible($group1->id, $course, null, $user1->id);
 832          $this->assertTrue($result);
 833          $result = groups_group_visible(0, $course, null, $user1->id);
 834          $this->assertTrue($result); // Requesting all groups.
 835  
 836          $cm->groupmode = NOGROUPS;
 837          $result = groups_group_visible($group1->id, $course, $cm, $user1->id);
 838          $this->assertTrue($result); // Cm with no groups.
 839  
 840          $cm->groupmode = SEPARATEGROUPS;
 841          $result = groups_group_visible($group1->id, $course, $cm, $user1->id);
 842          $this->assertTrue($result); // Cm with separate groups.
 843          $result = groups_group_visible($group1->id, $course, $cm, $user2->id);
 844          $this->assertTrue($result); // Cm with separate groups.
 845  
 846          $cm->groupmode = VISIBLEGROUPS;
 847          $result = groups_group_visible($group1->id, $course, $cm, $user1->id);
 848          $this->assertTrue($result); // Cm with visible groups.
 849  
 850          // Visible groups, not forced.
 851          $course->groupmode = VISIBLEGROUPS;
 852          $course->groupmodeforce = false;
 853          update_course($course);
 854          $result = groups_group_visible($group1->id, $course, null, $user1->id);
 855          $this->assertTrue($result);
 856          $result = groups_group_visible(0, $course, null, $user1->id);
 857          $this->assertTrue($result); // Requesting all groups.
 858  
 859          $cm->groupmode = NOGROUPS;
 860          $result = groups_group_visible($group1->id, $course, $cm, $user1->id);
 861          $this->assertTrue($result); // Cm with no groups.
 862  
 863          $cm->groupmode = SEPARATEGROUPS;
 864          $result = groups_group_visible($group1->id, $course, $cm, $user1->id);
 865          $this->assertFalse($result); // Cm with separate groups.
 866          $result = groups_group_visible($group1->id, $course, $cm, $user2->id);
 867          $this->assertTrue($result); // Cm with separate groups.
 868  
 869          $cm->groupmode = VISIBLEGROUPS;
 870          $result = groups_group_visible($group1->id, $course, $cm, $user1->id);
 871          $this->assertTrue($result); // Cm with visible groups.
 872  
 873          // Separate groups, forced.
 874          $course->groupmode = SEPARATEGROUPS;
 875          $course->groupmodeforce = true;
 876          update_course($course);
 877          $result = groups_group_visible($group1->id, $course, null, $user1->id);
 878          $this->assertFalse($result);
 879          $result = groups_group_visible($group1->id, $course, null, $user2->id);
 880          $this->assertTrue($result);
 881          $result = groups_group_visible(0, $course, null, $user2->id);
 882          $this->assertFalse($result); // Requesting all groups.
 883          $result = groups_group_visible(0, $course, null, $user3->id);
 884          $this->assertTrue($result); // Requesting all groups.
 885          $result = groups_group_visible($group1->id, $course, null, $user3->id);
 886          $this->assertTrue($result); // Make sure user with access to all groups can see any group.
 887  
 888          $cm->groupmode = NOGROUPS;
 889          $result = groups_group_visible($group1->id, $course, $cm, $user1->id);
 890          $this->assertFalse($result); // Cm with no groups.
 891  
 892          $cm->groupmode = SEPARATEGROUPS;
 893          $result = groups_group_visible($group1->id, $course, $cm, $user1->id);
 894          $this->assertFalse($result); // Cm with separate groups.
 895          $result = groups_group_visible($group1->id, $course, $cm, $user2->id);
 896          $this->assertTrue($result); // Cm with separate groups.
 897          $result = groups_group_visible($group1->id, $course, $cm, $user3->id);
 898          $this->assertTrue($result); // Make sure user with access to all groups can see any group.
 899  
 900          $cm->groupmode = VISIBLEGROUPS;
 901          $result = groups_group_visible($group1->id, $course, $cm, $user1->id);
 902          $this->assertFalse($result); // Cm with visible groups.
 903  
 904          // Separate groups, not forced.
 905          $course->groupmode = SEPARATEGROUPS;
 906          $course->groupmodeforce = false;
 907          update_course($course);
 908          $result = groups_group_visible($group1->id, $course, null, $user1->id);
 909          $this->assertFalse($result);
 910          $result = groups_group_visible($group1->id, $course, null, $user2->id);
 911          $this->assertTrue($result);
 912          $result = groups_group_visible(0, $course, null, $user2->id);
 913          $this->assertFalse($result); // Requesting all groups.
 914          $result = groups_group_visible(0, $course, null, $user3->id);
 915          $this->assertTrue($result); // Requesting all groups.
 916  
 917          $cm->groupmode = NOGROUPS;
 918          $result = groups_group_visible($group1->id, $course, $cm, $user1->id);
 919          $this->assertTrue($result); // Cm with no groups.
 920  
 921          $cm->groupmode = SEPARATEGROUPS;
 922          $result = groups_group_visible($group1->id, $course, $cm, $user1->id);
 923          $this->assertFalse($result); // Cm with separate groups.
 924          $result = groups_group_visible($group1->id, $course, $cm, $user2->id);
 925          $this->assertTrue($result); // Cm with separate groups.
 926  
 927          $cm->groupmode = VISIBLEGROUPS;
 928          $result = groups_group_visible($group1->id, $course, $cm, $user1->id);
 929          $this->assertTrue($result); // Cm with visible groups.
 930      }
 931  
 932      function test_groups_get_groupmode() {
 933          global $DB;
 934          $generator = $this->getDataGenerator();
 935          $this->resetAfterTest();
 936          $this->setAdminUser();
 937  
 938          // Create a course with no groups forcing.
 939          $course1 = $generator->create_course();
 940  
 941          // Create cm1 with no groups, cm1 with visible groups, cm2 with separate groups and cm3 with visible groups.
 942          $assign1 = $generator->create_module("assign", array('course' => $course1->id));
 943          $assign2 = $generator->create_module("assign", array('course' => $course1->id),
 944                  array('groupmode' => SEPARATEGROUPS));
 945          $assign3 = $generator->create_module("assign", array('course' => $course1->id),
 946                  array('groupmode' => VISIBLEGROUPS));
 947  
 948          // Request data for tests.
 949          $cm1 = get_coursemodule_from_instance("assign", $assign1->id);
 950          $cm2 = get_coursemodule_from_instance("assign", $assign2->id);
 951          $cm3 = get_coursemodule_from_instance("assign", $assign3->id);
 952          $modinfo = get_fast_modinfo($course1->id);
 953  
 954          // Assert that any method of getting activity groupmode returns the correct result.
 955          $this->assertEquals(NOGROUPS, groups_get_activity_groupmode($cm1));
 956          $this->assertEquals(NOGROUPS, groups_get_activity_groupmode($cm1, $course1));
 957          $this->assertEquals(NOGROUPS, groups_get_activity_groupmode($modinfo->cms[$cm1->id]));
 958          $this->assertEquals(SEPARATEGROUPS, groups_get_activity_groupmode($cm2));
 959          $this->assertEquals(SEPARATEGROUPS, groups_get_activity_groupmode($cm2, $course1));
 960          $this->assertEquals(SEPARATEGROUPS, groups_get_activity_groupmode($modinfo->cms[$cm2->id]));
 961          $this->assertEquals(VISIBLEGROUPS, groups_get_activity_groupmode($cm3));
 962          $this->assertEquals(VISIBLEGROUPS, groups_get_activity_groupmode($cm3, $course1));
 963          $this->assertEquals(VISIBLEGROUPS, groups_get_activity_groupmode($modinfo->cms[$cm3->id]));
 964  
 965          // Update the course set the groupmode SEPARATEGROUPS but not forced.
 966          update_course((object)array('id' => $course1->id, 'groupmode' => SEPARATEGROUPS));
 967          // Re-request the data from DB.
 968          $course1 = $DB->get_record('course', array('id' => $course1->id));
 969          $modinfo = get_fast_modinfo($course1->id);
 970  
 971          // Existing activities are not changed.
 972          $this->assertEquals(NOGROUPS, groups_get_activity_groupmode($cm1));
 973          $this->assertEquals(NOGROUPS, groups_get_activity_groupmode($cm1, $course1));
 974          $this->assertEquals(NOGROUPS, groups_get_activity_groupmode($modinfo->cms[$cm1->id]));
 975          $this->assertEquals(SEPARATEGROUPS, groups_get_activity_groupmode($cm2));
 976          $this->assertEquals(SEPARATEGROUPS, groups_get_activity_groupmode($cm2, $course1));
 977          $this->assertEquals(SEPARATEGROUPS, groups_get_activity_groupmode($modinfo->cms[$cm2->id]));
 978          $this->assertEquals(VISIBLEGROUPS, groups_get_activity_groupmode($cm3));
 979          $this->assertEquals(VISIBLEGROUPS, groups_get_activity_groupmode($cm3, $course1));
 980          $this->assertEquals(VISIBLEGROUPS, groups_get_activity_groupmode($modinfo->cms[$cm3->id]));
 981  
 982          // Update the course set the groupmode SEPARATEGROUPS and forced.
 983          update_course((object)array('id' => $course1->id, 'groupmode' => SEPARATEGROUPS, 'groupmodeforce' => true));
 984          // Re-request the data from DB.
 985          $course1 = $DB->get_record('course', array('id' => $course1->id));
 986          $modinfo = get_fast_modinfo($course1->id);
 987  
 988          // Make sure all activities have separate groups mode now.
 989          $this->assertEquals(SEPARATEGROUPS, groups_get_activity_groupmode($cm1));
 990          $this->assertEquals(SEPARATEGROUPS, groups_get_activity_groupmode($cm1, $course1));
 991          $this->assertEquals(SEPARATEGROUPS, groups_get_activity_groupmode($modinfo->cms[$cm1->id]));
 992          $this->assertEquals(SEPARATEGROUPS, groups_get_activity_groupmode($cm2));
 993          $this->assertEquals(SEPARATEGROUPS, groups_get_activity_groupmode($cm2, $course1));
 994          $this->assertEquals(SEPARATEGROUPS, groups_get_activity_groupmode($modinfo->cms[$cm2->id]));
 995          $this->assertEquals(SEPARATEGROUPS, groups_get_activity_groupmode($cm3));
 996          $this->assertEquals(SEPARATEGROUPS, groups_get_activity_groupmode($cm3, $course1));
 997          $this->assertEquals(SEPARATEGROUPS, groups_get_activity_groupmode($modinfo->cms[$cm3->id]));
 998      }
 999  
1000      /**
1001       * Tests for groups_allgroups_course_menu() .
1002       */
1003      public function test_groups_allgroups_course_menu() {
1004          global $SESSION;
1005  
1006          $this->resetAfterTest();
1007  
1008          // Generate data.
1009          $course = $this->getDataGenerator()->create_course();
1010          $record = new \stdClass();
1011          $record->courseid = $course->id;
1012          $group1 = $this->getDataGenerator()->create_group($record);
1013          $group2 = $this->getDataGenerator()->create_group($record);
1014          $user = $this->getDataGenerator()->create_user();
1015          $this->getDataGenerator()->enrol_user($user->id, $course->id);
1016          $this->setUser($user);
1017  
1018          $html = groups_allgroups_course_menu($course, 'someurl.php');
1019          // Since user is not a part of this group and doesn't have accessallgroups permission,
1020          // the html should be empty.
1021          $this->assertEmpty($html);
1022  
1023          groups_add_member($group1->id, $user);
1024          // Now user can access one of the group. We can't assert an exact match here because of random ids generated by yui. So do
1025          // partial match to see if all groups are listed or not.
1026          $html = groups_allgroups_course_menu($course, 'someurl.php');
1027          $this->assertStringContainsString(format_string($group1->name), $html);
1028          $this->assertStringNotContainsString(format_string($group2->name), $html);
1029  
1030          $this->setAdminUser();
1031  
1032          // Now user can access everything.
1033          $html = groups_allgroups_course_menu($course, 'someurl.php');
1034          $this->assertStringContainsString(format_string($group1->name), $html);
1035          $this->assertStringContainsString(format_string($group2->name), $html);
1036  
1037          // Make sure separate groups mode, doesn't change anything.
1038          $course->groupmode = SEPARATEGROUPS;
1039          update_course($course);
1040          $html = groups_allgroups_course_menu($course, 'someurl.php');
1041          $this->assertStringContainsString(format_string($group1->name), $html);
1042          $this->assertStringContainsString(format_string($group2->name), $html);
1043  
1044          // Make sure Visible groups mode, doesn't change anything.
1045          $course->groupmode = VISIBLEGROUPS;
1046          update_course($course);
1047          $html = groups_allgroups_course_menu($course, 'someurl.php');
1048          $this->assertStringContainsString(format_string($group1->name), $html);
1049          $this->assertStringContainsString(format_string($group2->name), $html);
1050  
1051          // Let us test activegroup changes now.
1052          $this->setUser($user);
1053          $SESSION->activegroup[$course->id][VISIBLEGROUPS][$course->defaultgroupingid] = 5;
1054          groups_allgroups_course_menu($course, 'someurl.php', false); // Do not update session.
1055          $this->assertSame(5, $SESSION->activegroup[$course->id][VISIBLEGROUPS][$course->defaultgroupingid]);
1056          groups_allgroups_course_menu($course, 'someurl.php', true, $group1->id); // Update session.
1057          $this->assertSame($group1->id, $SESSION->activegroup[$course->id][VISIBLEGROUPS][$course->defaultgroupingid]);
1058          // Try to update session with an invalid groupid. It should not accept the invalid id.
1059          groups_allgroups_course_menu($course, 'someurl.php', true, 256);
1060          $this->assertEquals($group1->id, $SESSION->activegroup[$course->id][VISIBLEGROUPS][$course->defaultgroupingid]);
1061      }
1062  
1063      /**
1064       * This unit test checks that groups_get_all_groups returns groups in
1065       * alphabetical order even if they are in a grouping.
1066       */
1067      public function test_groups_ordering() {
1068          $generator = $this->getDataGenerator();
1069          $this->resetAfterTest();
1070  
1071          // Create a course category and course.
1072          $cat = $generator->create_category(array('parent' => 0));
1073          $course = $generator->create_course(array('category' => $cat->id));
1074          $grouping = $generator->create_grouping(array('courseid' => $course->id, 'name' => 'Grouping'));
1075  
1076          // Create groups in reverse order.
1077          $group2 = $generator->create_group(array('courseid' => $course->id, 'name' => 'Group 2'));
1078          $group1 = $generator->create_group(array('courseid' => $course->id, 'name' => 'Group 1'));
1079  
1080          // Assign the groups to the grouping in reverse order.
1081          $this->assertTrue(groups_assign_grouping($grouping->id, $group2->id));
1082          $this->assertTrue(groups_assign_grouping($grouping->id, $group1->id));
1083  
1084          // Get all groups and check they are alphabetical.
1085          $groups = array_values(groups_get_all_groups($course->id, 0));
1086          $this->assertEquals('Group 1', $groups[0]->name);
1087          $this->assertEquals('Group 2', $groups[1]->name);
1088  
1089          // Now check the same is true when accessed by grouping.
1090          $groups = array_values(groups_get_all_groups($course->id, 0, $grouping->id));
1091          $this->assertEquals('Group 1', $groups[0]->name);
1092          $this->assertEquals('Group 2', $groups[1]->name);
1093      }
1094  
1095      /**
1096       * Tests for groups_get_all_groups when grouping is set and we want members as well.
1097       */
1098      public function test_groups_get_all_groups_in_grouping_with_members() {
1099          $generator = $this->getDataGenerator();
1100          $this->resetAfterTest();
1101  
1102          // Create courses.
1103          $course1 = $generator->create_course();
1104          $course2 = $generator->create_course();
1105  
1106          // Create users.
1107          $c1user1 = $generator->create_user();
1108          $c12user1 = $generator->create_user();
1109          $c12user2 = $generator->create_user();
1110  
1111          // Enrol users.
1112          $generator->enrol_user($c1user1->id, $course1->id);
1113          $generator->enrol_user($c12user1->id, $course1->id);
1114          $generator->enrol_user($c12user1->id, $course2->id);
1115          $generator->enrol_user($c12user2->id, $course1->id);
1116          $generator->enrol_user($c12user2->id, $course2->id);
1117  
1118          // Create groupings and groups for course1.
1119          $c1grouping1 = $generator->create_grouping(array('courseid' => $course1->id));
1120          $c1grouping2 = $generator->create_grouping(array('courseid' => $course1->id));
1121          $c1group1 = $generator->create_group(array('courseid' => $course1->id));
1122          $c1group2 = $generator->create_group(array('courseid' => $course1->id));
1123          $c1group3 = $generator->create_group(array('courseid' => $course1->id));
1124          groups_assign_grouping($c1grouping1->id, $c1group1->id);
1125          groups_assign_grouping($c1grouping1->id, $c1group2->id);
1126          groups_assign_grouping($c1grouping2->id, $c1group3->id);
1127  
1128          // Create groupings and groups for course2.
1129          $c2grouping1 = $generator->create_grouping(array('courseid' => $course2->id));
1130          $c2group1 = $generator->create_group(array('courseid' => $course1->id));
1131          groups_assign_grouping($c2grouping1->id, $c2group1->id);
1132  
1133          // Assign users to groups.
1134          $generator->create_group_member(array('groupid' => $c1group1->id, 'userid' => $c1user1->id));
1135          $generator->create_group_member(array('groupid' => $c1group1->id, 'userid' => $c12user1->id));
1136          $generator->create_group_member(array('groupid' => $c1group2->id, 'userid' => $c12user2->id));
1137          $generator->create_group_member(array('groupid' => $c2group1->id, 'userid' => $c12user2->id));
1138  
1139          // Test without userid.
1140          $groups = groups_get_all_groups($course1->id, null, $c1grouping1->id, 'g.*', true);
1141  
1142          $this->assertEqualsCanonicalizing(
1143                  [$c1group1->id, $c1group2->id],
1144                  array_keys($groups)
1145          );
1146          $this->assertEquals(
1147                  [$c1user1->id => $c1user1->id, $c12user1->id => $c12user1->id],
1148                  $groups[$c1group1->id]->members
1149          );
1150          $this->assertEquals(
1151                  [$c12user2->id => $c12user2->id],
1152                  $groups[$c1group2->id]->members
1153          );
1154  
1155          // Test with userid.
1156          $groups = groups_get_all_groups($course1->id, $c1user1->id, $c1grouping1->id, 'g.*', true);
1157  
1158          $this->assertEquals([$c1group1->id], array_keys($groups));
1159          $this->assertEqualsCanonicalizing(
1160                  [$c1user1->id, $c12user1->id],
1161                  $groups[$c1group1->id]->members
1162          );
1163      }
1164  
1165      /**
1166       * Tests for groups_get_user_groups() method.
1167       */
1168      public function test_groups_get_user_groups() {
1169          $this->resetAfterTest(true);
1170          $generator = $this->getDataGenerator();
1171  
1172          // Create courses.
1173          $course1 = $generator->create_course();
1174          $course2 = $generator->create_course();
1175  
1176          // Create users.
1177          $user1 = $generator->create_user();
1178          $user2 = $generator->create_user();
1179          $user3 = $generator->create_user();
1180  
1181          // Enrol users.
1182          $generator->enrol_user($user1->id, $course1->id);
1183          $generator->enrol_user($user1->id, $course2->id);
1184          $generator->enrol_user($user2->id, $course2->id);
1185          $generator->enrol_user($user3->id, $course2->id);
1186  
1187          // Create groups.
1188          $group1 = $generator->create_group(array('courseid' => $course1->id));
1189          $group2 = $generator->create_group(array('courseid' => $course2->id));
1190          $group3 = $generator->create_group(array('courseid' => $course2->id));
1191  
1192          // Assign users to groups.
1193          $this->assertTrue($generator->create_group_member(array('groupid' => $group1->id, 'userid' => $user1->id)));
1194          $this->assertTrue($generator->create_group_member(array('groupid' => $group2->id, 'userid' => $user2->id)));
1195  
1196          // Get user groups.
1197          $usergroups1 = groups_get_user_groups($course1->id, $user1->id);
1198          $usergroups2 = groups_get_user_groups($course2->id, $user2->id);;
1199  
1200          // Assert return data.
1201          $this->assertEquals($group1->id, $usergroups1[0][0]);
1202          $this->assertEquals($group2->id, $usergroups2[0][0]);
1203  
1204          // Now, test with groupings.
1205          $grouping1 = $generator->create_grouping(array('courseid' => $course1->id));
1206          $grouping2 = $generator->create_grouping(array('courseid' => $course2->id));
1207  
1208          // Assign the groups to grouping.
1209          groups_assign_grouping($grouping1->id, $group1->id);
1210          groups_assign_grouping($grouping2->id, $group2->id);
1211          groups_assign_grouping($grouping2->id, $group3->id);
1212  
1213          // Test with grouping.
1214          $usergroups1 = groups_get_user_groups($course1->id, $user1->id);
1215          $usergroups2 = groups_get_user_groups($course2->id, $user2->id);
1216          $this->assertArrayHasKey($grouping1->id, $usergroups1);
1217          $this->assertArrayHasKey($grouping2->id, $usergroups2);
1218  
1219          // Test user without a group.
1220          $usergroups1 = groups_get_user_groups($course2->id, $user3->id);
1221          $this->assertCount(0, $usergroups1[0]);
1222  
1223          // Test with userid = 0.
1224          $usergroups1 = groups_get_user_groups($course1->id, 0);
1225          $usergroups2 = groups_get_user_groups($course2->id, 0);
1226          $this->assertCount(0, $usergroups1[0]);
1227          $this->assertCount(0, $usergroups2[0]);
1228  
1229          // Test with courseid = 0.
1230          $usergroups1 = groups_get_user_groups(0, $user1->id);
1231          $usergroups2 = groups_get_user_groups(0, $user2->id);
1232          $this->assertCount(0, $usergroups1[0]);
1233          $this->assertCount(0, $usergroups2[0]);
1234      }
1235  
1236      /**
1237       * Create dummy groups array for use in menu tests
1238       * @param int $number
1239       * @return array
1240       */
1241      protected function make_group_list($number) {
1242          $testgroups = array();
1243          for ($a = 0; $a < $number; $a++) {
1244              $grp = new \stdClass();
1245              $grp->id = 100 + $a;
1246              $grp->name = 'test group ' . $grp->id;
1247              $testgroups[$grp->id] = $grp;
1248          }
1249          return $testgroups;
1250      }
1251  
1252      public function test_groups_sort_menu_options_empty() {
1253          $this->assertEquals(array(), groups_sort_menu_options(array(), array()));
1254      }
1255  
1256      public function test_groups_sort_menu_options_allowed_goups_only() {
1257          $this->assertEquals(array(
1258              100 => 'test group 100',
1259              101 => 'test group 101',
1260          ), groups_sort_menu_options($this->make_group_list(2), array()));
1261      }
1262  
1263      public function test_groups_sort_menu_options_user_goups_only() {
1264          $this->assertEquals(array(
1265              100 => 'test group 100',
1266              101 => 'test group 101',
1267          ), groups_sort_menu_options(array(), $this->make_group_list(2)));
1268      }
1269  
1270      public function test_groups_sort_menu_options_user_both() {
1271          $this->assertEquals(array(
1272              1 => array(get_string('mygroups', 'group') => array(
1273                  100 => 'test group 100',
1274                  101 => 'test group 101',
1275              )),
1276              2 => array(get_string('othergroups', 'group') => array(
1277                  102 => 'test group 102',
1278                  103 => 'test group 103',
1279              )),
1280          ), groups_sort_menu_options($this->make_group_list(4), $this->make_group_list(2)));
1281      }
1282  
1283      public function test_groups_sort_menu_options_user_both_many_groups() {
1284          $this->assertEquals(array(
1285              1 => array(get_string('mygroups', 'group') => array(
1286                  100 => 'test group 100',
1287                  101 => 'test group 101',
1288              )),
1289              2 => array (get_string('othergroups', 'group') => array(
1290                  102 => 'test group 102',
1291                  103 => 'test group 103',
1292                  104 => 'test group 104',
1293                  105 => 'test group 105',
1294                  106 => 'test group 106',
1295                  107 => 'test group 107',
1296                  108 => 'test group 108',
1297                  109 => 'test group 109',
1298                  110 => 'test group 110',
1299                  111 => 'test group 111',
1300                  112 => 'test group 112',
1301              )),
1302          ), groups_sort_menu_options($this->make_group_list(13), $this->make_group_list(2)));
1303      }
1304  
1305      /**
1306       * Tests for groups_user_groups_visible.
1307       */
1308      public function test_groups_user_groups_visible() {
1309          global $DB;
1310  
1311          $generator = $this->getDataGenerator();
1312          $this->resetAfterTest();
1313          $this->setAdminUser();
1314  
1315          // Create a course category, course and groups.
1316          $cat = $generator->create_category(array('parent' => 0));
1317          $course = $generator->create_course(array('category' => $cat->id));
1318          $coursecontext = \context_course::instance($course->id);
1319          $group1 = $generator->create_group(array('courseid' => $course->id, 'name' => 'Group 1'));
1320          $group2 = $generator->create_group(array('courseid' => $course->id, 'name' => 'Group 2'));
1321          $group3 = $generator->create_group(array('courseid' => $course->id, 'name' => 'Group 3'));
1322          $group4 = $generator->create_group(array('courseid' => $course->id, 'name' => 'Group 4'));
1323  
1324          // Create cm.
1325          $assign = $generator->create_module("assign", array('course' => $course->id));
1326          $cm = get_coursemodule_from_instance("assign", $assign->id);
1327  
1328          // Create users.
1329          $user1 = $generator->create_user(); // Normal user.
1330          $user2 = $generator->create_user(); // Normal user.
1331          $user3 = $generator->create_user(); // Teacher, access all groups.
1332          $user4 = $generator->create_user(); // Normal user.
1333  
1334          // Enrol users into the course.
1335          $generator->enrol_user($user1->id, $course->id);
1336          $generator->enrol_user($user2->id, $course->id);
1337          $generator->enrol_user($user4->id, $course->id);
1338  
1339          // Assign groups.
1340          // User1 and User4 share groups.
1341          groups_add_member($group1, $user1);
1342          groups_add_member($group2, $user2);
1343          groups_add_member($group1, $user4);
1344  
1345          // Give capability at course level to the user to access all groups.
1346          $role = $DB->get_field("role", "id", array("shortname" => "manager"));
1347          $generator->enrol_user($user3->id, $course->id, $role);
1348          // Make sure the user has the capability.
1349          assign_capability('moodle/site:accessallgroups', CAP_ALLOW, $role, $coursecontext->id);
1350  
1351          // Normal users in different groups.
1352          $this->setUser($user1);
1353  
1354          // No groups , not forced.
1355          $result = groups_user_groups_visible($course, $user2->id);
1356          $this->assertTrue($result);
1357  
1358          $cm->groupmode = NOGROUPS;
1359          $result = groups_user_groups_visible($course, $user2->id, $cm);
1360          $this->assertTrue($result); // Cm with no groups.
1361  
1362          $cm->groupmode = SEPARATEGROUPS;
1363          $result = groups_user_groups_visible($course, $user2->id, $cm);
1364          $this->assertFalse($result); // Cm with separate groups.
1365  
1366          $cm->groupmode = VISIBLEGROUPS;
1367          $result = groups_user_groups_visible($course, $user2->id, $cm);
1368          $this->assertTrue($result); // Cm with visible groups.
1369  
1370          // No groups, forced.
1371          $course->groupmode = NOGROUPS;
1372          $course->groupmodeforce = true;
1373          update_course($course);
1374          $result = groups_user_groups_visible($course, $user2->id);
1375          $this->assertTrue($result);
1376  
1377          $cm->groupmode = NOGROUPS;
1378          $result = groups_user_groups_visible($course, $user2->id, $cm);
1379          $this->assertTrue($result); // Cm with no groups.
1380  
1381          $cm->groupmode = SEPARATEGROUPS;
1382          $result = groups_user_groups_visible($course, $user2->id, $cm);
1383          $this->assertTrue($result); // Cm with separate groups.
1384  
1385          $cm->groupmode = SEPARATEGROUPS;
1386          $result = groups_user_groups_visible($course, $user2->id);
1387          $this->assertTrue($result); // Cm with visible groups.
1388  
1389          // Visible groups, forced.
1390          $course->groupmode = VISIBLEGROUPS;
1391          $course->groupmodeforce = true;
1392          update_course($course);
1393          $result = groups_user_groups_visible($course, $user2->id);
1394          $this->assertTrue($result);
1395  
1396          $cm->groupmode = NOGROUPS;
1397          $result = groups_user_groups_visible($course, $user2->id, $cm);
1398          $this->assertTrue($result); // Cm with no groups.
1399  
1400          $cm->groupmode = SEPARATEGROUPS;
1401          $result = groups_user_groups_visible($course, $user2->id, $cm);
1402          $this->assertTrue($result); // Cm with separate groups.
1403  
1404          $cm->groupmode = VISIBLEGROUPS;
1405          $result = groups_user_groups_visible($course, $user2->id, $cm);
1406          $this->assertTrue($result); // Cm with visible groups.
1407  
1408          // Visible groups, not forced.
1409          $course->groupmode = VISIBLEGROUPS;
1410          $course->groupmodeforce = false;
1411          update_course($course);
1412          $result = groups_user_groups_visible($course, $user2->id);
1413          $this->assertTrue($result);
1414  
1415          $cm->groupmode = NOGROUPS;
1416          $result = groups_user_groups_visible($course, $user2->id, $cm);
1417          $this->assertTrue($result); // Cm with no groups.
1418  
1419          $cm->groupmode = SEPARATEGROUPS;
1420          $result = groups_user_groups_visible($course, $user2->id, $cm);
1421          $this->assertFalse($result); // Cm with separate groups.
1422  
1423          $cm->groupmode = VISIBLEGROUPS;
1424          $result = groups_user_groups_visible($course, $user2->id, $cm);
1425          $this->assertTrue($result); // Cm with visible groups.
1426  
1427          // Separate groups, forced.
1428          $course->groupmode = SEPARATEGROUPS;
1429          $course->groupmodeforce = true;
1430          update_course($course);
1431          $result = groups_user_groups_visible($course, $user2->id);
1432          $this->assertFalse($result);
1433  
1434          $result = groups_user_groups_visible($course, $user3->id);
1435          $this->assertFalse($result); // Requesting all groups.
1436  
1437          $cm->groupmode = NOGROUPS;
1438          $result = groups_user_groups_visible($course, $user2->id, $cm);
1439          $this->assertFalse($result); // Cm with no groups.
1440  
1441          $cm->groupmode = SEPARATEGROUPS;
1442          $result = groups_user_groups_visible($course, $user2->id, $cm);
1443          $this->assertFalse($result); // Cm with separate groups.
1444  
1445          $result = groups_user_groups_visible($course, $user3->id, $cm);
1446          $this->assertTrue($result);
1447  
1448          $cm->groupmode = VISIBLEGROUPS;
1449          $result = groups_user_groups_visible($course, $user2->id, $cm);
1450          $this->assertFalse($result); // Cm with visible groups.
1451  
1452          // Separate groups, not forced.
1453          $course->groupmode = SEPARATEGROUPS;
1454          $course->groupmodeforce = false;
1455          update_course($course);
1456          $result = groups_user_groups_visible($course, $user2->id);
1457          $this->assertFalse($result);
1458  
1459          $result = groups_user_groups_visible($course, $user3->id);
1460          $this->assertFalse($result); // Requesting all groups.
1461  
1462          $cm->groupmode = NOGROUPS;
1463          $result = groups_user_groups_visible($course, $user2->id, $cm);
1464          $this->assertTrue($result); // Cm with no groups.
1465  
1466          $cm->groupmode = SEPARATEGROUPS;
1467          $result = groups_user_groups_visible($course, $user2->id, $cm);
1468          $this->assertFalse($result); // Cm with separate groups.
1469  
1470          $cm->groupmode = VISIBLEGROUPS;
1471          $result = groups_user_groups_visible($course, $user2->id, $cm);
1472          $this->assertTrue($result); // Cm with visible groups.
1473  
1474          // Users sharing groups.
1475  
1476          // No groups , not forced.
1477          $course->groupmode = NOGROUPS;
1478          $course->groupmodeforce = false;
1479          update_course($course);
1480  
1481          $result = groups_user_groups_visible($course, $user4->id);
1482          $this->assertTrue($result);
1483  
1484          $cm->groupmode = NOGROUPS;
1485          $result = groups_user_groups_visible($course, $user4->id, $cm);
1486          $this->assertTrue($result); // Cm with no groups.
1487  
1488          $cm->groupmode = SEPARATEGROUPS;
1489          $result = groups_user_groups_visible($course, $user4->id, $cm);
1490          $this->assertTrue($result); // Cm with separate groups.
1491  
1492          $cm->groupmode = VISIBLEGROUPS;
1493          $result = groups_user_groups_visible($course, $user4->id, $cm);
1494          $this->assertTrue($result); // Cm with visible groups.
1495  
1496          // No groups, forced.
1497          $course->groupmode = NOGROUPS;
1498          $course->groupmodeforce = true;
1499          update_course($course);
1500          $result = groups_user_groups_visible($course, $user4->id);
1501          $this->assertTrue($result);
1502  
1503          $cm->groupmode = NOGROUPS;
1504          $result = groups_user_groups_visible($course, $user4->id, $cm);
1505          $this->assertTrue($result); // Cm with no groups.
1506  
1507          $cm->groupmode = SEPARATEGROUPS;
1508          $result = groups_user_groups_visible($course, $user4->id, $cm);
1509          $this->assertTrue($result); // Cm with separate groups.
1510  
1511          $cm->groupmode = SEPARATEGROUPS;
1512          $result = groups_user_groups_visible($course, $user4->id, $cm);
1513          $this->assertTrue($result); // Cm with visible groups.
1514  
1515          // Visible groups, forced.
1516          $course->groupmode = VISIBLEGROUPS;
1517          $course->groupmodeforce = true;
1518          update_course($course);
1519          $result = groups_user_groups_visible($course, $user4->id);
1520          $this->assertTrue($result);
1521  
1522          $cm->groupmode = NOGROUPS;
1523          $result = groups_user_groups_visible($course, $user4->id, $cm);
1524          $this->assertTrue($result); // Cm with no groups.
1525  
1526          $cm->groupmode = SEPARATEGROUPS;
1527          $result = groups_user_groups_visible($course, $user4->id, $cm);
1528          $this->assertTrue($result); // Cm with separate groups.
1529  
1530          $cm->groupmode = VISIBLEGROUPS;
1531          $result = groups_user_groups_visible($course, $user4->id, $cm);
1532          $this->assertTrue($result); // Cm with visible groups.
1533  
1534          // Visible groups, not forced.
1535          $course->groupmode = VISIBLEGROUPS;
1536          $course->groupmodeforce = false;
1537          update_course($course);
1538          $result = groups_user_groups_visible($course, $user4->id);
1539          $this->assertTrue($result);
1540  
1541          $cm->groupmode = NOGROUPS;
1542          $result = groups_user_groups_visible($course, $user4->id, $cm);
1543          $this->assertTrue($result); // Cm with no groups.
1544  
1545          $cm->groupmode = SEPARATEGROUPS;
1546          $result = groups_user_groups_visible($course, $user4->id, $cm);
1547          $this->assertTrue($result); // Cm with separate groups.
1548  
1549          $cm->groupmode = VISIBLEGROUPS;
1550          $result = groups_user_groups_visible($course, $user4->id, $cm);
1551          $this->assertTrue($result); // Cm with visible groups.
1552  
1553          // Separate groups, forced.
1554          $course->groupmode = SEPARATEGROUPS;
1555          $course->groupmodeforce = true;
1556          update_course($course);
1557          $result = groups_user_groups_visible($course, $user4->id);
1558          $this->assertTrue($result);
1559  
1560          $result = groups_user_groups_visible($course, $user3->id);
1561          $this->assertFalse($result); // Requesting all groups.
1562  
1563          $cm->groupmode = NOGROUPS;
1564          $result = groups_user_groups_visible($course, $user4->id, $cm);
1565          $this->assertTrue($result); // Cm with no groups.
1566  
1567          $cm->groupmode = SEPARATEGROUPS;
1568          $result = groups_user_groups_visible($course, $user4->id, $cm);
1569          $this->assertTrue($result); // Cm with separate groups.
1570  
1571          $result = groups_user_groups_visible($course, $user3->id, $cm);
1572          $this->assertTrue($result);
1573  
1574          $cm->groupmode = VISIBLEGROUPS;
1575          $result = groups_user_groups_visible($course, $user4->id, $cm);
1576          $this->assertTrue($result); // Cm with visible groups.
1577  
1578          // Separate groups, not forced.
1579          $course->groupmode = SEPARATEGROUPS;
1580          $course->groupmodeforce = false;
1581          update_course($course);
1582          $result = groups_user_groups_visible($course, $user4->id);
1583          $this->assertTrue($result);
1584  
1585          $result = groups_user_groups_visible($course, $user3->id);
1586          $this->assertFalse($result); // Requesting all groups.
1587  
1588          $cm->groupmode = NOGROUPS;
1589          $result = groups_user_groups_visible($course, $user4->id, $cm);
1590          $this->assertTrue($result); // Cm with no groups.
1591  
1592          $cm->groupmode = SEPARATEGROUPS;
1593          $result = groups_user_groups_visible($course, $user4->id, $cm);
1594          $this->assertTrue($result); // Cm with separate groups.
1595  
1596          $cm->groupmode = VISIBLEGROUPS;
1597          $result = groups_user_groups_visible($course, $user4->id, $cm);
1598          $this->assertTrue($result); // Cm with visible groups.
1599  
1600          // For teacher with access all groups.
1601  
1602          // No groups , not forced.
1603          $course->groupmode = NOGROUPS;
1604          $course->groupmodeforce = false;
1605          update_course($course);
1606  
1607          $this->setUser($user3);
1608  
1609          $result = groups_user_groups_visible($course, $user1->id);
1610          $this->assertTrue($result);
1611          $result = groups_user_groups_visible($course, $user1->id);
1612          $this->assertTrue($result); // Requesting all groups.
1613  
1614          $cm->groupmode = NOGROUPS;
1615          $result = groups_user_groups_visible($course, $user1->id, $cm);
1616          $this->assertTrue($result); // Cm with no groups.
1617  
1618          $cm->groupmode = SEPARATEGROUPS;
1619          $result = groups_user_groups_visible($course, $user1->id, $cm);
1620          $this->assertTrue($result); // Cm with separate groups.
1621          $result = groups_user_groups_visible($course, $user2->id, $cm);
1622          $this->assertTrue($result); // Cm with separate groups.
1623  
1624          $cm->groupmode = VISIBLEGROUPS;
1625          $result = groups_user_groups_visible($course, $user1->id, $cm);
1626          $this->assertTrue($result); // Cm with visible groups.
1627  
1628          // No groups, forced.
1629          $course->groupmode = NOGROUPS;
1630          $course->groupmodeforce = true;
1631          update_course($course);
1632          $result = groups_user_groups_visible($course, $user1->id);
1633          $this->assertTrue($result);
1634          $result = groups_user_groups_visible($course, $user1->id);
1635          $this->assertTrue($result); // Requesting all groups.
1636  
1637          $cm->groupmode = NOGROUPS;
1638          $result = groups_user_groups_visible($course, $user1->id, $cm);
1639          $this->assertTrue($result); // Cm with no groups.
1640  
1641          $cm->groupmode = SEPARATEGROUPS;
1642          $result = groups_user_groups_visible($course, $user1->id, $cm);
1643          $this->assertTrue($result); // Cm with separate groups.
1644          $result = groups_user_groups_visible($course, $user2->id, $cm);
1645          $this->assertTrue($result); // Cm with separate groups.
1646  
1647          $cm->groupmode = SEPARATEGROUPS;
1648          $result = groups_user_groups_visible($course, $user1->id, $cm);
1649          $this->assertTrue($result); // Cm with visible groups.
1650  
1651          // Visible groups, forced.
1652          $course->groupmode = VISIBLEGROUPS;
1653          $course->groupmodeforce = true;
1654          update_course($course);
1655          $result = groups_user_groups_visible($course, $user1->id);
1656          $this->assertTrue($result);
1657          $result = groups_user_groups_visible($course, $user1->id);
1658          $this->assertTrue($result); // Requesting all groups.
1659  
1660          $cm->groupmode = NOGROUPS;
1661          $result = groups_user_groups_visible($course, $user1->id, $cm);
1662          $this->assertTrue($result); // Cm with no groups.
1663  
1664          $cm->groupmode = SEPARATEGROUPS;
1665          $result = groups_user_groups_visible($course, $user1->id, $cm);
1666          $this->assertTrue($result); // Cm with separate groups.
1667          $result = groups_user_groups_visible($course, $user2->id, $cm);
1668          $this->assertTrue($result); // Cm with separate groups.
1669  
1670          $cm->groupmode = VISIBLEGROUPS;
1671          $result = groups_user_groups_visible($course, $user1->id, $cm);
1672          $this->assertTrue($result); // Cm with visible groups.
1673  
1674          // Visible groups, not forced.
1675          $course->groupmode = VISIBLEGROUPS;
1676          $course->groupmodeforce = false;
1677          update_course($course);
1678          $result = groups_user_groups_visible($course, $user1->id);
1679          $this->assertTrue($result);
1680          $result = groups_user_groups_visible($course, $user1->id);
1681          $this->assertTrue($result); // Requesting all groups.
1682  
1683          $cm->groupmode = NOGROUPS;
1684          $result = groups_user_groups_visible($course, $user1->id, $cm);
1685          $this->assertTrue($result); // Cm with no groups.
1686  
1687          $cm->groupmode = SEPARATEGROUPS;
1688          $result = groups_user_groups_visible($course, $user1->id, $cm);
1689          $this->assertTrue($result); // Cm with separate groups.
1690          $result = groups_user_groups_visible($course, $user2->id, $cm);
1691          $this->assertTrue($result); // Cm with separate groups.
1692  
1693          $cm->groupmode = VISIBLEGROUPS;
1694          $result = groups_user_groups_visible($course, $user1->id, $cm);
1695          $this->assertTrue($result); // Cm with visible groups.
1696  
1697          // Separate groups, forced.
1698          $course->groupmode = SEPARATEGROUPS;
1699          $course->groupmodeforce = true;
1700          update_course($course);
1701          $result = groups_user_groups_visible($course, $user1->id);
1702          $this->assertTrue($result);
1703          $result = groups_user_groups_visible($course, $user2->id);
1704          $this->assertTrue($result);
1705          $result = groups_user_groups_visible($course, $user2->id);
1706          $this->assertTrue($result); // Requesting all groups.
1707          $result = groups_user_groups_visible($course, $user3->id);
1708          $this->assertTrue($result); // Requesting all groups.
1709          $result = groups_user_groups_visible($course, $user3->id);
1710          $this->assertTrue($result);
1711  
1712          $cm->groupmode = NOGROUPS;
1713          $result = groups_user_groups_visible($course, $user1->id, $cm);
1714          $this->assertTrue($result); // Cm with no groups.
1715  
1716          $cm->groupmode = SEPARATEGROUPS;
1717          $result = groups_user_groups_visible($course, $user1->id, $cm);
1718          $this->assertTrue($result); // Cm with separate groups.
1719          $result = groups_user_groups_visible($course, $user2->id, $cm);
1720          $this->assertTrue($result); // Cm with separate groups.
1721          $result = groups_user_groups_visible($course, $user3->id, $cm);
1722          $this->assertTrue($result);
1723  
1724          $cm->groupmode = VISIBLEGROUPS;
1725          $result = groups_user_groups_visible($course, $user1->id, $cm);
1726          $this->assertTrue($result); // Cm with visible groups.
1727  
1728          // Separate groups, not forced.
1729          $course->groupmode = SEPARATEGROUPS;
1730          $course->groupmodeforce = false;
1731          update_course($course);
1732          $result = groups_user_groups_visible($course, $user1->id);
1733          $this->assertTrue($result);
1734          $result = groups_user_groups_visible($course, $user2->id);
1735          $this->assertTrue($result);
1736          $result = groups_user_groups_visible($course, $user2->id);
1737          $this->assertTrue($result); // Requesting all groups.
1738          $result = groups_user_groups_visible($course, $user3->id);
1739          $this->assertTrue($result); // Requesting all groups.
1740  
1741          $cm->groupmode = NOGROUPS;
1742          $result = groups_user_groups_visible($course, $user1->id, $cm);
1743          $this->assertTrue($result); // Cm with no groups.
1744  
1745          $cm->groupmode = SEPARATEGROUPS;
1746          $result = groups_user_groups_visible($course, $user1->id, $cm);
1747          $this->assertTrue($result); // Cm with separate groups.
1748          $result = groups_user_groups_visible($course, $user2->id, $cm);
1749          $this->assertTrue($result); // Cm with separate groups.
1750  
1751          $cm->groupmode = VISIBLEGROUPS;
1752          $result = groups_user_groups_visible($course, $user1->id, $cm);
1753          $this->assertTrue($result); // Cm with visible groups.
1754      }
1755  
1756      /**
1757       * Tests for groups_get_groups_members() method.
1758       *
1759       * @covers ::groups_get_groups_members
1760       */
1761      public function test_groups_get_groups_members() {
1762          $this->resetAfterTest(true);
1763          $generator = $this->getDataGenerator();
1764  
1765          // Create courses.
1766          $course1 = $generator->create_course();
1767          $course2 = $generator->create_course();
1768  
1769          // Create users.
1770          $user1 = $generator->create_user();
1771          $user2 = $generator->create_user();
1772          $user3 = $generator->create_user();
1773  
1774          // Enrol users.
1775          $generator->enrol_user($user1->id, $course1->id);
1776          $generator->enrol_user($user1->id, $course2->id);
1777          $generator->enrol_user($user2->id, $course2->id);
1778          $generator->enrol_user($user3->id, $course2->id);
1779  
1780          // Create groups.
1781          $group1 = $generator->create_group(array('courseid' => $course1->id));
1782          $group2 = $generator->create_group(array('courseid' => $course2->id));
1783          $group3 = $generator->create_group(array('courseid' => $course2->id));
1784  
1785          // Assign users to groups.
1786          $this->assertTrue($generator->create_group_member(array('groupid' => $group1->id, 'userid' => $user1->id)));
1787          $this->assertTrue($generator->create_group_member(array('groupid' => $group2->id, 'userid' => $user1->id)));
1788          $this->assertTrue($generator->create_group_member(array('groupid' => $group2->id, 'userid' => $user2->id)));
1789  
1790          // Test get_groups_members (with extra field and ordering).
1791          $members = groups_get_groups_members([$group1->id, $group2->id], ['lastaccess'], 'u.id ASC');
1792          $this->assertCount(2, $members);
1793          $this->assertEquals([$user1->id, $user2->id], array_keys($members));
1794          $this->assertTrue(isset($members[$user1->id]->lastaccess));
1795          $this->assertTrue(isset($members[$user2->id]->lastaccess));
1796  
1797          // Group with just one.
1798          $members = groups_get_groups_members([$group1->id]);
1799          $this->assertCount(1, $members);
1800          $this->assertEquals($user1->id, $members[$user1->id]->id);
1801  
1802          // Test the info matches group membership for the entire course.
1803          $groups  = groups_get_all_groups($course1->id, 0, 0, 'g.*', true);
1804          $group1withmembers = array_pop($groups);
1805  
1806          // Compare the sorted keys of both arrays (should be list of user ids).
1807          $members = array_keys($members);
1808          sort($members);
1809          $group1members = array_keys($group1withmembers->members);
1810          sort($group1members);
1811          $this->assertEquals($members, $group1members);
1812  
1813          // Group with just one plus empty group.
1814          $members = groups_get_groups_members([$group1->id, $group3->id]);
1815          $this->assertCount(1, $members);
1816          $this->assertEquals($user1->id, $members[$user1->id]->id);
1817  
1818          // Empty group.
1819          $members = groups_get_groups_members([$group3->id]);
1820          $this->assertCount(0, $members);
1821  
1822          // Our second group.
1823          $members = groups_get_groups_members([$group2->id]);
1824          $this->assertEqualsCanonicalizing([$user1->id, $user2->id], array_column($members, 'id'));
1825  
1826          // Test the info matches group membership for the entire course.
1827          $groups  = groups_get_all_groups($course2->id, 0, 0, 'g.*', true);
1828          $group2withmembers = $groups[$group2->id];
1829  
1830          // Compare the sorted keys of both arrays (should be list of user ids).
1831          $members = array_keys($members);
1832          sort($members);
1833          $group2members = array_keys($group2withmembers->members);
1834          sort($group2members);
1835          $this->assertEquals($members, $group2members);
1836  
1837      }
1838  
1839      /**
1840       * Tests for groups_get_activity_shared_group_members() method.
1841       */
1842      public function test_groups_get_activity_shared_group_members() {
1843          $this->resetAfterTest(true);
1844          $generator = $this->getDataGenerator();
1845  
1846          // Create courses.
1847          $course = $generator->create_course();
1848  
1849          // Create cm.
1850          $assign = $generator->create_module("assign", array('course' => $course->id));
1851          $cm = get_coursemodule_from_instance("assign", $assign->id);
1852  
1853          // Create users.
1854          $user1 = $generator->create_user();
1855          $user2 = $generator->create_user();
1856          $user3 = $generator->create_user();
1857          $user4 = $generator->create_user();
1858  
1859          // Enrol users.
1860          $generator->enrol_user($user1->id, $course->id);
1861          $generator->enrol_user($user2->id, $course->id);
1862          $generator->enrol_user($user3->id, $course->id);
1863          $generator->enrol_user($user4->id, $course->id);
1864  
1865          // Create groups.
1866          $group1 = $generator->create_group(array('courseid' => $course->id));
1867          $group2 = $generator->create_group(array('courseid' => $course->id));
1868          $group3 = $generator->create_group(array('courseid' => $course->id));
1869  
1870          // Assign users to groups.
1871          $generator->create_group_member(array('groupid' => $group1->id, 'userid' => $user1->id));
1872          $generator->create_group_member(array('groupid' => $group2->id, 'userid' => $user1->id));
1873          $generator->create_group_member(array('groupid' => $group2->id, 'userid' => $user2->id));
1874          $generator->create_group_member(array('groupid' => $group3->id, 'userid' => $user3->id));
1875  
1876          // Retrieve users sharing groups with user1.
1877          $members = groups_get_activity_shared_group_members($cm, $user1->id);
1878          $this->assertCount(2, $members);
1879          $this->assertEqualsCanonicalizing([$user1->id, $user2->id], array_keys($members));
1880  
1881          // Retrieve users sharing groups with user2.
1882          $members = groups_get_activity_shared_group_members($cm, $user2->id);
1883          $this->assertCount(2, $members);
1884          $this->assertEqualsCanonicalizing([$user1->id, $user2->id], array_keys($members));
1885  
1886          // Retrieve users sharing groups with user3.
1887          $members = groups_get_activity_shared_group_members($cm, $user3->id);
1888          $this->assertCount(1, $members);
1889          $this->assertEquals($user3->id, $members[$user3->id]->id);
1890  
1891          // Retrieve users sharing groups with user without groups (user4).
1892          $members = groups_get_activity_shared_group_members($cm, $user4->id);
1893          $this->assertCount(0, $members);
1894  
1895          // Now, create a different activity using groupings.
1896          $grouping = $generator->create_grouping(array('courseid' => $course->id, 'name' => 'Grouping 1'));
1897          // Skip group 2.
1898          groups_assign_grouping($grouping->id, $group1->id);
1899          groups_assign_grouping($grouping->id, $group3->id);
1900  
1901          $assign = $generator->create_module("assign", array('course' => $course->id, 'groupingid' => $grouping->id));
1902          $cm = get_coursemodule_from_instance("assign", $assign->id);
1903  
1904          // Since the activity is forced to groupings (groups 1 and 3), I don't see members of group 2.
1905          $members = groups_get_activity_shared_group_members($cm, $user1->id);
1906          $this->assertCount(1, $members);
1907          $this->assertEquals($user1->id, $members[$user1->id]->id);
1908  
1909          // Add user1 to group 3 (in the grouping).
1910          $generator->create_group_member(array('groupid' => $group3->id, 'userid' => $user1->id));
1911          $members = groups_get_activity_shared_group_members($cm, $user1->id);
1912          $this->assertCount(2, $members);    // Now I see members of group 3.
1913          $this->assertEqualsCanonicalizing([$user1->id, $user3->id], array_keys($members));
1914      }
1915  
1916      /**
1917       * Generate a set of groups with different visibility levels and users to assign to them.
1918       *
1919       * @return array
1920       */
1921      protected function create_groups_with_visibilty(): array {
1922          $this->resetAfterTest(true);
1923          $generator = $this->getDataGenerator();
1924  
1925          // Create courses.
1926          $course = $generator->create_course();
1927  
1928          // Create users.
1929          $users = [
1930              1 => $generator->create_user(),
1931              2 => $generator->create_user(),
1932              3 => $generator->create_user(),
1933              4 => $generator->create_user(),
1934              5 => $generator->create_user(),
1935          ];
1936  
1937          // Enrol users.
1938          $generator->enrol_user($users[1]->id, $course->id);
1939          $generator->enrol_user($users[2]->id, $course->id);
1940          $generator->enrol_user($users[3]->id, $course->id);
1941          $generator->enrol_user($users[4]->id, $course->id);
1942          $generator->enrol_user($users[5]->id, $course->id, 'editingteacher');
1943  
1944          // Create groups.
1945          $groups = [
1946              'all' => $generator->create_group(['courseid' => $course->id, 'visibility' => GROUPS_VISIBILITY_ALL]),
1947              'members' => $generator->create_group(['courseid' => $course->id, 'visibility' => GROUPS_VISIBILITY_MEMBERS]),
1948              'own' => $generator->create_group(['courseid' => $course->id, 'visibility' => GROUPS_VISIBILITY_OWN]),
1949              'none' => $generator->create_group(['courseid' => $course->id, 'visibility' => GROUPS_VISIBILITY_NONE]),
1950          ];
1951  
1952          return [
1953               $users,
1954               $groups,
1955               $course,
1956          ];
1957      }
1958  
1959      /**
1960       * Tests getting groups and group members based on visibility settings.
1961       *
1962       * This also covers the groupdata cache, since calls without $withmembers = true use the cache.
1963       *
1964       * @covers \groups_get_all_groups()
1965       */
1966      public function test_get_all_groups_with_visibility() {
1967          list($users, $groups, $course) = $this->create_groups_with_visibilty();
1968  
1969          // Assign users to groups.
1970          $generator = $this->getDataGenerator();
1971          $generator->create_group_member(['groupid' => $groups['all']->id, 'userid' => $users[1]->id]);
1972          $generator->create_group_member(['groupid' => $groups['members']->id, 'userid' => $users[1]->id]);
1973          $generator->create_group_member(['groupid' => $groups['members']->id, 'userid' => $users[2]->id]);
1974          $generator->create_group_member(['groupid' => $groups['own']->id, 'userid' => $users[1]->id]);
1975          $generator->create_group_member(['groupid' => $groups['own']->id, 'userid' => $users[3]->id]);
1976          $generator->create_group_member(['groupid' => $groups['none']->id, 'userid' => $users[4]->id]);
1977  
1978          $this->setUser($users[1]);
1979          $groups1 = groups_get_all_groups($course->id);
1980          // User1 is in groups all, members and own, and can see them.
1981          $this->assertArrayHasKey($groups['all']->id, $groups1);
1982          $this->assertArrayHasKey($groups['members']->id, $groups1);
1983          $this->assertArrayHasKey($groups['own']->id, $groups1);
1984          $this->assertArrayNotHasKey($groups['none']->id, $groups1);
1985          // User1 can see members of groups all and members, but only themselves in group own.
1986          $groupsmembers1 = groups_get_all_groups($course->id, 0, 0, 'g.*', true);
1987          $this->assertArrayHasKey($users[1]->id, $groupsmembers1[$groups['all']->id]->members);
1988          $this->assertArrayHasKey($users[1]->id, $groupsmembers1[$groups['members']->id]->members);
1989          $this->assertArrayHasKey($users[2]->id, $groupsmembers1[$groups['members']->id]->members);
1990          $this->assertArrayHasKey($users[1]->id, $groupsmembers1[$groups['own']->id]->members);
1991          $this->assertArrayNotHasKey($users[3]->id, $groupsmembers1[$groups['own']->id]->members);
1992  
1993          $this->setUser($users[2]);
1994          $groups2 = groups_get_all_groups($course->id);
1995          // User2 is in group members, and can see group all as well.
1996          $this->assertArrayHasKey($groups['all']->id, $groups2);
1997          $this->assertArrayHasKey($groups['members']->id, $groups2);
1998          $this->assertArrayNotHasKey($groups['own']->id, $groups2);
1999          $this->assertArrayNotHasKey($groups['none']->id, $groups2);
2000          // User2 can see members of groups all and members.
2001          $groupsmembers2 = groups_get_all_groups($course->id, 0, 0, 'g.*', true);
2002          $this->assertArrayHasKey($users[1]->id, $groupsmembers2[$groups['all']->id]->members);
2003          $this->assertArrayHasKey($users[1]->id, $groupsmembers2[$groups['members']->id]->members);
2004          $this->assertArrayHasKey($users[2]->id, $groupsmembers2[$groups['members']->id]->members);
2005  
2006          $this->setUser($users[3]);
2007          $groups3 = groups_get_all_groups($course->id);
2008          // User3 is in group own, and can see group all as well.
2009          $this->assertArrayHasKey($groups['all']->id, $groups3);
2010          $this->assertArrayNotHasKey($groups['members']->id, $groups3);
2011          $this->assertArrayHasKey($groups['own']->id, $groups3);
2012          $this->assertArrayNotHasKey($groups['none']->id, $groups3);
2013          $groupsmembers3 = groups_get_all_groups($course->id, 0, 0, 'g.*', true);
2014          // User3 can see members of group all, but only themselves in group own.
2015          $this->assertArrayHasKey($users[1]->id, $groupsmembers3[$groups['all']->id]->members);
2016          $this->assertArrayHasKey($users[3]->id, $groupsmembers3[$groups['own']->id]->members);
2017          $this->assertArrayNotHasKey($users[1]->id, $groupsmembers3[$groups['own']->id]->members);
2018  
2019          $this->setUser($users[4]);
2020          $groups4 = groups_get_all_groups($course->id);
2021          // User4 can see group all and its members. They are in group none but cannot see it.
2022          $this->assertArrayHasKey($groups['all']->id, $groups4);
2023          $this->assertArrayNotHasKey($groups['members']->id, $groups4);
2024          $this->assertArrayNotHasKey($groups['own']->id, $groups4);
2025          $this->assertArrayNotHasKey($groups['none']->id, $groups4);
2026          // User4 can see members of group all.
2027          $groupsmembers4 = groups_get_all_groups($course->id, 0, 0, 'g.*', true);
2028          $this->assertArrayHasKey($users[1]->id, $groupsmembers4[$groups['all']->id]->members);
2029  
2030          $this->setUser($users[5]);
2031          $groups5 = groups_get_all_groups($course->id);
2032          // User5 is has viewallgroups, so can see all groups.
2033          $this->assertArrayHasKey($groups['all']->id, $groups5);
2034          $this->assertArrayHasKey($groups['members']->id, $groups5);
2035          $this->assertArrayHasKey($groups['own']->id, $groups5);
2036          $this->assertArrayHasKey($groups['none']->id, $groups5);
2037          // User5 is has viewallgroups, so can see all members.
2038          $groupsmembers5 = groups_get_all_groups($course->id, 0, 0, 'g.*', true);
2039          $this->assertArrayHasKey($users[1]->id, $groupsmembers5[$groups['all']->id]->members);
2040          $this->assertArrayHasKey($users[1]->id, $groupsmembers5[$groups['members']->id]->members);
2041          $this->assertArrayHasKey($users[2]->id, $groupsmembers5[$groups['members']->id]->members);
2042          $this->assertArrayHasKey($users[1]->id, $groupsmembers5[$groups['own']->id]->members);
2043          $this->assertArrayHasKey($users[3]->id, $groupsmembers5[$groups['own']->id]->members);
2044          $this->assertArrayHasKey($users[4]->id, $groupsmembers5[$groups['none']->id]->members);
2045  
2046      }
2047  
2048      /**
2049       * Tests getting groups the current user is a member of, with visibility settings applied.
2050       *
2051       * @covers \groups_get_my_groups()
2052       */
2053      public function test_get_my_groups_with_visibility() {
2054          list($users, $groups) = $this->create_groups_with_visibilty();
2055  
2056          // Assign users to groups.
2057          $generator = $this->getDataGenerator();
2058          $generator->create_group_member(['groupid' => $groups['all']->id, 'userid' => $users[1]->id]);
2059          $generator->create_group_member(['groupid' => $groups['members']->id, 'userid' => $users[1]->id]);
2060          $generator->create_group_member(['groupid' => $groups['own']->id, 'userid' => $users[1]->id]);
2061          $generator->create_group_member(['groupid' => $groups['none']->id, 'userid' => $users[1]->id]);
2062          $generator->create_group_member(['groupid' => $groups['all']->id, 'userid' => $users[5]->id]);
2063          $generator->create_group_member(['groupid' => $groups['members']->id, 'userid' => $users[5]->id]);
2064          $generator->create_group_member(['groupid' => $groups['own']->id, 'userid' => $users[5]->id]);
2065          $generator->create_group_member(['groupid' => $groups['none']->id, 'userid' => $users[5]->id]);
2066  
2067          $generator->role_assign('editingteacher', $users[5]->id, \context_system::instance());
2068  
2069          // User can see all groups they are in, except group with visibility::NONE.
2070          $this->setUser($users[1]);
2071          $groups1 = groups_get_my_groups();
2072          $this->assertCount(3, $groups1);
2073          $groupids1 = array_map(function($groupmember) {
2074              return $groupmember->groupid;
2075          }, $groups1);
2076          sort($groupids1);
2077          $this->assertEquals([$groups['all']->id, $groups['members']->id, $groups['own']->id], $groupids1);
2078  
2079          $this->setUser($users[5]);
2080          $groups2 = groups_get_my_groups();
2081          $this->assertCount(4, $groups2);
2082          $groupids2 = array_map(function($groupmember) {
2083              return $groupmember->groupid;
2084          }, $groups2);
2085          sort($groupids2);
2086          $this->assertEquals([$groups['all']->id, $groups['members']->id, $groups['own']->id, $groups['none']->id], $groupids2);
2087      }
2088  
2089      /**
2090       * Tests getting groups a user is a member of, with visibility settings applied.
2091       *
2092       * @covers \groups_get_user_groups()
2093       */
2094      public function test_get_user_groups_with_visibility() {
2095          list($users, $groups, $course) = $this->create_groups_with_visibilty();
2096  
2097          // Assign users to groups.
2098          $generator = $this->getDataGenerator();
2099          $generator->create_group_member(['groupid' => $groups['all']->id, 'userid' => $users[1]->id]);
2100          $generator->create_group_member(['groupid' => $groups['members']->id, 'userid' => $users[1]->id]);
2101          $generator->create_group_member(['groupid' => $groups['members']->id, 'userid' => $users[2]->id]);
2102          $generator->create_group_member(['groupid' => $groups['own']->id, 'userid' => $users[1]->id]);
2103          $generator->create_group_member(['groupid' => $groups['own']->id, 'userid' => $users[3]->id]);
2104          $generator->create_group_member(['groupid' => $groups['none']->id, 'userid' => $users[4]->id]);
2105          $generator->create_group_member(['groupid' => $groups['none']->id, 'userid' => $users[1]->id]);
2106  
2107          // Run as unprivileged user.
2108          $this->setUser($users[1]);
2109          // Own groups - should see all groups except group with visibility::NONE.
2110          $usergroups1 = groups_get_user_groups($course->id, $users[1]->id);
2111          $this->assertEquals([$groups['all']->id, $groups['members']->id, $groups['own']->id], $usergroups1[0]);
2112          // Fellow member of a group with visiblity::MEMBERS. Should see that group.
2113          $usergroups2 = groups_get_user_groups($course->id, $users[2]->id);
2114          $this->assertEquals([$groups['members']->id], $usergroups2[0]);
2115          // Fellow member of a group with visiblity::OWN. Should not see that group.
2116          $usergroups3 = groups_get_user_groups($course->id, $users[3]->id);
2117          $this->assertEmpty($usergroups3[0]);
2118          // Fellow member of a group with visiblity::NONE. Should not see that group.
2119          $usergroups4 = groups_get_user_groups($course->id, $users[4]->id);
2120          $this->assertEmpty($usergroups4[0]);
2121  
2122          // Run as a user with viewhiddengroups. Should see all group memberships for each member.
2123          $this->setUser($users[5]);
2124          $usergroups1 = groups_get_user_groups($course->id, $users[1]->id);
2125          $this->assertEquals([$groups['all']->id, $groups['members']->id, $groups['own']->id, $groups['none']->id], $usergroups1[0]);
2126          // Fellow member of a group with visiblity::MEMBERS. Should see that group.
2127          $usergroups2 = groups_get_user_groups($course->id, $users[2]->id);
2128          $this->assertEquals([$groups['members']->id], $usergroups2[0]);
2129          // Fellow member of a group with visiblity::OWN. Should not see that group.
2130          $usergroups3 = groups_get_user_groups($course->id, $users[3]->id);
2131          $this->assertEquals([$groups['own']->id], $usergroups3[0]);
2132          // Fellow member of a group with visiblity::NONE. Should not see that group.
2133          $usergroups4 = groups_get_user_groups($course->id, $users[4]->id);
2134          $this->assertEquals([$groups['none']->id], $usergroups4[0]);
2135  
2136      }
2137  
2138      /**
2139       * Test groups_is_member() using groups with different visibility settings.
2140       *
2141       * @covers \groups_is_member()
2142       */
2143      public function test_groups_is_member_with_visibility(): void {
2144          list($users, $groups) = $this->create_groups_with_visibilty();
2145  
2146          // Assign users to groups.
2147          $generator = $this->getDataGenerator();
2148          $generator->create_group_member(['groupid' => $groups['all']->id, 'userid' => $users[1]->id]);
2149          $generator->create_group_member(['groupid' => $groups['members']->id, 'userid' => $users[1]->id]);
2150          $generator->create_group_member(['groupid' => $groups['members']->id, 'userid' => $users[2]->id]);
2151          $generator->create_group_member(['groupid' => $groups['own']->id, 'userid' => $users[1]->id]);
2152          $generator->create_group_member(['groupid' => $groups['own']->id, 'userid' => $users[3]->id]);
2153          $generator->create_group_member(['groupid' => $groups['none']->id, 'userid' => $users[4]->id]);
2154          $generator->create_group_member(['groupid' => $groups['none']->id, 'userid' => $users[1]->id]);
2155  
2156          // Run as unprivileged user.
2157          $this->setUser($users[1]);
2158          $this->assertTrue(groups_is_member($groups['all']->id, $users[1]->id)); // All can see members.
2159          $this->assertTrue(groups_is_member($groups['members']->id, $users[1]->id)); // Can see members.
2160          $this->assertTrue(groups_is_member($groups['own']->id, $users[1]->id)); // Can see own membership.
2161          $this->assertFalse(groups_is_member($groups['none']->id, $users[1]->id)); // Cannot see group.
2162  
2163          $this->assertFalse(groups_is_member($groups['all']->id, $users[2]->id)); // Not a member.
2164          $this->assertTrue(groups_is_member($groups['members']->id, $users[2]->id)); // Can see other members.
2165          $this->assertFalse(groups_is_member($groups['own']->id, $users[3]->id)); // Can only see own membership, not others.
2166          $this->assertFalse(groups_is_member($groups['none']->id, $users[4]->id)); // Cannot see group.
2167  
2168          // Run as a user not in group 1 or 2.
2169          $this->setUser($users[3]);
2170          $this->assertTrue(groups_is_member($groups['all']->id, $users[1]->id)); // All can see members.
2171          $this->assertFalse(groups_is_member($groups['members']->id, $users[2]->id)); // Cannot see members of the group.
2172  
2173          // Run as a user with viewhiddengroups. Should be able to see memberships that exist in any group.
2174          $this->setUser($users[5]);
2175          $this->assertTrue(groups_is_member($groups['all']->id, $users[1]->id));
2176          $this->assertTrue(groups_is_member($groups['members']->id, $users[1]->id));
2177          $this->assertTrue(groups_is_member($groups['own']->id, $users[1]->id));
2178          $this->assertTrue(groups_is_member($groups['none']->id, $users[1]->id));
2179  
2180          $this->assertFalse(groups_is_member($groups['all']->id, $users[2]->id)); // Not a member.
2181          $this->assertTrue(groups_is_member($groups['members']->id, $users[2]->id));
2182          $this->assertTrue(groups_is_member($groups['own']->id, $users[3]->id));
2183          $this->assertTrue(groups_is_member($groups['none']->id, $users[4]->id));
2184      }
2185  
2186      /**
2187       * Test groups_get_members
2188       *
2189       * @covers ::groups_get_members
2190       */
2191      public function test_groups_get_members(): void {
2192          $this->resetAfterTest();
2193  
2194          $course = $this->getDataGenerator()->create_course();
2195          $userone = $this->getDataGenerator()->create_and_enrol($course);
2196          $usertwo = $this->getDataGenerator()->create_and_enrol($course);
2197  
2198          $group = $this->getDataGenerator()->create_group(['courseid' => $course->id]);
2199          $this->getDataGenerator()->create_group_member(['groupid' => $group->id, 'userid' => $userone->id]);
2200          $this->getDataGenerator()->create_group_member(['groupid' => $group->id, 'userid' => $usertwo->id]);
2201  
2202          $users = groups_get_members($group->id);
2203          $this->assertEqualsCanonicalizing([$userone->id, $usertwo->id], array_column($users, 'id'));
2204  
2205          // Test invalid group.
2206          $users = groups_get_members(-1);
2207          $this->assertEmpty($users);
2208      }
2209  
2210      /**
2211       * Test groups_get_members() using groups with different visibility settings.
2212       *
2213       * @covers ::groups_get_members
2214       */
2215      public function test_groups_get_members_with_visibility(): void {
2216          list($users, $groups) = $this->create_groups_with_visibilty();
2217  
2218          // Assign users to groups.
2219          $generator = $this->getDataGenerator();
2220          $generator->create_group_member(['groupid' => $groups['all']->id, 'userid' => $users[1]->id]);
2221          $generator->create_group_member(['groupid' => $groups['members']->id, 'userid' => $users[1]->id]);
2222          $generator->create_group_member(['groupid' => $groups['members']->id, 'userid' => $users[2]->id]);
2223          $generator->create_group_member(['groupid' => $groups['own']->id, 'userid' => $users[1]->id]);
2224          $generator->create_group_member(['groupid' => $groups['own']->id, 'userid' => $users[3]->id]);
2225          $generator->create_group_member(['groupid' => $groups['none']->id, 'userid' => $users[4]->id]);
2226          $generator->create_group_member(['groupid' => $groups['none']->id, 'userid' => $users[1]->id]);
2227  
2228          // Run as unprivileged user.
2229          $this->setUser($users[1]);
2230          $this->assertEquals([$users[1]->id],
2231                  array_keys(groups_get_members($groups['all']->id, 'u.id', 'u.id'))); // All can see members.
2232          $this->assertEquals([$users[1]->id, $users[2]->id],
2233                  array_keys(groups_get_members($groups['members']->id, 'u.id', 'u.id'))); // Can see members.
2234          $this->assertEquals([$users[1]->id],
2235                  array_keys(groups_get_members($groups['own']->id, 'u.id', 'u.id'))); // Can see own membership.
2236          $this->assertEquals([], array_keys(groups_get_members($groups['none']->id, 'u.id', 'u.id'))); // Cannot see group.
2237  
2238          // Run as a user not in group 1 or 2.
2239          $this->setUser($users[3]);
2240          $this->assertEquals([$users[1]->id],
2241                  array_keys(groups_get_members($groups['all']->id, 'u.id', 'u.id'))); // All can see members.
2242          $this->assertEquals([], array_keys(groups_get_members($groups['members']->id, 'u.id', 'u.id'))); // Cannot see members.
2243  
2244          // Run as a user with viewhiddengroups. Should be able to see memberships that exist in any group.
2245          $this->setUser($users[5]);
2246          $this->assertEquals([$users[1]->id], array_keys(groups_get_members($groups['all']->id, 'u.id', 'u.id')));
2247          $this->assertEquals([$users[1]->id, $users[2]->id],
2248                  array_keys(groups_get_members($groups['members']->id, 'u.id', 'u.id')));
2249          $this->assertEquals([$users[1]->id, $users[3]->id],
2250                  array_keys(groups_get_members($groups['own']->id, 'u.id', 'u.id')));
2251          $this->assertEquals([$users[1]->id, $users[4]->id],
2252                  array_keys(groups_get_members($groups['none']->id, 'u.id', 'u.id')));
2253      }
2254  
2255      /**
2256       * Test groups_get_groups_members() using groups with different visibility settings.
2257       *
2258       * @covers \groups_get_groups_members()
2259       */
2260      public function test_groups_get_groups_members_with_visibility(): void {
2261          list($users, $groups) = $this->create_groups_with_visibilty();
2262  
2263          // Assign users to groups.
2264          $generator = $this->getDataGenerator();
2265          $generator->create_group_member(['groupid' => $groups['all']->id, 'userid' => $users[1]->id]);
2266          $generator->create_group_member(['groupid' => $groups['members']->id, 'userid' => $users[1]->id]);
2267          $generator->create_group_member(['groupid' => $groups['members']->id, 'userid' => $users[2]->id]);
2268          $generator->create_group_member(['groupid' => $groups['own']->id, 'userid' => $users[1]->id]);
2269          $generator->create_group_member(['groupid' => $groups['own']->id, 'userid' => $users[3]->id]);
2270          $generator->create_group_member(['groupid' => $groups['none']->id, 'userid' => $users[4]->id]);
2271          $generator->create_group_member(['groupid' => $groups['none']->id, 'userid' => $users[1]->id]);
2272  
2273          $groupids = [$groups['all']->id, $groups['members']->id, $groups['own']->id, $groups['none']->id];
2274  
2275          $this->setUser($users[1]);
2276          // Can see self in group1/3, other users in group2.
2277          $this->assertEquals([$users[1]->id, $users[2]->id], array_keys(groups_get_groups_members($groupids, null, 'id ASC')));
2278  
2279          $this->setUser($users[2]);
2280          // Can see self in group2, user1 from group1/2.
2281          $this->assertEquals([$users[1]->id, $users[2]->id], array_keys(groups_get_groups_members($groupids, null, 'id ASC')));
2282  
2283          $this->setUser($users[3]);
2284          // Can see self in group3, user1 from group1.
2285          $this->assertEquals([$users[1]->id, $users[3]->id], array_keys(groups_get_groups_members($groupids, null, 'id ASC')));
2286  
2287          $this->setUser($users[4]);
2288          // Can see user1 from group1, cannot see self in group4.
2289          $this->assertEquals([$users[1]->id], array_keys(groups_get_groups_members($groupids, null, 'id ASC')));
2290  
2291          $this->setUser($users[5]);
2292          // Can see all users from all groups.
2293          $this->assertEquals([$users[1]->id, $users[2]->id, $users[3]->id, $users[4]->id],
2294                  array_keys(groups_get_groups_members($groupids, null, 'id ASC')));
2295      }
2296  
2297      /**
2298       * Only groups with participation == true should be returned for an activity.
2299       *
2300       * @covers \groups_get_activity_allowed_groups()
2301       * @return void
2302       * @throws \coding_exception
2303       */
2304      public function test_groups_get_activity_allowed_groups(): void {
2305          $this->resetAfterTest(true);
2306          $generator = $this->getDataGenerator();
2307  
2308          // Create courses.
2309          $course = $generator->create_course();
2310  
2311          // Create user.
2312          $user = $generator->create_user();
2313  
2314          // Enrol user.
2315          $generator->enrol_user($user->id, $course->id);
2316  
2317          // Create groups.
2318          $groups = [
2319              'all-p' => $generator->create_group(['courseid' => $course->id, 'visibility' => GROUPS_VISIBILITY_ALL]),
2320              'members-p' => $generator->create_group(['courseid' => $course->id, 'visibility' => GROUPS_VISIBILITY_MEMBERS]),
2321              'all-n' => $generator->create_group([
2322                  'courseid' => $course->id,
2323                  'visibility' => GROUPS_VISIBILITY_ALL,
2324                  'participation' => false
2325              ]),
2326              'members-n' => $generator->create_group([
2327                  'courseid' => $course->id,
2328                  'visibility' => GROUPS_VISIBILITY_MEMBERS,
2329                  'participation' => false
2330              ]),
2331              'own' => $generator->create_group(['courseid' => $course->id, 'visibility' => GROUPS_VISIBILITY_OWN]),
2332              'none' => $generator->create_group(['courseid' => $course->id, 'visibility' => GROUPS_VISIBILITY_NONE]),
2333          ];
2334          // Add user to all groups.
2335          $generator->create_group_member(['groupid' => $groups['all-p']->id, 'userid' => $user->id]);
2336          $generator->create_group_member(['groupid' => $groups['members-p']->id, 'userid' => $user->id]);
2337          $generator->create_group_member(['groupid' => $groups['all-n']->id, 'userid' => $user->id]);
2338          $generator->create_group_member(['groupid' => $groups['members-n']->id, 'userid' => $user->id]);
2339          $generator->create_group_member(['groupid' => $groups['own']->id, 'userid' => $user->id]);
2340          $generator->create_group_member(['groupid' => $groups['none']->id, 'userid' => $user->id]);
2341  
2342          $module = $generator->create_module('forum', ['course' => $course->id]);
2343          $cm = get_fast_modinfo($course)->get_cm($module->cmid);
2344  
2345          $activitygroups = groups_get_activity_allowed_groups($cm, $user->id);
2346  
2347          $this->assertContains((int)$groups['all-p']->id, array_keys($activitygroups));
2348          $this->assertContains((int)$groups['members-p']->id, array_keys($activitygroups));
2349          $this->assertNotContains((int)$groups['all-n']->id, array_keys($activitygroups));
2350          $this->assertNotContains((int)$groups['members-n']->id, array_keys($activitygroups));
2351          $this->assertNotContains((int)$groups['own']->id, array_keys($activitygroups));
2352          $this->assertNotContains((int)$groups['none']->id, array_keys($activitygroups));
2353  
2354      }
2355  }