Search moodle.org's
Developer Documentation

See Release Notes
Long Term Support Release

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

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

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