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