Differences Between: [Versions 310 and 311] [Versions 311 and 401] [Versions 311 and 402] [Versions 311 and 403] [Versions 39 and 311]
1 <?php 2 // This file is part of Moodle - http://moodle.org/ 3 // 4 // Moodle is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // Moodle is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU General Public License for more details. 13 // 14 // You should have received a copy of the GNU General Public License 15 // along with Moodle. If not, see <http://www.gnu.org/licenses/>. 16 17 namespace tool_uploadcourse; 18 19 use tool_uploadcourse_processor; 20 use tool_uploadcourse_course; 21 22 /** 23 * Course test case. 24 * 25 * @package tool_uploadcourse 26 * @copyright 2013 Frédéric Massart 27 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or late 28 */ 29 class course_test extends \advanced_testcase { 30 31 public function test_proceed_without_prepare() { 32 $this->resetAfterTest(true); 33 $mode = tool_uploadcourse_processor::MODE_CREATE_NEW; 34 $updatemode = tool_uploadcourse_processor::UPDATE_NOTHING; 35 $data = array(); 36 $co = new tool_uploadcourse_course($mode, $updatemode, $data); 37 $this->expectException(\coding_exception::class); 38 $co->proceed(); 39 } 40 41 public function test_proceed_when_prepare_failed() { 42 $this->resetAfterTest(true); 43 $mode = tool_uploadcourse_processor::MODE_CREATE_NEW; 44 $updatemode = tool_uploadcourse_processor::UPDATE_NOTHING; 45 $data = array(); 46 $co = new tool_uploadcourse_course($mode, $updatemode, $data); 47 $this->assertFalse($co->prepare()); 48 $this->expectException(\moodle_exception::class); 49 $co->proceed(); 50 } 51 52 public function test_proceed_when_already_started() { 53 $this->resetAfterTest(true); 54 $mode = tool_uploadcourse_processor::MODE_CREATE_NEW; 55 $updatemode = tool_uploadcourse_processor::UPDATE_NOTHING; 56 $data = array('shortname' => 'test', 'fullname' => 'New course', 'summary' => 'New', 'category' => 1); 57 $co = new tool_uploadcourse_course($mode, $updatemode, $data); 58 $this->assertTrue($co->prepare()); 59 $co->proceed(); 60 $this->expectException('coding_exception'); 61 $co->proceed(); 62 } 63 64 public function test_invalid_shortname() { 65 $this->resetAfterTest(true); 66 $mode = tool_uploadcourse_processor::MODE_CREATE_NEW; 67 $updatemode = tool_uploadcourse_processor::UPDATE_NOTHING; 68 $data = array('shortname' => '<invalid>', 'fullname' => 'New course', 'summary' => 'New', 'category' => 1); 69 $co = new tool_uploadcourse_course($mode, $updatemode, $data); 70 $this->assertFalse($co->prepare()); 71 $this->assertArrayHasKey('invalidshortname', $co->get_errors()); 72 } 73 74 public function test_invalid_shortname_too_long() { 75 $this->resetAfterTest(); 76 77 $mode = tool_uploadcourse_processor::MODE_CREATE_NEW; 78 $updatemode = tool_uploadcourse_processor::UPDATE_NOTHING; 79 80 $upload = new tool_uploadcourse_course($mode, $updatemode, [ 81 'category' => 1, 82 'fullname' => 'New course', 83 'shortname' => str_repeat('X', 2000), 84 ]); 85 86 $this->assertFalse($upload->prepare()); 87 $this->assertArrayHasKey('invalidshortnametoolong', $upload->get_errors()); 88 } 89 90 public function test_invalid_fullname_too_long() { 91 $this->resetAfterTest(); 92 93 $mode = tool_uploadcourse_processor::MODE_CREATE_NEW; 94 $updatemode = tool_uploadcourse_processor::UPDATE_NOTHING; 95 96 $upload = new tool_uploadcourse_course($mode, $updatemode, [ 97 'category' => 1, 98 'fullname' => str_repeat('X', 2000), 99 ]); 100 101 $this->assertFalse($upload->prepare()); 102 $this->assertArrayHasKey('invalidfullnametoolong', $upload->get_errors()); 103 } 104 105 public function test_invalid_visibility() { 106 $this->resetAfterTest(true); 107 $mode = tool_uploadcourse_processor::MODE_CREATE_NEW; 108 $updatemode = tool_uploadcourse_processor::UPDATE_NOTHING; 109 $data = array('shortname' => 'test', 'fullname' => 'New course', 'summary' => 'New', 'category' => 1, 'visible' => 2); 110 $co = new tool_uploadcourse_course($mode, $updatemode, $data); 111 $this->assertFalse($co->prepare()); 112 $this->assertArrayHasKey('invalidvisibilitymode', $co->get_errors()); 113 } 114 115 /** 116 * Test setting 'downloadcontent' field when the feature is globally disabled 117 */ 118 public function test_downloadcontent_disabled(): void { 119 $this->resetAfterTest(); 120 $this->setAdminUser(); 121 122 set_config('downloadcoursecontentallowed', 0); 123 124 $mode = tool_uploadcourse_processor::MODE_CREATE_NEW; 125 $updatemode = tool_uploadcourse_processor::UPDATE_NOTHING; 126 127 $upload = new tool_uploadcourse_course($mode, $updatemode, [ 128 'category' => 1, 129 'fullname' => 'Testing', 130 'shortname' => 'T101', 131 'downloadcontent' => DOWNLOAD_COURSE_CONTENT_ENABLED, 132 ]); 133 134 $this->assertFalse($upload->prepare()); 135 $this->assertArrayHasKey('downloadcontentnotallowed', $upload->get_errors()); 136 } 137 138 /** 139 * Test setting 'downloadcontent' field when user doesn't have required capability 140 */ 141 public function test_downloadcontent_capability(): void { 142 global $DB; 143 144 $this->resetAfterTest(); 145 146 set_config('downloadcoursecontentallowed', 1); 147 148 // Create category in which to create the new course. 149 $category = $this->getDataGenerator()->create_category(); 150 $categorycontext = \context_coursecat::instance($category->id); 151 152 $user = $this->getDataGenerator()->create_user(); 153 $this->setUser($user); 154 155 // Assign the user as a manager of the category, disable ability to configure course content download. 156 $roleid = $DB->get_field('role', 'id', ['shortname' => 'manager']); 157 role_assign($roleid, $user->id, $categorycontext); 158 role_change_permission($roleid, $categorycontext, 'moodle/course:configuredownloadcontent', CAP_PROHIBIT); 159 160 $mode = tool_uploadcourse_processor::MODE_CREATE_NEW; 161 $updatemode = tool_uploadcourse_processor::UPDATE_NOTHING; 162 163 $upload = new tool_uploadcourse_course($mode, $updatemode, [ 164 'category' => $category->id, 165 'fullname' => 'Testing', 166 'shortname' => 'T101', 167 'downloadcontent' => DOWNLOAD_COURSE_CONTENT_ENABLED, 168 ]); 169 170 $this->assertFalse($upload->prepare()); 171 $this->assertArrayHasKey('downloadcontentnotallowed', $upload->get_errors()); 172 } 173 174 /** 175 * Test setting 'downloadcontent' field to an invalid value 176 */ 177 public function test_downloadcontent_invalid(): void { 178 $this->resetAfterTest(); 179 $this->setAdminUser(); 180 181 set_config('downloadcoursecontentallowed', 1); 182 183 $mode = tool_uploadcourse_processor::MODE_CREATE_NEW; 184 $updatemode = tool_uploadcourse_processor::UPDATE_NOTHING; 185 186 $upload = new tool_uploadcourse_course($mode, $updatemode, [ 187 'category' => 1, 188 'fullname' => 'Testing', 189 'shortname' => 'T101', 190 'downloadcontent' => 42, 191 ]); 192 193 $this->assertFalse($upload->prepare()); 194 $this->assertArrayHasKey('invaliddownloadcontent', $upload->get_errors()); 195 } 196 197 public function test_create() { 198 global $DB; 199 $this->resetAfterTest(true); 200 201 // Existing course. 202 $c1 = $this->getDataGenerator()->create_course(array('shortname' => 'c1', 'summary' => 'Yay!')); 203 $this->assertTrue($DB->record_exists('course', array('shortname' => 'c1'))); 204 205 $updatemode = tool_uploadcourse_processor::UPDATE_NOTHING; 206 207 // Try to add a new course. 208 $mode = tool_uploadcourse_processor::MODE_CREATE_NEW; 209 $data = array('shortname' => 'newcourse', 'fullname' => 'New course', 'summary' => 'New', 'category' => 1); 210 $co = new tool_uploadcourse_course($mode, $updatemode, $data); 211 $this->assertTrue($co->prepare()); 212 $this->assertFalse($DB->record_exists('course', array('shortname' => 'newcourse'))); 213 $co->proceed(); 214 $course = $DB->get_record('course', array('shortname' => 'newcourse'), '*', MUST_EXIST); 215 $this->assertEquals(0, course_get_format($course)->get_course()->coursedisplay); 216 217 // Try to add a new course, that already exists. 218 $coursecount = $DB->count_records('course', array()); 219 $mode = tool_uploadcourse_processor::MODE_CREATE_NEW; 220 $data = array('shortname' => 'c1', 'fullname' => 'C1FN', 'summary' => 'C1', 'category' => 1); 221 $co = new tool_uploadcourse_course($mode, $updatemode, $data); 222 $this->assertFalse($co->prepare()); 223 $this->assertArrayHasKey('courseexistsanduploadnotallowed', $co->get_errors()); 224 $this->assertEquals($coursecount, $DB->count_records('course', array())); 225 $this->assertNotEquals('C1', $DB->get_field_select('course', 'summary', 'shortname = :s', array('s' => 'c1'))); 226 227 // Try to add new with shortname incrementation. 228 $mode = tool_uploadcourse_processor::MODE_CREATE_ALL; 229 $data = array('shortname' => 'c1', 'fullname' => 'C1FN', 'summary' => 'C1', 'category' => 1); 230 $co = new tool_uploadcourse_course($mode, $updatemode, $data); 231 $this->assertTrue($co->prepare()); 232 $co->proceed(); 233 $this->assertTrue($DB->record_exists('course', array('shortname' => 'c2'))); 234 235 // Add a new course with non-default course format option. 236 $mode = tool_uploadcourse_processor::MODE_CREATE_NEW; 237 $data = array('shortname' => 'c3', 'fullname' => 'C3', 'summary' => 'New c3', 'category' => 1, 238 'format' => 'weeks', 'coursedisplay' => 1); 239 $co = new tool_uploadcourse_course($mode, $updatemode, $data); 240 $this->assertTrue($co->prepare()); 241 $co->proceed(); 242 $course = $DB->get_record('course', array('shortname' => 'c3'), '*', MUST_EXIST); 243 $this->assertEquals(1, course_get_format($course)->get_course()->coursedisplay); 244 } 245 246 public function test_create_with_sections() { 247 global $DB; 248 $this->resetAfterTest(true); 249 $updatemode = tool_uploadcourse_processor::UPDATE_NOTHING; 250 $defaultnumsections = get_config('moodlecourse', 'numsections'); 251 252 // Add new course, make sure default number of sections is created. 253 $mode = tool_uploadcourse_processor::MODE_CREATE_NEW; 254 $data = array('shortname' => 'newcourse1', 'fullname' => 'New course1', 'format' => 'topics', 'category' => 1); 255 $co = new tool_uploadcourse_course($mode, $updatemode, $data); 256 $this->assertTrue($co->prepare()); 257 $co->proceed(); 258 $courseid = $DB->get_field('course', 'id', array('shortname' => 'newcourse1')); 259 $this->assertNotEmpty($courseid); 260 $this->assertEquals($defaultnumsections + 1, 261 $DB->count_records('course_sections', ['course' => $courseid])); 262 263 // Add new course specifying number of sections. 264 $mode = tool_uploadcourse_processor::MODE_CREATE_NEW; 265 $data = array('shortname' => 'newcourse2', 'fullname' => 'New course2', 'format' => 'topics', 'category' => 1, 266 'numsections' => 15); 267 $co = new tool_uploadcourse_course($mode, $updatemode, $data); 268 $this->assertTrue($co->prepare()); 269 $co->proceed(); 270 $courseid = $DB->get_field('course', 'id', array('shortname' => 'newcourse2')); 271 $this->assertNotEmpty($courseid); 272 $this->assertEquals(15 + 1, 273 $DB->count_records('course_sections', ['course' => $courseid])); 274 } 275 276 public function test_delete() { 277 global $DB; 278 $this->resetAfterTest(true); 279 280 $c1 = $this->getDataGenerator()->create_course(); 281 $c2 = $this->getDataGenerator()->create_course(); 282 283 $this->assertTrue($DB->record_exists('course', array('shortname' => $c1->shortname))); 284 $this->assertFalse($DB->record_exists('course', array('shortname' => 'DoesNotExist'))); 285 286 $mode = tool_uploadcourse_processor::MODE_CREATE_OR_UPDATE; 287 $updatemode = tool_uploadcourse_processor::UPDATE_ALL_WITH_DATA_ONLY; 288 289 // Try delete when option not available. 290 $importoptions = array('candelete' => false); 291 $data = array('shortname' => $c1->shortname, 'delete' => 1); 292 $co = new tool_uploadcourse_course($mode, $updatemode, $data, array(), $importoptions); 293 $this->assertFalse($co->prepare()); 294 $this->assertArrayHasKey('coursedeletionnotallowed', $co->get_errors()); 295 $this->assertTrue($DB->record_exists('course', array('shortname' => $c1->shortname))); 296 297 // Try delete when not requested. 298 $importoptions = array('candelete' => true); 299 $data = array('shortname' => $c1->shortname, 'delete' => 0); 300 $co = new tool_uploadcourse_course($mode, $updatemode, $data, array(), $importoptions); 301 $this->assertTrue($co->prepare()); 302 $co->proceed(); 303 $this->assertTrue($DB->record_exists('course', array('shortname' => $c1->shortname))); 304 305 // Try delete when requested. 306 $importoptions = array('candelete' => true); 307 $data = array('shortname' => $c1->shortname, 'delete' => 1); 308 $co = new tool_uploadcourse_course($mode, $updatemode, $data, array(), $importoptions); 309 $this->assertTrue($co->prepare()); 310 $co->proceed(); 311 $this->assertFalse($DB->record_exists('course', array('shortname' => $c1->shortname))); 312 $this->assertTrue($DB->record_exists('course', array('shortname' => $c2->shortname))); 313 314 // Try deleting non-existing record, this should not fail. 315 $data = array('shortname' => 'DoesNotExist', 'delete' => 1); 316 $co = new tool_uploadcourse_course($mode, $updatemode, $data, array(), $importoptions); 317 $this->assertFalse($co->prepare()); 318 $this->assertArrayHasKey('cannotdeletecoursenotexist', $co->get_errors()); 319 } 320 321 public function test_update() { 322 global $DB; 323 $this->resetAfterTest(true); 324 325 $c1 = $this->getDataGenerator()->create_course(array('shortname' => 'c1')); 326 327 // Try to update with existing shortnames, not allowing creation, and updating nothing. 328 $mode = tool_uploadcourse_processor::MODE_UPDATE_ONLY; 329 $updatemode = tool_uploadcourse_processor::UPDATE_NOTHING; 330 $data = array('shortname' => 'c1', 'fullname' => 'New fullname'); 331 $co = new tool_uploadcourse_course($mode, $updatemode, $data); 332 $this->assertFalse($co->prepare()); 333 $this->assertArrayHasKey('updatemodedoessettonothing', $co->get_errors()); 334 335 // Try to update with non-existing shortnames. 336 $mode = tool_uploadcourse_processor::MODE_UPDATE_ONLY; 337 $updatemode = tool_uploadcourse_processor::UPDATE_ALL_WITH_DATA_ONLY; 338 $data = array('shortname' => 'DoesNotExist', 'fullname' => 'New fullname'); 339 $co = new tool_uploadcourse_course($mode, $updatemode, $data); 340 $this->assertFalse($co->prepare()); 341 $this->assertArrayHasKey('coursedoesnotexistandcreatenotallowed', $co->get_errors()); 342 343 // Try a proper update. 344 $mode = tool_uploadcourse_processor::MODE_UPDATE_ONLY; 345 $updatemode = tool_uploadcourse_processor::UPDATE_ALL_WITH_DATA_ONLY; 346 $data = array('shortname' => 'c1', 'fullname' => 'New fullname'); 347 $co = new tool_uploadcourse_course($mode, $updatemode, $data); 348 $this->assertTrue($co->prepare()); 349 $co->proceed(); 350 $this->assertEquals('New fullname', $DB->get_field_select('course', 'fullname', 'shortname = :s', array('s' => 'c1'))); 351 352 // Try a proper update with defaults. 353 $mode = tool_uploadcourse_processor::MODE_UPDATE_ONLY; 354 $updatemode = tool_uploadcourse_processor::UPDATE_ALL_WITH_DATA_OR_DEFAUTLS; 355 $data = array('shortname' => 'c1', 'fullname' => 'Another fullname'); 356 $defaults = array('fullname' => 'Not this one', 'summary' => 'Awesome summary'); 357 $co = new tool_uploadcourse_course($mode, $updatemode, $data, $defaults); 358 $this->assertTrue($co->prepare()); 359 $co->proceed(); 360 $this->assertEquals('Another fullname', $DB->get_field_select('course', 'fullname', 'shortname = :s', array('s' => 'c1'))); 361 $this->assertEquals('Awesome summary', $DB->get_field_select('course', 'summary', 'shortname = :s', array('s' => 'c1'))); 362 363 // Try a proper update missing only. 364 $mode = tool_uploadcourse_processor::MODE_UPDATE_ONLY; 365 $updatemode = tool_uploadcourse_processor::UPDATE_MISSING_WITH_DATA_OR_DEFAUTLS; 366 $DB->set_field('course', 'summary', '', array('shortname' => 'c1')); 367 $this->assertEquals('', $DB->get_field_select('course', 'summary', 'shortname = :s', array('s' => 'c1'))); 368 $data = array('shortname' => 'c1', 'summary' => 'Fill in summary'); 369 $defaults = array('summary' => 'Do not use this summary'); 370 $co = new tool_uploadcourse_course($mode, $updatemode, $data, $defaults); 371 $this->assertTrue($co->prepare()); 372 $co->proceed(); 373 $this->assertEquals('Fill in summary', $DB->get_field_select('course', 'summary', 'shortname = :s', array('s' => 'c1'))); 374 375 // Try a proper update missing only using defaults. 376 $mode = tool_uploadcourse_processor::MODE_UPDATE_ONLY; 377 $updatemode = tool_uploadcourse_processor::UPDATE_MISSING_WITH_DATA_OR_DEFAUTLS; 378 $DB->set_field('course', 'summary', '', array('shortname' => 'c1')); 379 $this->assertEquals('', $DB->get_field_select('course', 'summary', 'shortname = :s', array('s' => 'c1'))); 380 $data = array('shortname' => 'c1'); 381 $defaults = array('summary' => 'Use this summary'); 382 $co = new tool_uploadcourse_course($mode, $updatemode, $data, $defaults); 383 $this->assertTrue($co->prepare()); 384 $co->proceed(); 385 $this->assertEquals('Use this summary', $DB->get_field_select('course', 'summary', 'shortname = :s', array('s' => 'c1'))); 386 387 // Update course format option. 388 $mode = tool_uploadcourse_processor::MODE_UPDATE_ONLY; 389 $updatemode = tool_uploadcourse_processor::UPDATE_ALL_WITH_DATA_ONLY; 390 $data = array('shortname' => 'c1', 'coursedisplay' => 1); 391 $co = new tool_uploadcourse_course($mode, $updatemode, $data); 392 $this->assertTrue($co->prepare()); 393 $co->proceed(); 394 $course = $DB->get_record('course', array('shortname' => 'c1'), '*', MUST_EXIST); 395 $this->assertEquals(1, course_get_format($course)->get_course()->coursedisplay); 396 } 397 398 public function test_data_saved() { 399 global $DB; 400 401 $this->resetAfterTest(true); 402 $this->setAdminUser(); // To avoid warnings related to 'moodle/course:setforcedlanguage' capability check. 403 404 set_config('downloadcoursecontentallowed', 1); 405 406 // Create. 407 $mode = tool_uploadcourse_processor::MODE_CREATE_NEW; 408 $updatemode = tool_uploadcourse_processor::UPDATE_NOTHING; 409 $data = array( 410 'shortname' => 'c1', 411 'fullname' => 'Fullname', 412 'category' => '1', 413 'visible' => '0', 414 'downloadcontent' => DOWNLOAD_COURSE_CONTENT_DISABLED, 415 'idnumber' => '123abc', 416 'summary' => 'Summary', 417 'format' => 'topics', 418 'theme' => 'afterburner', 419 'lang' => 'en', 420 'newsitems' => '7', 421 'showgrades' => '0', 422 'showreports' => '1', 423 'legacyfiles' => '1', 424 'maxbytes' => '1234', 425 'groupmode' => '2', 426 'groupmodeforce' => '1', 427 'enablecompletion' => '1', 428 'tags' => 'Cat, Dog', 429 430 'role_teacher' => 'Knight', 431 'role_manager' => 'Jedi', 432 433 'enrolment_1' => 'guest', 434 'enrolment_2' => 'self', 435 'enrolment_2_roleid' => '1', 436 'enrolment_3' => 'manual', 437 'enrolment_3_disable' => '1', 438 ); 439 440 // There should be a start date if there is a end date. 441 $data['enddate'] = '7 June 1990'; 442 $co = new tool_uploadcourse_course($mode, $updatemode, $data); 443 $this->assertFalse($co->prepare()); 444 $this->assertArrayHasKey('nostartdatenoenddate', $co->get_errors()); 445 446 $data['startdate'] = '8 June 1990'; 447 $co = new tool_uploadcourse_course($mode, $updatemode, $data); 448 $this->assertFalse($co->prepare()); 449 $this->assertArrayHasKey('enddatebeforestartdate', $co->get_errors()); 450 451 // They are correct now. 452 $data['enddate'] = '18 June 1990'; 453 454 $this->assertFalse($DB->record_exists('course', array('shortname' => 'c1'))); 455 $co = new tool_uploadcourse_course($mode, $updatemode, $data); 456 $this->assertTrue($co->prepare()); 457 $co->proceed(); 458 $this->assertTrue($DB->record_exists('course', array('shortname' => 'c1'))); 459 $course = $DB->get_record('course', array('shortname' => 'c1')); 460 $ctx = \context_course::instance($course->id); 461 462 $this->assertEquals($data['fullname'], $course->fullname); 463 $this->assertEquals($data['category'], $course->category); 464 $this->assertEquals($data['visible'], $course->visible); 465 $this->assertEquals($data['downloadcontent'], $course->downloadcontent); 466 $this->assertEquals(mktime(0, 0, 0, 6, 8, 1990), $course->startdate); 467 $this->assertEquals(mktime(0, 0, 0, 6, 18, 1990), $course->enddate); 468 $this->assertEquals($data['idnumber'], $course->idnumber); 469 $this->assertEquals($data['summary'], $course->summary); 470 $this->assertEquals($data['format'], $course->format); 471 $this->assertEquals($data['theme'], $course->theme); 472 $this->assertEquals($data['lang'], $course->lang); 473 $this->assertEquals($data['newsitems'], $course->newsitems); 474 $this->assertEquals($data['showgrades'], $course->showgrades); 475 $this->assertEquals($data['showreports'], $course->showreports); 476 $this->assertEquals($data['legacyfiles'], $course->legacyfiles); 477 $this->assertEquals($data['maxbytes'], $course->maxbytes); 478 $this->assertEquals($data['groupmode'], $course->groupmode); 479 $this->assertEquals($data['groupmodeforce'], $course->groupmodeforce); 480 $this->assertEquals($data['enablecompletion'], $course->enablecompletion); 481 $this->assertEquals($data['tags'], join(', ', \core_tag_tag::get_item_tags_array('core', 'course', $course->id))); 482 483 // Roles. 484 $roleids = array(); 485 $roles = get_all_roles(); 486 foreach ($roles as $role) { 487 $roleids[$role->shortname] = $role->id; 488 } 489 $this->assertEquals('Knight', $DB->get_field_select('role_names', 'name', 490 'roleid = :roleid AND contextid = :ctxid', array('ctxid' => $ctx->id, 'roleid' => $roleids['teacher']))); 491 $this->assertEquals('Jedi', $DB->get_field_select('role_names', 'name', 492 'roleid = :roleid AND contextid = :ctxid', array('ctxid' => $ctx->id, 'roleid' => $roleids['manager']))); 493 494 // Enrolment methods. 495 $enroldata = array(); 496 $instances = enrol_get_instances($course->id, false); 497 $this->assertCount(3, $instances); 498 foreach ($instances as $instance) { 499 $enroldata[$instance->enrol] = $instance; 500 } 501 502 $this->assertNotEmpty($enroldata['guest']); 503 $this->assertEquals(ENROL_INSTANCE_ENABLED, $enroldata['guest']->status); 504 $this->assertNotEmpty($enroldata['self']); 505 $this->assertEquals($data['enrolment_2_roleid'], $enroldata['self']->roleid); 506 $this->assertEquals(ENROL_INSTANCE_ENABLED, $enroldata['self']->status); 507 $this->assertNotEmpty($enroldata['manual']); 508 $this->assertEquals(ENROL_INSTANCE_DISABLED, $enroldata['manual']->status); 509 510 // Update existing course. 511 $cat = $this->getDataGenerator()->create_category(); 512 $mode = tool_uploadcourse_processor::MODE_UPDATE_ONLY; 513 $updatemode = tool_uploadcourse_processor::UPDATE_ALL_WITH_DATA_ONLY; 514 $data = array( 515 'shortname' => 'c1', 516 'fullname' => 'Fullname 2', 517 'category' => $cat->id, 518 'visible' => '1', 519 'downloadcontent' => DOWNLOAD_COURSE_CONTENT_ENABLED, 520 'idnumber' => 'changeidn', 521 'summary' => 'Summary 2', 522 'format' => 'topics', 523 'theme' => 'classic', 524 'lang' => '', 525 'newsitems' => '2', 526 'showgrades' => '1', 527 'showreports' => '0', 528 'legacyfiles' => '0', 529 'maxbytes' => '4321', 530 'groupmode' => '1', 531 'groupmodeforce' => '0', 532 'enablecompletion' => '0', 533 534 'role_teacher' => 'Teacher', 535 'role_manager' => 'Manager', 536 537 'enrolment_1' => 'guest', 538 'enrolment_1_disable' => '1', 539 'enrolment_2' => 'self', 540 'enrolment_2_roleid' => '2', 541 'enrolment_3' => 'manual', 542 'enrolment_3_delete' => '1', 543 ); 544 545 $this->assertTrue($DB->record_exists('course', array('shortname' => 'c1'))); 546 547 $data['enddate'] = '31 June 1984'; 548 // Previous start and end dates are 8 and 18 June 1990. 549 $co = new tool_uploadcourse_course($mode, $updatemode, $data); 550 $this->assertFalse($co->prepare()); 551 $this->assertArrayHasKey('enddatebeforestartdate', $co->get_errors()); 552 553 $data['startdate'] = '19 June 1990'; 554 $co = new tool_uploadcourse_course($mode, $updatemode, $data); 555 $this->assertFalse($co->prepare()); 556 $this->assertArrayHasKey('enddatebeforestartdate', $co->get_errors()); 557 558 // They are correct now. 559 $data['startdate'] = '11 June 1984'; 560 561 $co = new tool_uploadcourse_course($mode, $updatemode, $data); 562 $this->assertTrue($co->prepare()); 563 $co->proceed(); 564 $course = $DB->get_record('course', array('shortname' => 'c1')); 565 $ctx = \context_course::instance($course->id); 566 567 $this->assertEquals($data['fullname'], $course->fullname); 568 $this->assertEquals($data['category'], $course->category); 569 $this->assertEquals($data['visible'], $course->visible); 570 $this->assertEquals($data['downloadcontent'], $course->downloadcontent); 571 $this->assertEquals(mktime(0, 0, 0, 6, 11, 1984), $course->startdate); 572 $this->assertEquals(mktime(0, 0, 0, 6, 31, 1984), $course->enddate); 573 $this->assertEquals($data['idnumber'], $course->idnumber); 574 $this->assertEquals($data['summary'], $course->summary); 575 $this->assertEquals($data['format'], $course->format); 576 $this->assertEquals($data['theme'], $course->theme); 577 $this->assertEquals($data['lang'], $course->lang); 578 $this->assertEquals($data['newsitems'], $course->newsitems); 579 $this->assertEquals($data['showgrades'], $course->showgrades); 580 $this->assertEquals($data['showreports'], $course->showreports); 581 $this->assertEquals($data['legacyfiles'], $course->legacyfiles); 582 $this->assertEquals($data['maxbytes'], $course->maxbytes); 583 $this->assertEquals($data['groupmode'], $course->groupmode); 584 $this->assertEquals($data['groupmodeforce'], $course->groupmodeforce); 585 $this->assertEquals($data['enablecompletion'], $course->enablecompletion); 586 587 // Roles. 588 $roleids = array(); 589 $roles = get_all_roles(); 590 foreach ($roles as $role) { 591 $roleids[$role->shortname] = $role->id; 592 } 593 $this->assertEquals('Teacher', $DB->get_field_select('role_names', 'name', 594 'roleid = :roleid AND contextid = :ctxid', array('ctxid' => $ctx->id, 'roleid' => $roleids['teacher']))); 595 $this->assertEquals('Manager', $DB->get_field_select('role_names', 'name', 596 'roleid = :roleid AND contextid = :ctxid', array('ctxid' => $ctx->id, 'roleid' => $roleids['manager']))); 597 598 // Enrolment methods. 599 $enroldata = array(); 600 $instances = enrol_get_instances($course->id, false); 601 $this->assertCount(2, $instances); 602 foreach ($instances as $instance) { 603 $enroldata[$instance->enrol] = $instance; 604 } 605 606 $this->assertNotEmpty($enroldata['guest']); 607 $this->assertEquals(ENROL_INSTANCE_DISABLED, $enroldata['guest']->status); 608 $this->assertNotEmpty($enroldata['self']); 609 $this->assertEquals($data['enrolment_2_roleid'], $enroldata['self']->roleid); 610 $this->assertEquals(ENROL_INSTANCE_ENABLED, $enroldata['self']->status); 611 } 612 613 public function test_default_data_saved() { 614 global $DB; 615 616 $this->resetAfterTest(true); 617 $this->setAdminUser(); 618 619 set_config('downloadcoursecontentallowed', 1); 620 621 // Create. 622 $mode = tool_uploadcourse_processor::MODE_CREATE_NEW; 623 $updatemode = tool_uploadcourse_processor::UPDATE_NOTHING; 624 $data = array( 625 'shortname' => 'c1', 626 ); 627 $defaultdata = array( 628 'fullname' => 'Fullname', 629 'category' => '1', 630 'visible' => '0', 631 'downloadcontent' => DOWNLOAD_COURSE_CONTENT_DISABLED, 632 'startdate' => 644803200, 633 'enddate' => 645667200, 634 'idnumber' => '123abc', 635 'summary' => 'Summary', 636 'format' => 'topics', 637 'theme' => 'afterburner', 638 'lang' => 'en', 639 'newsitems' => '7', 640 'showgrades' => '0', 641 'showreports' => '1', 642 'legacyfiles' => '1', 643 'maxbytes' => '1234', 644 'groupmode' => '2', 645 'groupmodeforce' => '1', 646 'enablecompletion' => '1', 647 ); 648 649 $this->assertFalse($DB->record_exists('course', array('shortname' => 'c1'))); 650 $co = new tool_uploadcourse_course($mode, $updatemode, $data, $defaultdata); 651 $this->assertTrue($co->prepare()); 652 $co->proceed(); 653 $this->assertTrue($DB->record_exists('course', array('shortname' => 'c1'))); 654 $course = $DB->get_record('course', array('shortname' => 'c1')); 655 $ctx = \context_course::instance($course->id); 656 657 $this->assertEquals($defaultdata['fullname'], $course->fullname); 658 $this->assertEquals($defaultdata['category'], $course->category); 659 $this->assertEquals($defaultdata['visible'], $course->visible); 660 $this->assertEquals($defaultdata['downloadcontent'], $course->downloadcontent); 661 $this->assertEquals($defaultdata['startdate'], $course->startdate); 662 $this->assertEquals($defaultdata['enddate'], $course->enddate); 663 $this->assertEquals($defaultdata['idnumber'], $course->idnumber); 664 $this->assertEquals($defaultdata['summary'], $course->summary); 665 $this->assertEquals($defaultdata['format'], $course->format); 666 $this->assertEquals($defaultdata['theme'], $course->theme); 667 $this->assertEquals($defaultdata['lang'], $course->lang); 668 $this->assertEquals($defaultdata['newsitems'], $course->newsitems); 669 $this->assertEquals($defaultdata['showgrades'], $course->showgrades); 670 $this->assertEquals($defaultdata['showreports'], $course->showreports); 671 $this->assertEquals($defaultdata['legacyfiles'], $course->legacyfiles); 672 $this->assertEquals($defaultdata['maxbytes'], $course->maxbytes); 673 $this->assertEquals($defaultdata['groupmode'], $course->groupmode); 674 $this->assertEquals($defaultdata['groupmodeforce'], $course->groupmodeforce); 675 $this->assertEquals($defaultdata['enablecompletion'], $course->enablecompletion); 676 677 // Update. 678 $cat = $this->getDataGenerator()->create_category(); 679 $mode = tool_uploadcourse_processor::MODE_UPDATE_ONLY; 680 $updatemode = tool_uploadcourse_processor::UPDATE_ALL_WITH_DATA_OR_DEFAUTLS; 681 $data = array( 682 'shortname' => 'c1', 683 ); 684 $defaultdata = array( 685 'fullname' => 'Fullname 2', 686 'category' => $cat->id, 687 'visible' => '1', 688 'downloadcontent' => DOWNLOAD_COURSE_CONTENT_ENABLED, 689 'startdate' => 455760000, 690 'enddate' => 457488000, 691 'idnumber' => 'changedid', 692 'summary' => 'Summary 2', 693 'format' => 'topics', 694 'theme' => 'classic', 695 'lang' => '', 696 'newsitems' => '2', 697 'showgrades' => '1', 698 'showreports' => '0', 699 'legacyfiles' => '0', 700 'maxbytes' => '1111', 701 'groupmode' => '1', 702 'groupmodeforce' => '0', 703 'enablecompletion' => '0', 704 ); 705 706 $this->assertTrue($DB->record_exists('course', array('shortname' => 'c1'))); 707 $co = new tool_uploadcourse_course($mode, $updatemode, $data, $defaultdata); 708 $this->assertTrue($co->prepare()); 709 $co->proceed(); 710 $this->assertTrue($DB->record_exists('course', array('shortname' => 'c1'))); 711 $course = $DB->get_record('course', array('shortname' => 'c1')); 712 $ctx = \context_course::instance($course->id); 713 714 $this->assertEquals($defaultdata['fullname'], $course->fullname); 715 $this->assertEquals($defaultdata['category'], $course->category); 716 $this->assertEquals($defaultdata['visible'], $course->visible); 717 $this->assertEquals($defaultdata['downloadcontent'], $course->downloadcontent); 718 $this->assertEquals($defaultdata['startdate'], $course->startdate); 719 $this->assertEquals($defaultdata['enddate'], $course->enddate); 720 $this->assertEquals($defaultdata['idnumber'], $course->idnumber); 721 $this->assertEquals($defaultdata['summary'], $course->summary); 722 $this->assertEquals($defaultdata['format'], $course->format); 723 $this->assertEquals($defaultdata['theme'], $course->theme); 724 $this->assertEquals($defaultdata['lang'], $course->lang); 725 $this->assertEquals($defaultdata['newsitems'], $course->newsitems); 726 $this->assertEquals($defaultdata['showgrades'], $course->showgrades); 727 $this->assertEquals($defaultdata['showreports'], $course->showreports); 728 $this->assertEquals($defaultdata['legacyfiles'], $course->legacyfiles); 729 $this->assertEquals($defaultdata['maxbytes'], $course->maxbytes); 730 $this->assertEquals($defaultdata['groupmode'], $course->groupmode); 731 $this->assertEquals($defaultdata['groupmodeforce'], $course->groupmodeforce); 732 $this->assertEquals($defaultdata['enablecompletion'], $course->enablecompletion); 733 } 734 735 public function test_rename() { 736 global $DB; 737 $this->resetAfterTest(true); 738 739 $c1 = $this->getDataGenerator()->create_course(array('shortname' => 'c1')); 740 $c2 = $this->getDataGenerator()->create_course(array('shortname' => 'c2')); 741 742 // Cannot rename when creating. 743 $mode = tool_uploadcourse_processor::MODE_CREATE_NEW; 744 $updatemode = tool_uploadcourse_processor::UPDATE_ALL_WITH_DATA_ONLY; 745 $importoptions = array('canrename' => true); 746 $data = array('shortname' => 'c1', 'rename' => 'newshortname'); 747 $co = new tool_uploadcourse_course($mode, $updatemode, $data, array(), $importoptions); 748 $this->assertFalse($co->prepare()); 749 $this->assertArrayHasKey('courseexistsanduploadnotallowed', $co->get_errors()); 750 751 // Cannot rename when creating. 752 $mode = tool_uploadcourse_processor::MODE_CREATE_ALL; 753 $updatemode = tool_uploadcourse_processor::UPDATE_ALL_WITH_DATA_ONLY; 754 $importoptions = array('canrename' => true); 755 $data = array('shortname' => 'c1', 'rename' => 'newshortname', 'category' => 1, 'summary' => 'S', 'fullname' => 'F'); 756 $co = new tool_uploadcourse_course($mode, $updatemode, $data, array(), $importoptions); 757 $this->assertFalse($co->prepare()); 758 $this->assertArrayHasKey('canonlyrenameinupdatemode', $co->get_errors()); 759 760 // Error when not allowed to rename the course. 761 $mode = tool_uploadcourse_processor::MODE_UPDATE_ONLY; 762 $updatemode = tool_uploadcourse_processor::UPDATE_ALL_WITH_DATA_ONLY; 763 $importoptions = array('canrename' => false); 764 $data = array('shortname' => 'c1', 'rename' => 'newshortname'); 765 $co = new tool_uploadcourse_course($mode, $updatemode, $data, array(), $importoptions); 766 $this->assertFalse($co->prepare()); 767 $this->assertArrayHasKey('courserenamingnotallowed', $co->get_errors()); 768 769 // Can rename when updating. 770 $mode = tool_uploadcourse_processor::MODE_CREATE_OR_UPDATE; 771 $updatemode = tool_uploadcourse_processor::UPDATE_ALL_WITH_DATA_ONLY; 772 $importoptions = array('canrename' => true); 773 $data = array('shortname' => 'c1', 'rename' => 'newshortname'); 774 $co = new tool_uploadcourse_course($mode, $updatemode, $data, array(), $importoptions); 775 $this->assertTrue($co->prepare()); 776 $co->proceed(); 777 $this->assertEquals('newshortname', $DB->get_field_select('course', 'shortname', 'id = :id', array('id' => $c1->id))); 778 779 // Can rename when updating. 780 $mode = tool_uploadcourse_processor::MODE_UPDATE_ONLY; 781 $updatemode = tool_uploadcourse_processor::UPDATE_ALL_WITH_DATA_ONLY; 782 $importoptions = array('canrename' => true); 783 $data = array('shortname' => 'newshortname', 'rename' => 'newshortname2'); 784 $co = new tool_uploadcourse_course($mode, $updatemode, $data, array(), $importoptions); 785 $this->assertTrue($co->prepare()); 786 $co->proceed(); 787 $this->assertEquals('newshortname2', $DB->get_field_select('course', 'shortname', 'id = :id', array('id' => $c1->id))); 788 789 // Error when course does not exist. 790 $mode = tool_uploadcourse_processor::MODE_CREATE_OR_UPDATE; 791 $updatemode = tool_uploadcourse_processor::UPDATE_ALL_WITH_DATA_ONLY; 792 $importoptions = array('canrename' => true); 793 $data = array('shortname' => 'DoesNotExist', 'rename' => 'c1', 'category' => 1, 'summary' => 'S', 'fullname' => 'F'); 794 $co = new tool_uploadcourse_course($mode, $updatemode, $data, array(), $importoptions); 795 $this->assertFalse($co->prepare()); 796 $this->assertArrayHasKey('cannotrenamecoursenotexist', $co->get_errors()); 797 798 // Renaming still updates the other values. 799 $mode = tool_uploadcourse_processor::MODE_CREATE_OR_UPDATE; 800 $updatemode = tool_uploadcourse_processor::UPDATE_ALL_WITH_DATA_OR_DEFAUTLS; 801 $importoptions = array('canrename' => true); 802 $data = array('shortname' => 'newshortname2', 'rename' => 'c1', 'fullname' => 'Another fullname!'); 803 $defaultdata = array('summary' => 'New summary!'); 804 $co = new tool_uploadcourse_course($mode, $updatemode, $data, $defaultdata, $importoptions); 805 $this->assertTrue($co->prepare()); 806 $co->proceed(); 807 $this->assertEquals('c1', $DB->get_field_select('course', 'shortname', 'id = :id', array('id' => $c1->id))); 808 $this->assertEquals('New summary!', $DB->get_field_select('course', 'summary', 'id = :id', array('id' => $c1->id))); 809 $this->assertEquals('Another fullname!', $DB->get_field_select('course', 'fullname', 'id = :id', array('id' => $c1->id))); 810 811 // Renaming with invalid shortname. 812 $mode = tool_uploadcourse_processor::MODE_CREATE_OR_UPDATE; 813 $updatemode = tool_uploadcourse_processor::UPDATE_ALL_WITH_DATA_ONLY; 814 $importoptions = array('canrename' => true); 815 $data = array('shortname' => 'c1', 'rename' => '<span>invalid</span>'); 816 $co = new tool_uploadcourse_course($mode, $updatemode, $data, array(), $importoptions); 817 $this->assertFalse($co->prepare()); 818 $this->assertArrayHasKey('invalidshortname', $co->get_errors()); 819 820 // Renaming with invalid shortname. 821 $mode = tool_uploadcourse_processor::MODE_CREATE_OR_UPDATE; 822 $updatemode = tool_uploadcourse_processor::UPDATE_ALL_WITH_DATA_ONLY; 823 $importoptions = array('canrename' => true); 824 $data = array('shortname' => 'c1', 'rename' => 'c2'); 825 $co = new tool_uploadcourse_course($mode, $updatemode, $data, array(), $importoptions); 826 $this->assertFalse($co->prepare()); 827 $this->assertArrayHasKey('cannotrenameshortnamealreadyinuse', $co->get_errors()); 828 } 829 830 public function test_restore_course() { 831 global $DB; 832 $this->resetAfterTest(true); 833 $this->setAdminUser(); 834 835 $c1 = $this->getDataGenerator()->create_course(); 836 $c1f1 = $this->getDataGenerator()->create_module('forum', array('course' => $c1->id)); 837 838 $mode = tool_uploadcourse_processor::MODE_CREATE_NEW; 839 $updatemode = tool_uploadcourse_processor::UPDATE_ALL_WITH_DATA_ONLY; 840 $data = array('shortname' => 'A1', 'templatecourse' => $c1->shortname, 'summary' => 'A', 'category' => 1, 841 'fullname' => 'A1'); 842 $co = new tool_uploadcourse_course($mode, $updatemode, $data); 843 $this->assertTrue($co->prepare()); 844 $co->proceed(); 845 $course = $DB->get_record('course', array('shortname' => 'A1')); 846 $modinfo = get_fast_modinfo($course); 847 $found = false; 848 foreach ($modinfo->get_cms() as $cmid => $cm) { 849 if ($cm->modname == 'forum' && $cm->name == $c1f1->name) { 850 $found = true; 851 break; 852 } 853 } 854 $this->assertTrue($found); 855 856 // Restoring twice from the same course should work. 857 $data = array('shortname' => 'B1', 'templatecourse' => $c1->shortname, 'summary' => 'B', 'category' => 1, 858 'fullname' => 'B1'); 859 $co = new tool_uploadcourse_course($mode, $updatemode, $data); 860 $this->assertTrue($co->prepare()); 861 $co->proceed(); 862 $course = $DB->get_record('course', array('shortname' => 'B1')); 863 $modinfo = get_fast_modinfo($course); 864 $found = false; 865 foreach ($modinfo->get_cms() as $cmid => $cm) { 866 if ($cm->modname == 'forum' && $cm->name == $c1f1->name) { 867 $found = true; 868 break; 869 } 870 } 871 $this->assertTrue($found); 872 } 873 874 public function test_restore_file() { 875 global $DB; 876 $this->resetAfterTest(true); 877 $this->setAdminUser(); 878 879 $c1 = $this->getDataGenerator()->create_course(); 880 $c1f1 = $this->getDataGenerator()->create_module('forum', array('course' => $c1->id)); 881 882 // Restore from a file, checking that the file takes priority over the templatecourse. 883 $mode = tool_uploadcourse_processor::MODE_CREATE_NEW; 884 $updatemode = tool_uploadcourse_processor::UPDATE_ALL_WITH_DATA_ONLY; 885 $data = array('shortname' => 'A1', 'backupfile' => __DIR__ . '/fixtures/backup.mbz', 886 'summary' => 'A', 'category' => 1, 'fullname' => 'A1', 'templatecourse' => $c1->shortname); 887 $co = new tool_uploadcourse_course($mode, $updatemode, $data); 888 $this->assertTrue($co->prepare()); 889 $co->proceed(); 890 $course = $DB->get_record('course', array('shortname' => 'A1')); 891 $modinfo = get_fast_modinfo($course); 892 $found = false; 893 foreach ($modinfo->get_cms() as $cmid => $cm) { 894 if ($cm->modname == 'glossary' && $cm->name == 'Imported Glossary') { 895 $found = true; 896 } else if ($cm->modname == 'forum' && $cm->name == $c1f1->name) { 897 // We should not find this! 898 $this->assertTrue(false); 899 } 900 } 901 $this->assertTrue($found); 902 903 // Restoring twice from the same file should work. 904 $data = array('shortname' => 'B1', 'backupfile' => __DIR__ . '/fixtures/backup.mbz', 905 'summary' => 'B', 'category' => 1, 'fullname' => 'B1'); 906 $co = new tool_uploadcourse_course($mode, $updatemode, $data); 907 $this->assertTrue($co->prepare()); 908 $co->proceed(); 909 $course = $DB->get_record('course', array('shortname' => 'B1')); 910 $modinfo = get_fast_modinfo($course); 911 $found = false; 912 foreach ($modinfo->get_cms() as $cmid => $cm) { 913 if ($cm->modname == 'glossary' && $cm->name == 'Imported Glossary') { 914 $found = true; 915 } else if ($cm->modname == 'forum' && $cm->name == $c1f1->name) { 916 // We should not find this! 917 $this->assertTrue(false); 918 } 919 } 920 $this->assertTrue($found); 921 } 922 923 /** 924 * Test that specifying course template respects default restore settings 925 */ 926 public function test_restore_file_settings() { 927 global $DB; 928 $this->resetAfterTest(true); 929 $this->setAdminUser(); 930 931 // Set admin config setting so that activities are not restored by default. 932 set_config('restore_general_activities', 0, 'restore'); 933 934 $c1 = $this->getDataGenerator()->create_course(); 935 936 $mode = tool_uploadcourse_processor::MODE_CREATE_NEW; 937 $updatemode = tool_uploadcourse_processor::UPDATE_ALL_WITH_DATA_ONLY; 938 $data = array('shortname' => 'A1', 'backupfile' => __DIR__ . '/fixtures/backup.mbz', 939 'summary' => 'A', 'category' => 1, 'fullname' => 'A1', 'templatecourse' => $c1->shortname); 940 $co = new tool_uploadcourse_course($mode, $updatemode, $data); 941 $this->assertTrue($co->prepare()); 942 $co->proceed(); 943 $course = $DB->get_record('course', array('shortname' => 'A1')); 944 945 // Make sure the glossary is not restored. 946 $modinfo = get_fast_modinfo($course); 947 $this->assertEmpty($modinfo->get_instances_of('glossary')); 948 } 949 950 public function test_restore_invalid_file() { 951 $this->resetAfterTest(); 952 953 // Restore from a non-existing file should not be allowed. 954 $mode = tool_uploadcourse_processor::MODE_CREATE_NEW; 955 $updatemode = tool_uploadcourse_processor::UPDATE_ALL_WITH_DATA_ONLY; 956 $data = array('shortname' => 'A1', 'backupfile' => '/lead/no/where', 957 'category' => 1, 'fullname' => 'A1'); 958 $co = new tool_uploadcourse_course($mode, $updatemode, $data); 959 $this->assertFalse($co->prepare()); 960 $this->assertArrayHasKey('cannotreadbackupfile', $co->get_errors()); 961 962 // Restore from an invalid file should not be allowed. 963 $mode = tool_uploadcourse_processor::MODE_CREATE_NEW; 964 $updatemode = tool_uploadcourse_processor::UPDATE_ALL_WITH_DATA_ONLY; 965 $data = array('shortname' => 'A1', 'backupfile' => __FILE__, 966 'category' => 1, 'fullname' => 'A1'); 967 $co = new tool_uploadcourse_course($mode, $updatemode, $data); 968 969 $this->assertFalse($co->prepare()); 970 $this->assertArrayHasKey('invalidbackupfile', $co->get_errors()); 971 972 // Zip packer throws a debugging message, this assertion is only here to prevent 973 // the message from being displayed. 974 $this->assertDebuggingCalled(); 975 } 976 977 public function test_restore_invalid_course() { 978 $this->resetAfterTest(); 979 980 // Restore from an invalid file should not be allowed. 981 $mode = tool_uploadcourse_processor::MODE_CREATE_NEW; 982 $updatemode = tool_uploadcourse_processor::UPDATE_ALL_WITH_DATA_ONLY; 983 $data = array('shortname' => 'A1', 'templatecourse' => 'iamnotavalidcourse', 984 'category' => 1, 'fullname' => 'A1'); 985 $co = new tool_uploadcourse_course($mode, $updatemode, $data); 986 $this->assertFalse($co->prepare()); 987 $this->assertArrayHasKey('coursetorestorefromdoesnotexist', $co->get_errors()); 988 } 989 990 /** 991 * Testing the reset on groups, group members and enrolments. 992 */ 993 public function test_reset() { 994 global $DB; 995 $this->resetAfterTest(true); 996 997 $c1 = $this->getDataGenerator()->create_course(); 998 $c1ctx = \context_course::instance($c1->id); 999 $studentrole = $DB->get_record('role', array('shortname' => 'student')); 1000 $teacherrole = $DB->get_record('role', array('shortname' => 'teacher')); 1001 1002 $u1 = $this->getDataGenerator()->create_user(); 1003 $this->getDataGenerator()->enrol_user($u1->id, $c1->id, $studentrole->id); 1004 $this->assertCount(1, get_enrolled_users($c1ctx)); 1005 1006 $g1 = $this->getDataGenerator()->create_group(array('courseid' => $c1->id)); 1007 $this->getDataGenerator()->create_group_member(array('groupid' => $g1->id, 'userid' => $u1->id)); 1008 $this->assertEquals(1, $DB->count_records('groups', array('courseid' => $c1->id))); 1009 $this->assertTrue($DB->record_exists('groups_members', array('groupid' => $g1->id, 'userid' => $u1->id))); 1010 1011 // Wrong mode. 1012 $mode = tool_uploadcourse_processor::MODE_CREATE_NEW; 1013 $updatemode = tool_uploadcourse_processor::UPDATE_ALL_WITH_DATA_ONLY; 1014 $data = array('shortname' => 'DoesNotExist', 'reset' => '1', 'summary' => 'summary', 'fullname' => 'FN', 'category' => 1); 1015 $co = new tool_uploadcourse_course($mode, $updatemode, $data); 1016 $this->assertFalse($co->prepare()); 1017 $this->assertArrayHasKey('canonlyresetcourseinupdatemode', $co->get_errors()); 1018 $this->assertTrue($DB->record_exists('groups', array('id' => $g1->id))); 1019 $this->assertTrue($DB->record_exists('groups_members', array('groupid' => $g1->id, 'userid' => $u1->id))); 1020 $this->assertCount(1, get_enrolled_users($c1ctx)); 1021 1022 // Reset not allowed. 1023 $mode = tool_uploadcourse_processor::MODE_UPDATE_ONLY; 1024 $updatemode = tool_uploadcourse_processor::UPDATE_ALL_WITH_DATA_ONLY; 1025 $data = array('shortname' => $c1->shortname, 'reset' => '1'); 1026 $importoptions = array('canreset' => false); 1027 $co = new tool_uploadcourse_course($mode, $updatemode, $data, array(), $importoptions); 1028 $this->assertFalse($co->prepare()); 1029 $this->assertArrayHasKey('courseresetnotallowed', $co->get_errors()); 1030 $this->assertTrue($DB->record_exists('groups', array('id' => $g1->id))); 1031 $this->assertTrue($DB->record_exists('groups_members', array('groupid' => $g1->id, 'userid' => $u1->id))); 1032 $this->assertCount(1, get_enrolled_users($c1ctx)); 1033 1034 // Reset allowed but not requested. 1035 $mode = tool_uploadcourse_processor::MODE_UPDATE_ONLY; 1036 $updatemode = tool_uploadcourse_processor::UPDATE_ALL_WITH_DATA_ONLY; 1037 $data = array('shortname' => $c1->shortname, 'reset' => '0'); 1038 $importoptions = array('canreset' => true); 1039 $co = new tool_uploadcourse_course($mode, $updatemode, $data, array(), $importoptions); 1040 $this->assertTrue($co->prepare()); 1041 $co->proceed(); 1042 $this->assertTrue($DB->record_exists('groups', array('id' => $g1->id))); 1043 $this->assertTrue($DB->record_exists('groups_members', array('groupid' => $g1->id, 'userid' => $u1->id))); 1044 $this->assertCount(1, get_enrolled_users($c1ctx)); 1045 1046 // Reset passed as a default parameter, should not be taken in account. 1047 $mode = tool_uploadcourse_processor::MODE_UPDATE_ONLY; 1048 $updatemode = tool_uploadcourse_processor::UPDATE_ALL_WITH_DATA_ONLY; 1049 $data = array('shortname' => $c1->shortname); 1050 $importoptions = array('canreset' => true); 1051 $co = new tool_uploadcourse_course($mode, $updatemode, $data, array('reset' => 1), $importoptions); 1052 $this->assertTrue($co->prepare()); 1053 $co->proceed(); 1054 $this->assertTrue($DB->record_exists('groups', array('id' => $g1->id))); 1055 $this->assertTrue($DB->record_exists('groups_members', array('groupid' => $g1->id, 'userid' => $u1->id))); 1056 $this->assertCount(1, get_enrolled_users($c1ctx)); 1057 1058 // Reset executed from data. 1059 $mode = tool_uploadcourse_processor::MODE_UPDATE_ONLY; 1060 $updatemode = tool_uploadcourse_processor::UPDATE_ALL_WITH_DATA_ONLY; 1061 $data = array('shortname' => $c1->shortname, 'reset' => 1); 1062 $importoptions = array('canreset' => true); 1063 $co = new tool_uploadcourse_course($mode, $updatemode, $data, array(), $importoptions); 1064 $this->assertTrue($co->prepare()); 1065 $co->proceed(); 1066 $this->assertFalse($DB->record_exists('groups', array('id' => $g1->id))); 1067 $this->assertFalse($DB->record_exists('groups_members', array('groupid' => $g1->id, 'userid' => $u1->id))); 1068 $this->assertCount(0, get_enrolled_users($c1ctx)); 1069 1070 // Reset executed from import option. 1071 $mode = tool_uploadcourse_processor::MODE_UPDATE_ONLY; 1072 $updatemode = tool_uploadcourse_processor::UPDATE_ALL_WITH_DATA_ONLY; 1073 $data = array('shortname' => $c1->shortname, 'reset' => 0); 1074 $importoptions = array('reset' => 1, 'canreset' => true); 1075 $co = new tool_uploadcourse_course($mode, $updatemode, $data, array(), $importoptions); 1076 1077 $g1 = $this->getDataGenerator()->create_group(array('courseid' => $c1->id)); 1078 $this->getDataGenerator()->create_group_member(array('groupid' => $g1->id, 'userid' => $u1->id)); 1079 $this->assertEquals(1, $DB->count_records('groups', array('courseid' => $c1->id))); 1080 $this->assertTrue($co->prepare()); 1081 $co->proceed(); 1082 $this->assertFalse($DB->record_exists('groups', array('id' => $g1->id))); 1083 } 1084 1085 public function test_create_bad_category() { 1086 global $DB; 1087 $this->resetAfterTest(true); 1088 1089 // Ensure fails when category cannot be resolved upon creation. 1090 $mode = tool_uploadcourse_processor::MODE_CREATE_NEW; 1091 $updatemode = tool_uploadcourse_processor::UPDATE_ALL_WITH_DATA_ONLY; 1092 $data = array('shortname' => 'c1', 'summary' => 'summary', 'fullname' => 'FN', 'category' => 'Wrong cat'); 1093 $co = new tool_uploadcourse_course($mode, $updatemode, $data); 1094 $this->assertFalse($co->prepare()); 1095 $this->assertArrayHasKey('couldnotresolvecatgorybyid', $co->get_errors()); 1096 1097 // Ensure fails when category is 0 on create. 1098 $mode = tool_uploadcourse_processor::MODE_CREATE_NEW; 1099 $updatemode = tool_uploadcourse_processor::UPDATE_ALL_WITH_DATA_ONLY; 1100 $data = array('shortname' => 'c1', 'summary' => 'summary', 'fullname' => 'FN', 'category' => '0'); 1101 $co = new tool_uploadcourse_course($mode, $updatemode, $data); 1102 $this->assertFalse($co->prepare()); 1103 $this->assertArrayHasKey('missingmandatoryfields', $co->get_errors()); 1104 1105 // Ensure fails when category cannot be resolved upon update. 1106 $c1 = $this->getDataGenerator()->create_course(); 1107 $mode = tool_uploadcourse_processor::MODE_UPDATE_ONLY; 1108 $updatemode = tool_uploadcourse_processor::UPDATE_ALL_WITH_DATA_ONLY; 1109 $data = array('shortname' => $c1->shortname, 'category' => 'Wrong cat'); 1110 $co = new tool_uploadcourse_course($mode, $updatemode, $data); 1111 $this->assertFalse($co->prepare()); 1112 $this->assertArrayHasKey('couldnotresolvecatgorybyid', $co->get_errors()); 1113 1114 // Ensure does not update the category when it is 0. 1115 $c1 = $this->getDataGenerator()->create_course(); 1116 $mode = tool_uploadcourse_processor::MODE_UPDATE_ONLY; 1117 $updatemode = tool_uploadcourse_processor::UPDATE_ALL_WITH_DATA_ONLY; 1118 $data = array('shortname' => $c1->shortname, 'category' => '0'); 1119 $co = new tool_uploadcourse_course($mode, $updatemode, $data); 1120 $this->assertTrue($co->prepare()); 1121 $this->assertEmpty($co->get_errors()); 1122 $this->assertEmpty($co->get_statuses()); 1123 $co->proceed(); 1124 $this->assertEquals($c1->category, $DB->get_field('course', 'category', array('id' => $c1->id))); 1125 1126 // Ensure does not update the category when it is set to 0 in the defaults. 1127 $c1 = $this->getDataGenerator()->create_course(); 1128 $mode = tool_uploadcourse_processor::MODE_UPDATE_ONLY; 1129 $updatemode = tool_uploadcourse_processor::UPDATE_ALL_WITH_DATA_OR_DEFAUTLS; 1130 $data = array('shortname' => $c1->shortname); 1131 $defaults = array('category' => '0'); 1132 $co = new tool_uploadcourse_course($mode, $updatemode, $data, $defaults); 1133 $this->assertTrue($co->prepare()); 1134 $this->assertEmpty($co->get_errors()); 1135 $this->assertEmpty($co->get_statuses()); 1136 $co->proceed(); 1137 $this->assertEquals($c1->category, $DB->get_field('course', 'category', array('id' => $c1->id))); 1138 } 1139 1140 public function test_enrolment_data() { 1141 $this->resetAfterTest(true); 1142 1143 // We need to set the current user as one with the capability to edit manual enrolment instances in the new course. 1144 $this->setAdminUser(); 1145 1146 $mode = tool_uploadcourse_processor::MODE_CREATE_NEW; 1147 $updatemode = tool_uploadcourse_processor::UPDATE_ALL_WITH_DATA_ONLY; 1148 $data = array('shortname' => 'c1', 'summary' => 'S', 'fullname' => 'FN', 'category' => '1'); 1149 $data['enrolment_1'] = 'manual'; 1150 $data['enrolment_1_role'] = 'teacher'; 1151 $data['enrolment_1_startdate'] = '2nd July 2013'; 1152 $data['enrolment_1_enddate'] = '2nd August 2013'; 1153 $data['enrolment_1_enrolperiod'] = '10 days'; 1154 $co = new tool_uploadcourse_course($mode, $updatemode, $data); 1155 $this->assertTrue($co->prepare()); 1156 $co->proceed(); 1157 1158 // Enrolment methods. 1159 $enroldata = array(); 1160 $instances = enrol_get_instances($co->get_id(), false); 1161 foreach ($instances as $instance) { 1162 $enroldata[$instance->enrol] = $instance; 1163 } 1164 1165 $this->assertNotEmpty($enroldata['manual']); 1166 $this->assertEquals(ENROL_INSTANCE_ENABLED, $enroldata['manual']->status); 1167 $this->assertEquals(strtotime($data['enrolment_1_startdate']), $enroldata['manual']->enrolstartdate); 1168 $this->assertEquals(strtotime('1970-01-01 GMT + ' . $data['enrolment_1_enrolperiod']), $enroldata['manual']->enrolperiod); 1169 $this->assertEquals(strtotime('12th July 2013'), $enroldata['manual']->enrolenddate); 1170 } 1171 1172 /** 1173 * Data provider for testing enrolment errors 1174 * 1175 * @return array 1176 */ 1177 public function enrolment_uploaddata_error_provider(): array { 1178 return [ 1179 ['errorcannotcreateorupdateenrolment', [ 1180 'shortname' => 'C1', 1181 'enrolment_1' => 'manual', 1182 ]], 1183 ['errorcannotdeleteenrolment', [ 1184 'shortname' => 'C1', 1185 'enrolment_1' => 'manual', 1186 'enrolment_1_delete' => '1', 1187 ]], 1188 ['errorcannotdisableenrolment', [ 1189 'shortname' => 'C1', 1190 'enrolment_1' => 'manual', 1191 'enrolment_1_disable' => '1', 1192 ]], 1193 ]; 1194 } 1195 1196 /** 1197 * Test that user without permission, cannot modify enrolment instances when creating courses 1198 * 1199 * @param string $expectederror 1200 * @param array $uploaddata 1201 * 1202 * @dataProvider enrolment_uploaddata_error_provider 1203 */ 1204 public function test_enrolment_error_create_course(string $expectederror, array $uploaddata): void { 1205 global $DB; 1206 1207 $this->resetAfterTest(); 1208 1209 // Create category in which to create the new course. 1210 $category = $this->getDataGenerator()->create_category(); 1211 $categorycontext = \context_coursecat::instance($category->id); 1212 1213 $user = $this->getDataGenerator()->create_user(); 1214 $this->setUser($user); 1215 1216 // Assign the user as a manager of the category, disable ability to configure manual enrolment instances. 1217 $roleid = $DB->get_field('role', 'id', ['shortname' => 'manager']); 1218 role_assign($roleid, $user->id, $categorycontext); 1219 role_change_permission($roleid, $categorycontext, 'enrol/manual:config', CAP_PROHIBIT); 1220 1221 $mode = tool_uploadcourse_processor::MODE_CREATE_NEW; 1222 $updatemode = tool_uploadcourse_processor::UPDATE_ALL_WITH_DATA_ONLY; 1223 1224 $upload = new tool_uploadcourse_course($mode, $updatemode, array_merge($uploaddata, [ 1225 'category' => $category->id, 1226 'fullname' => 'My course', 1227 ])); 1228 1229 // Enrolment validation isn't performed during 'prepare' for new courses. 1230 $this->assertTrue($upload->prepare()); 1231 $upload->proceed(); 1232 1233 $errors = $upload->get_errors(); 1234 $this->assertArrayHasKey($expectederror, $errors); 1235 1236 $this->assertEquals(get_string($expectederror, 'tool_uploadcourse', 'Manual enrolments'), 1237 (string) $errors[$expectederror]); 1238 } 1239 1240 /** 1241 * Test that user without permission, cannot modify enrolment instances when updating courses 1242 * 1243 * @param string $expectederror 1244 * @param array $uploaddata 1245 * 1246 * @dataProvider enrolment_uploaddata_error_provider 1247 */ 1248 public function test_enrolment_error_update_course(string $expectederror, array $uploaddata): void { 1249 global $DB; 1250 1251 $this->resetAfterTest(); 1252 1253 // Create category in which to create the new course. 1254 $category = $this->getDataGenerator()->create_category(); 1255 $categorycontext = \context_coursecat::instance($category->id); 1256 1257 $course = $this->getDataGenerator()->create_course([ 1258 'category' => $category->id, 1259 'shortname' => $uploaddata['shortname'], 1260 ]); 1261 1262 $user = $this->getDataGenerator()->create_user(); 1263 $this->setUser($user); 1264 1265 // Assign the user as a manager of the category, disable ability to configure manual enrolment instances. 1266 $roleid = $DB->get_field('role', 'id', ['shortname' => 'manager']); 1267 role_assign($roleid, $user->id, $categorycontext); 1268 role_change_permission($roleid, $categorycontext, 'enrol/manual:config', CAP_PROHIBIT); 1269 1270 // Sanity check. 1271 $instances = enrol_get_instances($course->id, true); 1272 $this->assertCount(1, $instances); 1273 $this->assertEquals('manual', reset($instances)->enrol); 1274 1275 $mode = tool_uploadcourse_processor::MODE_UPDATE_ONLY; 1276 $updatemode = tool_uploadcourse_processor::UPDATE_ALL_WITH_DATA_ONLY; 1277 1278 $upload = new tool_uploadcourse_course($mode, $updatemode, $uploaddata); 1279 1280 $this->assertFalse($upload->prepare()); 1281 1282 $errors = $upload->get_errors(); 1283 $this->assertArrayHasKey($expectederror, $errors); 1284 1285 $this->assertEquals(get_string($expectederror, 'tool_uploadcourse', 'Manual enrolments'), 1286 (string) $errors[$expectederror]); 1287 } 1288 1289 /** 1290 * Test upload processing of course custom fields 1291 */ 1292 public function test_custom_fields_data() { 1293 $this->resetAfterTest(); 1294 $this->setAdminUser(); 1295 1296 $course = $this->getDataGenerator()->create_course(['shortname' => 'C1']); 1297 1298 // Create our custom fields. 1299 $category = $this->get_customfield_generator()->create_category(); 1300 $this->create_custom_field($category, 'date', 'mydatefield'); 1301 $this->create_custom_field($category, 'text', 'mytextfield'); 1302 $this->create_custom_field($category, 'textarea', 'mytextareafield'); 1303 1304 // Perform upload. 1305 $mode = tool_uploadcourse_processor::MODE_UPDATE_ONLY; 1306 $updatemode = tool_uploadcourse_processor::UPDATE_ALL_WITH_DATA_ONLY; 1307 $dataupload = [ 1308 'shortname' => $course->shortname, 1309 'customfield_mydatefield' => '2020-04-01 16:00', 1310 'customfield_mytextfield' => 'Hello', 1311 'customfield_mytextareafield' => 'Is it me you\'re looking for?', 1312 ]; 1313 1314 $uploader = new tool_uploadcourse_course($mode, $updatemode, $dataupload); 1315 $this->assertTrue($uploader->prepare()); 1316 $uploader->proceed(); 1317 1318 // Confirm presence of course custom fields. 1319 $data = \core_course\customfield\course_handler::create()->export_instance_data_object($course->id); 1320 $this->assertEqualsIgnoringCase('Wednesday, 1 April 2020, 4:00 PM', $data->mydatefield); 1321 $this->assertEquals($dataupload['customfield_mytextfield'], $data->mytextfield); 1322 $this->assertStringContainsString($dataupload['customfield_mytextareafield'], $data->mytextareafield); 1323 } 1324 1325 /** 1326 * Test upload processing of course custom field that is required but empty 1327 */ 1328 public function test_custom_fields_data_required() { 1329 $this->resetAfterTest(); 1330 $this->setAdminUser(); 1331 1332 $course = $this->getDataGenerator()->create_course(['shortname' => 'C1']); 1333 1334 // Create our custom field. 1335 $category = $this->get_customfield_generator()->create_category(); 1336 $this->create_custom_field($category, 'select', 'myselect', ['required' => true, 'options' => "Cat\nDog"]); 1337 1338 $mode = tool_uploadcourse_processor::MODE_UPDATE_ONLY; 1339 $updatemode = tool_uploadcourse_processor::UPDATE_ALL_WITH_DATA_ONLY; 1340 $dataupload = [ 1341 'shortname' => $course->shortname, 1342 'customfield_myselect' => null, 1343 ]; 1344 1345 $uploader = new tool_uploadcourse_course($mode, $updatemode, $dataupload); 1346 $this->assertFalse($uploader->prepare()); 1347 $this->assertArrayHasKey('customfieldinvalid', $uploader->get_errors()); 1348 1349 // Try again with a default value. 1350 $defaults = [ 1351 'customfield_myselect' => 2, // Our second option: Dog. 1352 ]; 1353 1354 $uploader = new tool_uploadcourse_course($mode, $updatemode, $dataupload, $defaults); 1355 $this->assertTrue($uploader->prepare()); 1356 $uploader->proceed(); 1357 1358 // Confirm presence of course custom fields. 1359 $data = \core_course\customfield\course_handler::create()->export_instance_data_object($course->id); 1360 $this->assertEquals('Dog', $data->myselect); 1361 } 1362 1363 /** 1364 * Test upload processing of course custom field with an invalid select option 1365 */ 1366 public function test_custom_fields_data_invalid_select_option() { 1367 $this->resetAfterTest(); 1368 $this->setAdminUser(); 1369 1370 $course = $this->getDataGenerator()->create_course(['shortname' => 'C1']); 1371 1372 // Create our custom field. 1373 $category = $this->get_customfield_generator()->create_category(); 1374 $this->create_custom_field($category, 'select', 'myselect', 1375 ['required' => true, 'options' => "Cat\nDog", 'defaultvalue' => 'Cat']); 1376 1377 $mode = tool_uploadcourse_processor::MODE_UPDATE_ONLY; 1378 $updatemode = tool_uploadcourse_processor::UPDATE_ALL_WITH_DATA_ONLY; 1379 $dataupload = [ 1380 'shortname' => $course->shortname, 1381 'customfield_myselect' => 'Fish', // No, invalid. 1382 ]; 1383 1384 $uploader = new tool_uploadcourse_course($mode, $updatemode, $dataupload); 1385 $this->assertTrue($uploader->prepare()); 1386 $uploader->proceed(); 1387 1388 // Confirm presence of course custom fields. 1389 $data = \core_course\customfield\course_handler::create()->export_instance_data_object($course->id); 1390 $this->assertEquals('Cat', $data->myselect); 1391 } 1392 1393 /** 1394 * Test upload processing of course custom field with an out of range date 1395 */ 1396 public function test_custom_fields_data_invalid_date() { 1397 $this->resetAfterTest(); 1398 $this->setAdminUser(); 1399 1400 $course = $this->getDataGenerator()->create_course(['shortname' => 'C1']); 1401 1402 // Create our custom field. 1403 $category = $this->get_customfield_generator()->create_category(); 1404 $this->create_custom_field($category, 'date', 'mydate', 1405 ['mindate' => strtotime('2020-04-01'), 'maxdate' => '2020-04-30']); 1406 1407 $mode = tool_uploadcourse_processor::MODE_UPDATE_ONLY; 1408 $updatemode = tool_uploadcourse_processor::UPDATE_ALL_WITH_DATA_ONLY; 1409 $dataupload = [ 1410 'shortname' => $course->shortname, 1411 'customfield_mydate' => '2020-05-06', // Out of range. 1412 ]; 1413 1414 $uploader = new tool_uploadcourse_course($mode, $updatemode, $dataupload); 1415 $this->assertFalse($uploader->prepare()); 1416 $this->assertArrayHasKey('customfieldinvalid', $uploader->get_errors()); 1417 } 1418 1419 public function test_idnumber_problems() { 1420 $this->resetAfterTest(true); 1421 1422 $c1 = $this->getDataGenerator()->create_course(array('shortname' => 'sntaken', 'idnumber' => 'taken')); 1423 $c2 = $this->getDataGenerator()->create_course(); 1424 1425 // Create with existing ID number. 1426 $mode = tool_uploadcourse_processor::MODE_CREATE_NEW; 1427 $updatemode = tool_uploadcourse_processor::UPDATE_ALL_WITH_DATA_ONLY; 1428 $data = array('shortname' => 'c2', 'summary' => 'summary', 'fullname' => 'FN', 'category' => '1', 1429 'idnumber' => $c1->idnumber); 1430 $co = new tool_uploadcourse_course($mode, $updatemode, $data); 1431 $this->assertFalse($co->prepare()); 1432 $this->assertArrayHasKey('idnumberalreadyinuse', $co->get_errors()); 1433 1434 // Rename to existing ID number. 1435 $mode = tool_uploadcourse_processor::MODE_UPDATE_ONLY; 1436 $updatemode = tool_uploadcourse_processor::UPDATE_ALL_WITH_DATA_ONLY; 1437 $data = array('shortname' => $c2->shortname, 'rename' => 'SN', 'idnumber' => $c1->idnumber); 1438 $importoptions = array('canrename' => true); 1439 $co = new tool_uploadcourse_course($mode, $updatemode, $data, array(), $importoptions); 1440 $this->assertFalse($co->prepare()); 1441 $this->assertArrayHasKey('cannotrenameidnumberconflict', $co->get_errors()); 1442 1443 // Incrementing shortname increments idnumber. 1444 $mode = tool_uploadcourse_processor::MODE_CREATE_ALL; 1445 $updatemode = tool_uploadcourse_processor::UPDATE_NOTHING; 1446 $data = array('shortname' => $c1->shortname, 'idnumber' => $c1->idnumber, 'summary' => 'S', 'fullname' => 'F', 1447 'category' => 1); 1448 $co = new tool_uploadcourse_course($mode, $updatemode, $data, array(), array()); 1449 $this->assertTrue($co->prepare()); 1450 $this->assertArrayHasKey('courseshortnameincremented', $co->get_statuses()); 1451 $this->assertArrayHasKey('courseidnumberincremented', $co->get_statuses()); 1452 $data = $co->get_data(); 1453 $this->assertEquals('sntaken_2', $data['shortname']); 1454 $this->assertEquals('taken_2', $data['idnumber']); 1455 1456 // Incrementing shortname increments idnumber unless available. 1457 $mode = tool_uploadcourse_processor::MODE_CREATE_ALL; 1458 $updatemode = tool_uploadcourse_processor::UPDATE_NOTHING; 1459 $data = array('shortname' => $c1->shortname, 'idnumber' => 'nottaken', 'summary' => 'S', 'fullname' => 'F', 1460 'category' => 1); 1461 $co = new tool_uploadcourse_course($mode, $updatemode, $data, array(), array()); 1462 $this->assertTrue($co->prepare()); 1463 $this->assertArrayHasKey('courseshortnameincremented', $co->get_statuses()); 1464 $this->assertArrayNotHasKey('courseidnumberincremented', $co->get_statuses()); 1465 $data = $co->get_data(); 1466 $this->assertEquals('sntaken_2', $data['shortname']); 1467 $this->assertEquals('nottaken', $data['idnumber']); 1468 } 1469 1470 public function test_generate_shortname() { 1471 $this->resetAfterTest(true); 1472 1473 $c1 = $this->getDataGenerator()->create_course(array('shortname' => 'taken')); 1474 1475 // Generate a shortname. 1476 $mode = tool_uploadcourse_processor::MODE_CREATE_NEW; 1477 $updatemode = tool_uploadcourse_processor::UPDATE_NOTHING; 1478 $data = array('summary' => 'summary', 'fullname' => 'FN', 'category' => '1', 'idnumber' => 'IDN'); 1479 $importoptions = array('shortnametemplate' => '%i'); 1480 $co = new tool_uploadcourse_course($mode, $updatemode, $data, array(), $importoptions); 1481 $this->assertTrue($co->prepare()); 1482 $this->assertArrayHasKey('courseshortnamegenerated', $co->get_statuses()); 1483 1484 // Generate a shortname without a template. 1485 $mode = tool_uploadcourse_processor::MODE_CREATE_NEW; 1486 $updatemode = tool_uploadcourse_processor::UPDATE_NOTHING; 1487 $data = array('summary' => 'summary', 'fullname' => 'FN', 'category' => '1'); 1488 $co = new tool_uploadcourse_course($mode, $updatemode, $data, array(), array()); 1489 $this->assertFalse($co->prepare()); 1490 $this->assertArrayHasKey('missingshortnamenotemplate', $co->get_errors()); 1491 1492 // Generate a shortname in update mode. 1493 $mode = tool_uploadcourse_processor::MODE_UPDATE_ONLY; 1494 $updatemode = tool_uploadcourse_processor::UPDATE_ALL_WITH_DATA_ONLY; 1495 $data = array('summary' => 'summary', 'fullname' => 'FN', 'category' => '1'); 1496 $importoptions = array('shortnametemplate' => '%f'); 1497 $co = new tool_uploadcourse_course($mode, $updatemode, $data, array(), $importoptions); 1498 $this->assertFalse($co->prepare()); 1499 // Commented because we never get here as the course without shortname does not exist. 1500 // $this->assertArrayHasKey('cannotgenerateshortnameupdatemode', $co->get_errors()); 1501 1502 // Generate a shortname to a course that already exists. 1503 $mode = tool_uploadcourse_processor::MODE_CREATE_NEW; 1504 $updatemode = tool_uploadcourse_processor::UPDATE_NOTHING; 1505 $data = array('summary' => 'summary', 'fullname' => 'taken', 'category' => '1'); 1506 $importoptions = array('shortnametemplate' => '%f'); 1507 $co = new tool_uploadcourse_course($mode, $updatemode, $data, array(), $importoptions); 1508 $this->assertFalse($co->prepare()); 1509 $this->assertArrayHasKey('generatedshortnamealreadyinuse', $co->get_errors()); 1510 1511 // Generate a shortname to a course that already exists will be incremented. 1512 $mode = tool_uploadcourse_processor::MODE_CREATE_ALL; 1513 $updatemode = tool_uploadcourse_processor::UPDATE_NOTHING; 1514 $data = array('summary' => 'summary', 'fullname' => 'taken', 'category' => '1'); 1515 $importoptions = array('shortnametemplate' => '%f'); 1516 $co = new tool_uploadcourse_course($mode, $updatemode, $data, array(), $importoptions); 1517 $this->assertTrue($co->prepare()); 1518 $this->assertArrayHasKey('courseshortnamegenerated', $co->get_statuses()); 1519 $this->assertArrayHasKey('courseshortnameincremented', $co->get_statuses()); 1520 } 1521 1522 public function test_mess_with_frontpage() { 1523 global $SITE; 1524 $this->resetAfterTest(true); 1525 1526 // Updating the front page. 1527 $mode = tool_uploadcourse_processor::MODE_UPDATE_ONLY; 1528 $updatemode = tool_uploadcourse_processor::UPDATE_ALL_WITH_DATA_ONLY; 1529 $data = array('shortname' => $SITE->shortname, 'idnumber' => 'NewIDN'); 1530 $importoptions = array(); 1531 $co = new tool_uploadcourse_course($mode, $updatemode, $data, array(), $importoptions); 1532 $this->assertFalse($co->prepare()); 1533 $this->assertArrayHasKey('cannotupdatefrontpage', $co->get_errors()); 1534 1535 // Updating the front page. 1536 $mode = tool_uploadcourse_processor::MODE_CREATE_OR_UPDATE; 1537 $updatemode = tool_uploadcourse_processor::UPDATE_ALL_WITH_DATA_ONLY; 1538 $data = array('shortname' => $SITE->shortname, 'idnumber' => 'NewIDN'); 1539 $importoptions = array(); 1540 $co = new tool_uploadcourse_course($mode, $updatemode, $data, array(), $importoptions); 1541 $this->assertFalse($co->prepare()); 1542 $this->assertArrayHasKey('cannotupdatefrontpage', $co->get_errors()); 1543 1544 // Generating a shortname should not be allowed in update mode, and so we cannot update the front page. 1545 $mode = tool_uploadcourse_processor::MODE_CREATE_OR_UPDATE; 1546 $updatemode = tool_uploadcourse_processor::UPDATE_ALL_WITH_DATA_ONLY; 1547 $data = array('idnumber' => 'NewIDN', 'fullname' => 'FN', 'category' => 1); 1548 $importoptions = array('shortnametemplate' => $SITE->shortname); 1549 $co = new tool_uploadcourse_course($mode, $updatemode, $data, array(), $importoptions); 1550 $this->assertFalse($co->prepare()); 1551 $this->assertArrayHasKey('cannotgenerateshortnameupdatemode', $co->get_errors()); 1552 1553 // Renaming to the front page should not be allowed. 1554 $c1 = $this->getDataGenerator()->create_course(); 1555 $mode = tool_uploadcourse_processor::MODE_CREATE_OR_UPDATE; 1556 $updatemode = tool_uploadcourse_processor::UPDATE_ALL_WITH_DATA_ONLY; 1557 $data = array('shortname' => $c1->shortname, 'fullname' => 'FN', 'idnumber' => 'NewIDN', 'rename' => $SITE->shortname); 1558 $importoptions = array('canrename' => true); 1559 $co = new tool_uploadcourse_course($mode, $updatemode, $data, array(), $importoptions); 1560 $this->assertFalse($co->prepare()); 1561 $this->assertArrayHasKey('cannotrenameshortnamealreadyinuse', $co->get_errors()); 1562 } 1563 1564 /** 1565 * Test when role doesn't exist. 1566 * 1567 * @covers \tool_uploadcourse_course::prepare 1568 */ 1569 public function test_role_not_exist() { 1570 $this->resetAfterTest(); 1571 $this->setAdminUser(); 1572 1573 $mode = tool_uploadcourse_processor::MODE_CREATE_NEW; 1574 $updatemode = tool_uploadcourse_processor::UPDATE_NOTHING; 1575 1576 $upload = new tool_uploadcourse_course($mode, $updatemode, [ 1577 'category' => 1, 1578 'fullname' => 'Testing', 1579 'shortname' => 'T101', 1580 'enrolment_1' => 'manual', 1581 'enrolment_1_role' => 'notexist' 1582 ]); 1583 1584 $this->assertFalse($upload->prepare()); 1585 $this->assertArrayHasKey('invalidroles', $upload->get_errors()); 1586 } 1587 1588 /** 1589 * Test when role not allowed in course context. 1590 * 1591 * @covers \tool_uploadcourse_course::proceed 1592 */ 1593 public function test_role_not_allowed() { 1594 $this->resetAfterTest(); 1595 $this->setAdminUser(); 1596 1597 $roleid = create_role('New student role', 'student2', 'New student description', 'student'); 1598 set_role_contextlevels($roleid, [CONTEXT_BLOCK]); 1599 1600 $mode = tool_uploadcourse_processor::MODE_CREATE_NEW; 1601 $updatemode = tool_uploadcourse_processor::UPDATE_NOTHING; 1602 1603 $upload = new tool_uploadcourse_course($mode, $updatemode, [ 1604 'category' => 1, 1605 'fullname' => 'Testing', 1606 'shortname' => 'T101', 1607 'enrolment_1' => 'manual', 1608 'enrolment_1_role' => 'student2' 1609 ]); 1610 1611 $this->assertFalse($upload->prepare()); 1612 $this->assertArrayHasKey('contextrolenotallowed', $upload->get_errors()); 1613 } 1614 1615 /** 1616 * Test when role is allowed. 1617 * 1618 * @covers \tool_uploadcourse_course::proceed 1619 */ 1620 public function test_role_allowed() { 1621 global $DB; 1622 1623 $this->resetAfterTest(); 1624 $this->setAdminUser(); 1625 1626 $mode = tool_uploadcourse_processor::MODE_UPDATE_ONLY; 1627 $updatemode = tool_uploadcourse_processor::UPDATE_MISSING_WITH_DATA_OR_DEFAUTLS; 1628 1629 $course = $this->getDataGenerator()->create_course([ 1630 'shortname' => 'c1', 1631 ]); 1632 1633 $instances = enrol_get_instances($course->id, true); 1634 $studentrole = $DB->get_record('role', ['shortname' => 'student']); 1635 $teacherrole = $DB->get_record('role', ['shortname' => 'teacher']); 1636 $instance = reset($instances); 1637 $this->assertEquals($studentrole->id, $instance->roleid); 1638 1639 $upload = new tool_uploadcourse_course($mode, $updatemode, [ 1640 'shortname' => 'c1', 1641 'enrolment_1' => 'manual', 1642 'enrolment_1_role' => 'teacher' 1643 ]); 1644 1645 $this->assertTrue($upload->prepare()); 1646 $upload->proceed(); 1647 $instances = enrol_get_instances($course->id, true); 1648 $instance = reset($instances); 1649 $this->assertEquals($teacherrole->id, $instance->roleid); 1650 } 1651 1652 /** 1653 * Get custom field plugin generator 1654 * 1655 * @return core_customfield_generator 1656 */ 1657 protected function get_customfield_generator() : \core_customfield_generator { 1658 return $this->getDataGenerator()->get_plugin_generator('core_customfield'); 1659 } 1660 1661 /** 1662 * Helper method to create custom course field 1663 * 1664 * @param \core_customfield\category_controller $category 1665 * @param string $type 1666 * @param string $shortname 1667 * @param array $configdata 1668 * @return \core_customfield\field_controller 1669 */ 1670 protected function create_custom_field(\core_customfield\category_controller $category, string $type, string $shortname, 1671 array $configdata = []) : \core_customfield\field_controller { 1672 1673 return $this->get_customfield_generator()->create_field([ 1674 'categoryid' => $category->get('id'), 1675 'type' => $type, 1676 'shortname' => $shortname, 1677 'configdata' => $configdata, 1678 ]); 1679 } 1680 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body