Search moodle.org's
Developer Documentation

See Release Notes
Long Term Support Release

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

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

   1  <?php
   2  // This file is part of Moodle - http://moodle.org/
   3  //
   4  // Moodle is free software: you can redistribute it and/or modify
   5  // it under the terms of the GNU General Public License as published by
   6  // the Free Software Foundation, either version 3 of the License, or
   7  // (at your option) any later version.
   8  //
   9  // Moodle is distributed in the hope that it will be useful,
  10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12  // GNU General Public License for more details.
  13  //
  14  // You should have received a copy of the GNU General Public License
  15  // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
  16  
  17  namespace core_group;
  18  
  19  use core_group_external;
  20  use externallib_advanced_testcase;
  21  
  22  defined('MOODLE_INTERNAL') || die();
  23  
  24  global $CFG;
  25  
  26  require_once($CFG->dirroot . '/webservice/tests/helpers.php');
  27  require_once($CFG->dirroot . '/group/externallib.php');
  28  require_once($CFG->dirroot . '/group/lib.php');
  29  
  30  /**
  31   * Group external PHPunit tests
  32   *
  33   * @package    core_group
  34   * @category   external
  35   * @copyright  2012 Jerome Mouneyrac
  36   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  37   * @since Moodle 2.4
  38   */
  39  class externallib_test extends externallib_advanced_testcase {
  40  
  41      /**
  42       * Test create_groups
  43       */
  44      public function test_create_groups() {
  45          global $DB;
  46  
  47          $this->resetAfterTest(true);
  48  
  49          $course  = self::getDataGenerator()->create_course();
  50  
  51          $group1 = array();
  52          $group1['courseid'] = $course->id;
  53          $group1['name'] = 'Group Test 1';
  54          $group1['description'] = 'Group Test 1 description';
  55          $group1['descriptionformat'] = FORMAT_MOODLE;
  56          $group1['enrolmentkey'] = 'Test group enrol secret phrase';
  57          $group1['idnumber'] = 'TEST1';
  58          $group2 = array();
  59          $group2['courseid'] = $course->id;
  60          $group2['name'] = 'Group Test 2';
  61          $group2['description'] = 'Group Test 2 description';
  62          $group3 = array();
  63          $group3['courseid'] = $course->id;
  64          $group3['name'] = 'Group Test 3';
  65          $group3['description'] = 'Group Test 3 description';
  66          $group3['idnumber'] = 'TEST1';
  67          $group4 = array();
  68          $group4['courseid'] = $course->id;
  69          $group4['name'] = 'Group Test 4';
  70          $group4['description'] = 'Group Test 4 description';
  71  
  72          // Set the required capabilities by the external function
  73          $context = \context_course::instance($course->id);
  74          $roleid = $this->assignUserCapability('moodle/course:managegroups', $context->id);
  75          $this->assignUserCapability('moodle/course:view', $context->id, $roleid);
  76  
  77          // Call the external function.
  78          $groups = core_group_external::create_groups(array($group1, $group2));
  79  
  80          // We need to execute the return values cleaning process to simulate the web service server.
  81          $groups = \external_api::clean_returnvalue(core_group_external::create_groups_returns(), $groups);
  82  
  83          // Checks against DB values
  84          $this->assertEquals(2, count($groups));
  85          foreach ($groups as $group) {
  86              $dbgroup = $DB->get_record('groups', array('id' => $group['id']), '*', MUST_EXIST);
  87              switch ($dbgroup->name) {
  88                  case $group1['name']:
  89                      $groupdescription = $group1['description'];
  90                      $groupcourseid = $group1['courseid'];
  91                      $this->assertEquals($dbgroup->descriptionformat, $group1['descriptionformat']);
  92                      $this->assertEquals($dbgroup->enrolmentkey, $group1['enrolmentkey']);
  93                      $this->assertEquals($dbgroup->idnumber, $group1['idnumber']);
  94                      break;
  95                  case $group2['name']:
  96                      $groupdescription = $group2['description'];
  97                      $groupcourseid = $group2['courseid'];
  98                      break;
  99                  default:
 100                      throw new \moodle_exception('unknowgroupname');
 101                      break;
 102              }
 103              $this->assertEquals($dbgroup->description, $groupdescription);
 104              $this->assertEquals($dbgroup->courseid, $groupcourseid);
 105          }
 106  
 107          try {
 108              $froups = core_group_external::create_groups(array($group3));
 109              $this->fail('Exception expected due to already existing idnumber.');
 110          } catch (\moodle_exception $e) {
 111              $this->assertInstanceOf('moodle_exception', $e);
 112              $this->assertEquals(get_string('idnumbertaken', 'error'), $e->getMessage());
 113          }
 114  
 115          // Call without required capability
 116          $this->unassignUserCapability('moodle/course:managegroups', $context->id, $roleid);
 117  
 118          $this->expectException(\required_capability_exception::class);
 119          $froups = core_group_external::create_groups(array($group4));
 120      }
 121  
 122      /**
 123       * Test update_groups
 124       */
 125      public function test_update_groups() {
 126          global $DB;
 127  
 128          $this->resetAfterTest(true);
 129  
 130          $course = self::getDataGenerator()->create_course();
 131  
 132          $group1data = array();
 133          $group1data['courseid'] = $course->id;
 134          $group1data['name'] = 'Group Test 1';
 135          $group1data['description'] = 'Group Test 1 description';
 136          $group1data['descriptionformat'] = FORMAT_MOODLE;
 137          $group1data['enrolmentkey'] = 'Test group enrol secret phrase';
 138          $group1data['idnumber'] = 'TEST1';
 139          $group2data = array();
 140          $group2data['courseid'] = $course->id;
 141          $group2data['name'] = 'Group Test 2';
 142          $group2data['description'] = 'Group Test 2 description';
 143          $group2data['idnumber'] = 'TEST2';
 144  
 145          // Set the required capabilities by the external function.
 146          $context = \context_course::instance($course->id);
 147          $roleid = $this->assignUserCapability('moodle/course:managegroups', $context->id);
 148          $this->assignUserCapability('moodle/course:view', $context->id, $roleid);
 149  
 150          // Create the test groups.
 151          $group1 = self::getDataGenerator()->create_group($group1data);
 152          $group2 = self::getDataGenerator()->create_group($group2data);
 153  
 154          $group1data['id'] = $group1->id;
 155          unset($group1data['courseid']);
 156          $group2data['id'] = $group2->id;
 157          unset($group2data['courseid']);
 158  
 159          // No exceptions should be triggered.
 160          $group1data['idnumber'] = 'CHANGED';
 161          core_group_external::update_groups(array($group1data));
 162          $group2data['description'] = 'Group Test 2 description CHANGED';
 163          core_group_external::update_groups(array($group2data));
 164  
 165          foreach ([$group1, $group2] as $group) {
 166              $dbgroup = $DB->get_record('groups', array('id' => $group->id), '*', MUST_EXIST);
 167              switch ($dbgroup->name) {
 168                  case $group1data['name']:
 169                      $this->assertEquals($dbgroup->idnumber, $group1data['idnumber']);
 170                      $groupdescription = $group1data['description'];
 171                      break;
 172                  case $group2data['name']:
 173                      $this->assertEquals($dbgroup->idnumber, $group2data['idnumber']);
 174                      $groupdescription = $group2data['description'];
 175                      break;
 176                  default:
 177                      throw new \moodle_exception('unknowngroupname');
 178                      break;
 179              }
 180              $this->assertEquals($dbgroup->description, $groupdescription);
 181          }
 182  
 183          // Taken idnumber exception.
 184          $group1data['idnumber'] = 'TEST2';
 185          try {
 186              $groups = core_group_external::update_groups(array($group1data));
 187              $this->fail('Exception expected due to already existing idnumber.');
 188          } catch (\moodle_exception $e) {
 189              $this->assertInstanceOf('moodle_exception', $e);
 190              $this->assertEquals(get_string('idnumbertaken', 'error'), $e->getMessage());
 191          }
 192  
 193          // Call without required capability.
 194          $group1data['idnumber'] = 'TEST1';
 195          $this->unassignUserCapability('moodle/course:managegroups', $context->id, $roleid);
 196  
 197          $this->expectException(\required_capability_exception::class);
 198          $groups = core_group_external::update_groups(array($group1data));
 199      }
 200  
 201      /**
 202       * Test get_groups
 203       */
 204      public function test_get_groups() {
 205          global $DB;
 206  
 207          $this->resetAfterTest(true);
 208  
 209          $course = self::getDataGenerator()->create_course();
 210          $group1data = array();
 211          $group1data['courseid'] = $course->id;
 212          $group1data['name'] = 'Group Test 1';
 213          $group1data['description'] = 'Group Test 1 description';
 214          $group1data['descriptionformat'] = FORMAT_MOODLE;
 215          $group1data['enrolmentkey'] = 'Test group enrol secret phrase';
 216          $group1data['idnumber'] = 'TEST1';
 217          $group2data = array();
 218          $group2data['courseid'] = $course->id;
 219          $group2data['name'] = 'Group Test 2';
 220          $group2data['description'] = 'Group Test 2 description';
 221          $group1 = self::getDataGenerator()->create_group($group1data);
 222          $group2 = self::getDataGenerator()->create_group($group2data);
 223  
 224          // Set the required capabilities by the external function
 225          $context = \context_course::instance($course->id);
 226          $roleid = $this->assignUserCapability('moodle/course:managegroups', $context->id);
 227          $this->assignUserCapability('moodle/course:view', $context->id, $roleid);
 228  
 229          // Call the external function.
 230          $groups = core_group_external::get_groups(array($group1->id, $group2->id));
 231  
 232          // We need to execute the return values cleaning process to simulate the web service server.
 233          $groups = \external_api::clean_returnvalue(core_group_external::get_groups_returns(), $groups);
 234  
 235          // Checks against DB values
 236          $this->assertEquals(2, count($groups));
 237          foreach ($groups as $group) {
 238              $dbgroup = $DB->get_record('groups', array('id' => $group['id']), '*', MUST_EXIST);
 239              switch ($dbgroup->name) {
 240                  case $group1->name:
 241                      $groupdescription = $group1->description;
 242                      $groupcourseid = $group1->courseid;
 243                      $this->assertEquals($dbgroup->descriptionformat, $group1->descriptionformat);
 244                      $this->assertEquals($dbgroup->enrolmentkey, $group1->enrolmentkey);
 245                      $this->assertEquals($dbgroup->idnumber, $group1->idnumber);
 246                      break;
 247                  case $group2->name:
 248                      $groupdescription = $group2->description;
 249                      $groupcourseid = $group2->courseid;
 250                      break;
 251                  default:
 252                      throw new \moodle_exception('unknowgroupname');
 253                      break;
 254              }
 255              $this->assertEquals($dbgroup->description, $groupdescription);
 256              $this->assertEquals($dbgroup->courseid, $groupcourseid);
 257          }
 258  
 259          // Call without required capability
 260          $this->unassignUserCapability('moodle/course:managegroups', $context->id, $roleid);
 261  
 262          $this->expectException(\required_capability_exception::class);
 263          $groups = core_group_external::get_groups(array($group1->id, $group2->id));
 264      }
 265  
 266      /**
 267       * Test delete_groups
 268       */
 269      public function test_delete_groups() {
 270          global $DB;
 271  
 272          $this->resetAfterTest(true);
 273  
 274          $course = self::getDataGenerator()->create_course();
 275          $group1data = array();
 276          $group1data['courseid'] = $course->id;
 277          $group1data['name'] = 'Group Test 1';
 278          $group1data['description'] = 'Group Test 1 description';
 279          $group1data['descriptionformat'] = FORMAT_MOODLE;
 280          $group1data['enrolmentkey'] = 'Test group enrol secret phrase';
 281          $group2data = array();
 282          $group2data['courseid'] = $course->id;
 283          $group2data['name'] = 'Group Test 2';
 284          $group2data['description'] = 'Group Test 2 description';
 285          $group3data['courseid'] = $course->id;
 286          $group3data['name'] = 'Group Test 3';
 287          $group3data['description'] = 'Group Test 3 description';
 288          $group1 = self::getDataGenerator()->create_group($group1data);
 289          $group2 = self::getDataGenerator()->create_group($group2data);
 290          $group3 = self::getDataGenerator()->create_group($group3data);
 291  
 292          // Set the required capabilities by the external function
 293          $context = \context_course::instance($course->id);
 294          $roleid = $this->assignUserCapability('moodle/course:managegroups', $context->id);
 295          $this->assignUserCapability('moodle/course:view', $context->id, $roleid);
 296  
 297          // Checks against DB values
 298          $groupstotal = $DB->count_records('groups', array());
 299          $this->assertEquals(3, $groupstotal);
 300  
 301          // Call the external function.
 302          core_group_external::delete_groups(array($group1->id, $group2->id));
 303  
 304          // Checks against DB values
 305          $groupstotal = $DB->count_records('groups', array());
 306          $this->assertEquals(1, $groupstotal);
 307  
 308          // Call without required capability
 309          $this->unassignUserCapability('moodle/course:managegroups', $context->id, $roleid);
 310  
 311          $this->expectException(\required_capability_exception::class);
 312          $froups = core_group_external::delete_groups(array($group3->id));
 313      }
 314  
 315      /**
 316       * Test create and update groupings.
 317       * @return void
 318       */
 319      public function test_create_update_groupings() {
 320          global $DB;
 321  
 322          $this->resetAfterTest(true);
 323  
 324          $this->setAdminUser();
 325  
 326          $course = self::getDataGenerator()->create_course();
 327  
 328          $grouping1data = array();
 329          $grouping1data['courseid'] = $course->id;
 330          $grouping1data['name'] = 'Grouping 1 Test';
 331          $grouping1data['description'] = 'Grouping 1 Test description';
 332          $grouping1data['descriptionformat'] = FORMAT_MOODLE;
 333          $grouping1data['idnumber'] = 'TEST';
 334  
 335          $grouping1 = self::getDataGenerator()->create_grouping($grouping1data);
 336  
 337          $grouping1data['name'] = 'Another group';
 338  
 339          try {
 340              $groupings = core_group_external::create_groupings(array($grouping1data));
 341              $this->fail('Exception expected due to already existing idnumber.');
 342          } catch (\moodle_exception $e) {
 343              $this->assertInstanceOf('moodle_exception', $e);
 344              $this->assertEquals(get_string('idnumbertaken', 'error'), $e->getMessage());
 345          }
 346  
 347          // No exception should be triggered.
 348          $grouping1data['id'] = $grouping1->id;
 349          $grouping1data['idnumber'] = 'CHANGED';
 350          unset($grouping1data['courseid']);
 351          core_group_external::update_groupings(array($grouping1data));
 352  
 353          $grouping2data = array();
 354          $grouping2data['courseid'] = $course->id;
 355          $grouping2data['name'] = 'Grouping 2 Test';
 356          $grouping2data['description'] = 'Grouping 2 Test description';
 357          $grouping2data['descriptionformat'] = FORMAT_MOODLE;
 358          $grouping2data['idnumber'] = 'TEST';
 359  
 360          $grouping2 = self::getDataGenerator()->create_grouping($grouping2data);
 361  
 362          $grouping2data['id'] = $grouping2->id;
 363          $grouping2data['idnumber'] = 'CHANGED';
 364          unset($grouping2data['courseid']);
 365          try {
 366              $groupings = core_group_external::update_groupings(array($grouping2data));
 367              $this->fail('Exception expected due to already existing idnumber.');
 368          } catch (\moodle_exception $e) {
 369              $this->assertInstanceOf('moodle_exception', $e);
 370              $this->assertEquals(get_string('idnumbertaken', 'error'), $e->getMessage());
 371          }
 372      }
 373  
 374      /**
 375       * Test get_groupings
 376       */
 377      public function test_get_groupings() {
 378          global $DB;
 379  
 380          $this->resetAfterTest(true);
 381  
 382          $course = self::getDataGenerator()->create_course();
 383  
 384          $groupingdata = array();
 385          $groupingdata['courseid'] = $course->id;
 386          $groupingdata['name'] = 'Grouping Test';
 387          $groupingdata['description'] = 'Grouping Test description';
 388          $groupingdata['descriptionformat'] = FORMAT_MOODLE;
 389  
 390          $grouping = self::getDataGenerator()->create_grouping($groupingdata);
 391  
 392          // Set the required capabilities by the external function.
 393          $context = \context_course::instance($course->id);
 394          $roleid = $this->assignUserCapability('moodle/course:managegroups', $context->id);
 395          $this->assignUserCapability('moodle/course:view', $context->id, $roleid);
 396  
 397          // Call the external function without specifying the optional parameter.
 398          $groupings = core_group_external::get_groupings(array($grouping->id));
 399          // We need to execute the return values cleaning process to simulate the web service server.
 400          $groupings = \external_api::clean_returnvalue(core_group_external::get_groupings_returns(), $groupings);
 401  
 402          $this->assertEquals(1, count($groupings));
 403  
 404          $group1data = array();
 405          $group1data['courseid'] = $course->id;
 406          $group1data['name'] = 'Group Test 1';
 407          $group1data['description'] = 'Group Test 1 description';
 408          $group1data['descriptionformat'] = FORMAT_MOODLE;
 409          $group2data = array();
 410          $group2data['courseid'] = $course->id;
 411          $group2data['name'] = 'Group Test 2';
 412          $group2data['description'] = 'Group Test 2 description';
 413          $group2data['descriptionformat'] = FORMAT_MOODLE;
 414  
 415          $group1 = self::getDataGenerator()->create_group($group1data);
 416          $group2 = self::getDataGenerator()->create_group($group2data);
 417  
 418          groups_assign_grouping($grouping->id, $group1->id);
 419          groups_assign_grouping($grouping->id, $group2->id);
 420  
 421          // Call the external function specifying that groups are returned.
 422          $groupings = core_group_external::get_groupings(array($grouping->id), true);
 423          // We need to execute the return values cleaning process to simulate the web service server.
 424          $groupings = \external_api::clean_returnvalue(core_group_external::get_groupings_returns(), $groupings);
 425          $this->assertEquals(1, count($groupings));
 426          $this->assertEquals(2, count($groupings[0]['groups']));
 427          foreach ($groupings[0]['groups'] as $group) {
 428              $dbgroup = $DB->get_record('groups', array('id' => $group['id']), '*', MUST_EXIST);
 429              $dbgroupinggroups = $DB->get_record('groupings_groups',
 430                                                  array('groupingid' => $groupings[0]['id'],
 431                                                        'groupid' => $group['id']),
 432                                                  '*', MUST_EXIST);
 433              switch ($dbgroup->name) {
 434                  case $group1->name:
 435                      $groupdescription = $group1->description;
 436                      $groupcourseid = $group1->courseid;
 437                      break;
 438                  case $group2->name:
 439                      $groupdescription = $group2->description;
 440                      $groupcourseid = $group2->courseid;
 441                      break;
 442                  default:
 443                      throw new \moodle_exception('unknowgroupname');
 444                      break;
 445              }
 446              $this->assertEquals($dbgroup->description, $groupdescription);
 447              $this->assertEquals($dbgroup->courseid, $groupcourseid);
 448          }
 449      }
 450  
 451      /**
 452       * Test delete_groupings.
 453       */
 454      public function test_delete_groupings() {
 455          global $DB;
 456  
 457          $this->resetAfterTest(true);
 458  
 459          $course = self::getDataGenerator()->create_course();
 460  
 461          $groupingdata1 = array();
 462          $groupingdata1['courseid'] = $course->id;
 463          $groupingdata1['name'] = 'Grouping Test';
 464          $groupingdata1['description'] = 'Grouping Test description';
 465          $groupingdata1['descriptionformat'] = FORMAT_MOODLE;
 466          $groupingdata2 = array();
 467          $groupingdata2['courseid'] = $course->id;
 468          $groupingdata2['name'] = 'Grouping Test';
 469          $groupingdata2['description'] = 'Grouping Test description';
 470          $groupingdata2['descriptionformat'] = FORMAT_MOODLE;
 471          $groupingdata3 = array();
 472          $groupingdata3['courseid'] = $course->id;
 473          $groupingdata3['name'] = 'Grouping Test';
 474          $groupingdata3['description'] = 'Grouping Test description';
 475          $groupingdata3['descriptionformat'] = FORMAT_MOODLE;
 476  
 477          $grouping1 = self::getDataGenerator()->create_grouping($groupingdata1);
 478          $grouping2 = self::getDataGenerator()->create_grouping($groupingdata2);
 479          $grouping3 = self::getDataGenerator()->create_grouping($groupingdata3);
 480  
 481          // Set the required capabilities by the external function.
 482          $context = \context_course::instance($course->id);
 483          $roleid = $this->assignUserCapability('moodle/course:managegroups', $context->id);
 484          $this->assignUserCapability('moodle/course:view', $context->id, $roleid);
 485  
 486          // Checks against DB values.
 487          $groupingstotal = $DB->count_records('groupings', array());
 488          $this->assertEquals(3, $groupingstotal);
 489  
 490          // Call the external function.
 491          core_group_external::delete_groupings(array($grouping1->id, $grouping2->id));
 492  
 493          // Checks against DB values.
 494          $groupingstotal = $DB->count_records('groupings', array());
 495          $this->assertEquals(1, $groupingstotal);
 496  
 497          // Call without required capability.
 498          $this->unassignUserCapability('moodle/course:managegroups', $context->id, $roleid);
 499  
 500          $this->expectException(\required_capability_exception::class);
 501          core_group_external::delete_groupings(array($grouping3->id));
 502      }
 503  
 504      /**
 505       * Test get_groups
 506       */
 507      public function test_get_course_user_groups() {
 508          global $DB;
 509  
 510          $this->resetAfterTest(true);
 511  
 512          $student1 = self::getDataGenerator()->create_user();
 513          $student2 = self::getDataGenerator()->create_user();
 514          $teacher = self::getDataGenerator()->create_user();
 515  
 516          $course = self::getDataGenerator()->create_course();
 517          $anothercourse = self::getDataGenerator()->create_course();
 518          $emptycourse = self::getDataGenerator()->create_course();
 519  
 520          $studentrole = $DB->get_record('role', array('shortname' => 'student'));
 521          $this->getDataGenerator()->enrol_user($student1->id, $course->id, $studentrole->id);
 522          $this->getDataGenerator()->enrol_user($student1->id, $anothercourse->id, $studentrole->id);
 523          $this->getDataGenerator()->enrol_user($student2->id, $course->id, $studentrole->id);
 524  
 525          $teacherrole = $DB->get_record('role', array('shortname' => 'editingteacher'));
 526          $this->getDataGenerator()->enrol_user($teacher->id, $course->id, $teacherrole->id);
 527          $this->getDataGenerator()->enrol_user($teacher->id, $emptycourse->id, $teacherrole->id);
 528  
 529          $group1data = array();
 530          $group1data['courseid'] = $course->id;
 531          $group1data['name'] = 'Group Test 1';
 532          $group1data['description'] = 'Group Test 1 description';
 533          $group1data['idnumber'] = 'TEST1';
 534          $group2data = array();
 535          $group2data['courseid'] = $course->id;
 536          $group2data['name'] = 'Group Test 2';
 537          $group2data['description'] = 'Group Test 2 description';
 538          $group3data = array();
 539          $group3data['courseid'] = $anothercourse->id;
 540          $group3data['name'] = 'Group Test 3';
 541          $group3data['description'] = 'Group Test 3 description';
 542          $group3data['idnumber'] = 'TEST3';
 543          $group1 = self::getDataGenerator()->create_group($group1data);
 544          $group2 = self::getDataGenerator()->create_group($group2data);
 545          $group3 = self::getDataGenerator()->create_group($group3data);
 546  
 547          groups_add_member($group1->id, $student1->id);
 548          groups_add_member($group1->id, $student2->id);
 549          groups_add_member($group2->id, $student1->id);
 550          groups_add_member($group3->id, $student1->id);
 551  
 552          // Create a grouping.
 553          $groupingdata = array();
 554          $groupingdata['courseid'] = $course->id;
 555          $groupingdata['name'] = 'Grouping Test';
 556          $groupingdata['description'] = 'Grouping Test description';
 557          $groupingdata['descriptionformat'] = FORMAT_MOODLE;
 558  
 559          $grouping = self::getDataGenerator()->create_grouping($groupingdata);
 560          // Grouping only containing group1.
 561          groups_assign_grouping($grouping->id, $group1->id);
 562  
 563          $this->setUser($student1);
 564  
 565          $groups = core_group_external::get_course_user_groups($course->id, $student1->id);
 566          $groups = \external_api::clean_returnvalue(core_group_external::get_course_user_groups_returns(), $groups);
 567          // Check that I see my groups.
 568          $this->assertCount(2, $groups['groups']);
 569          $this->assertEquals($course->id, $groups['groups'][0]['courseid']);
 570          $this->assertEquals($course->id, $groups['groups'][1]['courseid']);
 571  
 572          // Check that I only see my groups inside the given grouping.
 573          $groups = core_group_external::get_course_user_groups($course->id, $student1->id, $grouping->id);
 574          $groups = \external_api::clean_returnvalue(core_group_external::get_course_user_groups_returns(), $groups);
 575          // Check that I see my groups in the grouping.
 576          $this->assertCount(1, $groups['groups']);
 577          $this->assertEquals($group1->id, $groups['groups'][0]['id']);
 578  
 579  
 580          // Check optional parameters (all student 1 courses and current user).
 581          $groups = core_group_external::get_course_user_groups();
 582          $groups = \external_api::clean_returnvalue(core_group_external::get_course_user_groups_returns(), $groups);
 583          // Check that I see my groups in all my courses.
 584          $this->assertCount(3, $groups['groups']);
 585  
 586          $this->setUser($student2);
 587          $groups = core_group_external::get_course_user_groups($course->id, $student2->id);
 588          $groups = \external_api::clean_returnvalue(core_group_external::get_course_user_groups_returns(), $groups);
 589          // Check that I see my groups.
 590          $this->assertCount(1, $groups['groups']);
 591  
 592          $this->assertEquals($group1data['name'], $groups['groups'][0]['name']);
 593          $this->assertEquals($group1data['description'], $groups['groups'][0]['description']);
 594          $this->assertEquals($group1data['idnumber'], $groups['groups'][0]['idnumber']);
 595  
 596          $this->setUser($teacher);
 597          $groups = core_group_external::get_course_user_groups($course->id, $student1->id);
 598          $groups = \external_api::clean_returnvalue(core_group_external::get_course_user_groups_returns(), $groups);
 599          // Check that a teacher can see student groups in given course.
 600          $this->assertCount(2, $groups['groups']);
 601  
 602          $groups = core_group_external::get_course_user_groups($course->id, $student2->id);
 603          $groups = \external_api::clean_returnvalue(core_group_external::get_course_user_groups_returns(), $groups);
 604          // Check that a teacher can see student groups in given course.
 605          $this->assertCount(1, $groups['groups']);
 606  
 607          $groups = core_group_external::get_course_user_groups(0, $student1->id);
 608          $groups = \external_api::clean_returnvalue(core_group_external::get_course_user_groups_returns(), $groups);
 609          // Check that a teacher can see student groups in all the user courses if the teacher is enrolled in the course.
 610          $this->assertCount(2, $groups['groups']); // Teacher only see groups in first course.
 611          $this->assertCount(1, $groups['warnings']); // Enrolment warnings.
 612          $this->assertEquals('1', $groups['warnings'][0]['warningcode']);
 613  
 614          // Enrol teacher in second course.
 615          $this->getDataGenerator()->enrol_user($teacher->id, $anothercourse->id, $teacherrole->id);
 616          $groups = core_group_external::get_course_user_groups(0, $student1->id);
 617          $groups = \external_api::clean_returnvalue(core_group_external::get_course_user_groups_returns(), $groups);
 618          // Check that a teacher can see student groups in all the user courses if the teacher is enrolled in the course.
 619          $this->assertCount(3, $groups['groups']);
 620  
 621          // Check permissions.
 622          $this->setUser($student1);
 623  
 624          // Student can's see other students group.
 625          $groups = core_group_external::get_course_user_groups($course->id, $student2->id);
 626          $groups = \external_api::clean_returnvalue(core_group_external::get_course_user_groups_returns(), $groups);
 627          $this->assertCount(1, $groups['warnings']);
 628          $this->assertEquals('cannotmanagegroups', $groups['warnings'][0]['warningcode']);
 629  
 630          // Not enrolled course.
 631          $groups = core_group_external::get_course_user_groups($emptycourse->id, $student2->id);
 632          $groups = \external_api::clean_returnvalue(core_group_external::get_course_user_groups_returns(), $groups);
 633          $this->assertCount(1, $groups['warnings']);
 634          $this->assertEquals('1', $groups['warnings'][0]['warningcode']);
 635  
 636          $this->setUser($teacher);
 637          // Check user checking not enrolled in given course.
 638          $groups = core_group_external::get_course_user_groups($emptycourse->id, $student1->id);
 639          $groups = \external_api::clean_returnvalue(core_group_external::get_course_user_groups_returns(), $groups);
 640          $this->assertCount(1, $groups['warnings']);
 641          $this->assertEquals('notenrolled', $groups['warnings'][0]['warningcode']);
 642      }
 643  
 644      /**
 645       * Test get_activity_allowed_groups
 646       */
 647      public function test_get_activity_allowed_groups() {
 648          global $DB;
 649  
 650          $this->resetAfterTest(true);
 651  
 652          $generator = self::getDataGenerator();
 653  
 654          $student = $generator->create_user();
 655          $otherstudent = $generator->create_user();
 656          $teacher = $generator->create_user();
 657          $course = $generator->create_course();
 658          $othercourse = $generator->create_course();
 659  
 660          $studentrole = $DB->get_record('role', array('shortname' => 'student'));
 661          $teacherrole = $DB->get_record('role', array('shortname' => 'editingteacher'));
 662          $generator->enrol_user($student->id, $course->id, $studentrole->id);
 663          $generator->enrol_user($otherstudent->id, $othercourse->id, $studentrole->id);
 664          $generator->enrol_user($teacher->id, $course->id, $teacherrole->id);
 665  
 666          $forum1 = $generator->create_module("forum", array('course' => $course->id), array('groupmode' => VISIBLEGROUPS));
 667          $forum2 = $generator->create_module("forum", array('course' => $othercourse->id));
 668          $forum3 = $generator->create_module("forum", array('course' => $course->id), array('visible' => 0));
 669  
 670          // Request data for tests.
 671          $cm1 = get_coursemodule_from_instance("forum", $forum1->id);
 672          $cm2 = get_coursemodule_from_instance("forum", $forum2->id);
 673          $cm3 = get_coursemodule_from_instance("forum", $forum3->id);
 674  
 675          $group1data = array();
 676          $group1data['courseid'] = $course->id;
 677          $group1data['name'] = 'Group Test 1';
 678          $group1data['description'] = 'Group Test 1 description';
 679          $group1data['idnumber'] = 'TEST1';
 680          $group2data = array();
 681          $group2data['courseid'] = $course->id;
 682          $group2data['name'] = 'Group Test 2';
 683          $group2data['description'] = 'Group Test 2 description';
 684          $group2data['idnumber'] = 'TEST2';
 685          $group1 = $generator->create_group($group1data);
 686          $group2 = $generator->create_group($group2data);
 687  
 688          groups_add_member($group1->id, $student->id);
 689          groups_add_member($group2->id, $student->id);
 690  
 691          $this->setUser($student);
 692  
 693          // First try possible errors.
 694          try {
 695              $data = core_group_external::get_activity_allowed_groups($cm2->id);
 696          } catch (\moodle_exception $e) {
 697              $this->assertEquals('requireloginerror', $e->errorcode);
 698          }
 699  
 700          try {
 701              $data = core_group_external::get_activity_allowed_groups($cm3->id);
 702          } catch (\moodle_exception $e) {
 703              $this->assertEquals('requireloginerror', $e->errorcode);
 704          }
 705  
 706          // Retrieve my groups.
 707          $groups = core_group_external::get_activity_allowed_groups($cm1->id);
 708          $groups = \external_api::clean_returnvalue(core_group_external::get_activity_allowed_groups_returns(), $groups);
 709          $this->assertCount(2, $groups['groups']);
 710          $this->assertFalse($groups['canaccessallgroups']);
 711  
 712          foreach ($groups['groups'] as $group) {
 713              if ($group['name'] == $group1data['name']) {
 714                  $this->assertEquals($group1data['description'], $group['description']);
 715                  $this->assertEquals($group1data['idnumber'], $group['idnumber']);
 716              } else {
 717                  $this->assertEquals($group2data['description'], $group['description']);
 718                  $this->assertEquals($group2data['idnumber'], $group['idnumber']);
 719              }
 720          }
 721  
 722          $this->setUser($teacher);
 723          // Retrieve other users groups.
 724          $groups = core_group_external::get_activity_allowed_groups($cm1->id, $student->id);
 725          $groups = \external_api::clean_returnvalue(core_group_external::get_activity_allowed_groups_returns(), $groups);
 726          $this->assertCount(2, $groups['groups']);
 727          // We are checking the $student passed as parameter so this will return false.
 728          $this->assertFalse($groups['canaccessallgroups']);
 729  
 730          // Check warnings. Trying to get groups for a user not enrolled in course.
 731          $groups = core_group_external::get_activity_allowed_groups($cm1->id, $otherstudent->id);
 732          $groups = \external_api::clean_returnvalue(core_group_external::get_activity_allowed_groups_returns(), $groups);
 733          $this->assertCount(1, $groups['warnings']);
 734          $this->assertFalse($groups['canaccessallgroups']);
 735  
 736          // Checking teacher groups.
 737          $groups = core_group_external::get_activity_allowed_groups($cm1->id);
 738          $groups = \external_api::clean_returnvalue(core_group_external::get_activity_allowed_groups_returns(), $groups);
 739          $this->assertCount(2, $groups['groups']);
 740          // Teachers by default can access all groups.
 741          $this->assertTrue($groups['canaccessallgroups']);
 742      }
 743  
 744      /**
 745       * Test get_activity_groupmode
 746       */
 747      public function test_get_activity_groupmode() {
 748          global $DB;
 749  
 750          $this->resetAfterTest(true);
 751  
 752          $generator = self::getDataGenerator();
 753  
 754          $student = $generator->create_user();
 755          $course = $generator->create_course();
 756          $othercourse = $generator->create_course();
 757  
 758          $studentrole = $DB->get_record('role', array('shortname' => 'student'));
 759          $generator->enrol_user($student->id, $course->id, $studentrole->id);
 760  
 761          $forum1 = $generator->create_module("forum", array('course' => $course->id), array('groupmode' => VISIBLEGROUPS));
 762          $forum2 = $generator->create_module("forum", array('course' => $othercourse->id));
 763          $forum3 = $generator->create_module("forum", array('course' => $course->id), array('visible' => 0));
 764  
 765          // Request data for tests.
 766          $cm1 = get_coursemodule_from_instance("forum", $forum1->id);
 767          $cm2 = get_coursemodule_from_instance("forum", $forum2->id);
 768          $cm3 = get_coursemodule_from_instance("forum", $forum3->id);
 769  
 770          $this->setUser($student);
 771  
 772          $data = core_group_external::get_activity_groupmode($cm1->id);
 773          $data = \external_api::clean_returnvalue(core_group_external::get_activity_groupmode_returns(), $data);
 774          $this->assertEquals(VISIBLEGROUPS, $data['groupmode']);
 775  
 776          try {
 777              $data = core_group_external::get_activity_groupmode($cm2->id);
 778          } catch (\moodle_exception $e) {
 779              $this->assertEquals('requireloginerror', $e->errorcode);
 780          }
 781  
 782          try {
 783              $data = core_group_external::get_activity_groupmode($cm3->id);
 784          } catch (\moodle_exception $e) {
 785              $this->assertEquals('requireloginerror', $e->errorcode);
 786          }
 787  
 788      }
 789  
 790      /**
 791       * Test add_group_members.
 792       */
 793      public function test_add_group_members() {
 794          global $DB;
 795  
 796          $this->resetAfterTest(true);
 797  
 798          $student1 = self::getDataGenerator()->create_user();
 799          $student2 = self::getDataGenerator()->create_user();
 800          $student3 = self::getDataGenerator()->create_user();
 801  
 802          $course = self::getDataGenerator()->create_course();
 803  
 804          $studentrole = $DB->get_record('role', array('shortname' => 'student'));
 805          $this->getDataGenerator()->enrol_user($student1->id, $course->id, $studentrole->id);
 806          $this->getDataGenerator()->enrol_user($student2->id, $course->id, $studentrole->id);
 807          $this->getDataGenerator()->enrol_user($student3->id, $course->id, $studentrole->id);
 808  
 809          $group1data = array();
 810          $group1data['courseid'] = $course->id;
 811          $group1data['name'] = 'Group Test 1';
 812          $group1data['description'] = 'Group Test 1 description';
 813          $group1data['idnumber'] = 'TEST1';
 814          $group1 = self::getDataGenerator()->create_group($group1data);
 815  
 816          // Checks against DB values.
 817          $memberstotal = $DB->count_records('groups_members', ['groupid' => $group1->id]);
 818          $this->assertEquals(0, $memberstotal);
 819  
 820          // Set the required capabilities by the external function.
 821          $context = \context_course::instance($course->id);
 822          $roleid = $this->assignUserCapability('moodle/course:managegroups', $context->id);
 823          $this->assignUserCapability('moodle/course:view', $context->id, $roleid);
 824  
 825          core_group_external::add_group_members([
 826              'members' => [
 827                  'groupid' => $group1->id,
 828                  'userid' => $student1->id,
 829              ]
 830          ]);
 831          core_group_external::add_group_members([
 832              'members' => [
 833                  'groupid' => $group1->id,
 834                  'userid' => $student2->id,
 835              ]
 836          ]);
 837          core_group_external::add_group_members([
 838              'members' => [
 839                  'groupid' => $group1->id,
 840                  'userid' => $student3->id,
 841              ]
 842          ]);
 843  
 844          // Checks against DB values.
 845          $memberstotal = $DB->count_records('groups_members', ['groupid' => $group1->id]);
 846          $this->assertEquals(3, $memberstotal);
 847      }
 848  
 849      /**
 850       * Test delete_group_members.
 851       */
 852      public function test_delete_group_members() {
 853          global $DB;
 854  
 855          $this->resetAfterTest(true);
 856  
 857          $student1 = self::getDataGenerator()->create_user();
 858          $student2 = self::getDataGenerator()->create_user();
 859          $student3 = self::getDataGenerator()->create_user();
 860  
 861          $course = self::getDataGenerator()->create_course();
 862  
 863          $studentrole = $DB->get_record('role', array('shortname' => 'student'));
 864          $this->getDataGenerator()->enrol_user($student1->id, $course->id, $studentrole->id);
 865          $this->getDataGenerator()->enrol_user($student2->id, $course->id, $studentrole->id);
 866          $this->getDataGenerator()->enrol_user($student3->id, $course->id, $studentrole->id);
 867  
 868          $group1data = array();
 869          $group1data['courseid'] = $course->id;
 870          $group1data['name'] = 'Group Test 1';
 871          $group1data['description'] = 'Group Test 1 description';
 872          $group1data['idnumber'] = 'TEST1';
 873          $group1 = self::getDataGenerator()->create_group($group1data);
 874  
 875          groups_add_member($group1->id, $student1->id);
 876          groups_add_member($group1->id, $student2->id);
 877          groups_add_member($group1->id, $student3->id);
 878  
 879          // Checks against DB values.
 880          $memberstotal = $DB->count_records('groups_members', ['groupid' => $group1->id]);
 881          $this->assertEquals(3, $memberstotal);
 882  
 883          // Set the required capabilities by the external function.
 884          $context = \context_course::instance($course->id);
 885          $roleid = $this->assignUserCapability('moodle/course:managegroups', $context->id);
 886          $this->assignUserCapability('moodle/course:view', $context->id, $roleid);
 887  
 888          core_group_external::delete_group_members([
 889              'members' => [
 890                  'groupid' => $group1->id,
 891                  'userid' => $student2->id,
 892              ]
 893          ]);
 894  
 895          // Checks against DB values.
 896          $memberstotal = $DB->count_records('groups_members', ['groupid' => $group1->id]);
 897          $this->assertEquals(2, $memberstotal);
 898      }
 899  }