[ Index ] |
PHP Cross Reference of Unnamed Project |
[Summary view] [Print] [Text view]
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 /** 18 * External course functions unit tests 19 * 20 * @package core_course 21 * @category external 22 * @copyright 2012 Jerome Mouneyrac 23 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 24 */ 25 26 defined('MOODLE_INTERNAL') || die(); 27 28 global $CFG; 29 30 require_once($CFG->dirroot . '/webservice/tests/helpers.php'); 31 32 /** 33 * External course functions unit tests 34 * 35 * @package core_course 36 * @category external 37 * @copyright 2012 Jerome Mouneyrac 38 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 39 */ 40 class core_course_externallib_testcase extends externallib_advanced_testcase { 41 42 /** 43 * Tests set up 44 */ 45 protected function setUp() { 46 global $CFG; 47 require_once($CFG->dirroot . '/course/externallib.php'); 48 } 49 50 /** 51 * Test create_categories 52 */ 53 public function test_create_categories() { 54 55 global $DB; 56 57 $this->resetAfterTest(true); 58 59 // Set the required capabilities by the external function 60 $contextid = context_system::instance()->id; 61 $roleid = $this->assignUserCapability('moodle/category:manage', $contextid); 62 63 // Create base categories. 64 $category1 = new stdClass(); 65 $category1->name = 'Root Test Category 1'; 66 $category2 = new stdClass(); 67 $category2->name = 'Root Test Category 2'; 68 $category2->idnumber = 'rootcattest2'; 69 $category2->desc = 'Description for root test category 1'; 70 $category2->theme = 'base'; 71 $categories = array( 72 array('name' => $category1->name, 'parent' => 0), 73 array('name' => $category2->name, 'parent' => 0, 'idnumber' => $category2->idnumber, 74 'description' => $category2->desc, 'theme' => $category2->theme) 75 ); 76 77 $createdcats = core_course_external::create_categories($categories); 78 79 // We need to execute the return values cleaning process to simulate the web service server. 80 $createdcats = external_api::clean_returnvalue(core_course_external::create_categories_returns(), $createdcats); 81 82 // Initially confirm that base data was inserted correctly. 83 $this->assertEquals($category1->name, $createdcats[0]['name']); 84 $this->assertEquals($category2->name, $createdcats[1]['name']); 85 86 // Save the ids. 87 $category1->id = $createdcats[0]['id']; 88 $category2->id = $createdcats[1]['id']; 89 90 // Create on sub category. 91 $category3 = new stdClass(); 92 $category3->name = 'Sub Root Test Category 3'; 93 $subcategories = array( 94 array('name' => $category3->name, 'parent' => $category1->id) 95 ); 96 97 $createdsubcats = core_course_external::create_categories($subcategories); 98 99 // We need to execute the return values cleaning process to simulate the web service server. 100 $createdsubcats = external_api::clean_returnvalue(core_course_external::create_categories_returns(), $createdsubcats); 101 102 // Confirm that sub categories were inserted correctly. 103 $this->assertEquals($category3->name, $createdsubcats[0]['name']); 104 105 // Save the ids. 106 $category3->id = $createdsubcats[0]['id']; 107 108 // Calling the ws function should provide a new sortorder to give category1, 109 // category2, category3. New course categories are ordered by id not name. 110 $category1 = $DB->get_record('course_categories', array('id' => $category1->id)); 111 $category2 = $DB->get_record('course_categories', array('id' => $category2->id)); 112 $category3 = $DB->get_record('course_categories', array('id' => $category3->id)); 113 114 // sortorder sequence (and sortorder) must be: 115 // category 1 116 // category 3 117 // category 2 118 $this->assertGreaterThan($category1->sortorder, $category3->sortorder); 119 $this->assertGreaterThan($category3->sortorder, $category2->sortorder); 120 121 // Call without required capability 122 $this->unassignUserCapability('moodle/category:manage', $contextid, $roleid); 123 $this->expectException('required_capability_exception'); 124 $createdsubcats = core_course_external::create_categories($subcategories); 125 126 } 127 128 /** 129 * Test delete categories 130 */ 131 public function test_delete_categories() { 132 global $DB; 133 134 $this->resetAfterTest(true); 135 136 // Set the required capabilities by the external function 137 $contextid = context_system::instance()->id; 138 $roleid = $this->assignUserCapability('moodle/category:manage', $contextid); 139 140 $category1 = self::getDataGenerator()->create_category(); 141 $category2 = self::getDataGenerator()->create_category( 142 array('parent' => $category1->id)); 143 $category3 = self::getDataGenerator()->create_category(); 144 $category4 = self::getDataGenerator()->create_category( 145 array('parent' => $category3->id)); 146 $category5 = self::getDataGenerator()->create_category( 147 array('parent' => $category4->id)); 148 149 //delete category 1 and 2 + delete category 4, category 5 moved under category 3 150 core_course_external::delete_categories(array( 151 array('id' => $category1->id, 'recursive' => 1), 152 array('id' => $category4->id) 153 )); 154 155 //check $category 1 and 2 are deleted 156 $notdeletedcount = $DB->count_records_select('course_categories', 157 'id IN ( ' . $category1->id . ',' . $category2->id . ',' . $category4->id . ')'); 158 $this->assertEquals(0, $notdeletedcount); 159 160 //check that $category5 as $category3 for parent 161 $dbcategory5 = $DB->get_record('course_categories', array('id' => $category5->id)); 162 $this->assertEquals($dbcategory5->path, $category3->path . '/' . $category5->id); 163 164 // Call without required capability 165 $this->unassignUserCapability('moodle/category:manage', $contextid, $roleid); 166 $this->expectException('required_capability_exception'); 167 $createdsubcats = core_course_external::delete_categories( 168 array(array('id' => $category3->id))); 169 } 170 171 /** 172 * Test get categories 173 */ 174 public function test_get_categories() { 175 global $DB; 176 177 $this->resetAfterTest(true); 178 179 $generatedcats = array(); 180 $category1data['idnumber'] = 'idnumbercat1'; 181 $category1data['name'] = 'Category 1 for PHPunit test'; 182 $category1data['description'] = 'Category 1 description'; 183 $category1data['descriptionformat'] = FORMAT_MOODLE; 184 $category1 = self::getDataGenerator()->create_category($category1data); 185 $generatedcats[$category1->id] = $category1; 186 $category2 = self::getDataGenerator()->create_category( 187 array('parent' => $category1->id)); 188 $generatedcats[$category2->id] = $category2; 189 $category6 = self::getDataGenerator()->create_category( 190 array('parent' => $category1->id, 'visible' => 0)); 191 $generatedcats[$category6->id] = $category6; 192 $category3 = self::getDataGenerator()->create_category(); 193 $generatedcats[$category3->id] = $category3; 194 $category4 = self::getDataGenerator()->create_category( 195 array('parent' => $category3->id)); 196 $generatedcats[$category4->id] = $category4; 197 $category5 = self::getDataGenerator()->create_category( 198 array('parent' => $category4->id)); 199 $generatedcats[$category5->id] = $category5; 200 201 // Set the required capabilities by the external function. 202 $context = context_system::instance(); 203 $roleid = $this->assignUserCapability('moodle/category:manage', $context->id); 204 205 // Retrieve category1 + sub-categories except not visible ones 206 $categories = core_course_external::get_categories(array( 207 array('key' => 'id', 'value' => $category1->id), 208 array('key' => 'visible', 'value' => 1)), 1); 209 210 // We need to execute the return values cleaning process to simulate the web service server. 211 $categories = external_api::clean_returnvalue(core_course_external::get_categories_returns(), $categories); 212 213 // Check we retrieve the good total number of categories. 214 $this->assertEquals(2, count($categories)); 215 216 // Check the return values 217 foreach ($categories as $category) { 218 $generatedcat = $generatedcats[$category['id']]; 219 $this->assertEquals($category['idnumber'], $generatedcat->idnumber); 220 $this->assertEquals($category['name'], $generatedcat->name); 221 // Description was converted to the HTML format. 222 $this->assertEquals($category['description'], format_text($generatedcat->description, FORMAT_MOODLE, array('para' => false))); 223 $this->assertEquals($category['descriptionformat'], FORMAT_HTML); 224 } 225 226 // Check categories by ids. 227 $ids = implode(',', array_keys($generatedcats)); 228 $categories = core_course_external::get_categories(array( 229 array('key' => 'ids', 'value' => $ids)), 0); 230 231 // We need to execute the return values cleaning process to simulate the web service server. 232 $categories = external_api::clean_returnvalue(core_course_external::get_categories_returns(), $categories); 233 234 // Check we retrieve the good total number of categories. 235 $this->assertEquals(6, count($categories)); 236 // Check ids. 237 $returnedids = []; 238 foreach ($categories as $category) { 239 $returnedids[] = $category['id']; 240 } 241 // Sort the arrays upon comparision. 242 $this->assertEquals(array_keys($generatedcats), $returnedids, '', 0.0, 10, true); 243 244 // Check different params. 245 $categories = core_course_external::get_categories(array( 246 array('key' => 'id', 'value' => $category1->id), 247 array('key' => 'ids', 'value' => $category1->id), 248 array('key' => 'idnumber', 'value' => $category1->idnumber), 249 array('key' => 'visible', 'value' => 1)), 0); 250 251 // We need to execute the return values cleaning process to simulate the web service server. 252 $categories = external_api::clean_returnvalue(core_course_external::get_categories_returns(), $categories); 253 254 $this->assertEquals(1, count($categories)); 255 256 // Same query, but forcing a parameters clean. 257 $categories = core_course_external::get_categories(array( 258 array('key' => 'id', 'value' => "$category1->id"), 259 array('key' => 'idnumber', 'value' => $category1->idnumber), 260 array('key' => 'name', 'value' => $category1->name . "<br/>"), 261 array('key' => 'visible', 'value' => '1')), 0); 262 $categories = external_api::clean_returnvalue(core_course_external::get_categories_returns(), $categories); 263 264 $this->assertEquals(1, count($categories)); 265 266 // Retrieve categories from parent. 267 $categories = core_course_external::get_categories(array( 268 array('key' => 'parent', 'value' => $category3->id)), 1); 269 $categories = external_api::clean_returnvalue(core_course_external::get_categories_returns(), $categories); 270 271 $this->assertEquals(2, count($categories)); 272 273 // Retrieve all categories. 274 $categories = core_course_external::get_categories(); 275 276 // We need to execute the return values cleaning process to simulate the web service server. 277 $categories = external_api::clean_returnvalue(core_course_external::get_categories_returns(), $categories); 278 279 $this->assertEquals($DB->count_records('course_categories'), count($categories)); 280 281 // Call without required capability (it will fail cause of the search on idnumber). 282 $this->unassignUserCapability('moodle/category:manage', $context->id, $roleid); 283 $this->expectException('moodle_exception'); 284 $categories = core_course_external::get_categories(array( 285 array('key' => 'id', 'value' => $category1->id), 286 array('key' => 'idnumber', 'value' => $category1->idnumber), 287 array('key' => 'visible', 'value' => 1)), 0); 288 } 289 290 /** 291 * Test update_categories 292 */ 293 public function test_update_categories() { 294 global $DB; 295 296 $this->resetAfterTest(true); 297 298 // Set the required capabilities by the external function 299 $contextid = context_system::instance()->id; 300 $roleid = $this->assignUserCapability('moodle/category:manage', $contextid); 301 302 // Create base categories. 303 $category1data['idnumber'] = 'idnumbercat1'; 304 $category1data['name'] = 'Category 1 for PHPunit test'; 305 $category1data['description'] = 'Category 1 description'; 306 $category1data['descriptionformat'] = FORMAT_MOODLE; 307 $category1 = self::getDataGenerator()->create_category($category1data); 308 $category2 = self::getDataGenerator()->create_category( 309 array('parent' => $category1->id)); 310 $category3 = self::getDataGenerator()->create_category(); 311 $category4 = self::getDataGenerator()->create_category( 312 array('parent' => $category3->id)); 313 $category5 = self::getDataGenerator()->create_category( 314 array('parent' => $category4->id)); 315 316 // We update all category1 attribut. 317 // Then we move cat4 and cat5 parent: cat3 => cat1 318 $categories = array( 319 array('id' => $category1->id, 320 'name' => $category1->name . '_updated', 321 'idnumber' => $category1->idnumber . '_updated', 322 'description' => $category1->description . '_updated', 323 'descriptionformat' => FORMAT_HTML, 324 'theme' => $category1->theme), 325 array('id' => $category4->id, 'parent' => $category1->id)); 326 327 core_course_external::update_categories($categories); 328 329 // Check the values were updated. 330 $dbcategories = $DB->get_records_select('course_categories', 331 'id IN (' . $category1->id . ',' . $category2->id . ',' . $category2->id 332 . ',' . $category3->id . ',' . $category4->id . ',' . $category5->id .')'); 333 $this->assertEquals($category1->name . '_updated', 334 $dbcategories[$category1->id]->name); 335 $this->assertEquals($category1->idnumber . '_updated', 336 $dbcategories[$category1->id]->idnumber); 337 $this->assertEquals($category1->description . '_updated', 338 $dbcategories[$category1->id]->description); 339 $this->assertEquals(FORMAT_HTML, $dbcategories[$category1->id]->descriptionformat); 340 341 // Check that category4 and category5 have been properly moved. 342 $this->assertEquals('/' . $category1->id . '/' . $category4->id, 343 $dbcategories[$category4->id]->path); 344 $this->assertEquals('/' . $category1->id . '/' . $category4->id . '/' . $category5->id, 345 $dbcategories[$category5->id]->path); 346 347 // Call without required capability. 348 $this->unassignUserCapability('moodle/category:manage', $contextid, $roleid); 349 $this->expectException('required_capability_exception'); 350 core_course_external::update_categories($categories); 351 } 352 353 /** 354 * Test create_courses 355 */ 356 public function test_create_courses() { 357 global $DB; 358 359 $this->resetAfterTest(true); 360 361 // Enable course completion. 362 set_config('enablecompletion', 1); 363 // Enable course themes. 364 set_config('allowcoursethemes', 1); 365 366 // Set the required capabilities by the external function 367 $contextid = context_system::instance()->id; 368 $roleid = $this->assignUserCapability('moodle/course:create', $contextid); 369 $this->assignUserCapability('moodle/course:visibility', $contextid, $roleid); 370 371 $category = self::getDataGenerator()->create_category(); 372 373 // Create base categories. 374 $course1['fullname'] = 'Test course 1'; 375 $course1['shortname'] = 'Testcourse1'; 376 $course1['categoryid'] = $category->id; 377 $course2['fullname'] = 'Test course 2'; 378 $course2['shortname'] = 'Testcourse2'; 379 $course2['categoryid'] = $category->id; 380 $course2['idnumber'] = 'testcourse2idnumber'; 381 $course2['summary'] = 'Description for course 2'; 382 $course2['summaryformat'] = FORMAT_MOODLE; 383 $course2['format'] = 'weeks'; 384 $course2['showgrades'] = 1; 385 $course2['newsitems'] = 3; 386 $course2['startdate'] = 1420092000; // 01/01/2015 387 $course2['numsections'] = 4; 388 $course2['maxbytes'] = 100000; 389 $course2['showreports'] = 1; 390 $course2['visible'] = 0; 391 $course2['hiddensections'] = 0; 392 $course2['groupmode'] = 0; 393 $course2['groupmodeforce'] = 0; 394 $course2['defaultgroupingid'] = 0; 395 $course2['enablecompletion'] = 1; 396 $course2['completionnotify'] = 1; 397 $course2['lang'] = 'en'; 398 $course2['forcetheme'] = 'base'; 399 $course3['fullname'] = 'Test course 3'; 400 $course3['shortname'] = 'Testcourse3'; 401 $course3['categoryid'] = $category->id; 402 $course3['format'] = 'topics'; 403 $course3options = array('numsections' => 8, 404 'hiddensections' => 1, 405 'coursedisplay' => 1); 406 $course3['courseformatoptions'] = array(); 407 foreach ($course3options as $key => $value) { 408 $course3['courseformatoptions'][] = array('name' => $key, 'value' => $value); 409 } 410 $courses = array($course1, $course2, $course3); 411 412 $createdcourses = core_course_external::create_courses($courses); 413 414 // We need to execute the return values cleaning process to simulate the web service server. 415 $createdcourses = external_api::clean_returnvalue(core_course_external::create_courses_returns(), $createdcourses); 416 417 // Check that right number of courses were created. 418 $this->assertEquals(3, count($createdcourses)); 419 420 // Check that the courses were correctly created. 421 foreach ($createdcourses as $createdcourse) { 422 $courseinfo = course_get_format($createdcourse['id'])->get_course(); 423 424 if ($createdcourse['shortname'] == $course2['shortname']) { 425 $this->assertEquals($courseinfo->fullname, $course2['fullname']); 426 $this->assertEquals($courseinfo->shortname, $course2['shortname']); 427 $this->assertEquals($courseinfo->category, $course2['categoryid']); 428 $this->assertEquals($courseinfo->idnumber, $course2['idnumber']); 429 $this->assertEquals($courseinfo->summary, $course2['summary']); 430 $this->assertEquals($courseinfo->summaryformat, $course2['summaryformat']); 431 $this->assertEquals($courseinfo->format, $course2['format']); 432 $this->assertEquals($courseinfo->showgrades, $course2['showgrades']); 433 $this->assertEquals($courseinfo->newsitems, $course2['newsitems']); 434 $this->assertEquals($courseinfo->startdate, $course2['startdate']); 435 $this->assertEquals($courseinfo->numsections, $course2['numsections']); 436 $this->assertEquals($courseinfo->maxbytes, $course2['maxbytes']); 437 $this->assertEquals($courseinfo->showreports, $course2['showreports']); 438 $this->assertEquals($courseinfo->visible, $course2['visible']); 439 $this->assertEquals($courseinfo->hiddensections, $course2['hiddensections']); 440 $this->assertEquals($courseinfo->groupmode, $course2['groupmode']); 441 $this->assertEquals($courseinfo->groupmodeforce, $course2['groupmodeforce']); 442 $this->assertEquals($courseinfo->defaultgroupingid, $course2['defaultgroupingid']); 443 $this->assertEquals($courseinfo->completionnotify, $course2['completionnotify']); 444 $this->assertEquals($courseinfo->lang, $course2['lang']); 445 $this->assertEquals($courseinfo->theme, $course2['forcetheme']); 446 447 // We enabled completion at the beginning of the test. 448 $this->assertEquals($courseinfo->enablecompletion, $course2['enablecompletion']); 449 450 } else if ($createdcourse['shortname'] == $course1['shortname']) { 451 $courseconfig = get_config('moodlecourse'); 452 $this->assertEquals($courseinfo->fullname, $course1['fullname']); 453 $this->assertEquals($courseinfo->shortname, $course1['shortname']); 454 $this->assertEquals($courseinfo->category, $course1['categoryid']); 455 $this->assertEquals($courseinfo->summaryformat, FORMAT_HTML); 456 $this->assertEquals($courseinfo->format, $courseconfig->format); 457 $this->assertEquals($courseinfo->showgrades, $courseconfig->showgrades); 458 $this->assertEquals($courseinfo->newsitems, $courseconfig->newsitems); 459 $this->assertEquals($courseinfo->maxbytes, $courseconfig->maxbytes); 460 $this->assertEquals($courseinfo->showreports, $courseconfig->showreports); 461 $this->assertEquals($courseinfo->groupmode, $courseconfig->groupmode); 462 $this->assertEquals($courseinfo->groupmodeforce, $courseconfig->groupmodeforce); 463 $this->assertEquals($courseinfo->defaultgroupingid, 0); 464 } else if ($createdcourse['shortname'] == $course3['shortname']) { 465 $this->assertEquals($courseinfo->fullname, $course3['fullname']); 466 $this->assertEquals($courseinfo->shortname, $course3['shortname']); 467 $this->assertEquals($courseinfo->category, $course3['categoryid']); 468 $this->assertEquals($courseinfo->format, $course3['format']); 469 $this->assertEquals($courseinfo->hiddensections, $course3options['hiddensections']); 470 $this->assertEquals($courseinfo->numsections, $course3options['numsections']); 471 $this->assertEquals($courseinfo->coursedisplay, $course3options['coursedisplay']); 472 } else { 473 throw moodle_exception('Unexpected shortname'); 474 } 475 } 476 477 // Call without required capability 478 $this->unassignUserCapability('moodle/course:create', $contextid, $roleid); 479 $this->expectException('required_capability_exception'); 480 $createdsubcats = core_course_external::create_courses($courses); 481 } 482 483 /** 484 * Test delete_courses 485 */ 486 public function test_delete_courses() { 487 global $DB, $USER; 488 489 $this->resetAfterTest(true); 490 491 // Admin can delete a course. 492 $this->setAdminUser(); 493 // Validate_context() will fail as the email is not set by $this->setAdminUser(). 494 $USER->email = 'emailtopass@example.com'; 495 496 $course1 = self::getDataGenerator()->create_course(); 497 $course2 = self::getDataGenerator()->create_course(); 498 $course3 = self::getDataGenerator()->create_course(); 499 500 // Delete courses. 501 $result = core_course_external::delete_courses(array($course1->id, $course2->id)); 502 $result = external_api::clean_returnvalue(core_course_external::delete_courses_returns(), $result); 503 // Check for 0 warnings. 504 $this->assertEquals(0, count($result['warnings'])); 505 506 // Check $course 1 and 2 are deleted. 507 $notdeletedcount = $DB->count_records_select('course', 508 'id IN ( ' . $course1->id . ',' . $course2->id . ')'); 509 $this->assertEquals(0, $notdeletedcount); 510 511 // Try to delete non-existent course. 512 $result = core_course_external::delete_courses(array($course1->id)); 513 $result = external_api::clean_returnvalue(core_course_external::delete_courses_returns(), $result); 514 // Check for 1 warnings. 515 $this->assertEquals(1, count($result['warnings'])); 516 517 // Try to delete Frontpage course. 518 $result = core_course_external::delete_courses(array(0)); 519 $result = external_api::clean_returnvalue(core_course_external::delete_courses_returns(), $result); 520 // Check for 1 warnings. 521 $this->assertEquals(1, count($result['warnings'])); 522 523 // Fail when the user has access to course (enrolled) but does not have permission or is not admin. 524 $student1 = self::getDataGenerator()->create_user(); 525 $studentrole = $DB->get_record('role', array('shortname' => 'student')); 526 $this->getDataGenerator()->enrol_user($student1->id, 527 $course3->id, 528 $studentrole->id); 529 $this->setUser($student1); 530 $result = core_course_external::delete_courses(array($course3->id)); 531 $result = external_api::clean_returnvalue(core_course_external::delete_courses_returns(), $result); 532 // Check for 1 warnings. 533 $this->assertEquals(1, count($result['warnings'])); 534 535 // Fail when the user is not allow to access the course (enrolled) or is not admin. 536 $this->setGuestUser(); 537 $this->expectException('require_login_exception'); 538 539 $result = core_course_external::delete_courses(array($course3->id)); 540 $result = external_api::clean_returnvalue(core_course_external::delete_courses_returns(), $result); 541 } 542 543 /** 544 * Test get_courses 545 */ 546 public function test_get_courses () { 547 global $DB; 548 549 $this->resetAfterTest(true); 550 551 $generatedcourses = array(); 552 $coursedata['idnumber'] = 'idnumbercourse1'; 553 // Adding tags here to check that format_string is applied. 554 $coursedata['fullname'] = '<b>Course 1 for PHPunit test</b>'; 555 $coursedata['shortname'] = '<b>Course 1 for PHPunit test</b>'; 556 $coursedata['summary'] = 'Course 1 description'; 557 $coursedata['summaryformat'] = FORMAT_MOODLE; 558 $course1 = self::getDataGenerator()->create_course($coursedata); 559 $generatedcourses[$course1->id] = $course1; 560 $course2 = self::getDataGenerator()->create_course(); 561 $generatedcourses[$course2->id] = $course2; 562 $course3 = self::getDataGenerator()->create_course(array('format' => 'topics')); 563 $generatedcourses[$course3->id] = $course3; 564 565 // Set the required capabilities by the external function. 566 $context = context_system::instance(); 567 $roleid = $this->assignUserCapability('moodle/course:view', $context->id); 568 $this->assignUserCapability('moodle/course:update', 569 context_course::instance($course1->id)->id, $roleid); 570 $this->assignUserCapability('moodle/course:update', 571 context_course::instance($course2->id)->id, $roleid); 572 $this->assignUserCapability('moodle/course:update', 573 context_course::instance($course3->id)->id, $roleid); 574 575 $courses = core_course_external::get_courses(array('ids' => 576 array($course1->id, $course2->id))); 577 578 // We need to execute the return values cleaning process to simulate the web service server. 579 $courses = external_api::clean_returnvalue(core_course_external::get_courses_returns(), $courses); 580 581 // Check we retrieve the good total number of categories. 582 $this->assertEquals(2, count($courses)); 583 584 foreach ($courses as $course) { 585 $coursecontext = context_course::instance($course['id']); 586 $dbcourse = $generatedcourses[$course['id']]; 587 $this->assertEquals($course['idnumber'], $dbcourse->idnumber); 588 $this->assertEquals($course['fullname'], external_format_string($dbcourse->fullname, $coursecontext->id)); 589 $this->assertEquals($course['displayname'], external_format_string(get_course_display_name_for_list($dbcourse), 590 $coursecontext->id)); 591 // Summary was converted to the HTML format. 592 $this->assertEquals($course['summary'], format_text($dbcourse->summary, FORMAT_MOODLE, array('para' => false))); 593 $this->assertEquals($course['summaryformat'], FORMAT_HTML); 594 $this->assertEquals($course['shortname'], external_format_string($dbcourse->shortname, $coursecontext->id)); 595 $this->assertEquals($course['categoryid'], $dbcourse->category); 596 $this->assertEquals($course['format'], $dbcourse->format); 597 $this->assertEquals($course['showgrades'], $dbcourse->showgrades); 598 $this->assertEquals($course['newsitems'], $dbcourse->newsitems); 599 $this->assertEquals($course['startdate'], $dbcourse->startdate); 600 $this->assertEquals($course['numsections'], $dbcourse->numsections); 601 $this->assertEquals($course['maxbytes'], $dbcourse->maxbytes); 602 $this->assertEquals($course['showreports'], $dbcourse->showreports); 603 $this->assertEquals($course['visible'], $dbcourse->visible); 604 $this->assertEquals($course['hiddensections'], $dbcourse->hiddensections); 605 $this->assertEquals($course['groupmode'], $dbcourse->groupmode); 606 $this->assertEquals($course['groupmodeforce'], $dbcourse->groupmodeforce); 607 $this->assertEquals($course['defaultgroupingid'], $dbcourse->defaultgroupingid); 608 $this->assertEquals($course['completionnotify'], $dbcourse->completionnotify); 609 $this->assertEquals($course['lang'], $dbcourse->lang); 610 $this->assertEquals($course['forcetheme'], $dbcourse->theme); 611 $this->assertEquals($course['enablecompletion'], $dbcourse->enablecompletion); 612 if ($dbcourse->format === 'topics') { 613 $this->assertEquals($course['courseformatoptions'], array( 614 array('name' => 'numsections', 'value' => $dbcourse->numsections), 615 array('name' => 'hiddensections', 'value' => $dbcourse->hiddensections), 616 array('name' => 'coursedisplay', 'value' => $dbcourse->coursedisplay), 617 )); 618 } 619 } 620 621 // Get all courses in the DB 622 $courses = core_course_external::get_courses(array()); 623 624 // We need to execute the return values cleaning process to simulate the web service server. 625 $courses = external_api::clean_returnvalue(core_course_external::get_courses_returns(), $courses); 626 627 $this->assertEquals($DB->count_records('course'), count($courses)); 628 } 629 630 /** 631 * Test search_courses 632 */ 633 public function test_search_courses () { 634 635 global $DB; 636 637 $this->resetAfterTest(true); 638 $this->setAdminUser(); 639 $generatedcourses = array(); 640 $coursedata1['fullname'] = 'FIRST COURSE'; 641 $course1 = self::getDataGenerator()->create_course($coursedata1); 642 $coursedata2['fullname'] = 'SECOND COURSE'; 643 $course2 = self::getDataGenerator()->create_course($coursedata2); 644 // Search by name. 645 $results = core_course_external::search_courses('search', 'FIRST'); 646 $results = external_api::clean_returnvalue(core_course_external::search_courses_returns(), $results); 647 $this->assertEquals($coursedata1['fullname'], $results['courses'][0]['fullname']); 648 $this->assertCount(1, $results['courses']); 649 650 // Create the forum. 651 $record = new stdClass(); 652 $record->introformat = FORMAT_HTML; 653 $record->course = $course2->id; 654 // Set Aggregate type = Average of ratings. 655 $forum = self::getDataGenerator()->create_module('forum', $record); 656 657 // Search by module. 658 $results = core_course_external::search_courses('modulelist', 'forum'); 659 $results = external_api::clean_returnvalue(core_course_external::search_courses_returns(), $results); 660 $this->assertEquals(1, $results['total']); 661 662 // Enable coursetag option. 663 set_config('block_tags_showcoursetags', true); 664 // Add tag 'TAG-LABEL ON SECOND COURSE' to Course2. 665 core_tag_tag::set_item_tags('core', 'course', $course2->id, context_course::instance($course2->id), 666 array('TAG-LABEL ON SECOND COURSE')); 667 $taginstance = $DB->get_record('tag_instance', 668 array('itemtype' => 'course', 'itemid' => $course2->id), '*', MUST_EXIST); 669 // Search by tagid. 670 $results = core_course_external::search_courses('tagid', $taginstance->tagid); 671 $results = external_api::clean_returnvalue(core_course_external::search_courses_returns(), $results); 672 $this->assertEquals($coursedata2['fullname'], $results['courses'][0]['fullname']); 673 674 // Search by block (use news_items default block). 675 $blockid = $DB->get_field('block', 'id', array('name' => 'news_items')); 676 $results = core_course_external::search_courses('blocklist', $blockid); 677 $results = external_api::clean_returnvalue(core_course_external::search_courses_returns(), $results); 678 $this->assertEquals(2, $results['total']); 679 680 // Now as a normal user. 681 $user = self::getDataGenerator()->create_user(); 682 683 // Add a 3rd, hidden, course we shouldn't see, even when enrolled as student. 684 $coursedata3['fullname'] = 'HIDDEN COURSE'; 685 $coursedata3['visible'] = 0; 686 $course3 = self::getDataGenerator()->create_course($coursedata3); 687 $this->getDataGenerator()->enrol_user($user->id, $course3->id, 'student'); 688 689 $this->getDataGenerator()->enrol_user($user->id, $course2->id, 'student'); 690 $this->setUser($user); 691 692 $results = core_course_external::search_courses('search', 'FIRST'); 693 $results = external_api::clean_returnvalue(core_course_external::search_courses_returns(), $results); 694 $this->assertCount(1, $results['courses']); 695 $this->assertEquals(1, $results['total']); 696 $this->assertEquals($coursedata1['fullname'], $results['courses'][0]['fullname']); 697 698 // Check that we can see both without the limit to enrolled setting. 699 $results = core_course_external::search_courses('search', 'COURSE', 0, 0, array(), 0); 700 $results = external_api::clean_returnvalue(core_course_external::search_courses_returns(), $results); 701 $this->assertCount(2, $results['courses']); 702 $this->assertEquals(2, $results['total']); 703 704 // Check that we only see our enrolled course when limiting. 705 $results = core_course_external::search_courses('search', 'COURSE', 0, 0, array(), 1); 706 $results = external_api::clean_returnvalue(core_course_external::search_courses_returns(), $results); 707 $this->assertCount(1, $results['courses']); 708 $this->assertEquals(1, $results['total']); 709 $this->assertEquals($coursedata2['fullname'], $results['courses'][0]['fullname']); 710 711 // Search by block (use news_items default block). Should fail (only admins allowed). 712 $this->expectException('required_capability_exception'); 713 $results = core_course_external::search_courses('blocklist', $blockid); 714 715 } 716 717 /** 718 * Create a course with contents 719 * @return array A list with the course object and course modules objects 720 */ 721 private function prepare_get_course_contents_test() { 722 global $DB; 723 $course = self::getDataGenerator()->create_course(); 724 $forumdescription = 'This is the forum description'; 725 $forum = $this->getDataGenerator()->create_module('forum', 726 array('course' => $course->id, 'intro' => $forumdescription), 727 array('showdescription' => true)); 728 $forumcm = get_coursemodule_from_id('forum', $forum->cmid); 729 $data = $this->getDataGenerator()->create_module('data', array('assessed' => 1, 'scale' => 100, 'course' => $course->id)); 730 $datacm = get_coursemodule_from_instance('page', $data->id); 731 $page = $this->getDataGenerator()->create_module('page', array('course' => $course->id)); 732 $pagecm = get_coursemodule_from_instance('page', $page->id); 733 $labeldescription = 'This is a very long label to test if more than 50 characters are returned. 734 So bla bla bla bla <b>bold bold bold</b> bla bla bla bla.'; 735 $label = $this->getDataGenerator()->create_module('label', array('course' => $course->id, 736 'intro' => $labeldescription)); 737 $labelcm = get_coursemodule_from_instance('label', $label->id); 738 $url = $this->getDataGenerator()->create_module('url', array('course' => $course->id, 739 'name' => 'URL: % & $ ../', 'section' => 2)); 740 $urlcm = get_coursemodule_from_instance('url', $url->id); 741 742 // Set the required capabilities by the external function. 743 $context = context_course::instance($course->id); 744 $roleid = $this->assignUserCapability('moodle/course:view', $context->id); 745 $this->assignUserCapability('moodle/course:update', $context->id, $roleid); 746 $this->assignUserCapability('mod/data:view', $context->id, $roleid); 747 748 $conditions = array('course' => $course->id, 'section' => 2); 749 $DB->set_field('course_sections', 'summary', 'Text with iframe <iframe src="https://moodle.org"></iframe>', $conditions); 750 rebuild_course_cache($course->id, true); 751 752 return array($course, $forumcm, $datacm, $pagecm, $labelcm, $urlcm); 753 } 754 755 /** 756 * Test get_course_contents 757 */ 758 public function test_get_course_contents() { 759 $this->resetAfterTest(true); 760 761 list($course, $forumcm, $datacm, $pagecm, $labelcm, $urlcm) = $this->prepare_get_course_contents_test(); 762 763 $sections = core_course_external::get_course_contents($course->id, array()); 764 // We need to execute the return values cleaning process to simulate the web service server. 765 $sections = external_api::clean_returnvalue(core_course_external::get_course_contents_returns(), $sections); 766 767 // Check that forum and label descriptions are correctly returned. 768 $firstsection = array_shift($sections); 769 $lastsection = array_pop($sections); 770 771 $modinfo = get_fast_modinfo($course); 772 $testexecuted = 0; 773 foreach ($firstsection['modules'] as $module) { 774 if ($module['id'] == $forumcm->id and $module['modname'] == 'forum') { 775 $cm = $modinfo->cms[$forumcm->id]; 776 $formattedtext = format_text($cm->content, FORMAT_HTML, 777 array('noclean' => true, 'para' => false, 'filter' => false)); 778 $this->assertEquals($formattedtext, $module['description']); 779 $this->assertEquals($forumcm->instance, $module['instance']); 780 $testexecuted = $testexecuted + 1; 781 } else if ($module['id'] == $labelcm->id and $module['modname'] == 'label') { 782 $cm = $modinfo->cms[$labelcm->id]; 783 $formattedtext = format_text($cm->content, FORMAT_HTML, 784 array('noclean' => true, 'para' => false, 'filter' => false)); 785 $this->assertEquals($formattedtext, $module['description']); 786 $this->assertEquals($labelcm->instance, $module['instance']); 787 $testexecuted = $testexecuted + 1; 788 } 789 } 790 $this->assertEquals(2, $testexecuted); 791 $this->assertEquals(0, $firstsection['section']); 792 793 // Check that the only return section has the 5 created modules. 794 $this->assertCount(4, $firstsection['modules']); 795 $this->assertCount(1, $lastsection['modules']); 796 $this->assertEquals(2, $lastsection['section']); 797 $this->assertContains('<iframe', $lastsection['summary']); 798 $this->assertContains('</iframe>', $lastsection['summary']); 799 800 try { 801 $sections = core_course_external::get_course_contents($course->id, 802 array(array("name" => "invalid", "value" => 1))); 803 $this->fail('Exception expected due to invalid option.'); 804 } catch (moodle_exception $e) { 805 $this->assertEquals('errorinvalidparam', $e->errorcode); 806 } 807 } 808 809 810 /** 811 * Test get_course_contents excluding modules 812 */ 813 public function test_get_course_contents_excluding_modules() { 814 $this->resetAfterTest(true); 815 816 list($course, $forumcm, $datacm, $pagecm, $labelcm, $urlcm) = $this->prepare_get_course_contents_test(); 817 818 // Test exclude modules. 819 $sections = core_course_external::get_course_contents($course->id, array(array("name" => "excludemodules", "value" => 1))); 820 821 // We need to execute the return values cleaning process to simulate the web service server. 822 $sections = external_api::clean_returnvalue(core_course_external::get_course_contents_returns(), $sections); 823 824 $firstsection = array_shift($sections); 825 $lastsection = array_pop($sections); 826 827 $this->assertEmpty($firstsection['modules']); 828 $this->assertEmpty($lastsection['modules']); 829 } 830 831 /** 832 * Test get_course_contents excluding contents 833 */ 834 public function test_get_course_contents_excluding_contents() { 835 $this->resetAfterTest(true); 836 837 list($course, $forumcm, $datacm, $pagecm, $labelcm, $urlcm) = $this->prepare_get_course_contents_test(); 838 839 // Test exclude modules. 840 $sections = core_course_external::get_course_contents($course->id, array(array("name" => "excludecontents", "value" => 1))); 841 842 // We need to execute the return values cleaning process to simulate the web service server. 843 $sections = external_api::clean_returnvalue(core_course_external::get_course_contents_returns(), $sections); 844 845 foreach ($sections as $section) { 846 foreach ($section['modules'] as $module) { 847 // Only resources return contents. 848 if (isset($module['contents'])) { 849 $this->assertEmpty($module['contents']); 850 } 851 } 852 } 853 } 854 855 /** 856 * Test get_course_contents filtering by section number 857 */ 858 public function test_get_course_contents_section_number() { 859 $this->resetAfterTest(true); 860 861 list($course, $forumcm, $datacm, $pagecm, $labelcm, $urlcm) = $this->prepare_get_course_contents_test(); 862 863 // Test exclude modules. 864 $sections = core_course_external::get_course_contents($course->id, array(array("name" => "sectionnumber", "value" => 0))); 865 866 // We need to execute the return values cleaning process to simulate the web service server. 867 $sections = external_api::clean_returnvalue(core_course_external::get_course_contents_returns(), $sections); 868 869 $this->assertCount(1, $sections); 870 $this->assertCount(4, $sections[0]['modules']); 871 } 872 873 /** 874 * Test get_course_contents filtering by cmid 875 */ 876 public function test_get_course_contents_cmid() { 877 $this->resetAfterTest(true); 878 879 list($course, $forumcm, $datacm, $pagecm, $labelcm, $urlcm) = $this->prepare_get_course_contents_test(); 880 881 // Test exclude modules. 882 $sections = core_course_external::get_course_contents($course->id, array(array("name" => "cmid", "value" => $forumcm->id))); 883 884 // We need to execute the return values cleaning process to simulate the web service server. 885 $sections = external_api::clean_returnvalue(core_course_external::get_course_contents_returns(), $sections); 886 887 $this->assertCount(2, $sections); 888 $this->assertCount(1, $sections[0]['modules']); 889 $this->assertEquals($forumcm->id, $sections[0]['modules'][0]["id"]); 890 } 891 892 893 /** 894 * Test get_course_contents filtering by cmid and section 895 */ 896 public function test_get_course_contents_section_cmid() { 897 $this->resetAfterTest(true); 898 899 list($course, $forumcm, $datacm, $pagecm, $labelcm, $urlcm) = $this->prepare_get_course_contents_test(); 900 901 // Test exclude modules. 902 $sections = core_course_external::get_course_contents($course->id, array( 903 array("name" => "cmid", "value" => $forumcm->id), 904 array("name" => "sectionnumber", "value" => 0) 905 )); 906 907 // We need to execute the return values cleaning process to simulate the web service server. 908 $sections = external_api::clean_returnvalue(core_course_external::get_course_contents_returns(), $sections); 909 910 $this->assertCount(1, $sections); 911 $this->assertCount(1, $sections[0]['modules']); 912 $this->assertEquals($forumcm->id, $sections[0]['modules'][0]["id"]); 913 } 914 915 /** 916 * Test get_course_contents filtering by modname 917 */ 918 public function test_get_course_contents_modname() { 919 $this->resetAfterTest(true); 920 921 list($course, $forumcm, $datacm, $pagecm, $labelcm, $urlcm) = $this->prepare_get_course_contents_test(); 922 923 // Test exclude modules. 924 $sections = core_course_external::get_course_contents($course->id, array(array("name" => "modname", "value" => "forum"))); 925 926 // We need to execute the return values cleaning process to simulate the web service server. 927 $sections = external_api::clean_returnvalue(core_course_external::get_course_contents_returns(), $sections); 928 929 $this->assertCount(2, $sections); 930 $this->assertCount(1, $sections[0]['modules']); 931 $this->assertEquals($forumcm->id, $sections[0]['modules'][0]["id"]); 932 } 933 934 /** 935 * Test get_course_contents filtering by modname 936 */ 937 public function test_get_course_contents_modid() { 938 $this->resetAfterTest(true); 939 940 list($course, $forumcm, $datacm, $pagecm, $labelcm, $urlcm) = $this->prepare_get_course_contents_test(); 941 942 // Test exclude modules. 943 $sections = core_course_external::get_course_contents($course->id, array( 944 array("name" => "modname", "value" => "page"), 945 array("name" => "modid", "value" => $pagecm->instance), 946 )); 947 948 // We need to execute the return values cleaning process to simulate the web service server. 949 $sections = external_api::clean_returnvalue(core_course_external::get_course_contents_returns(), $sections); 950 951 $this->assertCount(2, $sections); 952 $this->assertCount(1, $sections[0]['modules']); 953 $this->assertEquals("page", $sections[0]['modules'][0]["modname"]); 954 $this->assertEquals($pagecm->instance, $sections[0]['modules'][0]["instance"]); 955 } 956 957 /** 958 * Test duplicate_course 959 */ 960 public function test_duplicate_course() { 961 $this->resetAfterTest(true); 962 963 // Create one course with three modules. 964 $course = self::getDataGenerator()->create_course(); 965 $forum = $this->getDataGenerator()->create_module('forum', array('course'=>$course->id)); 966 $forumcm = get_coursemodule_from_id('forum', $forum->cmid); 967 $forumcontext = context_module::instance($forum->cmid); 968 $data = $this->getDataGenerator()->create_module('data', array('assessed'=>1, 'scale'=>100, 'course'=>$course->id)); 969 $datacontext = context_module::instance($data->cmid); 970 $datacm = get_coursemodule_from_instance('page', $data->id); 971 $page = $this->getDataGenerator()->create_module('page', array('course'=>$course->id)); 972 $pagecontext = context_module::instance($page->cmid); 973 $pagecm = get_coursemodule_from_instance('page', $page->id); 974 975 // Set the required capabilities by the external function. 976 $coursecontext = context_course::instance($course->id); 977 $categorycontext = context_coursecat::instance($course->category); 978 $roleid = $this->assignUserCapability('moodle/course:create', $categorycontext->id); 979 $this->assignUserCapability('moodle/course:view', $categorycontext->id, $roleid); 980 $this->assignUserCapability('moodle/restore:restorecourse', $categorycontext->id, $roleid); 981 $this->assignUserCapability('moodle/backup:backupcourse', $coursecontext->id, $roleid); 982 $this->assignUserCapability('moodle/backup:configure', $coursecontext->id, $roleid); 983 // Optional capabilities to copy user data. 984 $this->assignUserCapability('moodle/backup:userinfo', $coursecontext->id, $roleid); 985 $this->assignUserCapability('moodle/restore:userinfo', $categorycontext->id, $roleid); 986 987 $newcourse['fullname'] = 'Course duplicate'; 988 $newcourse['shortname'] = 'courseduplicate'; 989 $newcourse['categoryid'] = $course->category; 990 $newcourse['visible'] = true; 991 $newcourse['options'][] = array('name' => 'users', 'value' => true); 992 993 $duplicate = core_course_external::duplicate_course($course->id, $newcourse['fullname'], 994 $newcourse['shortname'], $newcourse['categoryid'], $newcourse['visible'], $newcourse['options']); 995 996 // We need to execute the return values cleaning process to simulate the web service server. 997 $duplicate = external_api::clean_returnvalue(core_course_external::duplicate_course_returns(), $duplicate); 998 999 // Check that the course has been duplicated. 1000 $this->assertEquals($newcourse['shortname'], $duplicate['shortname']); 1001 } 1002 1003 /** 1004 * Test update_courses 1005 */ 1006 public function test_update_courses() { 1007 global $DB, $CFG, $USER, $COURSE; 1008 1009 // Get current $COURSE to be able to restore it later (defaults to $SITE). We need this 1010 // trick because we are both updating and getting (for testing) course information 1011 // in the same request and core_course_external::update_courses() 1012 // is overwriting $COURSE all over the time with OLD values, so later 1013 // use of get_course() fetches those OLD values instead of the updated ones. 1014 // See MDL-39723 for more info. 1015 $origcourse = clone($COURSE); 1016 1017 $this->resetAfterTest(true); 1018 1019 // Set the required capabilities by the external function. 1020 $contextid = context_system::instance()->id; 1021 $roleid = $this->assignUserCapability('moodle/course:update', $contextid); 1022 $this->assignUserCapability('moodle/course:changecategory', $contextid, $roleid); 1023 $this->assignUserCapability('moodle/course:changefullname', $contextid, $roleid); 1024 $this->assignUserCapability('moodle/course:changeshortname', $contextid, $roleid); 1025 $this->assignUserCapability('moodle/course:changeidnumber', $contextid, $roleid); 1026 $this->assignUserCapability('moodle/course:changesummary', $contextid, $roleid); 1027 $this->assignUserCapability('moodle/course:visibility', $contextid, $roleid); 1028 $this->assignUserCapability('moodle/course:viewhiddencourses', $contextid, $roleid); 1029 1030 // Create category and course. 1031 $category1 = self::getDataGenerator()->create_category(); 1032 $category2 = self::getDataGenerator()->create_category(); 1033 $originalcourse1 = self::getDataGenerator()->create_course(); 1034 self::getDataGenerator()->enrol_user($USER->id, $originalcourse1->id, $roleid); 1035 $originalcourse2 = self::getDataGenerator()->create_course(); 1036 self::getDataGenerator()->enrol_user($USER->id, $originalcourse2->id, $roleid); 1037 1038 // Course values to be updated. 1039 $course1['id'] = $originalcourse1->id; 1040 $course1['fullname'] = 'Updated test course 1'; 1041 $course1['shortname'] = 'Udestedtestcourse1'; 1042 $course1['categoryid'] = $category1->id; 1043 $course2['id'] = $originalcourse2->id; 1044 $course2['fullname'] = 'Updated test course 2'; 1045 $course2['shortname'] = 'Updestedtestcourse2'; 1046 $course2['categoryid'] = $category2->id; 1047 $course2['idnumber'] = 'Updatedidnumber2'; 1048 $course2['summary'] = 'Updaated description for course 2'; 1049 $course2['summaryformat'] = FORMAT_HTML; 1050 $course2['format'] = 'topics'; 1051 $course2['showgrades'] = 1; 1052 $course2['newsitems'] = 3; 1053 $course2['startdate'] = 1420092000; // 01/01/2015. 1054 $course2['numsections'] = 4; 1055 $course2['maxbytes'] = 100000; 1056 $course2['showreports'] = 1; 1057 $course2['visible'] = 0; 1058 $course2['hiddensections'] = 0; 1059 $course2['groupmode'] = 0; 1060 $course2['groupmodeforce'] = 0; 1061 $course2['defaultgroupingid'] = 0; 1062 $course2['enablecompletion'] = 1; 1063 $course2['lang'] = 'en'; 1064 $course2['forcetheme'] = 'base'; 1065 $courses = array($course1, $course2); 1066 1067 $updatedcoursewarnings = core_course_external::update_courses($courses); 1068 $updatedcoursewarnings = external_api::clean_returnvalue(core_course_external::update_courses_returns(), 1069 $updatedcoursewarnings); 1070 $COURSE = $origcourse; // Restore $COURSE. Instead of using the OLD one set by the previous line. 1071 1072 // Check that right number of courses were created. 1073 $this->assertEquals(0, count($updatedcoursewarnings['warnings'])); 1074 1075 // Check that the courses were correctly created. 1076 foreach ($courses as $course) { 1077 $courseinfo = course_get_format($course['id'])->get_course(); 1078 if ($course['id'] == $course2['id']) { 1079 $this->assertEquals($course2['fullname'], $courseinfo->fullname); 1080 $this->assertEquals($course2['shortname'], $courseinfo->shortname); 1081 $this->assertEquals($course2['categoryid'], $courseinfo->category); 1082 $this->assertEquals($course2['idnumber'], $courseinfo->idnumber); 1083 $this->assertEquals($course2['summary'], $courseinfo->summary); 1084 $this->assertEquals($course2['summaryformat'], $courseinfo->summaryformat); 1085 $this->assertEquals($course2['format'], $courseinfo->format); 1086 $this->assertEquals($course2['showgrades'], $courseinfo->showgrades); 1087 $this->assertEquals($course2['newsitems'], $courseinfo->newsitems); 1088 $this->assertEquals($course2['startdate'], $courseinfo->startdate); 1089 $this->assertEquals($course2['numsections'], $courseinfo->numsections); 1090 $this->assertEquals($course2['maxbytes'], $courseinfo->maxbytes); 1091 $this->assertEquals($course2['showreports'], $courseinfo->showreports); 1092 $this->assertEquals($course2['visible'], $courseinfo->visible); 1093 $this->assertEquals($course2['hiddensections'], $courseinfo->hiddensections); 1094 $this->assertEquals($course2['groupmode'], $courseinfo->groupmode); 1095 $this->assertEquals($course2['groupmodeforce'], $courseinfo->groupmodeforce); 1096 $this->assertEquals($course2['defaultgroupingid'], $courseinfo->defaultgroupingid); 1097 $this->assertEquals($course2['lang'], $courseinfo->lang); 1098 1099 if (!empty($CFG->allowcoursethemes)) { 1100 $this->assertEquals($course2['forcetheme'], $courseinfo->theme); 1101 } 1102 1103 $this->assertEquals($course2['enablecompletion'], $courseinfo->enablecompletion); 1104 } else if ($course['id'] == $course1['id']) { 1105 $this->assertEquals($course1['fullname'], $courseinfo->fullname); 1106 $this->assertEquals($course1['shortname'], $courseinfo->shortname); 1107 $this->assertEquals($course1['categoryid'], $courseinfo->category); 1108 $this->assertEquals(FORMAT_MOODLE, $courseinfo->summaryformat); 1109 $this->assertEquals('topics', $courseinfo->format); 1110 $this->assertEquals(5, $courseinfo->numsections); 1111 $this->assertEquals(0, $courseinfo->newsitems); 1112 $this->assertEquals(FORMAT_MOODLE, $courseinfo->summaryformat); 1113 } else { 1114 throw moodle_exception('Unexpected shortname'); 1115 } 1116 } 1117 1118 $courses = array($course1); 1119 // Try update course without update capability. 1120 $user = self::getDataGenerator()->create_user(); 1121 $this->setUser($user); 1122 $this->unassignUserCapability('moodle/course:update', $contextid, $roleid); 1123 self::getDataGenerator()->enrol_user($user->id, $course1['id'], $roleid); 1124 $updatedcoursewarnings = core_course_external::update_courses($courses); 1125 $updatedcoursewarnings = external_api::clean_returnvalue(core_course_external::update_courses_returns(), 1126 $updatedcoursewarnings); 1127 $this->assertEquals(1, count($updatedcoursewarnings['warnings'])); 1128 1129 // Try update course category without capability. 1130 $this->assignUserCapability('moodle/course:update', $contextid, $roleid); 1131 $this->unassignUserCapability('moodle/course:changecategory', $contextid, $roleid); 1132 $user = self::getDataGenerator()->create_user(); 1133 $this->setUser($user); 1134 self::getDataGenerator()->enrol_user($user->id, $course1['id'], $roleid); 1135 $course1['categoryid'] = $category2->id; 1136 $courses = array($course1); 1137 $updatedcoursewarnings = core_course_external::update_courses($courses); 1138 $updatedcoursewarnings = external_api::clean_returnvalue(core_course_external::update_courses_returns(), 1139 $updatedcoursewarnings); 1140 $this->assertEquals(1, count($updatedcoursewarnings['warnings'])); 1141 1142 // Try update course fullname without capability. 1143 $this->assignUserCapability('moodle/course:changecategory', $contextid, $roleid); 1144 $this->unassignUserCapability('moodle/course:changefullname', $contextid, $roleid); 1145 $user = self::getDataGenerator()->create_user(); 1146 $this->setUser($user); 1147 self::getDataGenerator()->enrol_user($user->id, $course1['id'], $roleid); 1148 $updatedcoursewarnings = core_course_external::update_courses($courses); 1149 $updatedcoursewarnings = external_api::clean_returnvalue(core_course_external::update_courses_returns(), 1150 $updatedcoursewarnings); 1151 $this->assertEquals(0, count($updatedcoursewarnings['warnings'])); 1152 $course1['fullname'] = 'Testing fullname without permission'; 1153 $courses = array($course1); 1154 $updatedcoursewarnings = core_course_external::update_courses($courses); 1155 $updatedcoursewarnings = external_api::clean_returnvalue(core_course_external::update_courses_returns(), 1156 $updatedcoursewarnings); 1157 $this->assertEquals(1, count($updatedcoursewarnings['warnings'])); 1158 1159 // Try update course shortname without capability. 1160 $this->assignUserCapability('moodle/course:changefullname', $contextid, $roleid); 1161 $this->unassignUserCapability('moodle/course:changeshortname', $contextid, $roleid); 1162 $user = self::getDataGenerator()->create_user(); 1163 $this->setUser($user); 1164 self::getDataGenerator()->enrol_user($user->id, $course1['id'], $roleid); 1165 $updatedcoursewarnings = core_course_external::update_courses($courses); 1166 $updatedcoursewarnings = external_api::clean_returnvalue(core_course_external::update_courses_returns(), 1167 $updatedcoursewarnings); 1168 $this->assertEquals(0, count($updatedcoursewarnings['warnings'])); 1169 $course1['shortname'] = 'Testing shortname without permission'; 1170 $courses = array($course1); 1171 $updatedcoursewarnings = core_course_external::update_courses($courses); 1172 $updatedcoursewarnings = external_api::clean_returnvalue(core_course_external::update_courses_returns(), 1173 $updatedcoursewarnings); 1174 $this->assertEquals(1, count($updatedcoursewarnings['warnings'])); 1175 1176 // Try update course idnumber without capability. 1177 $this->assignUserCapability('moodle/course:changeshortname', $contextid, $roleid); 1178 $this->unassignUserCapability('moodle/course:changeidnumber', $contextid, $roleid); 1179 $user = self::getDataGenerator()->create_user(); 1180 $this->setUser($user); 1181 self::getDataGenerator()->enrol_user($user->id, $course1['id'], $roleid); 1182 $updatedcoursewarnings = core_course_external::update_courses($courses); 1183 $updatedcoursewarnings = external_api::clean_returnvalue(core_course_external::update_courses_returns(), 1184 $updatedcoursewarnings); 1185 $this->assertEquals(0, count($updatedcoursewarnings['warnings'])); 1186 $course1['idnumber'] = 'NEWIDNUMBER'; 1187 $courses = array($course1); 1188 $updatedcoursewarnings = core_course_external::update_courses($courses); 1189 $updatedcoursewarnings = external_api::clean_returnvalue(core_course_external::update_courses_returns(), 1190 $updatedcoursewarnings); 1191 $this->assertEquals(1, count($updatedcoursewarnings['warnings'])); 1192 1193 // Try update course summary without capability. 1194 $this->assignUserCapability('moodle/course:changeidnumber', $contextid, $roleid); 1195 $this->unassignUserCapability('moodle/course:changesummary', $contextid, $roleid); 1196 $user = self::getDataGenerator()->create_user(); 1197 $this->setUser($user); 1198 self::getDataGenerator()->enrol_user($user->id, $course1['id'], $roleid); 1199 $updatedcoursewarnings = core_course_external::update_courses($courses); 1200 $updatedcoursewarnings = external_api::clean_returnvalue(core_course_external::update_courses_returns(), 1201 $updatedcoursewarnings); 1202 $this->assertEquals(0, count($updatedcoursewarnings['warnings'])); 1203 $course1['summary'] = 'New summary'; 1204 $courses = array($course1); 1205 $updatedcoursewarnings = core_course_external::update_courses($courses); 1206 $updatedcoursewarnings = external_api::clean_returnvalue(core_course_external::update_courses_returns(), 1207 $updatedcoursewarnings); 1208 $this->assertEquals(1, count($updatedcoursewarnings['warnings'])); 1209 1210 // Try update course with invalid summary format. 1211 $this->assignUserCapability('moodle/course:changesummary', $contextid, $roleid); 1212 $user = self::getDataGenerator()->create_user(); 1213 $this->setUser($user); 1214 self::getDataGenerator()->enrol_user($user->id, $course1['id'], $roleid); 1215 $updatedcoursewarnings = core_course_external::update_courses($courses); 1216 $updatedcoursewarnings = external_api::clean_returnvalue(core_course_external::update_courses_returns(), 1217 $updatedcoursewarnings); 1218 $this->assertEquals(0, count($updatedcoursewarnings['warnings'])); 1219 $course1['summaryformat'] = 10; 1220 $courses = array($course1); 1221 $updatedcoursewarnings = core_course_external::update_courses($courses); 1222 $updatedcoursewarnings = external_api::clean_returnvalue(core_course_external::update_courses_returns(), 1223 $updatedcoursewarnings); 1224 $this->assertEquals(1, count($updatedcoursewarnings['warnings'])); 1225 1226 // Try update course visibility without capability. 1227 $this->unassignUserCapability('moodle/course:visibility', $contextid, $roleid); 1228 $user = self::getDataGenerator()->create_user(); 1229 $this->setUser($user); 1230 self::getDataGenerator()->enrol_user($user->id, $course1['id'], $roleid); 1231 $course1['summaryformat'] = FORMAT_MOODLE; 1232 $courses = array($course1); 1233 $updatedcoursewarnings = core_course_external::update_courses($courses); 1234 $updatedcoursewarnings = external_api::clean_returnvalue(core_course_external::update_courses_returns(), 1235 $updatedcoursewarnings); 1236 $this->assertEquals(0, count($updatedcoursewarnings['warnings'])); 1237 $course1['visible'] = 0; 1238 $courses = array($course1); 1239 $updatedcoursewarnings = core_course_external::update_courses($courses); 1240 $updatedcoursewarnings = external_api::clean_returnvalue(core_course_external::update_courses_returns(), 1241 $updatedcoursewarnings); 1242 $this->assertEquals(1, count($updatedcoursewarnings['warnings'])); 1243 } 1244 1245 /** 1246 * Test delete course_module. 1247 */ 1248 public function test_delete_modules() { 1249 global $DB; 1250 1251 // Ensure we reset the data after this test. 1252 $this->resetAfterTest(true); 1253 1254 // Create a user. 1255 $user = self::getDataGenerator()->create_user(); 1256 1257 // Set the tests to run as the user. 1258 self::setUser($user); 1259 1260 // Create a course to add the modules. 1261 $course = self::getDataGenerator()->create_course(); 1262 1263 // Create two test modules. 1264 $record = new stdClass(); 1265 $record->course = $course->id; 1266 $module1 = self::getDataGenerator()->create_module('forum', $record); 1267 $module2 = self::getDataGenerator()->create_module('assign', $record); 1268 1269 // Check the forum was correctly created. 1270 $this->assertEquals(1, $DB->count_records('forum', array('id' => $module1->id))); 1271 1272 // Check the assignment was correctly created. 1273 $this->assertEquals(1, $DB->count_records('assign', array('id' => $module2->id))); 1274 1275 // Check data exists in the course modules table. 1276 $this->assertEquals(2, $DB->count_records_select('course_modules', 'id = :module1 OR id = :module2', 1277 array('module1' => $module1->cmid, 'module2' => $module2->cmid))); 1278 1279 // Enrol the user in the course. 1280 $enrol = enrol_get_plugin('manual'); 1281 $enrolinstances = enrol_get_instances($course->id, true); 1282 foreach ($enrolinstances as $courseenrolinstance) { 1283 if ($courseenrolinstance->enrol == "manual") { 1284 $instance = $courseenrolinstance; 1285 break; 1286 } 1287 } 1288 $enrol->enrol_user($instance, $user->id); 1289 1290 // Assign capabilities to delete module 1. 1291 $modcontext = context_module::instance($module1->cmid); 1292 $this->assignUserCapability('moodle/course:manageactivities', $modcontext->id); 1293 1294 // Assign capabilities to delete module 2. 1295 $modcontext = context_module::instance($module2->cmid); 1296 $newrole = create_role('Role 2', 'role2', 'Role 2 description'); 1297 $this->assignUserCapability('moodle/course:manageactivities', $modcontext->id, $newrole); 1298 1299 // Deleting these module instances. 1300 core_course_external::delete_modules(array($module1->cmid, $module2->cmid)); 1301 1302 // Check the forum was deleted. 1303 $this->assertEquals(0, $DB->count_records('forum', array('id' => $module1->id))); 1304 1305 // Check the assignment was deleted. 1306 $this->assertEquals(0, $DB->count_records('assign', array('id' => $module2->id))); 1307 1308 // Check we retrieve no data in the course modules table. 1309 $this->assertEquals(0, $DB->count_records_select('course_modules', 'id = :module1 OR id = :module2', 1310 array('module1' => $module1->cmid, 'module2' => $module2->cmid))); 1311 1312 // Call with non-existent course module id and ensure exception thrown. 1313 try { 1314 core_course_external::delete_modules(array('1337')); 1315 $this->fail('Exception expected due to missing course module.'); 1316 } catch (dml_missing_record_exception $e) { 1317 $this->assertEquals('invalidcoursemodule', $e->errorcode); 1318 } 1319 1320 // Create two modules. 1321 $module1 = self::getDataGenerator()->create_module('forum', $record); 1322 $module2 = self::getDataGenerator()->create_module('assign', $record); 1323 1324 // Since these modules were recreated the user will not have capabilities 1325 // to delete them, ensure exception is thrown if they try. 1326 try { 1327 core_course_external::delete_modules(array($module1->cmid, $module2->cmid)); 1328 $this->fail('Exception expected due to missing capability.'); 1329 } catch (moodle_exception $e) { 1330 $this->assertEquals('nopermissions', $e->errorcode); 1331 } 1332 1333 // Unenrol user from the course. 1334 $enrol->unenrol_user($instance, $user->id); 1335 1336 // Try and delete modules from the course the user was unenrolled in, make sure exception thrown. 1337 try { 1338 core_course_external::delete_modules(array($module1->cmid, $module2->cmid)); 1339 $this->fail('Exception expected due to being unenrolled from the course.'); 1340 } catch (moodle_exception $e) { 1341 $this->assertEquals('requireloginerror', $e->errorcode); 1342 } 1343 } 1344 1345 /** 1346 * Test import_course into an empty course 1347 */ 1348 public function test_import_course_empty() { 1349 global $USER; 1350 1351 $this->resetAfterTest(true); 1352 1353 $course1 = self::getDataGenerator()->create_course(); 1354 $forum = $this->getDataGenerator()->create_module('forum', array('course' => $course1->id, 'name' => 'Forum test')); 1355 $page = $this->getDataGenerator()->create_module('page', array('course' => $course1->id, 'name' => 'Page test')); 1356 1357 $course2 = self::getDataGenerator()->create_course(); 1358 1359 $course1cms = get_fast_modinfo($course1->id)->get_cms(); 1360 $course2cms = get_fast_modinfo($course2->id)->get_cms(); 1361 1362 // Verify the state of the courses before we do the import. 1363 $this->assertCount(2, $course1cms); 1364 $this->assertEmpty($course2cms); 1365 1366 // Setup the user to run the operation (ugly hack because validate_context() will 1367 // fail as the email is not set by $this->setAdminUser()). 1368 $this->setAdminUser(); 1369 $USER->email = 'emailtopass@example.com'; 1370 1371 // Import from course1 to course2. 1372 core_course_external::import_course($course1->id, $course2->id, 0); 1373 1374 // Verify that now we have two modules in both courses. 1375 $course1cms = get_fast_modinfo($course1->id)->get_cms(); 1376 $course2cms = get_fast_modinfo($course2->id)->get_cms(); 1377 $this->assertCount(2, $course1cms); 1378 $this->assertCount(2, $course2cms); 1379 1380 // Verify that the names transfered across correctly. 1381 foreach ($course2cms as $cm) { 1382 if ($cm->modname === 'page') { 1383 $this->assertEquals($cm->name, $page->name); 1384 } else if ($cm->modname === 'forum') { 1385 $this->assertEquals($cm->name, $forum->name); 1386 } else { 1387 $this->fail('Unknown CM found.'); 1388 } 1389 } 1390 } 1391 1392 /** 1393 * Test import_course into an filled course 1394 */ 1395 public function test_import_course_filled() { 1396 global $USER; 1397 1398 $this->resetAfterTest(true); 1399 1400 // Add forum and page to course1. 1401 $course1 = self::getDataGenerator()->create_course(); 1402 $forum = $this->getDataGenerator()->create_module('forum', array('course'=>$course1->id, 'name' => 'Forum test')); 1403 $page = $this->getDataGenerator()->create_module('page', array('course'=>$course1->id, 'name' => 'Page test')); 1404 1405 // Add quiz to course 2. 1406 $course2 = self::getDataGenerator()->create_course(); 1407 $quiz = $this->getDataGenerator()->create_module('quiz', array('course'=>$course2->id, 'name' => 'Page test')); 1408 1409 $course1cms = get_fast_modinfo($course1->id)->get_cms(); 1410 $course2cms = get_fast_modinfo($course2->id)->get_cms(); 1411 1412 // Verify the state of the courses before we do the import. 1413 $this->assertCount(2, $course1cms); 1414 $this->assertCount(1, $course2cms); 1415 1416 // Setup the user to run the operation (ugly hack because validate_context() will 1417 // fail as the email is not set by $this->setAdminUser()). 1418 $this->setAdminUser(); 1419 $USER->email = 'emailtopass@example.com'; 1420 1421 // Import from course1 to course2 without deleting content. 1422 core_course_external::import_course($course1->id, $course2->id, 0); 1423 1424 $course2cms = get_fast_modinfo($course2->id)->get_cms(); 1425 1426 // Verify that now we have three modules in course2. 1427 $this->assertCount(3, $course2cms); 1428 1429 // Verify that the names transfered across correctly. 1430 foreach ($course2cms as $cm) { 1431 if ($cm->modname === 'page') { 1432 $this->assertEquals($cm->name, $page->name); 1433 } else if ($cm->modname === 'forum') { 1434 $this->assertEquals($cm->name, $forum->name); 1435 } else if ($cm->modname === 'quiz') { 1436 $this->assertEquals($cm->name, $quiz->name); 1437 } else { 1438 $this->fail('Unknown CM found.'); 1439 } 1440 } 1441 } 1442 1443 /** 1444 * Test import_course with only blocks set to backup 1445 */ 1446 public function test_import_course_blocksonly() { 1447 global $USER, $DB; 1448 1449 $this->resetAfterTest(true); 1450 1451 // Add forum and page to course1. 1452 $course1 = self::getDataGenerator()->create_course(); 1453 $course1ctx = context_course::instance($course1->id); 1454 $forum = $this->getDataGenerator()->create_module('forum', array('course'=>$course1->id, 'name' => 'Forum test')); 1455 $block = $this->getDataGenerator()->create_block('online_users', array('parentcontextid' => $course1ctx->id)); 1456 1457 $course2 = self::getDataGenerator()->create_course(); 1458 $course2ctx = context_course::instance($course2->id); 1459 $initialblockcount = $DB->count_records('block_instances', array('parentcontextid' => $course2ctx->id)); 1460 $initialcmcount = count(get_fast_modinfo($course2->id)->get_cms()); 1461 1462 // Setup the user to run the operation (ugly hack because validate_context() will 1463 // fail as the email is not set by $this->setAdminUser()). 1464 $this->setAdminUser(); 1465 $USER->email = 'emailtopass@example.com'; 1466 1467 // Import from course1 to course2 without deleting content, but excluding 1468 // activities. 1469 $options = array( 1470 array('name' => 'activities', 'value' => 0), 1471 array('name' => 'blocks', 'value' => 1), 1472 array('name' => 'filters', 'value' => 0), 1473 ); 1474 1475 core_course_external::import_course($course1->id, $course2->id, 0, $options); 1476 1477 $newcmcount = count(get_fast_modinfo($course2->id)->get_cms()); 1478 $newblockcount = $DB->count_records('block_instances', array('parentcontextid' => $course2ctx->id)); 1479 // Check that course modules haven't changed, but that blocks have. 1480 $this->assertEquals($initialcmcount, $newcmcount); 1481 $this->assertEquals(($initialblockcount + 1), $newblockcount); 1482 } 1483 1484 /** 1485 * Test import_course into an filled course, deleting content. 1486 */ 1487 public function test_import_course_deletecontent() { 1488 global $USER; 1489 $this->resetAfterTest(true); 1490 1491 // Add forum and page to course1. 1492 $course1 = self::getDataGenerator()->create_course(); 1493 $forum = $this->getDataGenerator()->create_module('forum', array('course'=>$course1->id, 'name' => 'Forum test')); 1494 $page = $this->getDataGenerator()->create_module('page', array('course'=>$course1->id, 'name' => 'Page test')); 1495 1496 // Add quiz to course 2. 1497 $course2 = self::getDataGenerator()->create_course(); 1498 $quiz = $this->getDataGenerator()->create_module('quiz', array('course'=>$course2->id, 'name' => 'Page test')); 1499 1500 $course1cms = get_fast_modinfo($course1->id)->get_cms(); 1501 $course2cms = get_fast_modinfo($course2->id)->get_cms(); 1502 1503 // Verify the state of the courses before we do the import. 1504 $this->assertCount(2, $course1cms); 1505 $this->assertCount(1, $course2cms); 1506 1507 // Setup the user to run the operation (ugly hack because validate_context() will 1508 // fail as the email is not set by $this->setAdminUser()). 1509 $this->setAdminUser(); 1510 $USER->email = 'emailtopass@example.com'; 1511 1512 // Import from course1 to course2, deleting content. 1513 core_course_external::import_course($course1->id, $course2->id, 1); 1514 1515 $course2cms = get_fast_modinfo($course2->id)->get_cms(); 1516 1517 // Verify that now we have two modules in course2. 1518 $this->assertCount(2, $course2cms); 1519 1520 // Verify that the course only contains the imported modules. 1521 foreach ($course2cms as $cm) { 1522 if ($cm->modname === 'page') { 1523 $this->assertEquals($cm->name, $page->name); 1524 } else if ($cm->modname === 'forum') { 1525 $this->assertEquals($cm->name, $forum->name); 1526 } else { 1527 $this->fail('Unknown CM found: '.$cm->name); 1528 } 1529 } 1530 } 1531 1532 /** 1533 * Ensure import_course handles incorrect deletecontent option correctly. 1534 */ 1535 public function test_import_course_invalid_deletecontent_option() { 1536 $this->resetAfterTest(true); 1537 1538 $course1 = self::getDataGenerator()->create_course(); 1539 $course2 = self::getDataGenerator()->create_course(); 1540 1541 $this->expectException('moodle_exception'); 1542 $this->expectExceptionMessage(get_string('invalidextparam', 'webservice', -1)); 1543 // Import from course1 to course2, with invalid option 1544 core_course_external::import_course($course1->id, $course2->id, -1);; 1545 } 1546 1547 /** 1548 * Test view_course function 1549 */ 1550 public function test_view_course() { 1551 1552 $this->resetAfterTest(); 1553 1554 // Course without sections. 1555 $course = $this->getDataGenerator()->create_course(array('numsections' => 5), array('createsections' => true)); 1556 $this->setAdminUser(); 1557 1558 // Redirect events to the sink, so we can recover them later. 1559 $sink = $this->redirectEvents(); 1560 1561 $result = core_course_external::view_course($course->id, 1); 1562 $result = external_api::clean_returnvalue(core_course_external::view_course_returns(), $result); 1563 $events = $sink->get_events(); 1564 $event = reset($events); 1565 1566 // Check the event details are correct. 1567 $this->assertInstanceOf('\core\event\course_viewed', $event); 1568 $this->assertEquals(context_course::instance($course->id), $event->get_context()); 1569 $this->assertEquals(1, $event->other['coursesectionnumber']); 1570 1571 $result = core_course_external::view_course($course->id); 1572 $result = external_api::clean_returnvalue(core_course_external::view_course_returns(), $result); 1573 $events = $sink->get_events(); 1574 $event = array_pop($events); 1575 $sink->close(); 1576 1577 // Check the event details are correct. 1578 $this->assertInstanceOf('\core\event\course_viewed', $event); 1579 $this->assertEquals(context_course::instance($course->id), $event->get_context()); 1580 $this->assertEmpty($event->other); 1581 1582 } 1583 1584 /** 1585 * Test get_course_module 1586 */ 1587 public function test_get_course_module() { 1588 global $DB; 1589 1590 $this->resetAfterTest(true); 1591 1592 $this->setAdminUser(); 1593 $course = self::getDataGenerator()->create_course(); 1594 $record = array( 1595 'course' => $course->id, 1596 'name' => 'First Chat' 1597 ); 1598 $options = array( 1599 'idnumber' => 'ABC', 1600 'visible' => 0 1601 ); 1602 // Hidden activity. 1603 $chat = self::getDataGenerator()->create_module('chat', $record, $options); 1604 1605 // Test admin user can see the complete hidden activity. 1606 $result = core_course_external::get_course_module($chat->cmid); 1607 $result = external_api::clean_returnvalue(core_course_external::get_course_module_returns(), $result); 1608 1609 $this->assertCount(0, $result['warnings']); 1610 // Test we retrieve all the fields. 1611 $this->assertCount(22, $result['cm']); 1612 $this->assertEquals($record['name'], $result['cm']['name']); 1613 $this->assertEquals($options['idnumber'], $result['cm']['idnumber']); 1614 1615 $student = $this->getDataGenerator()->create_user(); 1616 $studentrole = $DB->get_record('role', array('shortname' => 'student')); 1617 1618 self::getDataGenerator()->enrol_user($student->id, $course->id, $studentrole->id); 1619 $this->setUser($student); 1620 1621 // The user shouldn't be able to see the activity. 1622 try { 1623 core_course_external::get_course_module($chat->cmid); 1624 $this->fail('Exception expected due to invalid permissions.'); 1625 } catch (moodle_exception $e) { 1626 $this->assertEquals('requireloginerror', $e->errorcode); 1627 } 1628 1629 // Make module visible. 1630 set_coursemodule_visible($chat->cmid, 1); 1631 1632 // Test student user. 1633 $result = core_course_external::get_course_module($chat->cmid); 1634 $result = external_api::clean_returnvalue(core_course_external::get_course_module_returns(), $result); 1635 1636 $this->assertCount(0, $result['warnings']); 1637 // Test we retrieve only the few files we can see. 1638 $this->assertCount(11, $result['cm']); 1639 $this->assertEquals($chat->cmid, $result['cm']['id']); 1640 $this->assertEquals($course->id, $result['cm']['course']); 1641 $this->assertEquals('chat', $result['cm']['modname']); 1642 $this->assertEquals($chat->id, $result['cm']['instance']); 1643 1644 } 1645 1646 /** 1647 * Test get_course_module_by_instance 1648 */ 1649 public function test_get_course_module_by_instance() { 1650 global $DB; 1651 1652 $this->resetAfterTest(true); 1653 1654 $this->setAdminUser(); 1655 $course = self::getDataGenerator()->create_course(); 1656 $record = array( 1657 'course' => $course->id, 1658 'name' => 'First Chat' 1659 ); 1660 $options = array( 1661 'idnumber' => 'ABC', 1662 'visible' => 0 1663 ); 1664 // Hidden activity. 1665 $chat = self::getDataGenerator()->create_module('chat', $record, $options); 1666 1667 // Test admin user can see the complete hidden activity. 1668 $result = core_course_external::get_course_module_by_instance('chat', $chat->id); 1669 $result = external_api::clean_returnvalue(core_course_external::get_course_module_by_instance_returns(), $result); 1670 1671 $this->assertCount(0, $result['warnings']); 1672 // Test we retrieve all the fields. 1673 $this->assertCount(22, $result['cm']); 1674 $this->assertEquals($record['name'], $result['cm']['name']); 1675 $this->assertEquals($options['idnumber'], $result['cm']['idnumber']); 1676 1677 $student = $this->getDataGenerator()->create_user(); 1678 $studentrole = $DB->get_record('role', array('shortname' => 'student')); 1679 1680 self::getDataGenerator()->enrol_user($student->id, $course->id, $studentrole->id); 1681 $this->setUser($student); 1682 1683 // The user shouldn't be able to see the activity. 1684 try { 1685 core_course_external::get_course_module_by_instance('chat', $chat->id); 1686 $this->fail('Exception expected due to invalid permissions.'); 1687 } catch (moodle_exception $e) { 1688 $this->assertEquals('requireloginerror', $e->errorcode); 1689 } 1690 1691 // Make module visible. 1692 set_coursemodule_visible($chat->cmid, 1); 1693 1694 // Test student user. 1695 $result = core_course_external::get_course_module_by_instance('chat', $chat->id); 1696 $result = external_api::clean_returnvalue(core_course_external::get_course_module_by_instance_returns(), $result); 1697 1698 $this->assertCount(0, $result['warnings']); 1699 // Test we retrieve only the few files we can see. 1700 $this->assertCount(11, $result['cm']); 1701 $this->assertEquals($chat->cmid, $result['cm']['id']); 1702 $this->assertEquals($course->id, $result['cm']['course']); 1703 $this->assertEquals('chat', $result['cm']['modname']); 1704 $this->assertEquals($chat->id, $result['cm']['instance']); 1705 1706 // Try with an invalid module name. 1707 try { 1708 core_course_external::get_course_module_by_instance('abc', $chat->id); 1709 $this->fail('Exception expected due to invalid module name.'); 1710 } catch (dml_read_exception $e) { 1711 $this->assertEquals('dmlreadexception', $e->errorcode); 1712 } 1713 1714 } 1715 1716 /** 1717 * Test get_activities_overview 1718 */ 1719 public function test_get_activities_overview() { 1720 global $USER; 1721 1722 $this->resetAfterTest(); 1723 $course1 = self::getDataGenerator()->create_course(); 1724 $course2 = self::getDataGenerator()->create_course(); 1725 1726 // Create a viewer user. 1727 $viewer = self::getDataGenerator()->create_user((object) array('trackforums' => 1)); 1728 $this->getDataGenerator()->enrol_user($viewer->id, $course1->id); 1729 $this->getDataGenerator()->enrol_user($viewer->id, $course2->id); 1730 1731 // Create two forums - one in each course. 1732 $record = new stdClass(); 1733 $record->course = $course1->id; 1734 $forum1 = self::getDataGenerator()->create_module('forum', (object) array('course' => $course1->id)); 1735 $forum2 = self::getDataGenerator()->create_module('forum', (object) array('course' => $course2->id)); 1736 1737 $this->setAdminUser(); 1738 // A standard post in the forum. 1739 $record = new stdClass(); 1740 $record->course = $course1->id; 1741 $record->userid = $USER->id; 1742 $record->forum = $forum1->id; 1743 $this->getDataGenerator()->get_plugin_generator('mod_forum')->create_discussion($record); 1744 1745 $this->setUser($viewer->id); 1746 $courses = array($course1->id , $course2->id); 1747 1748 $result = core_course_external::get_activities_overview($courses); 1749 $result = external_api::clean_returnvalue(core_course_external::get_activities_overview_returns(), $result); 1750 1751 // There should be one entry for course1, and no others. 1752 $this->assertCount(1, $result['courses']); 1753 $this->assertEquals($course1->id, $result['courses'][0]['id']); 1754 // Check expected overview data for the module. 1755 $this->assertEquals('forum', $result['courses'][0]['overviews'][0]['module']); 1756 $this->assertContains('1 total unread', $result['courses'][0]['overviews'][0]['overviewtext']); 1757 } 1758 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Thu Aug 11 10:00:09 2016 | Cross-referenced by PHPXref 0.7.1 |