Search moodle.org's
Developer Documentation

See Release Notes

  • Bug fixes for general core bugs in 3.11.x will end 14 Nov 2022 (12 months plus 6 months extension).
  • Bug fixes for security issues in 3.11.x will end 13 Nov 2023 (18 months plus 12 months extension).
  • PHP version: minimum PHP 7.3.0 Note: minimum PHP version has increased since Moodle 3.10. PHP 7.4.x is supported too.

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

   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_cohort;
  18  
  19  use core_cohort_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 . '/cohort/externallib.php');
  28  
  29  /**
  30   * External cohort API
  31   *
  32   * @package    core_cohort
  33   * @category   external
  34   * @copyright  MediaTouch 2000 srl
  35   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  36   */
  37  class externallib_test extends externallib_advanced_testcase {
  38  
  39      /**
  40       * Test create_cohorts
  41       */
  42      public function test_create_cohorts() {
  43          global $USER, $CFG, $DB;
  44  
  45          $this->resetAfterTest(true);
  46  
  47          set_config('allowcohortthemes', 1);
  48  
  49          $contextid = \context_system::instance()->id;
  50          $category = $this->getDataGenerator()->create_category();
  51  
  52          $cohort1 = array(
  53              'categorytype' => array('type' => 'id', 'value' => $category->id),
  54              'name' => 'cohort test 1',
  55              'idnumber' => 'cohorttest1',
  56              'description' => 'This is a description for cohorttest1',
  57              'theme' => 'classic'
  58              );
  59  
  60          $cohort2 = array(
  61              'categorytype' => array('type' => 'system', 'value' => ''),
  62              'name' => 'cohort test 2',
  63              'idnumber' => 'cohorttest2',
  64              'description' => 'This is a description for cohorttest2',
  65              'visible' => 0
  66              );
  67  
  68          $cohort3 = array(
  69              'categorytype' => array('type' => 'id', 'value' => $category->id),
  70              'name' => 'cohort test 3',
  71              'idnumber' => 'cohorttest3',
  72              'description' => 'This is a description for cohorttest3'
  73              );
  74          $roleid = $this->assignUserCapability('moodle/cohort:manage', $contextid);
  75  
  76          $cohort4 = array(
  77              'categorytype' => array('type' => 'id', 'value' => $category->id),
  78              'name' => 'cohort test 4',
  79              'idnumber' => 'cohorttest4',
  80              'description' => 'This is a description for cohorttest4',
  81              'theme' => 'classic'
  82              );
  83  
  84          // Call the external function.
  85          $this->setCurrentTimeStart();
  86          $createdcohorts = core_cohort_external::create_cohorts(array($cohort1, $cohort2));
  87          $createdcohorts = \external_api::clean_returnvalue(core_cohort_external::create_cohorts_returns(), $createdcohorts);
  88  
  89          // Check we retrieve the good total number of created cohorts + no error on capability.
  90          $this->assertEquals(2, count($createdcohorts));
  91  
  92          foreach ($createdcohorts as $createdcohort) {
  93              $dbcohort = $DB->get_record('cohort', array('id' => $createdcohort['id']));
  94              if ($createdcohort['idnumber'] == $cohort1['idnumber']) {
  95                  $conid = $DB->get_field('context', 'id', array('instanceid' => $cohort1['categorytype']['value'],
  96                          'contextlevel' => CONTEXT_COURSECAT));
  97                  $this->assertEquals($dbcohort->contextid, $conid);
  98                  $this->assertEquals($dbcohort->name, $cohort1['name']);
  99                  $this->assertEquals($dbcohort->description, $cohort1['description']);
 100                  $this->assertEquals($dbcohort->visible, 1); // Field was not specified, ensure it is visible by default.
 101                  // As $CFG->allowcohortthemes is enabled, theme must be initialised.
 102                  $this->assertEquals($dbcohort->theme, $cohort1['theme']);
 103              } else if ($createdcohort['idnumber'] == $cohort2['idnumber']) {
 104                  $this->assertEquals($dbcohort->contextid, \context_system::instance()->id);
 105                  $this->assertEquals($dbcohort->name, $cohort2['name']);
 106                  $this->assertEquals($dbcohort->description, $cohort2['description']);
 107                  $this->assertEquals($dbcohort->visible, $cohort2['visible']);
 108                  // Although $CFG->allowcohortthemes is enabled, no theme is defined for this cohort.
 109                  $this->assertEquals($dbcohort->theme, '');
 110              } else {
 111                  $this->fail('Unrecognised cohort found');
 112              }
 113              $this->assertTimeCurrent($dbcohort->timecreated);
 114              $this->assertTimeCurrent($dbcohort->timemodified);
 115          }
 116  
 117          // Call when $CFG->allowcohortthemes is disabled.
 118          set_config('allowcohortthemes', 0);
 119          $createdcohorts = core_cohort_external::create_cohorts(array($cohort4));
 120          $createdcohorts = \external_api::clean_returnvalue(core_cohort_external::create_cohorts_returns(), $createdcohorts);
 121          foreach ($createdcohorts as $createdcohort) {
 122              $dbcohort = $DB->get_record('cohort', array('id' => $createdcohort['id']));
 123              if ($createdcohort['idnumber'] == $cohort4['idnumber']) {
 124                  $conid = $DB->get_field('context', 'id', array('instanceid' => $cohort4['categorytype']['value'],
 125                          'contextlevel' => CONTEXT_COURSECAT));
 126                  $this->assertEquals($dbcohort->contextid, $conid);
 127                  $this->assertEquals($dbcohort->name, $cohort4['name']);
 128                  $this->assertEquals($dbcohort->description, $cohort4['description']);
 129                  $this->assertEquals($dbcohort->visible, 1); // Field was not specified, ensure it is visible by default.
 130                  $this->assertEquals($dbcohort->theme, ''); // As $CFG->allowcohortthemes is disabled, theme must be empty.
 131              }
 132          }
 133  
 134          // Call without required capability.
 135          $this->unassignUserCapability('moodle/cohort:manage', $contextid, $roleid);
 136          $this->expectException(\required_capability_exception::class);
 137          $createdcohorts = core_cohort_external::create_cohorts(array($cohort3));
 138      }
 139  
 140      /**
 141       * Test delete_cohorts
 142       */
 143      public function test_delete_cohorts() {
 144          global $USER, $CFG, $DB;
 145  
 146          $this->resetAfterTest(true);
 147  
 148          $cohort1 = self::getDataGenerator()->create_cohort();
 149          $cohort2 = self::getDataGenerator()->create_cohort();
 150          // Check the cohorts were correctly created.
 151          $this->assertEquals(2, $DB->count_records_select('cohort', ' (id = :cohortid1 OR id = :cohortid2)',
 152                  array('cohortid1' => $cohort1->id, 'cohortid2' => $cohort2->id)));
 153  
 154          $contextid = $cohort1->contextid;
 155          $roleid = $this->assignUserCapability('moodle/cohort:manage', $contextid);
 156  
 157          // Call the external function.
 158          core_cohort_external::delete_cohorts(array($cohort1->id, $cohort2->id));
 159  
 160          // Check we retrieve no cohorts + no error on capability.
 161          $this->assertEquals(0, $DB->count_records_select('cohort', ' (id = :cohortid1 OR id = :cohortid2)',
 162                  array('cohortid1' => $cohort1->id, 'cohortid2' => $cohort2->id)));
 163  
 164          // Call without required capability.
 165          $cohort1 = self::getDataGenerator()->create_cohort();
 166          $cohort2 = self::getDataGenerator()->create_cohort();
 167          $this->unassignUserCapability('moodle/cohort:manage', $contextid, $roleid);
 168          $this->expectException(\required_capability_exception::class);
 169          core_cohort_external::delete_cohorts(array($cohort1->id, $cohort2->id));
 170      }
 171  
 172      /**
 173       * Test get_cohorts
 174       */
 175      public function test_get_cohorts() {
 176          global $USER, $CFG;
 177  
 178          $this->resetAfterTest(true);
 179  
 180          set_config('allowcohortthemes', 1);
 181  
 182          $cohort1 = array(
 183              'contextid' => 1,
 184              'name' => 'cohortnametest1',
 185              'idnumber' => 'idnumbertest1',
 186              'description' => 'This is a description for cohort 1',
 187              'theme' => 'classic'
 188              );
 189          $cohort1 = self::getDataGenerator()->create_cohort($cohort1);
 190          $cohort2 = self::getDataGenerator()->create_cohort();
 191  
 192          $context = \context_system::instance();
 193          $roleid = $this->assignUserCapability('moodle/cohort:view', $context->id);
 194  
 195          // Call the external function.
 196          $returnedcohorts = core_cohort_external::get_cohorts(array(
 197              $cohort1->id, $cohort2->id));
 198          $returnedcohorts = \external_api::clean_returnvalue(core_cohort_external::get_cohorts_returns(), $returnedcohorts);
 199  
 200          // Check we retrieve the good total number of enrolled cohorts + no error on capability.
 201          $this->assertEquals(2, count($returnedcohorts));
 202  
 203          foreach ($returnedcohorts as $enrolledcohort) {
 204              if ($enrolledcohort['idnumber'] == $cohort1->idnumber) {
 205                  $this->assertEquals($cohort1->name, $enrolledcohort['name']);
 206                  $this->assertEquals($cohort1->description, $enrolledcohort['description']);
 207                  $this->assertEquals($cohort1->visible, $enrolledcohort['visible']);
 208                  $this->assertEquals($cohort1->theme, $enrolledcohort['theme']);
 209              }
 210          }
 211  
 212          // Check that a user with cohort:manage can see the cohort.
 213          $this->unassignUserCapability('moodle/cohort:view', $context->id, $roleid);
 214          $roleid = $this->assignUserCapability('moodle/cohort:manage', $context->id, $roleid);
 215          // Call the external function.
 216          $returnedcohorts = core_cohort_external::get_cohorts(array(
 217              $cohort1->id, $cohort2->id));
 218          $returnedcohorts = \external_api::clean_returnvalue(core_cohort_external::get_cohorts_returns(), $returnedcohorts);
 219  
 220          // Check we retrieve the good total number of enrolled cohorts + no error on capability.
 221          $this->assertEquals(2, count($returnedcohorts));
 222  
 223          // Check when allowcohortstheme is disabled, theme is not returned.
 224          set_config('allowcohortthemes', 0);
 225          $returnedcohorts = core_cohort_external::get_cohorts(array(
 226              $cohort1->id));
 227          $returnedcohorts = \external_api::clean_returnvalue(core_cohort_external::get_cohorts_returns(), $returnedcohorts);
 228          foreach ($returnedcohorts as $enrolledcohort) {
 229              if ($enrolledcohort['idnumber'] == $cohort1->idnumber) {
 230                  $this->assertNull($enrolledcohort['theme']);
 231              }
 232          }
 233      }
 234  
 235      /**
 236       * Test update_cohorts
 237       */
 238      public function test_update_cohorts() {
 239          global $USER, $CFG, $DB;
 240  
 241          $this->resetAfterTest(true);
 242  
 243          set_config('allowcohortthemes', 0);
 244  
 245          $cohort1 = self::getDataGenerator()->create_cohort(array('visible' => 0));
 246  
 247          $cohort1 = array(
 248              'id' => $cohort1->id,
 249              'categorytype' => array('type' => 'id', 'value' => '1'),
 250              'name' => 'cohortnametest1',
 251              'idnumber' => 'idnumbertest1',
 252              'description' => 'This is a description for cohort 1',
 253              'theme' => 'classic'
 254              );
 255  
 256          $context = \context_system::instance();
 257          $roleid = $this->assignUserCapability('moodle/cohort:manage', $context->id);
 258  
 259          // Call the external function.
 260          core_cohort_external::update_cohorts(array($cohort1));
 261  
 262          $dbcohort = $DB->get_record('cohort', array('id' => $cohort1['id']));
 263          $contextid = $DB->get_field('context', 'id', array('instanceid' => $cohort1['categorytype']['value'],
 264          'contextlevel' => CONTEXT_COURSECAT));
 265          $this->assertEquals($dbcohort->contextid, $contextid);
 266          $this->assertEquals($dbcohort->name, $cohort1['name']);
 267          $this->assertEquals($dbcohort->idnumber, $cohort1['idnumber']);
 268          $this->assertEquals($dbcohort->description, $cohort1['description']);
 269          $this->assertEquals($dbcohort->visible, 0);
 270          $this->assertEmpty($dbcohort->theme);
 271  
 272          // Since field 'visible' was added in 2.8, make sure that update works correctly with and without this parameter.
 273          core_cohort_external::update_cohorts(array($cohort1 + array('visible' => 1)));
 274          $dbcohort = $DB->get_record('cohort', array('id' => $cohort1['id']));
 275          $this->assertEquals(1, $dbcohort->visible);
 276          core_cohort_external::update_cohorts(array($cohort1));
 277          $dbcohort = $DB->get_record('cohort', array('id' => $cohort1['id']));
 278          $this->assertEquals(1, $dbcohort->visible);
 279  
 280          // Call when $CFG->allowcohortthemes is enabled.
 281          set_config('allowcohortthemes', 1);
 282          core_cohort_external::update_cohorts(array($cohort1 + array('theme' => 'classic')));
 283          $dbcohort = $DB->get_record('cohort', array('id' => $cohort1['id']));
 284          $this->assertEquals('classic', $dbcohort->theme);
 285  
 286          // Call when $CFG->allowcohortthemes is disabled.
 287          set_config('allowcohortthemes', 0);
 288          core_cohort_external::update_cohorts(array($cohort1 + array('theme' => 'boost')));
 289          $dbcohort = $DB->get_record('cohort', array('id' => $cohort1['id']));
 290          $this->assertEquals('classic', $dbcohort->theme);
 291  
 292          // Call without required capability.
 293          $this->unassignUserCapability('moodle/cohort:manage', $context->id, $roleid);
 294          $this->expectException(\required_capability_exception::class);
 295          core_cohort_external::update_cohorts(array($cohort1));
 296      }
 297  
 298      /**
 299       * Verify handling of 'id' param.
 300       */
 301      public function test_update_cohorts_invalid_id_param() {
 302          $this->resetAfterTest(true);
 303          $cohort = self::getDataGenerator()->create_cohort();
 304  
 305          $cohort1 = array(
 306              'id' => 'THIS IS NOT AN ID',
 307              'name' => 'Changed cohort name',
 308              'categorytype' => array('type' => 'id', 'value' => '1'),
 309              'idnumber' => $cohort->idnumber,
 310          );
 311  
 312          try {
 313              core_cohort_external::update_cohorts(array($cohort1));
 314              $this->fail('Expecting invalid_parameter_exception exception, none occured');
 315          } catch (\invalid_parameter_exception $e1) {
 316              $this->assertStringContainsString('Invalid external api parameter: the value is "THIS IS NOT AN ID"', $e1->debuginfo);
 317          }
 318  
 319          $cohort1['id'] = 9.999; // Also not a valid id of a cohort.
 320          try {
 321              core_cohort_external::update_cohorts(array($cohort1));
 322              $this->fail('Expecting invalid_parameter_exception exception, none occured');
 323          } catch (\invalid_parameter_exception $e2) {
 324              $this->assertStringContainsString('Invalid external api parameter: the value is "9.999"', $e2->debuginfo);
 325          }
 326      }
 327  
 328      /**
 329       * Test update_cohorts without permission on the dest category.
 330       */
 331      public function test_update_cohorts_missing_dest() {
 332          global $USER, $CFG, $DB;
 333  
 334          $this->resetAfterTest(true);
 335  
 336          $category1 = self::getDataGenerator()->create_category(array(
 337              'name' => 'Test category 1'
 338          ));
 339          $category2 = self::getDataGenerator()->create_category(array(
 340              'name' => 'Test category 2'
 341          ));
 342          $context1 = \context_coursecat::instance($category1->id);
 343          $context2 = \context_coursecat::instance($category2->id);
 344  
 345          $cohort = array(
 346              'contextid' => $context1->id,
 347              'name' => 'cohortnametest1',
 348              'idnumber' => 'idnumbertest1',
 349              'description' => 'This is a description for cohort 1'
 350              );
 351          $cohort1 = self::getDataGenerator()->create_cohort($cohort);
 352  
 353          $roleid = $this->assignUserCapability('moodle/cohort:manage', $context1->id);
 354  
 355          $cohortupdate = array(
 356              'id' => $cohort1->id,
 357              'categorytype' => array('type' => 'id', 'value' => $category2->id),
 358              'name' => 'cohort update',
 359              'idnumber' => 'idnumber update',
 360              'description' => 'This is a description update'
 361              );
 362  
 363          // Call the external function.
 364          // Should fail because we don't have permission on the dest category
 365          $this->expectException(\required_capability_exception::class);
 366          core_cohort_external::update_cohorts(array($cohortupdate));
 367      }
 368  
 369      /**
 370       * Test update_cohorts without permission on the src category.
 371       */
 372      public function test_update_cohorts_missing_src() {
 373          global $USER, $CFG, $DB;
 374  
 375          $this->resetAfterTest(true);
 376  
 377          $category1 = self::getDataGenerator()->create_category(array(
 378              'name' => 'Test category 1'
 379          ));
 380          $category2 = self::getDataGenerator()->create_category(array(
 381              'name' => 'Test category 2'
 382          ));
 383          $context1 = \context_coursecat::instance($category1->id);
 384          $context2 = \context_coursecat::instance($category2->id);
 385  
 386          $cohort = array(
 387              'contextid' => $context1->id,
 388              'name' => 'cohortnametest1',
 389              'idnumber' => 'idnumbertest1',
 390              'description' => 'This is a description for cohort 1'
 391              );
 392          $cohort1 = self::getDataGenerator()->create_cohort($cohort);
 393  
 394          $roleid = $this->assignUserCapability('moodle/cohort:manage', $context2->id);
 395  
 396          $cohortupdate = array(
 397              'id' => $cohort1->id,
 398              'categorytype' => array('type' => 'id', 'value' => $category2->id),
 399              'name' => 'cohort update',
 400              'idnumber' => 'idnumber update',
 401              'description' => 'This is a description update'
 402              );
 403  
 404          // Call the external function.
 405          // Should fail because we don't have permission on the src category
 406          $this->expectException(\required_capability_exception::class);
 407          core_cohort_external::update_cohorts(array($cohortupdate));
 408      }
 409  
 410      /**
 411       * Test add_cohort_members
 412       */
 413      public function test_add_cohort_members() {
 414          global $DB;
 415  
 416          $this->resetAfterTest(true); // Reset all changes automatically after this test.
 417  
 418          $contextid = \context_system::instance()->id;
 419  
 420          $cohort = array(
 421              'contextid' => $contextid,
 422              'name' => 'cohortnametest1',
 423              'idnumber' => 'idnumbertest1',
 424              'description' => 'This is a description for cohort 1'
 425              );
 426          $cohort0 = self::getDataGenerator()->create_cohort($cohort);
 427          // Check the cohorts were correctly created.
 428          $this->assertEquals(1, $DB->count_records_select('cohort', ' (id = :cohortid0)',
 429              array('cohortid0' => $cohort0->id)));
 430  
 431          $cohort1 = array(
 432              'cohorttype' => array('type' => 'id', 'value' => $cohort0->id),
 433              'usertype' => array('type' => 'id', 'value' => '1')
 434              );
 435  
 436          $roleid = $this->assignUserCapability('moodle/cohort:assign', $contextid);
 437  
 438          // Call the external function.
 439          $addcohortmembers = core_cohort_external::add_cohort_members(array($cohort1));
 440          $addcohortmembers = \external_api::clean_returnvalue(core_cohort_external::add_cohort_members_returns(), $addcohortmembers);
 441  
 442          // Check we retrieve the good total number of created cohorts + no error on capability.
 443          $this->assertEquals(1, count($addcohortmembers));
 444  
 445          foreach ($addcohortmembers as $addcohortmember) {
 446              $dbcohort = $DB->get_record('cohort_members', array('cohortid' => $cohort0->id));
 447              $this->assertEquals($dbcohort->cohortid, $cohort1['cohorttype']['value']);
 448              $this->assertEquals($dbcohort->userid, $cohort1['usertype']['value']);
 449          }
 450  
 451          // Call without required capability.
 452          $cohort2 = array(
 453              'cohorttype' => array('type' => 'id', 'value' => $cohort0->id),
 454              'usertype' => array('type' => 'id', 'value' => '2')
 455              );
 456          $this->unassignUserCapability('moodle/cohort:assign', $contextid, $roleid);
 457          $this->expectException(\required_capability_exception::class);
 458          $addcohortmembers = core_cohort_external::add_cohort_members(array($cohort2));
 459      }
 460  
 461      /**
 462       * Test delete_cohort_members
 463       */
 464      public function test_delete_cohort_members() {
 465          global $DB;
 466  
 467          $this->resetAfterTest(true); // Reset all changes automatically after this test.
 468  
 469          $cohort1 = self::getDataGenerator()->create_cohort();
 470          $user1 = self::getDataGenerator()->create_user();
 471          $cohort2 = self::getDataGenerator()->create_cohort();
 472          $user2 = self::getDataGenerator()->create_user();
 473  
 474          $context = \context_system::instance();
 475          $roleid = $this->assignUserCapability('moodle/cohort:assign', $context->id);
 476  
 477          $cohortaddmember1 = array(
 478              'cohorttype' => array('type' => 'id', 'value' => $cohort1->id),
 479              'usertype' => array('type' => 'id', 'value' => $user1->id)
 480              );
 481          $cohortmembers1 = core_cohort_external::add_cohort_members(array($cohortaddmember1));
 482          $cohortmembers1 = \external_api::clean_returnvalue(core_cohort_external::add_cohort_members_returns(), $cohortmembers1);
 483  
 484          $cohortaddmember2 = array(
 485              'cohorttype' => array('type' => 'id', 'value' => $cohort2->id),
 486              'usertype' => array('type' => 'id', 'value' => $user2->id)
 487              );
 488          $cohortmembers2 = core_cohort_external::add_cohort_members(array($cohortaddmember2));
 489          $cohortmembers2 = \external_api::clean_returnvalue(core_cohort_external::add_cohort_members_returns(), $cohortmembers2);
 490  
 491          // Check we retrieve no cohorts + no error on capability.
 492          $this->assertEquals(2, $DB->count_records_select('cohort_members', ' ((cohortid = :idcohort1 AND userid = :iduser1)
 493              OR (cohortid = :idcohort2 AND userid = :iduser2))',
 494              array('idcohort1' => $cohort1->id, 'iduser1' => $user1->id, 'idcohort2' => $cohort2->id, 'iduser2' => $user2->id)));
 495  
 496          // Call the external function.
 497           $cohortdel1 = array(
 498              'cohortid' => $cohort1->id,
 499              'userid' => $user1->id
 500              );
 501           $cohortdel2 = array(
 502              'cohortid' => $cohort2->id,
 503              'userid' => $user2->id
 504              );
 505          core_cohort_external::delete_cohort_members(array($cohortdel1, $cohortdel2));
 506  
 507          // Check we retrieve no cohorts + no error on capability.
 508          $this->assertEquals(0, $DB->count_records_select('cohort_members', ' ((cohortid = :idcohort1 AND userid = :iduser1)
 509              OR (cohortid = :idcohort2 AND userid = :iduser2))',
 510              array('idcohort1' => $cohort1->id, 'iduser1' => $user1->id, 'idcohort2' => $cohort2->id, 'iduser2' => $user2->id)));
 511  
 512          // Call without required capability.
 513          $this->unassignUserCapability('moodle/cohort:assign', $context->id, $roleid);
 514          $this->expectException(\required_capability_exception::class);
 515          core_cohort_external::delete_cohort_members(array($cohortdel1, $cohortdel2));
 516      }
 517  
 518      /**
 519       * Search cohorts.
 520       */
 521      public function test_search_cohorts() {
 522          global $DB, $CFG;
 523          $this->resetAfterTest(true);
 524  
 525          $creator = $this->getDataGenerator()->create_user();
 526          $user = $this->getDataGenerator()->create_user();
 527          $catuser = $this->getDataGenerator()->create_user();
 528          $catcreator = $this->getDataGenerator()->create_user();
 529          $courseuser = $this->getDataGenerator()->create_user();
 530          $category = $this->getDataGenerator()->create_category();
 531          $othercategory = $this->getDataGenerator()->create_category();
 532          $course = $this->getDataGenerator()->create_course();
 533          $syscontext = \context_system::instance();
 534          $catcontext = \context_coursecat::instance($category->id);
 535          $coursecontext = \context_course::instance($course->id);
 536  
 537          // Fetching default authenticated user role.
 538          $authrole = $DB->get_record('role', array('id' => $CFG->defaultuserroleid));
 539  
 540          // Reset all default authenticated users permissions.
 541          unassign_capability('moodle/cohort:manage', $authrole->id);
 542  
 543          // Creating specific roles.
 544          $creatorrole = create_role('Creator role', 'creatorrole', 'creator role description');
 545          $userrole = create_role('User role', 'userrole', 'user role description');
 546          $courserole = create_role('Course user role', 'courserole', 'course user role description');
 547  
 548          assign_capability('moodle/cohort:manage', CAP_ALLOW, $creatorrole, $syscontext->id);
 549          assign_capability('moodle/cohort:view', CAP_ALLOW, $courserole, $syscontext->id);
 550  
 551          // Check for parameter $includes = 'parents'.
 552          role_assign($creatorrole, $creator->id, $syscontext->id);
 553          role_assign($creatorrole, $catcreator->id, $catcontext->id);
 554          role_assign($userrole, $user->id, $syscontext->id);
 555          role_assign($userrole, $catuser->id, $catcontext->id);
 556  
 557          // Enrol user in the course.
 558          $this->getDataGenerator()->enrol_user($courseuser->id, $course->id, 'courserole');
 559  
 560          $syscontext = array('contextid' => \context_system::instance()->id);
 561          $catcontext = array('contextid' => \context_coursecat::instance($category->id)->id);
 562          $othercatcontext = array('contextid' => \context_coursecat::instance($othercategory->id)->id);
 563          $coursecontext = array('contextid' => \context_course::instance($course->id)->id);
 564  
 565          $cohort1 = $this->getDataGenerator()->create_cohort(array_merge($syscontext, array('name' => 'Cohortsearch 1')));
 566          $cohort2 = $this->getDataGenerator()->create_cohort(array_merge($catcontext, array('name' => 'Cohortsearch 2')));
 567          $cohort3 = $this->getDataGenerator()->create_cohort(array_merge($othercatcontext, array('name' => 'Cohortsearch 3')));
 568  
 569          // A user without permission in the system.
 570          $this->setUser($user);
 571          try {
 572              $result = core_cohort_external::search_cohorts("Cohortsearch", $syscontext, 'parents');
 573              $this->fail('Invalid permissions in system');
 574          } catch (\required_capability_exception $e) {
 575              // All good.
 576          }
 577  
 578          // A user without permission in a category.
 579          $this->setUser($catuser);
 580          try {
 581              $result = core_cohort_external::search_cohorts("Cohortsearch", $catcontext, 'parents');
 582              $this->fail('Invalid permissions in category');
 583          } catch (\required_capability_exception $e) {
 584              // All good.
 585          }
 586  
 587          // A user with permissions in the system.
 588          $this->setUser($creator);
 589          $result = core_cohort_external::search_cohorts("Cohortsearch", $syscontext, 'parents');
 590          $this->assertEquals(1, count($result['cohorts']));
 591          $this->assertEquals('Cohortsearch 1', $result['cohorts'][$cohort1->id]->name);
 592  
 593          // A user with permissions in the category.
 594          $this->setUser($catcreator);
 595          $result = core_cohort_external::search_cohorts("Cohortsearch", $catcontext, 'parents');
 596          $this->assertEquals(2, count($result['cohorts']));
 597          $cohorts = array();
 598          foreach ($result['cohorts'] as $cohort) {
 599              $cohorts[] = $cohort->name;
 600          }
 601          $this->assertTrue(in_array('Cohortsearch 1', $cohorts));
 602  
 603          // Check for parameter $includes = 'self'.
 604          $this->setUser($creator);
 605          $result = core_cohort_external::search_cohorts("Cohortsearch", $othercatcontext, 'self');
 606          $this->assertEquals(1, count($result['cohorts']));
 607          $this->assertEquals('Cohortsearch 3', $result['cohorts'][$cohort3->id]->name);
 608  
 609          // Check for parameter $includes = 'all'.
 610          $this->setUser($creator);
 611          $result = core_cohort_external::search_cohorts("Cohortsearch", $syscontext, 'all');
 612          $this->assertEquals(3, count($result['cohorts']));
 613  
 614          // A user in the course context with the system cohort:view capability. Check that all the system cohorts are returned.
 615          $this->setUser($courseuser);
 616          $result = core_cohort_external::search_cohorts("Cohortsearch", $coursecontext, 'all');
 617          $this->assertEquals(1, count($result['cohorts']));
 618          $this->assertEquals('Cohortsearch 1', $result['cohorts'][$cohort1->id]->name);
 619  
 620          // Detect invalid parameter $includes.
 621          $this->setUser($creator);
 622          try {
 623              $result = core_cohort_external::search_cohorts("Cohortsearch", $syscontext, 'invalid');
 624              $this->fail('Invalid parameter includes');
 625          } catch (\coding_exception $e) {
 626              // All good.
 627          }
 628      }
 629  }