Differences Between: [Versions 310 and 311] [Versions 311 and 400] [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 core_completion; 18 19 use core_completion_external; 20 use externallib_advanced_testcase; 21 22 defined('MOODLE_INTERNAL') || die(); 23 24 global $CFG; 25 26 require_once($CFG->dirroot . '/webservice/tests/helpers.php'); 27 28 /** 29 * External completion functions unit tests 30 * 31 * @package core_completion 32 * @category external 33 * @copyright 2015 Juan Leyva <juan@moodle.com> 34 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 35 * @since Moodle 2.9 36 */ 37 class externallib_test extends externallib_advanced_testcase { 38 39 /** 40 * Test update_activity_completion_status_manually 41 */ 42 public function test_update_activity_completion_status_manually() { 43 global $DB, $CFG; 44 45 $this->resetAfterTest(true); 46 47 $CFG->enablecompletion = true; 48 $user = $this->getDataGenerator()->create_user(); 49 $course = $this->getDataGenerator()->create_course(array('enablecompletion' => 1)); 50 $data = $this->getDataGenerator()->create_module('data', array('course' => $course->id), 51 array('completion' => 1)); 52 $cm = get_coursemodule_from_id('data', $data->cmid); 53 54 $studentrole = $DB->get_record('role', array('shortname' => 'student')); 55 $this->getDataGenerator()->enrol_user($user->id, $course->id, $studentrole->id); 56 57 $this->setUser($user); 58 59 $result = core_completion_external::update_activity_completion_status_manually($data->cmid, true); 60 // We need to execute the return values cleaning process to simulate the web service server. 61 $result = \external_api::clean_returnvalue( 62 core_completion_external::update_activity_completion_status_manually_returns(), $result); 63 64 // Check in DB. 65 $this->assertEquals(1, $DB->get_field('course_modules_completion', 'completionstate', 66 array('coursemoduleid' => $data->cmid))); 67 68 // Check using the API. 69 $completion = new \completion_info($course); 70 $completiondata = $completion->get_data($cm); 71 $this->assertEquals(1, $completiondata->completionstate); 72 $this->assertTrue($result['status']); 73 74 $result = core_completion_external::update_activity_completion_status_manually($data->cmid, false); 75 // We need to execute the return values cleaning process to simulate the web service server. 76 $result = \external_api::clean_returnvalue( 77 core_completion_external::update_activity_completion_status_manually_returns(), $result); 78 79 $this->assertEquals(0, $DB->get_field('course_modules_completion', 'completionstate', 80 array('coursemoduleid' => $data->cmid))); 81 $completiondata = $completion->get_data($cm); 82 $this->assertEquals(0, $completiondata->completionstate); 83 $this->assertTrue($result['status']); 84 } 85 86 /** 87 * Test update_activity_completion_status 88 */ 89 public function test_get_activities_completion_status() { 90 global $DB, $CFG, $PAGE; 91 92 $this->resetAfterTest(true); 93 94 $CFG->enablecompletion = true; 95 $student = $this->getDataGenerator()->create_user(); 96 $teacher = $this->getDataGenerator()->create_user(); 97 98 $course = $this->getDataGenerator()->create_course(array('enablecompletion' => 1, 99 'groupmode' => SEPARATEGROUPS, 100 'groupmodeforce' => 1)); 101 \availability_completion\condition::wipe_static_cache(); 102 103 $data = $this->getDataGenerator()->create_module('data', 104 ['course' => $course->id], 105 ['completion' => COMPLETION_TRACKING_MANUAL], 106 ); 107 $forum = $this->getDataGenerator()->create_module('forum', 108 ['course' => $course->id], 109 ['completion' => COMPLETION_TRACKING_MANUAL], 110 ); 111 $forumautocompletion = $this->getDataGenerator()->create_module('forum', 112 ['course' => $course->id], 113 ['showdescription' => true, 'completionview' => 1, 'completion' => COMPLETION_TRACKING_AUTOMATIC], 114 ); 115 $availability = '{"op":"&","c":[{"type":"completion","cm":' . $forum->cmid .',"e":1}],"showc":[true]}'; 116 $assign = $this->getDataGenerator()->create_module('assign', 117 ['course' => $course->id], 118 ['availability' => $availability], 119 ); 120 $page = $this->getDataGenerator()->create_module('page', array('course' => $course->id), 121 array('completion' => 1, 'visible' => 0)); 122 123 $cmdata = get_coursemodule_from_id('data', $data->cmid); 124 $cmforum = get_coursemodule_from_id('forum', $forum->cmid); 125 $cmforumautocompletion = get_coursemodule_from_id('forum', $forumautocompletion->cmid); 126 127 $studentrole = $DB->get_record('role', array('shortname' => 'student')); 128 $teacherrole = $DB->get_record('role', array('shortname' => 'editingteacher')); 129 $this->getDataGenerator()->enrol_user($student->id, $course->id, $studentrole->id); 130 $this->getDataGenerator()->enrol_user($teacher->id, $course->id, $teacherrole->id); 131 132 $group1 = $this->getDataGenerator()->create_group(array('courseid' => $course->id)); 133 $group2 = $this->getDataGenerator()->create_group(array('courseid' => $course->id)); 134 135 // Teacher and student in different groups initially. 136 groups_add_member($group1->id, $student->id); 137 groups_add_member($group2->id, $teacher->id); 138 139 $this->setUser($student); 140 // Forum complete. 141 $completion = new \completion_info($course); 142 $completion->update_state($cmforum, COMPLETION_COMPLETE); 143 144 $result = core_completion_external::get_activities_completion_status($course->id, $student->id); 145 // We need to execute the return values cleaning process to simulate the web service server. 146 $result = \external_api::clean_returnvalue( 147 core_completion_external::get_activities_completion_status_returns(), $result); 148 149 // We added 5 activities, but only 4 with completion enabled and one of those is hidden. 150 $numberofactivities = 5; 151 $numberofhidden = 1; 152 $numberofcompletions = $numberofactivities - $numberofhidden; 153 $numberofstatusstudent = 3; 154 155 $this->assertCount($numberofstatusstudent, $result['statuses']); 156 157 $activitiesfound = 0; 158 foreach ($result['statuses'] as $status) { 159 if ($status['cmid'] == $forum->cmid and $status['modname'] == 'forum' and $status['instance'] == $forum->id) { 160 $activitiesfound++; 161 $this->assertEquals(COMPLETION_COMPLETE, $status['state']); 162 $this->assertEquals(COMPLETION_TRACKING_MANUAL, $status['tracking']); 163 $this->assertTrue($status['valueused']); 164 $this->assertTrue($status['hascompletion']); 165 $this->assertFalse($status['isautomatic']); 166 $this->assertTrue($status['istrackeduser']); 167 $this->assertTrue($status['uservisible']); 168 $details = $status['details']; 169 $this->assertCount(0, $details); 170 } else if ($status['cmid'] == $forumautocompletion->cmid) { 171 $activitiesfound++; 172 $this->assertEquals(COMPLETION_INCOMPLETE, $status['state']); 173 $this->assertEquals(COMPLETION_TRACKING_AUTOMATIC, $status['tracking']); 174 $this->assertFalse($status['valueused']); 175 $this->assertTrue($status['hascompletion']); 176 $this->assertTrue($status['isautomatic']); 177 $this->assertTrue($status['istrackeduser']); 178 $this->assertTrue($status['uservisible']); 179 $details = $status['details']; 180 $this->assertCount(1, $details); 181 $this->assertEquals('completionview', $details[0]['rulename']); 182 $this->assertEquals(0, $details[0]['rulevalue']['status']); 183 184 } else if ($status['cmid'] == $data->cmid and $status['modname'] == 'data' and $status['instance'] == $data->id) { 185 $activitiesfound++; 186 $this->assertEquals(COMPLETION_INCOMPLETE, $status['state']); 187 $this->assertEquals(COMPLETION_TRACKING_MANUAL, $status['tracking']); 188 $this->assertFalse($status['valueused']); 189 $this->assertFalse($status['valueused']); 190 $this->assertTrue($status['hascompletion']); 191 $this->assertFalse($status['isautomatic']); 192 $this->assertTrue($status['istrackeduser']); 193 $this->assertTrue($status['uservisible']); 194 $details = $status['details']; 195 $this->assertCount(0, $details); 196 } 197 } 198 $this->assertEquals(3, $activitiesfound); 199 200 // Teacher should see students status, they are in different groups but the teacher can access all groups. 201 $this->setUser($teacher); 202 $result = core_completion_external::get_activities_completion_status($course->id, $student->id); 203 // We need to execute the return values cleaning process to simulate the web service server. 204 $result = \external_api::clean_returnvalue( 205 core_completion_external::get_activities_completion_status_returns(), $result); 206 207 $this->assertCount($numberofcompletions, $result['statuses']); 208 209 // Override status by teacher. 210 $completion->update_state($cmforum, COMPLETION_INCOMPLETE, $student->id, true); 211 212 $result = core_completion_external::get_activities_completion_status($course->id, $student->id); 213 // We need to execute the return values cleaning process to simulate the web service server. 214 $result = \external_api::clean_returnvalue( 215 core_completion_external::get_activities_completion_status_returns(), $result); 216 217 // Check forum has been overriden by the teacher. 218 foreach ($result['statuses'] as $status) { 219 if ($status['cmid'] == $forum->cmid) { 220 $this->assertEquals(COMPLETION_INCOMPLETE, $status['state']); 221 $this->assertEquals(COMPLETION_TRACKING_MANUAL, $status['tracking']); 222 $this->assertEquals($teacher->id, $status['overrideby']); 223 break; 224 } 225 } 226 227 // Teacher should see his own completion status. 228 229 // Forum complete for teacher. 230 $completion = new \completion_info($course); 231 $completion->update_state($cmforum, COMPLETION_COMPLETE); 232 233 $result = core_completion_external::get_activities_completion_status($course->id, $teacher->id); 234 // We need to execute the return values cleaning process to simulate the web service server. 235 $result = \external_api::clean_returnvalue( 236 core_completion_external::get_activities_completion_status_returns(), $result); 237 238 $this->assertCount($numberofcompletions, $result['statuses']); 239 240 $activitiesfound = 0; 241 foreach ($result['statuses'] as $status) { 242 if ($status['cmid'] == $forum->cmid and $status['modname'] == 'forum' and $status['instance'] == $forum->id) { 243 $activitiesfound++; 244 $this->assertEquals(COMPLETION_COMPLETE, $status['state']); 245 $this->assertEquals(COMPLETION_TRACKING_MANUAL, $status['tracking']); 246 } else if ($status['cmid'] == $forumautocompletion->cmid) { 247 $activitiesfound++; 248 $this->assertEquals(COMPLETION_INCOMPLETE, $status['state']); 249 $this->assertEquals(COMPLETION_TRACKING_AUTOMATIC, $status['tracking']); 250 } else { 251 $activitiesfound++; 252 $this->assertEquals(COMPLETION_INCOMPLETE, $status['state']); 253 $this->assertEquals(COMPLETION_TRACKING_MANUAL, $status['tracking']); 254 } 255 } 256 $this->assertEquals(4, $activitiesfound); 257 258 // Change teacher role capabilities (disable access all groups). 259 $context = \context_course::instance($course->id); 260 assign_capability('moodle/site:accessallgroups', CAP_PROHIBIT, $teacherrole->id, $context); 261 accesslib_clear_all_caches_for_unit_testing(); 262 263 try { 264 $result = core_completion_external::get_activities_completion_status($course->id, $student->id); 265 $this->fail('Exception expected due to groups permissions.'); 266 } catch (\moodle_exception $e) { 267 $this->assertEquals('accessdenied', $e->errorcode); 268 } 269 270 // Now add the teacher in the same group. 271 groups_add_member($group1->id, $teacher->id); 272 $result = core_completion_external::get_activities_completion_status($course->id, $student->id); 273 // We need to execute the return values cleaning process to simulate the web service server. 274 $result = \external_api::clean_returnvalue( 275 core_completion_external::get_activities_completion_status_returns(), $result); 276 $this->assertCount($numberofcompletions, $result['statuses']); 277 } 278 279 /** 280 * Test override_activity_completion_status 281 */ 282 public function test_override_activity_completion_status() { 283 global $DB, $CFG; 284 $this->resetAfterTest(true); 285 286 // Create course with teacher and student enrolled. 287 $CFG->enablecompletion = true; 288 $course = $this->getDataGenerator()->create_course(['enablecompletion' => 1]); 289 $student = $this->getDataGenerator()->create_user(); 290 $teacher = $this->getDataGenerator()->create_user(); 291 $studentrole = $DB->get_record('role', ['shortname' => 'student']); 292 $this->getDataGenerator()->enrol_user($student->id, $course->id, $studentrole->id); 293 $teacherrole = $DB->get_record('role', ['shortname' => 'teacher']); 294 $this->getDataGenerator()->enrol_user($teacher->id, $course->id, $teacherrole->id); 295 296 // Create 2 activities, one with manual completion (data), one with automatic completion triggered by viewing it (forum). 297 $data = $this->getDataGenerator()->create_module('data', ['course' => $course->id], ['completion' => 1]); 298 $forum = $this->getDataGenerator()->create_module('forum', ['course' => $course->id], 299 ['completion' => 2, 'completionview' => 1]); 300 $cmdata = get_coursemodule_from_id('data', $data->cmid); 301 $cmforum = get_coursemodule_from_id('forum', $forum->cmid); 302 303 // Manually complete the data activity as the student. 304 $this->setUser($student); 305 $completion = new \completion_info($course); 306 $completion->update_state($cmdata, COMPLETION_COMPLETE); 307 308 // Test overriding the status of the manual-completion-activity 'incomplete'. 309 $this->setUser($teacher); 310 $result = core_completion_external::override_activity_completion_status($student->id, $data->cmid, COMPLETION_INCOMPLETE); 311 $result = \external_api::clean_returnvalue(core_completion_external::override_activity_completion_status_returns(), $result); 312 $this->assertEquals($result['state'], COMPLETION_INCOMPLETE); 313 $completiondata = $completion->get_data($cmdata, false, $student->id); 314 $this->assertEquals(COMPLETION_INCOMPLETE, $completiondata->completionstate); 315 316 // Test overriding the status of the manual-completion-activity back to 'complete'. 317 $result = core_completion_external::override_activity_completion_status($student->id, $data->cmid, COMPLETION_COMPLETE); 318 $result = \external_api::clean_returnvalue(core_completion_external::override_activity_completion_status_returns(), $result); 319 $this->assertEquals($result['state'], COMPLETION_COMPLETE); 320 $completiondata = $completion->get_data($cmdata, false, $student->id); 321 $this->assertEquals(COMPLETION_COMPLETE, $completiondata->completionstate); 322 323 // Test overriding the status of the auto-completion-activity to 'complete'. 324 $result = core_completion_external::override_activity_completion_status($student->id, $forum->cmid, COMPLETION_COMPLETE); 325 $result = \external_api::clean_returnvalue(core_completion_external::override_activity_completion_status_returns(), $result); 326 $this->assertEquals($result['state'], COMPLETION_COMPLETE); 327 $completionforum = $completion->get_data($cmforum, false, $student->id); 328 $this->assertEquals(COMPLETION_COMPLETE, $completionforum->completionstate); 329 330 // Test overriding the status of the auto-completion-activity to 'incomplete'. 331 $result = core_completion_external::override_activity_completion_status($student->id, $forum->cmid, COMPLETION_INCOMPLETE); 332 $result = \external_api::clean_returnvalue(core_completion_external::override_activity_completion_status_returns(), $result); 333 $this->assertEquals($result['state'], COMPLETION_INCOMPLETE); 334 $completionforum = $completion->get_data($cmforum, false, $student->id); 335 $this->assertEquals(COMPLETION_INCOMPLETE, $completionforum->completionstate); 336 337 // Test overriding the status of the auto-completion-activity to an invalid state. 338 $this->expectException('moodle_exception'); 339 core_completion_external::override_activity_completion_status($student->id, $forum->cmid, 3); 340 } 341 342 /** 343 * Test overriding the activity completion status as a user without the capability to do so. 344 */ 345 public function test_override_status_user_without_capability() { 346 global $DB, $CFG; 347 $this->resetAfterTest(true); 348 349 // Create course with teacher and student enrolled. 350 $CFG->enablecompletion = true; 351 $course = $this->getDataGenerator()->create_course(['enablecompletion' => 1]); 352 $student = $this->getDataGenerator()->create_user(); 353 $teacher = $this->getDataGenerator()->create_user(); 354 $studentrole = $DB->get_record('role', ['shortname' => 'student']); 355 $this->getDataGenerator()->enrol_user($student->id, $course->id, $studentrole->id); 356 $teacherrole = $DB->get_record('role', ['shortname' => 'teacher']); 357 $this->getDataGenerator()->enrol_user($teacher->id, $course->id, $teacherrole->id); 358 $coursecontext = \context_course::instance($course->id); 359 360 // Create an activity with automatic completion (a forum). 361 $forum = $this->getDataGenerator()->create_module('forum', ['course' => $course->id], 362 ['completion' => 2, 'completionview' => 1]); 363 364 // Test overriding the status of the activity for a user without the capability. 365 $this->setUser($teacher); 366 assign_capability('moodle/course:overridecompletion', CAP_PREVENT, $teacherrole->id, $coursecontext); 367 $this->expectException('required_capability_exception'); 368 core_completion_external::override_activity_completion_status($student->id, $forum->cmid, COMPLETION_COMPLETE); 369 } 370 371 /** 372 * Test get_course_completion_status 373 */ 374 public function test_get_course_completion_status() { 375 global $DB, $CFG, $COMPLETION_CRITERIA_TYPES; 376 require_once($CFG->dirroot.'/completion/criteria/completion_criteria_self.php'); 377 require_once($CFG->dirroot.'/completion/criteria/completion_criteria_date.php'); 378 require_once($CFG->dirroot.'/completion/criteria/completion_criteria_unenrol.php'); 379 require_once($CFG->dirroot.'/completion/criteria/completion_criteria_activity.php'); 380 require_once($CFG->dirroot.'/completion/criteria/completion_criteria_duration.php'); 381 require_once($CFG->dirroot.'/completion/criteria/completion_criteria_grade.php'); 382 require_once($CFG->dirroot.'/completion/criteria/completion_criteria_role.php'); 383 require_once($CFG->dirroot.'/completion/criteria/completion_criteria_course.php'); 384 385 $this->resetAfterTest(true); 386 387 $CFG->enablecompletion = true; 388 $student = $this->getDataGenerator()->create_user(); 389 $teacher = $this->getDataGenerator()->create_user(); 390 391 $course = $this->getDataGenerator()->create_course(array('enablecompletion' => 1, 392 'groupmode' => SEPARATEGROUPS, 393 'groupmodeforce' => 1)); 394 395 $data = $this->getDataGenerator()->create_module('data', array('course' => $course->id), 396 array('completion' => 1)); 397 $forum = $this->getDataGenerator()->create_module('forum', array('course' => $course->id), 398 array('completion' => 1)); 399 $assign = $this->getDataGenerator()->create_module('assign', array('course' => $course->id)); 400 401 $cmdata = get_coursemodule_from_id('data', $data->cmid); 402 $cmforum = get_coursemodule_from_id('forum', $forum->cmid); 403 404 $studentrole = $DB->get_record('role', array('shortname' => 'student')); 405 $teacherrole = $DB->get_record('role', array('shortname' => 'editingteacher')); 406 $this->getDataGenerator()->enrol_user($student->id, $course->id, $studentrole->id); 407 $this->getDataGenerator()->enrol_user($teacher->id, $course->id, $teacherrole->id); 408 409 $group1 = $this->getDataGenerator()->create_group(array('courseid' => $course->id)); 410 $group2 = $this->getDataGenerator()->create_group(array('courseid' => $course->id)); 411 // Teacher and student in different groups initially. 412 groups_add_member($group1->id, $student->id); 413 groups_add_member($group2->id, $teacher->id); 414 415 // Set completion rules. 416 $completion = new \completion_info($course); 417 418 // Loop through each criteria type and run its update_config() method. 419 420 $criteriadata = new \stdClass(); 421 $criteriadata->id = $course->id; 422 $criteriadata->criteria_activity = array(); 423 // Some activities. 424 $criteriadata->criteria_activity[$cmdata->id] = 1; 425 $criteriadata->criteria_activity[$cmforum->id] = 1; 426 427 // In a week criteria date value. 428 $criteriadata->criteria_date_value = time() + WEEKSECS; 429 430 // Self completion. 431 $criteriadata->criteria_self = 1; 432 433 foreach ($COMPLETION_CRITERIA_TYPES as $type) { 434 $class = 'completion_criteria_'.$type; 435 $criterion = new $class(); 436 $criterion->update_config($criteriadata); 437 } 438 439 // Handle overall aggregation. 440 $aggdata = array( 441 'course' => $course->id, 442 'criteriatype' => null 443 ); 444 $aggregation = new \completion_aggregation($aggdata); 445 $aggregation->setMethod(COMPLETION_AGGREGATION_ALL); 446 $aggregation->save(); 447 448 $aggdata['criteriatype'] = COMPLETION_CRITERIA_TYPE_ACTIVITY; 449 $aggregation = new \completion_aggregation($aggdata); 450 $aggregation->setMethod(COMPLETION_AGGREGATION_ALL); 451 $aggregation->save(); 452 453 $this->setUser($student); 454 455 $result = core_completion_external::get_course_completion_status($course->id, $student->id); 456 // We need to execute the return values cleaning process to simulate the web service server. 457 $studentresult = \external_api::clean_returnvalue( 458 core_completion_external::get_course_completion_status_returns(), $result); 459 460 // 3 different criteria. 461 $this->assertCount(3, $studentresult['completionstatus']['completions']); 462 463 $this->assertEquals(COMPLETION_AGGREGATION_ALL, $studentresult['completionstatus']['aggregation']); 464 $this->assertFalse($studentresult['completionstatus']['completed']); 465 466 $this->assertEquals('No', $studentresult['completionstatus']['completions'][0]['status']); 467 $this->assertEquals('No', $studentresult['completionstatus']['completions'][1]['status']); 468 $this->assertEquals('No', $studentresult['completionstatus']['completions'][2]['status']); 469 470 // Teacher should see students status, they are in different groups but the teacher can access all groups. 471 $this->setUser($teacher); 472 $result = core_completion_external::get_course_completion_status($course->id, $student->id); 473 // We need to execute the return values cleaning process to simulate the web service server. 474 $teacherresult = \external_api::clean_returnvalue( 475 core_completion_external::get_course_completion_status_returns(), $result); 476 477 $this->assertEquals($studentresult, $teacherresult); 478 479 // Change teacher role capabilities (disable access al goups). 480 $context = \context_course::instance($course->id); 481 assign_capability('moodle/site:accessallgroups', CAP_PROHIBIT, $teacherrole->id, $context); 482 accesslib_clear_all_caches_for_unit_testing(); 483 484 try { 485 $result = core_completion_external::get_course_completion_status($course->id, $student->id); 486 $this->fail('Exception expected due to groups permissions.'); 487 } catch (\moodle_exception $e) { 488 $this->assertEquals('accessdenied', $e->errorcode); 489 } 490 491 // Now add the teacher in the same group. 492 groups_add_member($group1->id, $teacher->id); 493 $result = core_completion_external::get_course_completion_status($course->id, $student->id); 494 // We need to execute the return values cleaning process to simulate the web service server. 495 $teacherresult = \external_api::clean_returnvalue( 496 core_completion_external::get_course_completion_status_returns(), $result); 497 498 $this->assertEquals($studentresult, $teacherresult); 499 500 } 501 502 /** 503 * Test mark_course_self_completed 504 */ 505 public function test_mark_course_self_completed() { 506 global $DB, $CFG; 507 require_once($CFG->dirroot.'/completion/criteria/completion_criteria_self.php'); 508 509 $this->resetAfterTest(true); 510 511 $CFG->enablecompletion = true; 512 $student = $this->getDataGenerator()->create_user(); 513 $teacher = $this->getDataGenerator()->create_user(); 514 515 $course = $this->getDataGenerator()->create_course(array('enablecompletion' => 1)); 516 517 $studentrole = $DB->get_record('role', array('shortname' => 'student')); 518 $this->getDataGenerator()->enrol_user($student->id, $course->id, $studentrole->id); 519 520 // Set completion rules. 521 $completion = new \completion_info($course); 522 523 $criteriadata = new \stdClass(); 524 $criteriadata->id = $course->id; 525 $criteriadata->criteria_activity = array(); 526 527 // Self completion. 528 $criteriadata->criteria_self = COMPLETION_CRITERIA_TYPE_SELF; 529 $class = 'completion_criteria_self'; 530 $criterion = new $class(); 531 $criterion->update_config($criteriadata); 532 533 // Handle overall aggregation. 534 $aggdata = array( 535 'course' => $course->id, 536 'criteriatype' => null 537 ); 538 $aggregation = new \completion_aggregation($aggdata); 539 $aggregation->setMethod(COMPLETION_AGGREGATION_ALL); 540 $aggregation->save(); 541 542 $this->setUser($student); 543 544 $result = core_completion_external::mark_course_self_completed($course->id); 545 // We need to execute the return values cleaning process to simulate the web service server. 546 $result = \external_api::clean_returnvalue( 547 core_completion_external::mark_course_self_completed_returns(), $result); 548 549 // We expect a valid result. 550 $this->assertEquals(true, $result['status']); 551 552 $result = core_completion_external::get_course_completion_status($course->id, $student->id); 553 // We need to execute the return values cleaning process to simulate the web service server. 554 $result = \external_api::clean_returnvalue( 555 core_completion_external::get_course_completion_status_returns(), $result); 556 557 // Course must be completed. 558 $this->assertEquals(COMPLETION_COMPLETE, $result['completionstatus']['completions'][0]['complete']); 559 560 try { 561 $result = core_completion_external::mark_course_self_completed($course->id); 562 $this->fail('Exception expected due course already self completed.'); 563 } catch (\moodle_exception $e) { 564 $this->assertEquals('useralreadymarkedcomplete', $e->errorcode); 565 } 566 567 } 568 569 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body