See Release Notes
Long Term Support Release
Differences Between: [Versions 310 and 401] [Versions 311 and 401] [Versions 39 and 401] [Versions 401 and 402] [Versions 401 and 403]
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 $assignautocompletion = $this->getDataGenerator()->create_module('assign', 121 ['course' => $course->id], [ 122 'showdescription' => true, 123 'completionview' => 1, 124 'completion' => COMPLETION_TRACKING_AUTOMATIC, 125 'completiongradeitemnumber' => 1, 126 'completionpassgrade' => 1, 127 ], 128 ); 129 $page = $this->getDataGenerator()->create_module('page', array('course' => $course->id), 130 array('completion' => 1, 'visible' => 0)); 131 132 $cmdata = get_coursemodule_from_id('data', $data->cmid); 133 $cmforum = get_coursemodule_from_id('forum', $forum->cmid); 134 $cmforumautocompletion = get_coursemodule_from_id('forum', $forumautocompletion->cmid); 135 136 $studentrole = $DB->get_record('role', array('shortname' => 'student')); 137 $teacherrole = $DB->get_record('role', array('shortname' => 'editingteacher')); 138 $this->getDataGenerator()->enrol_user($student->id, $course->id, $studentrole->id); 139 $this->getDataGenerator()->enrol_user($teacher->id, $course->id, $teacherrole->id); 140 141 $group1 = $this->getDataGenerator()->create_group(array('courseid' => $course->id)); 142 $group2 = $this->getDataGenerator()->create_group(array('courseid' => $course->id)); 143 144 // Teacher and student in different groups initially. 145 groups_add_member($group1->id, $student->id); 146 groups_add_member($group2->id, $teacher->id); 147 148 $this->setUser($student); 149 // Forum complete. 150 $completion = new \completion_info($course); 151 $completion->update_state($cmforum, COMPLETION_COMPLETE); 152 153 $result = core_completion_external::get_activities_completion_status($course->id, $student->id); 154 // We need to execute the return values cleaning process to simulate the web service server. 155 $result = \external_api::clean_returnvalue( 156 core_completion_external::get_activities_completion_status_returns(), $result); 157 158 // We added 6 activities, but only 4 with completion enabled and one of those is hidden. 159 $numberofactivities = 6; 160 $numberofhidden = 1; 161 $numberofcompletions = $numberofactivities - $numberofhidden; 162 $numberofstatusstudent = 4; 163 164 $this->assertCount($numberofstatusstudent, $result['statuses']); 165 166 $activitiesfound = 0; 167 foreach ($result['statuses'] as $status) { 168 if ($status['cmid'] == $forum->cmid and $status['modname'] == 'forum' and $status['instance'] == $forum->id) { 169 $activitiesfound++; 170 $this->assertEquals(COMPLETION_COMPLETE, $status['state']); 171 $this->assertEquals(COMPLETION_TRACKING_MANUAL, $status['tracking']); 172 $this->assertTrue($status['valueused']); 173 $this->assertTrue($status['hascompletion']); 174 $this->assertFalse($status['isautomatic']); 175 $this->assertTrue($status['istrackeduser']); 176 $this->assertTrue($status['uservisible']); 177 $details = $status['details']; 178 $this->assertCount(0, $details); 179 } else if ($status['cmid'] == $forumautocompletion->cmid) { 180 $activitiesfound++; 181 $this->assertEquals(COMPLETION_INCOMPLETE, $status['state']); 182 $this->assertEquals(COMPLETION_TRACKING_AUTOMATIC, $status['tracking']); 183 $this->assertFalse($status['valueused']); 184 $this->assertTrue($status['hascompletion']); 185 $this->assertTrue($status['isautomatic']); 186 $this->assertTrue($status['istrackeduser']); 187 $this->assertTrue($status['uservisible']); 188 $details = $status['details']; 189 $this->assertCount(1, $details); 190 $this->assertEquals('completionview', $details[0]['rulename']); 191 $this->assertEquals(0, $details[0]['rulevalue']['status']); 192 193 } else if ($status['cmid'] == $assignautocompletion->cmid) { 194 $activitiesfound++; 195 $this->assertEquals(COMPLETION_INCOMPLETE, $status['state']); 196 $this->assertEquals(COMPLETION_TRACKING_AUTOMATIC, $status['tracking']); 197 $this->assertFalse($status['valueused']); 198 $this->assertTrue($status['hascompletion']); 199 $this->assertTrue($status['isautomatic']); 200 $this->assertTrue($status['istrackeduser']); 201 $this->assertTrue($status['uservisible']); 202 $details = $status['details']; 203 $this->assertCount(3, $details); 204 $expecteddetails = [ 205 'completionview', 206 'completionusegrade', 207 'completionpassgrade', 208 ]; 209 foreach ($expecteddetails as $index => $name) { 210 $this->assertEquals($name, $details[$index]['rulename']); 211 $this->assertEquals(0, $details[$index]['rulevalue']['status']); 212 } 213 } else if ($status['cmid'] == $data->cmid and $status['modname'] == 'data' and $status['instance'] == $data->id) { 214 $activitiesfound++; 215 $this->assertEquals(COMPLETION_INCOMPLETE, $status['state']); 216 $this->assertEquals(COMPLETION_TRACKING_MANUAL, $status['tracking']); 217 $this->assertFalse($status['valueused']); 218 $this->assertFalse($status['valueused']); 219 $this->assertTrue($status['hascompletion']); 220 $this->assertFalse($status['isautomatic']); 221 $this->assertTrue($status['istrackeduser']); 222 $this->assertTrue($status['uservisible']); 223 $details = $status['details']; 224 $this->assertCount(0, $details); 225 } 226 } 227 $this->assertEquals(4, $activitiesfound); 228 229 // Teacher should see students status, they are in different groups but the teacher can access all groups. 230 $this->setUser($teacher); 231 $result = core_completion_external::get_activities_completion_status($course->id, $student->id); 232 // We need to execute the return values cleaning process to simulate the web service server. 233 $result = \external_api::clean_returnvalue( 234 core_completion_external::get_activities_completion_status_returns(), $result); 235 236 $this->assertCount($numberofcompletions, $result['statuses']); 237 238 // Override status by teacher. 239 $completion->update_state($cmforum, COMPLETION_INCOMPLETE, $student->id, true); 240 241 $result = core_completion_external::get_activities_completion_status($course->id, $student->id); 242 // We need to execute the return values cleaning process to simulate the web service server. 243 $result = \external_api::clean_returnvalue( 244 core_completion_external::get_activities_completion_status_returns(), $result); 245 246 // Check forum has been overriden by the teacher. 247 foreach ($result['statuses'] as $status) { 248 if ($status['cmid'] == $forum->cmid) { 249 $this->assertEquals(COMPLETION_INCOMPLETE, $status['state']); 250 $this->assertEquals(COMPLETION_TRACKING_MANUAL, $status['tracking']); 251 $this->assertEquals($teacher->id, $status['overrideby']); 252 break; 253 } 254 } 255 256 // Teacher should see his own completion status. 257 258 // Forum complete for teacher. 259 $completion = new \completion_info($course); 260 $completion->update_state($cmforum, COMPLETION_COMPLETE); 261 262 $result = core_completion_external::get_activities_completion_status($course->id, $teacher->id); 263 // We need to execute the return values cleaning process to simulate the web service server. 264 $result = \external_api::clean_returnvalue( 265 core_completion_external::get_activities_completion_status_returns(), $result); 266 267 $this->assertCount($numberofcompletions, $result['statuses']); 268 269 $activitiesfound = 0; 270 foreach ($result['statuses'] as $status) { 271 if ($status['cmid'] == $forum->cmid and $status['modname'] == 'forum' and $status['instance'] == $forum->id) { 272 $activitiesfound++; 273 $this->assertEquals(COMPLETION_COMPLETE, $status['state']); 274 $this->assertEquals(COMPLETION_TRACKING_MANUAL, $status['tracking']); 275 } else if (in_array($status['cmid'], [$forumautocompletion->cmid, $assignautocompletion->cmid])) { 276 $activitiesfound++; 277 $this->assertEquals(COMPLETION_INCOMPLETE, $status['state']); 278 $this->assertEquals(COMPLETION_TRACKING_AUTOMATIC, $status['tracking']); 279 } else { 280 $activitiesfound++; 281 $this->assertEquals(COMPLETION_INCOMPLETE, $status['state']); 282 $this->assertEquals(COMPLETION_TRACKING_MANUAL, $status['tracking']); 283 } 284 } 285 $this->assertEquals(5, $activitiesfound); 286 287 // Change teacher role capabilities (disable access all groups). 288 $context = \context_course::instance($course->id); 289 assign_capability('moodle/site:accessallgroups', CAP_PROHIBIT, $teacherrole->id, $context); 290 accesslib_clear_all_caches_for_unit_testing(); 291 292 try { 293 $result = core_completion_external::get_activities_completion_status($course->id, $student->id); 294 $this->fail('Exception expected due to groups permissions.'); 295 } catch (\moodle_exception $e) { 296 $this->assertEquals('accessdenied', $e->errorcode); 297 } 298 299 // Now add the teacher in the same group. 300 groups_add_member($group1->id, $teacher->id); 301 $result = core_completion_external::get_activities_completion_status($course->id, $student->id); 302 // We need to execute the return values cleaning process to simulate the web service server. 303 $result = \external_api::clean_returnvalue( 304 core_completion_external::get_activities_completion_status_returns(), $result); 305 $this->assertCount($numberofcompletions, $result['statuses']); 306 } 307 308 /** 309 * Test override_activity_completion_status 310 */ 311 public function test_override_activity_completion_status() { 312 global $DB, $CFG; 313 $this->resetAfterTest(true); 314 315 // Create course with teacher and student enrolled. 316 $CFG->enablecompletion = true; 317 $course = $this->getDataGenerator()->create_course(['enablecompletion' => 1]); 318 $student = $this->getDataGenerator()->create_user(); 319 $teacher = $this->getDataGenerator()->create_user(); 320 $studentrole = $DB->get_record('role', ['shortname' => 'student']); 321 $this->getDataGenerator()->enrol_user($student->id, $course->id, $studentrole->id); 322 $teacherrole = $DB->get_record('role', ['shortname' => 'teacher']); 323 $this->getDataGenerator()->enrol_user($teacher->id, $course->id, $teacherrole->id); 324 325 // Create 2 activities, one with manual completion (data), one with automatic completion triggered by viewing it (forum). 326 $data = $this->getDataGenerator()->create_module('data', ['course' => $course->id], ['completion' => 1]); 327 $forum = $this->getDataGenerator()->create_module('forum', ['course' => $course->id], 328 ['completion' => 2, 'completionview' => 1]); 329 $cmdata = get_coursemodule_from_id('data', $data->cmid); 330 $cmforum = get_coursemodule_from_id('forum', $forum->cmid); 331 332 // Manually complete the data activity as the student. 333 $this->setUser($student); 334 $completion = new \completion_info($course); 335 $completion->update_state($cmdata, COMPLETION_COMPLETE); 336 337 // Test overriding the status of the manual-completion-activity 'incomplete'. 338 $this->setUser($teacher); 339 $result = core_completion_external::override_activity_completion_status($student->id, $data->cmid, COMPLETION_INCOMPLETE); 340 $result = \external_api::clean_returnvalue(core_completion_external::override_activity_completion_status_returns(), $result); 341 $this->assertEquals($result['state'], COMPLETION_INCOMPLETE); 342 $completiondata = $completion->get_data($cmdata, false, $student->id); 343 $this->assertEquals(COMPLETION_INCOMPLETE, $completiondata->completionstate); 344 345 // Test overriding the status of the manual-completion-activity back to 'complete'. 346 $result = core_completion_external::override_activity_completion_status($student->id, $data->cmid, COMPLETION_COMPLETE); 347 $result = \external_api::clean_returnvalue(core_completion_external::override_activity_completion_status_returns(), $result); 348 $this->assertEquals($result['state'], COMPLETION_COMPLETE); 349 $completiondata = $completion->get_data($cmdata, false, $student->id); 350 $this->assertEquals(COMPLETION_COMPLETE, $completiondata->completionstate); 351 352 // Test overriding the status of the auto-completion-activity to 'complete'. 353 $result = core_completion_external::override_activity_completion_status($student->id, $forum->cmid, COMPLETION_COMPLETE); 354 $result = \external_api::clean_returnvalue(core_completion_external::override_activity_completion_status_returns(), $result); 355 $this->assertEquals($result['state'], COMPLETION_COMPLETE); 356 $completionforum = $completion->get_data($cmforum, false, $student->id); 357 $this->assertEquals(COMPLETION_COMPLETE, $completionforum->completionstate); 358 359 // Test overriding the status of the auto-completion-activity to 'incomplete'. 360 $result = core_completion_external::override_activity_completion_status($student->id, $forum->cmid, COMPLETION_INCOMPLETE); 361 $result = \external_api::clean_returnvalue(core_completion_external::override_activity_completion_status_returns(), $result); 362 $this->assertEquals($result['state'], COMPLETION_INCOMPLETE); 363 $completionforum = $completion->get_data($cmforum, false, $student->id); 364 $this->assertEquals(COMPLETION_INCOMPLETE, $completionforum->completionstate); 365 366 // Test overriding the status of the auto-completion-activity to an invalid state. 367 $this->expectException('moodle_exception'); 368 core_completion_external::override_activity_completion_status($student->id, $forum->cmid, 3); 369 } 370 371 /** 372 * Test overriding the activity completion status as a user without the capability to do so. 373 */ 374 public function test_override_status_user_without_capability() { 375 global $DB, $CFG; 376 $this->resetAfterTest(true); 377 378 // Create course with teacher and student enrolled. 379 $CFG->enablecompletion = true; 380 $course = $this->getDataGenerator()->create_course(['enablecompletion' => 1]); 381 $student = $this->getDataGenerator()->create_user(); 382 $teacher = $this->getDataGenerator()->create_user(); 383 $studentrole = $DB->get_record('role', ['shortname' => 'student']); 384 $this->getDataGenerator()->enrol_user($student->id, $course->id, $studentrole->id); 385 $teacherrole = $DB->get_record('role', ['shortname' => 'teacher']); 386 $this->getDataGenerator()->enrol_user($teacher->id, $course->id, $teacherrole->id); 387 $coursecontext = \context_course::instance($course->id); 388 389 // Create an activity with automatic completion (a forum). 390 $forum = $this->getDataGenerator()->create_module('forum', ['course' => $course->id], 391 ['completion' => 2, 'completionview' => 1]); 392 393 // Test overriding the status of the activity for a user without the capability. 394 $this->setUser($teacher); 395 assign_capability('moodle/course:overridecompletion', CAP_PREVENT, $teacherrole->id, $coursecontext); 396 $this->expectException('required_capability_exception'); 397 core_completion_external::override_activity_completion_status($student->id, $forum->cmid, COMPLETION_COMPLETE); 398 } 399 400 /** 401 * Test get_course_completion_status 402 */ 403 public function test_get_course_completion_status() { 404 global $DB, $CFG, $COMPLETION_CRITERIA_TYPES; 405 require_once($CFG->dirroot.'/completion/criteria/completion_criteria_self.php'); 406 require_once($CFG->dirroot.'/completion/criteria/completion_criteria_date.php'); 407 require_once($CFG->dirroot.'/completion/criteria/completion_criteria_unenrol.php'); 408 require_once($CFG->dirroot.'/completion/criteria/completion_criteria_activity.php'); 409 require_once($CFG->dirroot.'/completion/criteria/completion_criteria_duration.php'); 410 require_once($CFG->dirroot.'/completion/criteria/completion_criteria_grade.php'); 411 require_once($CFG->dirroot.'/completion/criteria/completion_criteria_role.php'); 412 require_once($CFG->dirroot.'/completion/criteria/completion_criteria_course.php'); 413 414 $this->resetAfterTest(true); 415 416 $CFG->enablecompletion = true; 417 $student = $this->getDataGenerator()->create_user(); 418 $teacher = $this->getDataGenerator()->create_user(); 419 420 $course = $this->getDataGenerator()->create_course(array('enablecompletion' => 1, 421 'groupmode' => SEPARATEGROUPS, 422 'groupmodeforce' => 1)); 423 424 $data = $this->getDataGenerator()->create_module('data', array('course' => $course->id), 425 array('completion' => 1)); 426 $forum = $this->getDataGenerator()->create_module('forum', array('course' => $course->id), 427 array('completion' => 1)); 428 $assign = $this->getDataGenerator()->create_module('assign', array('course' => $course->id)); 429 430 $cmdata = get_coursemodule_from_id('data', $data->cmid); 431 $cmforum = get_coursemodule_from_id('forum', $forum->cmid); 432 433 $studentrole = $DB->get_record('role', array('shortname' => 'student')); 434 $teacherrole = $DB->get_record('role', array('shortname' => 'editingteacher')); 435 $this->getDataGenerator()->enrol_user($student->id, $course->id, $studentrole->id); 436 $this->getDataGenerator()->enrol_user($teacher->id, $course->id, $teacherrole->id); 437 438 $group1 = $this->getDataGenerator()->create_group(array('courseid' => $course->id)); 439 $group2 = $this->getDataGenerator()->create_group(array('courseid' => $course->id)); 440 // Teacher and student in different groups initially. 441 groups_add_member($group1->id, $student->id); 442 groups_add_member($group2->id, $teacher->id); 443 444 // Set completion rules. 445 $completion = new \completion_info($course); 446 447 // Loop through each criteria type and run its update_config() method. 448 449 $criteriadata = new \stdClass(); 450 $criteriadata->id = $course->id; 451 $criteriadata->criteria_activity = array(); 452 // Some activities. 453 $criteriadata->criteria_activity[$cmdata->id] = 1; 454 $criteriadata->criteria_activity[$cmforum->id] = 1; 455 456 // In a week criteria date value. 457 $criteriadata->criteria_date_value = time() + WEEKSECS; 458 459 // Self completion. 460 $criteriadata->criteria_self = 1; 461 462 foreach ($COMPLETION_CRITERIA_TYPES as $type) { 463 $class = 'completion_criteria_'.$type; 464 $criterion = new $class(); 465 $criterion->update_config($criteriadata); 466 } 467 468 // Handle overall aggregation. 469 $aggdata = array( 470 'course' => $course->id, 471 'criteriatype' => null 472 ); 473 $aggregation = new \completion_aggregation($aggdata); 474 $aggregation->setMethod(COMPLETION_AGGREGATION_ALL); 475 $aggregation->save(); 476 477 $aggdata['criteriatype'] = COMPLETION_CRITERIA_TYPE_ACTIVITY; 478 $aggregation = new \completion_aggregation($aggdata); 479 $aggregation->setMethod(COMPLETION_AGGREGATION_ALL); 480 $aggregation->save(); 481 482 $this->setUser($student); 483 484 $result = core_completion_external::get_course_completion_status($course->id, $student->id); 485 // We need to execute the return values cleaning process to simulate the web service server. 486 $studentresult = \external_api::clean_returnvalue( 487 core_completion_external::get_course_completion_status_returns(), $result); 488 489 // 3 different criteria. 490 $this->assertCount(3, $studentresult['completionstatus']['completions']); 491 492 $this->assertEquals(COMPLETION_AGGREGATION_ALL, $studentresult['completionstatus']['aggregation']); 493 $this->assertFalse($studentresult['completionstatus']['completed']); 494 495 $this->assertEquals('No', $studentresult['completionstatus']['completions'][0]['status']); 496 $this->assertEquals('No', $studentresult['completionstatus']['completions'][1]['status']); 497 $this->assertEquals('No', $studentresult['completionstatus']['completions'][2]['status']); 498 499 // Teacher should see students status, they are in different groups but the teacher can access all groups. 500 $this->setUser($teacher); 501 $result = core_completion_external::get_course_completion_status($course->id, $student->id); 502 // We need to execute the return values cleaning process to simulate the web service server. 503 $teacherresult = \external_api::clean_returnvalue( 504 core_completion_external::get_course_completion_status_returns(), $result); 505 506 $this->assertEquals($studentresult, $teacherresult); 507 508 // Change teacher role capabilities (disable access al goups). 509 $context = \context_course::instance($course->id); 510 assign_capability('moodle/site:accessallgroups', CAP_PROHIBIT, $teacherrole->id, $context); 511 accesslib_clear_all_caches_for_unit_testing(); 512 513 try { 514 $result = core_completion_external::get_course_completion_status($course->id, $student->id); 515 $this->fail('Exception expected due to groups permissions.'); 516 } catch (\moodle_exception $e) { 517 $this->assertEquals('accessdenied', $e->errorcode); 518 } 519 520 // Now add the teacher in the same group. 521 groups_add_member($group1->id, $teacher->id); 522 $result = core_completion_external::get_course_completion_status($course->id, $student->id); 523 // We need to execute the return values cleaning process to simulate the web service server. 524 $teacherresult = \external_api::clean_returnvalue( 525 core_completion_external::get_course_completion_status_returns(), $result); 526 527 $this->assertEquals($studentresult, $teacherresult); 528 529 } 530 531 /** 532 * Test mark_course_self_completed 533 */ 534 public function test_mark_course_self_completed() { 535 global $DB, $CFG; 536 require_once($CFG->dirroot.'/completion/criteria/completion_criteria_self.php'); 537 538 $this->resetAfterTest(true); 539 540 $CFG->enablecompletion = true; 541 $student = $this->getDataGenerator()->create_user(); 542 $teacher = $this->getDataGenerator()->create_user(); 543 544 $course = $this->getDataGenerator()->create_course(array('enablecompletion' => 1)); 545 546 $studentrole = $DB->get_record('role', array('shortname' => 'student')); 547 $this->getDataGenerator()->enrol_user($student->id, $course->id, $studentrole->id); 548 549 // Set completion rules. 550 $completion = new \completion_info($course); 551 552 $criteriadata = new \stdClass(); 553 $criteriadata->id = $course->id; 554 $criteriadata->criteria_activity = array(); 555 556 // Self completion. 557 $criteriadata->criteria_self = COMPLETION_CRITERIA_TYPE_SELF; 558 $class = 'completion_criteria_self'; 559 $criterion = new $class(); 560 $criterion->update_config($criteriadata); 561 562 // Handle overall aggregation. 563 $aggdata = array( 564 'course' => $course->id, 565 'criteriatype' => null 566 ); 567 $aggregation = new \completion_aggregation($aggdata); 568 $aggregation->setMethod(COMPLETION_AGGREGATION_ALL); 569 $aggregation->save(); 570 571 $this->setUser($student); 572 573 $result = core_completion_external::mark_course_self_completed($course->id); 574 // We need to execute the return values cleaning process to simulate the web service server. 575 $result = \external_api::clean_returnvalue( 576 core_completion_external::mark_course_self_completed_returns(), $result); 577 578 // We expect a valid result. 579 $this->assertEquals(true, $result['status']); 580 581 $result = core_completion_external::get_course_completion_status($course->id, $student->id); 582 // We need to execute the return values cleaning process to simulate the web service server. 583 $result = \external_api::clean_returnvalue( 584 core_completion_external::get_course_completion_status_returns(), $result); 585 586 // Course must be completed. 587 $this->assertEquals(COMPLETION_COMPLETE, $result['completionstatus']['completions'][0]['complete']); 588 589 try { 590 $result = core_completion_external::mark_course_self_completed($course->id); 591 $this->fail('Exception expected due course already self completed.'); 592 } catch (\moodle_exception $e) { 593 $this->assertEquals('useralreadymarkedcomplete', $e->errorcode); 594 } 595 596 } 597 598 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body