Differences Between: [Versions 310 and 402] [Versions 311 and 402] [Versions 39 and 402] [Versions 400 and 402] [Versions 401 and 402]
1 <?php 2 // This file is part of Moodle - http://moodle.org/ 3 // 4 // Moodle is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // Moodle is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU General Public License for more details. 13 // 14 // You should have received a copy of the GNU General Public License 15 // along with Moodle. If not, see <http://www.gnu.org/licenses/>. 16 17 namespace core_cohort; 18 19 use core_cohort_external; 20 use core_external\external_api; 21 use externallib_advanced_testcase; 22 use core_cohort\customfield\cohort_handler; 23 24 defined('MOODLE_INTERNAL') || die(); 25 26 global $CFG; 27 28 require_once($CFG->dirroot . '/webservice/tests/helpers.php'); 29 require_once($CFG->dirroot . '/cohort/externallib.php'); 30 31 /** 32 * External cohort API 33 * 34 * @package core_cohort 35 * @category external 36 * @copyright MediaTouch 2000 srl 37 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 38 */ 39 class externallib_test extends externallib_advanced_testcase { 40 41 /** 42 * Create cohort custom fields for testing. 43 */ 44 protected function create_custom_fields(): void { 45 $fieldcategory = self::getDataGenerator()->create_custom_field_category([ 46 'component' => 'core_cohort', 47 'area' => 'cohort', 48 'name' => 'Other fields', 49 ]); 50 self::getDataGenerator()->create_custom_field([ 51 'shortname' => 'testfield1', 52 'name' => 'Custom field', 53 'type' => 'text', 54 'categoryid' => $fieldcategory->get('id'), 55 ]); 56 self::getDataGenerator()->create_custom_field([ 57 'shortname' => 'testfield2', 58 'name' => 'Custom field', 59 'type' => 'text', 60 'categoryid' => $fieldcategory->get('id'), 61 ]); 62 } 63 64 /** 65 * Test create_cohorts 66 */ 67 public function test_create_cohorts() { 68 global $DB; 69 70 $this->resetAfterTest(true); 71 72 set_config('allowcohortthemes', 1); 73 74 $contextid = \context_system::instance()->id; 75 $category = $this->getDataGenerator()->create_category(); 76 77 // Custom fields. 78 $this->create_custom_fields(); 79 80 $cohort1 = array( 81 'categorytype' => array('type' => 'id', 'value' => $category->id), 82 'name' => 'cohort test 1', 83 'idnumber' => 'cohorttest1', 84 'description' => 'This is a description for cohorttest1', 85 'theme' => 'classic' 86 ); 87 88 $cohort2 = array( 89 'categorytype' => array('type' => 'system', 'value' => ''), 90 'name' => 'cohort test 2', 91 'idnumber' => 'cohorttest2', 92 'description' => 'This is a description for cohorttest2', 93 'visible' => 0 94 ); 95 96 $cohort3 = array( 97 'categorytype' => array('type' => 'id', 'value' => $category->id), 98 'name' => 'cohort test 3', 99 'idnumber' => 'cohorttest3', 100 'description' => 'This is a description for cohorttest3' 101 ); 102 $roleid = $this->assignUserCapability('moodle/cohort:manage', $contextid); 103 104 $cohort4 = array( 105 'categorytype' => array('type' => 'id', 'value' => $category->id), 106 'name' => 'cohort test 4', 107 'idnumber' => 'cohorttest4', 108 'description' => 'This is a description for cohorttest4', 109 'theme' => 'classic' 110 ); 111 112 $cohort5 = array( 113 'categorytype' => array('type' => 'id', 'value' => $category->id), 114 'name' => 'cohort test 5 (with custom fields)', 115 'idnumber' => 'cohorttest5', 116 'description' => 'This is a description for cohorttest5', 117 'customfields' => array( 118 array( 119 'shortname' => 'testfield1', 120 'value' => 'Test value 1', 121 ), 122 array( 123 'shortname' => 'testfield2', 124 'value' => 'Test value 2', 125 ), 126 ), 127 ); 128 129 // Call the external function. 130 $this->setCurrentTimeStart(); 131 $createdcohorts = core_cohort_external::create_cohorts(array($cohort1, $cohort2)); 132 $createdcohorts = external_api::clean_returnvalue(core_cohort_external::create_cohorts_returns(), $createdcohorts); 133 134 // Check we retrieve the good total number of created cohorts + no error on capability. 135 $this->assertEquals(2, count($createdcohorts)); 136 137 foreach ($createdcohorts as $createdcohort) { 138 $dbcohort = $DB->get_record('cohort', array('id' => $createdcohort['id'])); 139 if ($createdcohort['idnumber'] == $cohort1['idnumber']) { 140 $conid = $DB->get_field('context', 'id', array('instanceid' => $cohort1['categorytype']['value'], 141 'contextlevel' => CONTEXT_COURSECAT)); 142 $this->assertEquals($dbcohort->contextid, $conid); 143 $this->assertEquals($dbcohort->name, $cohort1['name']); 144 $this->assertEquals($dbcohort->description, $cohort1['description']); 145 $this->assertEquals($dbcohort->visible, 1); // Field was not specified, ensure it is visible by default. 146 // As $CFG->allowcohortthemes is enabled, theme must be initialised. 147 $this->assertEquals($dbcohort->theme, $cohort1['theme']); 148 } else if ($createdcohort['idnumber'] == $cohort2['idnumber']) { 149 $this->assertEquals($dbcohort->contextid, \context_system::instance()->id); 150 $this->assertEquals($dbcohort->name, $cohort2['name']); 151 $this->assertEquals($dbcohort->description, $cohort2['description']); 152 $this->assertEquals($dbcohort->visible, $cohort2['visible']); 153 // Although $CFG->allowcohortthemes is enabled, no theme is defined for this cohort. 154 $this->assertEquals($dbcohort->theme, ''); 155 } else { 156 $this->fail('Unrecognised cohort found'); 157 } 158 $this->assertTimeCurrent($dbcohort->timecreated); 159 $this->assertTimeCurrent($dbcohort->timemodified); 160 } 161 162 $createdcohorts = core_cohort_external::create_cohorts(array($cohort5)); 163 $createdcohorts = external_api::clean_returnvalue(core_cohort_external::create_cohorts_returns(), $createdcohorts); 164 165 $this->assertCount(1, $createdcohorts); 166 $createdcohort = reset($createdcohorts); 167 $dbcohort = $DB->get_record('cohort', array('id' => $createdcohort['id'])); 168 $this->assertEquals($cohort5['name'], $dbcohort->name); 169 $this->assertEquals($cohort5['description'], $dbcohort->description); 170 $this->assertEquals(1, $dbcohort->visible); 171 $this->assertEquals('', $dbcohort->theme); 172 173 $data = cohort_handler::create()->export_instance_data_object($createdcohort['id'], true); 174 $this->assertEquals('Test value 1', $data->testfield1); 175 $this->assertEquals('Test value 2', $data->testfield2); 176 177 // Call when $CFG->allowcohortthemes is disabled. 178 set_config('allowcohortthemes', 0); 179 $createdcohorts = core_cohort_external::create_cohorts(array($cohort4)); 180 $createdcohorts = external_api::clean_returnvalue(core_cohort_external::create_cohorts_returns(), $createdcohorts); 181 foreach ($createdcohorts as $createdcohort) { 182 $dbcohort = $DB->get_record('cohort', array('id' => $createdcohort['id'])); 183 if ($createdcohort['idnumber'] == $cohort4['idnumber']) { 184 $conid = $DB->get_field('context', 'id', array('instanceid' => $cohort4['categorytype']['value'], 185 'contextlevel' => CONTEXT_COURSECAT)); 186 $this->assertEquals($dbcohort->contextid, $conid); 187 $this->assertEquals($dbcohort->name, $cohort4['name']); 188 $this->assertEquals($dbcohort->description, $cohort4['description']); 189 $this->assertEquals($dbcohort->visible, 1); // Field was not specified, ensure it is visible by default. 190 $this->assertEquals($dbcohort->theme, ''); // As $CFG->allowcohortthemes is disabled, theme must be empty. 191 } 192 } 193 194 // Call without required capability. 195 $this->unassignUserCapability('moodle/cohort:manage', $contextid, $roleid); 196 $this->expectException(\required_capability_exception::class); 197 $createdcohorts = core_cohort_external::create_cohorts(array($cohort3)); 198 } 199 200 /** 201 * Test delete_cohorts 202 */ 203 public function test_delete_cohorts() { 204 global $USER, $CFG, $DB; 205 206 $this->resetAfterTest(true); 207 208 $cohort1 = self::getDataGenerator()->create_cohort(); 209 $cohort2 = self::getDataGenerator()->create_cohort(); 210 // Check the cohorts were correctly created. 211 $this->assertEquals(2, $DB->count_records_select('cohort', ' (id = :cohortid1 OR id = :cohortid2)', 212 array('cohortid1' => $cohort1->id, 'cohortid2' => $cohort2->id))); 213 214 $contextid = $cohort1->contextid; 215 $roleid = $this->assignUserCapability('moodle/cohort:manage', $contextid); 216 217 // Call the external function. 218 core_cohort_external::delete_cohorts(array($cohort1->id, $cohort2->id)); 219 220 // Check we retrieve no cohorts + no error on capability. 221 $this->assertEquals(0, $DB->count_records_select('cohort', ' (id = :cohortid1 OR id = :cohortid2)', 222 array('cohortid1' => $cohort1->id, 'cohortid2' => $cohort2->id))); 223 224 // Call without required capability. 225 $cohort1 = self::getDataGenerator()->create_cohort(); 226 $cohort2 = self::getDataGenerator()->create_cohort(); 227 $this->unassignUserCapability('moodle/cohort:manage', $contextid, $roleid); 228 $this->expectException(\required_capability_exception::class); 229 core_cohort_external::delete_cohorts(array($cohort1->id, $cohort2->id)); 230 } 231 232 /** 233 * Test get_cohorts 234 */ 235 public function test_get_cohorts() { 236 $this->resetAfterTest(true); 237 238 // Custom fields. 239 $this->create_custom_fields(); 240 241 set_config('allowcohortthemes', 1); 242 243 $cohort1 = array( 244 'contextid' => 1, 245 'name' => 'cohortnametest1', 246 'idnumber' => 'idnumbertest1', 247 'description' => 'This is a description for cohort 1', 248 'theme' => 'classic', 249 'customfield_testfield1' => 'Test value 1', 250 'customfield_testfield2' => 'Test value 2', 251 ); 252 253 // We need a site admin to be able to populate cohorts custom fields. 254 $this->setAdminUser(); 255 256 $cohort1 = self::getDataGenerator()->create_cohort($cohort1); 257 $cohort2 = self::getDataGenerator()->create_cohort(); 258 259 $context = \context_system::instance(); 260 $roleid = $this->assignUserCapability('moodle/cohort:view', $context->id); 261 262 // Call the external function. 263 $returnedcohorts = core_cohort_external::get_cohorts(array( 264 $cohort1->id, $cohort2->id)); 265 $returnedcohorts = external_api::clean_returnvalue(core_cohort_external::get_cohorts_returns(), $returnedcohorts); 266 267 // Check we retrieve the good total number of enrolled cohorts + no error on capability. 268 $this->assertEquals(2, count($returnedcohorts)); 269 270 foreach ($returnedcohorts as $enrolledcohort) { 271 if ($enrolledcohort['idnumber'] == $cohort1->idnumber) { 272 $this->assertEquals($cohort1->name, $enrolledcohort['name']); 273 $this->assertEquals($cohort1->description, $enrolledcohort['description']); 274 $this->assertEquals($cohort1->visible, $enrolledcohort['visible']); 275 $this->assertEquals($cohort1->theme, $enrolledcohort['theme']); 276 $this->assertIsArray($enrolledcohort['customfields']); 277 $this->assertCount(2, $enrolledcohort['customfields']); 278 $actual = []; 279 foreach ($enrolledcohort['customfields'] as $customfield) { 280 $this->assertArrayHasKey('name', $customfield); 281 $this->assertArrayHasKey('shortname', $customfield); 282 $this->assertArrayHasKey('type', $customfield); 283 $this->assertArrayHasKey('valueraw', $customfield); 284 $this->assertArrayHasKey('value', $customfield); 285 $actual[$customfield['shortname']] = $customfield; 286 } 287 $this->assertEquals('Test value 1', $actual['testfield1']['value']); 288 $this->assertEquals('Test value 2', $actual['testfield2']['value']); 289 } 290 } 291 292 // Check that a user with cohort:manage can see the cohort. 293 $this->unassignUserCapability('moodle/cohort:view', $context->id, $roleid); 294 $roleid = $this->assignUserCapability('moodle/cohort:manage', $context->id, $roleid); 295 // Call the external function. 296 $returnedcohorts = core_cohort_external::get_cohorts(array( 297 $cohort1->id, $cohort2->id)); 298 $returnedcohorts = external_api::clean_returnvalue(core_cohort_external::get_cohorts_returns(), $returnedcohorts); 299 300 // Check we retrieve the good total number of enrolled cohorts + no error on capability. 301 $this->assertEquals(2, count($returnedcohorts)); 302 303 // Check when allowcohortstheme is disabled, theme is not returned. 304 set_config('allowcohortthemes', 0); 305 $returnedcohorts = core_cohort_external::get_cohorts(array( 306 $cohort1->id)); 307 $returnedcohorts = external_api::clean_returnvalue(core_cohort_external::get_cohorts_returns(), $returnedcohorts); 308 foreach ($returnedcohorts as $enrolledcohort) { 309 if ($enrolledcohort['idnumber'] == $cohort1->idnumber) { 310 $this->assertNull($enrolledcohort['theme']); 311 } 312 } 313 } 314 315 /** 316 * Test update_cohorts 317 */ 318 public function test_update_cohorts() { 319 global $DB; 320 321 $this->resetAfterTest(true); 322 323 // Custom fields. 324 $this->create_custom_fields(); 325 326 set_config('allowcohortthemes', 0); 327 328 $cohort1 = self::getDataGenerator()->create_cohort(array('visible' => 0)); 329 330 $data = cohort_handler::create()->export_instance_data_object($cohort1->id, true); 331 $this->assertNull($data->testfield1); 332 $this->assertNull($data->testfield2); 333 334 $cohort1 = array( 335 'id' => $cohort1->id, 336 'categorytype' => array('type' => 'id', 'value' => '1'), 337 'name' => 'cohortnametest1', 338 'idnumber' => 'idnumbertest1', 339 'description' => 'This is a description for cohort 1', 340 'theme' => 'classic', 341 'customfields' => array( 342 array( 343 'shortname' => 'testfield1', 344 'value' => 'Test value 1', 345 ), 346 array( 347 'shortname' => 'testfield2', 348 'value' => 'Test value 2', 349 ), 350 ), 351 ); 352 353 $context = \context_system::instance(); 354 $roleid = $this->assignUserCapability('moodle/cohort:manage', $context->id); 355 356 // Call the external function. 357 core_cohort_external::update_cohorts(array($cohort1)); 358 359 $dbcohort = $DB->get_record('cohort', array('id' => $cohort1['id'])); 360 $contextid = $DB->get_field('context', 'id', array('instanceid' => $cohort1['categorytype']['value'], 361 'contextlevel' => CONTEXT_COURSECAT)); 362 $this->assertEquals($dbcohort->contextid, $contextid); 363 $this->assertEquals($dbcohort->name, $cohort1['name']); 364 $this->assertEquals($dbcohort->idnumber, $cohort1['idnumber']); 365 $this->assertEquals($dbcohort->description, $cohort1['description']); 366 $this->assertEquals($dbcohort->visible, 0); 367 $this->assertEmpty($dbcohort->theme); 368 $data = cohort_handler::create()->export_instance_data_object($cohort1['id'], true); 369 $this->assertEquals('Test value 1', $data->testfield1); 370 $this->assertEquals('Test value 2', $data->testfield2); 371 372 // Since field 'visible' was added in 2.8, make sure that update works correctly with and without this parameter. 373 core_cohort_external::update_cohorts(array($cohort1 + array('visible' => 1))); 374 $dbcohort = $DB->get_record('cohort', array('id' => $cohort1['id'])); 375 $this->assertEquals(1, $dbcohort->visible); 376 core_cohort_external::update_cohorts(array($cohort1)); 377 $dbcohort = $DB->get_record('cohort', array('id' => $cohort1['id'])); 378 $this->assertEquals(1, $dbcohort->visible); 379 380 // Call when $CFG->allowcohortthemes is enabled. 381 set_config('allowcohortthemes', 1); 382 core_cohort_external::update_cohorts(array($cohort1 + array('theme' => 'classic'))); 383 $dbcohort = $DB->get_record('cohort', array('id' => $cohort1['id'])); 384 $this->assertEquals('classic', $dbcohort->theme); 385 386 // Call when $CFG->allowcohortthemes is disabled. 387 set_config('allowcohortthemes', 0); 388 core_cohort_external::update_cohorts(array($cohort1 + array('theme' => 'boost'))); 389 $dbcohort = $DB->get_record('cohort', array('id' => $cohort1['id'])); 390 $this->assertEquals('classic', $dbcohort->theme); 391 392 // Updating custom fields. 393 $cohort1['customfields'] = array( 394 array( 395 'shortname' => 'testfield1', 396 'value' => 'Test value 1 updated', 397 ), 398 array( 399 'shortname' => 'testfield2', 400 'value' => 'Test value 2 updated', 401 ), 402 ); 403 core_cohort_external::update_cohorts(array($cohort1)); 404 $data = cohort_handler::create()->export_instance_data_object($cohort1['id'], true); 405 $this->assertEquals('Test value 1 updated', $data->testfield1); 406 $this->assertEquals('Test value 2 updated', $data->testfield2); 407 408 // Call without required capability. 409 $this->unassignUserCapability('moodle/cohort:manage', $context->id, $roleid); 410 $this->expectException(\required_capability_exception::class); 411 core_cohort_external::update_cohorts(array($cohort1)); 412 } 413 414 /** 415 * Verify handling of 'id' param. 416 */ 417 public function test_update_cohorts_invalid_id_param() { 418 $this->resetAfterTest(true); 419 $cohort = self::getDataGenerator()->create_cohort(); 420 421 $cohort1 = array( 422 'id' => 'THIS IS NOT AN ID', 423 'name' => 'Changed cohort name', 424 'categorytype' => array('type' => 'id', 'value' => '1'), 425 'idnumber' => $cohort->idnumber, 426 ); 427 428 try { 429 core_cohort_external::update_cohorts(array($cohort1)); 430 $this->fail('Expecting invalid_parameter_exception exception, none occured'); 431 } catch (\invalid_parameter_exception $e1) { 432 $this->assertStringContainsString('Invalid external api parameter: the value is "THIS IS NOT AN ID"', $e1->debuginfo); 433 } 434 435 $cohort1['id'] = 9.999; // Also not a valid id of a cohort. 436 try { 437 core_cohort_external::update_cohorts(array($cohort1)); 438 $this->fail('Expecting invalid_parameter_exception exception, none occured'); 439 } catch (\invalid_parameter_exception $e2) { 440 $this->assertStringContainsString('Invalid external api parameter: the value is "9.999"', $e2->debuginfo); 441 } 442 } 443 444 /** 445 * Test update_cohorts without permission on the dest category. 446 */ 447 public function test_update_cohorts_missing_dest() { 448 global $USER, $CFG, $DB; 449 450 $this->resetAfterTest(true); 451 452 $category1 = self::getDataGenerator()->create_category(array( 453 'name' => 'Test category 1' 454 )); 455 $category2 = self::getDataGenerator()->create_category(array( 456 'name' => 'Test category 2' 457 )); 458 $context1 = \context_coursecat::instance($category1->id); 459 $context2 = \context_coursecat::instance($category2->id); 460 461 $cohort = array( 462 'contextid' => $context1->id, 463 'name' => 'cohortnametest1', 464 'idnumber' => 'idnumbertest1', 465 'description' => 'This is a description for cohort 1' 466 ); 467 $cohort1 = self::getDataGenerator()->create_cohort($cohort); 468 469 $roleid = $this->assignUserCapability('moodle/cohort:manage', $context1->id); 470 471 $cohortupdate = array( 472 'id' => $cohort1->id, 473 'categorytype' => array('type' => 'id', 'value' => $category2->id), 474 'name' => 'cohort update', 475 'idnumber' => 'idnumber update', 476 'description' => 'This is a description update' 477 ); 478 479 // Call the external function. 480 // Should fail because we don't have permission on the dest category 481 $this->expectException(\required_capability_exception::class); 482 core_cohort_external::update_cohorts(array($cohortupdate)); 483 } 484 485 /** 486 * Test update_cohorts without permission on the src category. 487 */ 488 public function test_update_cohorts_missing_src() { 489 global $USER, $CFG, $DB; 490 491 $this->resetAfterTest(true); 492 493 $category1 = self::getDataGenerator()->create_category(array( 494 'name' => 'Test category 1' 495 )); 496 $category2 = self::getDataGenerator()->create_category(array( 497 'name' => 'Test category 2' 498 )); 499 $context1 = \context_coursecat::instance($category1->id); 500 $context2 = \context_coursecat::instance($category2->id); 501 502 $cohort = array( 503 'contextid' => $context1->id, 504 'name' => 'cohortnametest1', 505 'idnumber' => 'idnumbertest1', 506 'description' => 'This is a description for cohort 1' 507 ); 508 $cohort1 = self::getDataGenerator()->create_cohort($cohort); 509 510 $roleid = $this->assignUserCapability('moodle/cohort:manage', $context2->id); 511 512 $cohortupdate = array( 513 'id' => $cohort1->id, 514 'categorytype' => array('type' => 'id', 'value' => $category2->id), 515 'name' => 'cohort update', 516 'idnumber' => 'idnumber update', 517 'description' => 'This is a description update' 518 ); 519 520 // Call the external function. 521 // Should fail because we don't have permission on the src category 522 $this->expectException(\required_capability_exception::class); 523 core_cohort_external::update_cohorts(array($cohortupdate)); 524 } 525 526 /** 527 * Test add_cohort_members 528 */ 529 public function test_add_cohort_members() { 530 global $DB; 531 532 $this->resetAfterTest(true); // Reset all changes automatically after this test. 533 534 $contextid = \context_system::instance()->id; 535 536 $cohort = array( 537 'contextid' => $contextid, 538 'name' => 'cohortnametest1', 539 'idnumber' => 'idnumbertest1', 540 'description' => 'This is a description for cohort 1' 541 ); 542 $cohort0 = self::getDataGenerator()->create_cohort($cohort); 543 // Check the cohorts were correctly created. 544 $this->assertEquals(1, $DB->count_records_select('cohort', ' (id = :cohortid0)', 545 array('cohortid0' => $cohort0->id))); 546 547 $cohort1 = array( 548 'cohorttype' => array('type' => 'id', 'value' => $cohort0->id), 549 'usertype' => array('type' => 'id', 'value' => '1') 550 ); 551 552 $roleid = $this->assignUserCapability('moodle/cohort:assign', $contextid); 553 554 // Call the external function. 555 $addcohortmembers = core_cohort_external::add_cohort_members(array($cohort1)); 556 $addcohortmembers = external_api::clean_returnvalue(core_cohort_external::add_cohort_members_returns(), $addcohortmembers); 557 558 // Check we retrieve the good total number of created cohorts + no error on capability. 559 $this->assertEquals(1, count($addcohortmembers)); 560 561 foreach ($addcohortmembers as $addcohortmember) { 562 $dbcohort = $DB->get_record('cohort_members', array('cohortid' => $cohort0->id)); 563 $this->assertEquals($dbcohort->cohortid, $cohort1['cohorttype']['value']); 564 $this->assertEquals($dbcohort->userid, $cohort1['usertype']['value']); 565 } 566 567 // Call without required capability. 568 $cohort2 = array( 569 'cohorttype' => array('type' => 'id', 'value' => $cohort0->id), 570 'usertype' => array('type' => 'id', 'value' => '2') 571 ); 572 $this->unassignUserCapability('moodle/cohort:assign', $contextid, $roleid); 573 $this->expectException(\required_capability_exception::class); 574 $addcohortmembers = core_cohort_external::add_cohort_members(array($cohort2)); 575 } 576 577 /** 578 * Test delete_cohort_members 579 */ 580 public function test_delete_cohort_members() { 581 global $DB; 582 583 $this->resetAfterTest(true); // Reset all changes automatically after this test. 584 585 $cohort1 = self::getDataGenerator()->create_cohort(); 586 $user1 = self::getDataGenerator()->create_user(); 587 $cohort2 = self::getDataGenerator()->create_cohort(); 588 $user2 = self::getDataGenerator()->create_user(); 589 590 $context = \context_system::instance(); 591 $roleid = $this->assignUserCapability('moodle/cohort:assign', $context->id); 592 593 $cohortaddmember1 = array( 594 'cohorttype' => array('type' => 'id', 'value' => $cohort1->id), 595 'usertype' => array('type' => 'id', 'value' => $user1->id) 596 ); 597 $cohortmembers1 = core_cohort_external::add_cohort_members(array($cohortaddmember1)); 598 $cohortmembers1 = external_api::clean_returnvalue(core_cohort_external::add_cohort_members_returns(), $cohortmembers1); 599 600 $cohortaddmember2 = array( 601 'cohorttype' => array('type' => 'id', 'value' => $cohort2->id), 602 'usertype' => array('type' => 'id', 'value' => $user2->id) 603 ); 604 $cohortmembers2 = core_cohort_external::add_cohort_members(array($cohortaddmember2)); 605 $cohortmembers2 = external_api::clean_returnvalue(core_cohort_external::add_cohort_members_returns(), $cohortmembers2); 606 607 // Check we retrieve no cohorts + no error on capability. 608 $this->assertEquals(2, $DB->count_records_select('cohort_members', ' ((cohortid = :idcohort1 AND userid = :iduser1) 609 OR (cohortid = :idcohort2 AND userid = :iduser2))', 610 array('idcohort1' => $cohort1->id, 'iduser1' => $user1->id, 'idcohort2' => $cohort2->id, 'iduser2' => $user2->id))); 611 612 // Call the external function. 613 $cohortdel1 = array( 614 'cohortid' => $cohort1->id, 615 'userid' => $user1->id 616 ); 617 $cohortdel2 = array( 618 'cohortid' => $cohort2->id, 619 'userid' => $user2->id 620 ); 621 core_cohort_external::delete_cohort_members(array($cohortdel1, $cohortdel2)); 622 623 // Check we retrieve no cohorts + no error on capability. 624 $this->assertEquals(0, $DB->count_records_select('cohort_members', ' ((cohortid = :idcohort1 AND userid = :iduser1) 625 OR (cohortid = :idcohort2 AND userid = :iduser2))', 626 array('idcohort1' => $cohort1->id, 'iduser1' => $user1->id, 'idcohort2' => $cohort2->id, 'iduser2' => $user2->id))); 627 628 // Call without required capability. 629 $this->unassignUserCapability('moodle/cohort:assign', $context->id, $roleid); 630 $this->expectException(\required_capability_exception::class); 631 core_cohort_external::delete_cohort_members(array($cohortdel1, $cohortdel2)); 632 } 633 634 /** 635 * Search cohorts. 636 */ 637 public function test_search_cohorts() { 638 global $DB, $CFG; 639 $this->resetAfterTest(true); 640 641 $this->create_custom_fields(); 642 $creator = $this->getDataGenerator()->create_user(); 643 $user = $this->getDataGenerator()->create_user(); 644 $catuser = $this->getDataGenerator()->create_user(); 645 $catcreator = $this->getDataGenerator()->create_user(); 646 $courseuser = $this->getDataGenerator()->create_user(); 647 $category = $this->getDataGenerator()->create_category(); 648 $othercategory = $this->getDataGenerator()->create_category(); 649 $course = $this->getDataGenerator()->create_course(); 650 $syscontext = \context_system::instance(); 651 $catcontext = \context_coursecat::instance($category->id); 652 $coursecontext = \context_course::instance($course->id); 653 654 // Fetching default authenticated user role. 655 $authrole = $DB->get_record('role', array('id' => $CFG->defaultuserroleid)); 656 657 // Reset all default authenticated users permissions. 658 unassign_capability('moodle/cohort:manage', $authrole->id); 659 660 // Creating specific roles. 661 $creatorrole = create_role('Creator role', 'creatorrole', 'creator role description'); 662 $userrole = create_role('User role', 'userrole', 'user role description'); 663 $courserole = create_role('Course user role', 'courserole', 'course user role description'); 664 665 assign_capability('moodle/cohort:manage', CAP_ALLOW, $creatorrole, $syscontext->id); 666 assign_capability('moodle/cohort:view', CAP_ALLOW, $courserole, $syscontext->id); 667 668 // Check for parameter $includes = 'parents'. 669 role_assign($creatorrole, $creator->id, $syscontext->id); 670 role_assign($creatorrole, $catcreator->id, $catcontext->id); 671 role_assign($userrole, $user->id, $syscontext->id); 672 role_assign($userrole, $catuser->id, $catcontext->id); 673 674 // Enrol user in the course. 675 $this->getDataGenerator()->enrol_user($courseuser->id, $course->id, 'courserole'); 676 677 $syscontext = array('contextid' => \context_system::instance()->id); 678 $catcontext = array('contextid' => \context_coursecat::instance($category->id)->id); 679 $othercatcontext = array('contextid' => \context_coursecat::instance($othercategory->id)->id); 680 $coursecontext = array('contextid' => \context_course::instance($course->id)->id); 681 $customfields = array( 682 'contextid' => \context_system::instance()->id, 683 'customfield_testfield1' => 'Test value 1', 684 'customfield_testfield2' => 'Test value 2', 685 ); 686 687 // We need a site admin to be able to populate cohorts custom fields. 688 $this->setAdminUser(); 689 690 $cohort1 = $this->getDataGenerator()->create_cohort(array_merge($syscontext, array('name' => 'Cohortsearch 1'))); 691 $cohort2 = $this->getDataGenerator()->create_cohort(array_merge($catcontext, array('name' => 'Cohortsearch 2'))); 692 $cohort3 = $this->getDataGenerator()->create_cohort(array_merge($othercatcontext, array('name' => 'Cohortsearch 3'))); 693 $cohort4 = $this->getDataGenerator()->create_cohort(array_merge($customfields, array('name' => 'Cohortsearch 4'))); 694 695 // A user without permission in the system. 696 $this->setUser($user); 697 try { 698 $result = core_cohort_external::search_cohorts("Cohortsearch", $syscontext, 'parents'); 699 $this->fail('Invalid permissions in system'); 700 } catch (\required_capability_exception $e) { 701 // All good. 702 } 703 704 // A user without permission in a category. 705 $this->setUser($catuser); 706 try { 707 $result = core_cohort_external::search_cohorts("Cohortsearch", $catcontext, 'parents'); 708 $this->fail('Invalid permissions in category'); 709 } catch (\required_capability_exception $e) { 710 // All good. 711 } 712 713 // A user with permissions in the system. 714 $this->setUser($creator); 715 $result = core_cohort_external::search_cohorts("Cohortsearch 4", $syscontext, 'parents'); 716 $this->assertCount(1, $result['cohorts']); 717 $this->assertEquals('Cohortsearch 4', $result['cohorts'][$cohort4->id]->name); 718 719 $result = core_cohort_external::search_cohorts("Cohortsearch 4", $syscontext, 'parents'); 720 $this->assertCount(1, $result['cohorts']); 721 $this->assertEquals('Cohortsearch 4', $result['cohorts'][$cohort4->id]->name); 722 $this->assertIsArray($result['cohorts'][$cohort4->id]->customfields); 723 $this->assertCount(2, $result['cohorts'][$cohort4->id]->customfields); 724 $actual = []; 725 foreach ($result['cohorts'][$cohort4->id]->customfields as $customfield) { 726 $this->assertArrayHasKey('name', $customfield); 727 $this->assertArrayHasKey('shortname', $customfield); 728 $this->assertArrayHasKey('type', $customfield); 729 $this->assertArrayHasKey('valueraw', $customfield); 730 $this->assertArrayHasKey('value', $customfield); 731 $actual[$customfield['shortname']] = $customfield; 732 } 733 $this->assertEquals('Test value 1', $actual['testfield1']['value']); 734 $this->assertEquals('Test value 2', $actual['testfield2']['value']); 735 736 // A user with permissions in the category. 737 $this->setUser($catcreator); 738 $result = core_cohort_external::search_cohorts("Cohortsearch", $catcontext, 'parents'); 739 $this->assertCount(3, $result['cohorts']); 740 $cohorts = array(); 741 foreach ($result['cohorts'] as $cohort) { 742 $cohorts[] = $cohort->name; 743 } 744 $this->assertTrue(in_array('Cohortsearch 1', $cohorts)); 745 746 // Check for parameter $includes = 'self'. 747 $this->setUser($creator); 748 $result = core_cohort_external::search_cohorts("Cohortsearch", $othercatcontext, 'self'); 749 $this->assertCount(1, $result['cohorts']); 750 $this->assertEquals('Cohortsearch 3', $result['cohorts'][$cohort3->id]->name); 751 752 // Check for parameter $includes = 'all'. 753 $this->setUser($creator); 754 $result = core_cohort_external::search_cohorts("Cohortsearch", $syscontext, 'all'); 755 $this->assertCount(4, $result['cohorts']); 756 757 // A user in the course context with the system cohort:view capability. Check that all the system cohorts are returned. 758 $this->setUser($courseuser); 759 $result = core_cohort_external::search_cohorts("Cohortsearch", $coursecontext, 'all'); 760 $this->assertCount(2, $result['cohorts']); 761 $this->assertEquals('Cohortsearch 1', $result['cohorts'][$cohort1->id]->name); 762 763 // Detect invalid parameter $includes. 764 $this->setUser($creator); 765 try { 766 $result = core_cohort_external::search_cohorts("Cohortsearch", $syscontext, 'invalid'); 767 $this->fail('Invalid parameter includes'); 768 } catch (\coding_exception $e) { 769 // All good. 770 } 771 } 772 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body