See Release Notes
Long Term Support Release
Differences Between: [Versions 311 and 401] [Versions 400 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 /** 18 * Workshop module external functions tests 19 * 20 * @package mod_workshop 21 * @category external 22 * @copyright 2017 Juan Leyva <juan@moodle.com> 23 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 24 * @since Moodle 3.4 25 */ 26 27 namespace mod_workshop\external; 28 29 use externallib_advanced_testcase; 30 use workshop; 31 use mod_workshop_external; 32 use mod_workshop\external\workshop_summary_exporter; 33 use mod_workshop\external\submission_exporter; 34 35 defined('MOODLE_INTERNAL') || die(); 36 37 global $CFG; 38 39 require_once($CFG->dirroot . '/webservice/tests/helpers.php'); 40 require_once($CFG->dirroot . '/mod/workshop/lib.php'); 41 42 /** 43 * Workshop module external functions tests 44 * 45 * @package mod_workshop 46 * @category external 47 * @copyright 2017 Juan Leyva <juan@moodle.com> 48 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 49 * @since Moodle 3.4 50 */ 51 class external_test extends externallib_advanced_testcase { 52 53 /** @var stdClass course object */ 54 private $course; 55 /** @var stdClass workshop object */ 56 private $workshop; 57 /** @var stdClass context object */ 58 private $context; 59 /** @var stdClass cm object */ 60 private $cm; 61 /** @var stdClass student object */ 62 private $student; 63 /** @var stdClass teacher object */ 64 private $teacher; 65 /** @var stdClass student role object */ 66 private $studentrole; 67 /** @var stdClass teacher role object */ 68 private $teacherrole; 69 70 /** 71 * Set up for every test 72 */ 73 public function setUp(): void { 74 global $DB; 75 $this->resetAfterTest(); 76 $this->setAdminUser(); 77 78 // Setup test data. 79 $course = new \stdClass(); 80 $course->groupmode = SEPARATEGROUPS; 81 $course->groupmodeforce = true; 82 $this->course = $this->getDataGenerator()->create_course($course); 83 $this->workshop = $this->getDataGenerator()->create_module('workshop', 84 array( 85 'course' => $this->course->id, 86 'overallfeedbackfiles' => 1, 87 ) 88 ); 89 $this->context = \context_module::instance($this->workshop->cmid); 90 $this->cm = get_coursemodule_from_instance('workshop', $this->workshop->id); 91 92 // Add grading strategy data (accumulative is the default). 93 $workshop = new workshop($this->workshop, $this->cm, $this->course); 94 $strategy = $workshop->grading_strategy_instance(); 95 $data = array(); 96 for ($i = 0; $i < 4; $i++) { 97 $data['dimensionid__idx_'.$i] = 0; 98 $data['description__idx_'.$i.'_editor'] = array('text' => "Content $i", 'format' => FORMAT_MOODLE); 99 $data['grade__idx_'.$i] = 25; 100 $data['weight__idx_'.$i] = 25; 101 } 102 $data['workshopid'] = $workshop->id; 103 $data['norepeats'] = 4; 104 $strategy->save_edit_strategy_form((object) $data); 105 106 // Create users. 107 $this->student = self::getDataGenerator()->create_user(); 108 $this->anotherstudentg1 = self::getDataGenerator()->create_user(); 109 $this->anotherstudentg2 = self::getDataGenerator()->create_user(); 110 $this->teacher = self::getDataGenerator()->create_user(); 111 112 // Users enrolments. 113 $this->studentrole = $DB->get_record('role', array('shortname' => 'student')); 114 $this->teacherrole = $DB->get_record('role', array('shortname' => 'editingteacher')); 115 $this->getDataGenerator()->enrol_user($this->student->id, $this->course->id, $this->studentrole->id, 'manual'); 116 $this->getDataGenerator()->enrol_user($this->anotherstudentg1->id, $this->course->id, $this->studentrole->id, 'manual'); 117 $this->getDataGenerator()->enrol_user($this->anotherstudentg2->id, $this->course->id, $this->studentrole->id, 'manual'); 118 $this->getDataGenerator()->enrol_user($this->teacher->id, $this->course->id, $this->teacherrole->id, 'manual'); 119 120 $this->group1 = $this->getDataGenerator()->create_group(array('courseid' => $this->course->id)); 121 $this->group2 = $this->getDataGenerator()->create_group(array('courseid' => $this->course->id)); 122 groups_add_member($this->group1, $this->student); 123 groups_add_member($this->group1, $this->anotherstudentg1); 124 groups_add_member($this->group2, $this->anotherstudentg2); 125 } 126 127 /** 128 * Test test_mod_workshop_get_workshops_by_courses 129 */ 130 public function test_mod_workshop_get_workshops_by_courses() { 131 132 // Create additional course. 133 $course2 = self::getDataGenerator()->create_course(); 134 135 // Second workshop. 136 $record = new \stdClass(); 137 $record->course = $course2->id; 138 $workshop2 = self::getDataGenerator()->create_module('workshop', $record); 139 140 // Execute real Moodle enrolment as we'll call unenrol() method on the instance later. 141 $enrol = enrol_get_plugin('manual'); 142 $enrolinstances = enrol_get_instances($course2->id, true); 143 foreach ($enrolinstances as $courseenrolinstance) { 144 if ($courseenrolinstance->enrol == "manual") { 145 $instance2 = $courseenrolinstance; 146 break; 147 } 148 } 149 $enrol->enrol_user($instance2, $this->student->id, $this->studentrole->id); 150 151 self::setUser($this->student); 152 153 $returndescription = mod_workshop_external::get_workshops_by_courses_returns(); 154 155 // Create what we expect to be returned when querying the two courses. 156 $properties = workshop_summary_exporter::read_properties_definition(); 157 $expectedfields = array_keys($properties); 158 159 // Add expected coursemodule and data. 160 $workshop1 = $this->workshop; 161 $workshop1->coursemodule = $workshop1->cmid; 162 $workshop1->introformat = 1; 163 $workshop1->introfiles = []; 164 $workshop1->lang = ''; 165 $workshop1->instructauthorsfiles = []; 166 $workshop1->instructauthorsformat = 1; 167 $workshop1->instructreviewersfiles = []; 168 $workshop1->instructreviewersformat = 1; 169 $workshop1->conclusionfiles = []; 170 $workshop1->conclusionformat = 1; 171 $workshop1->submissiontypetext = 1; 172 $workshop1->submissiontypefile = 1; 173 174 $workshop2->coursemodule = $workshop2->cmid; 175 $workshop2->introformat = 1; 176 $workshop2->introfiles = []; 177 $workshop2->lang = ''; 178 $workshop2->instructauthorsfiles = []; 179 $workshop2->instructauthorsformat = 1; 180 $workshop2->instructreviewersfiles = []; 181 $workshop2->instructreviewersformat = 1; 182 $workshop2->conclusionfiles = []; 183 $workshop2->conclusionformat = 1; 184 $workshop2->submissiontypetext = 1; 185 $workshop2->submissiontypefile = 1; 186 187 foreach ($expectedfields as $field) { 188 if (!empty($properties[$field]) && $properties[$field]['type'] == PARAM_BOOL) { 189 $workshop1->{$field} = (bool) $workshop1->{$field}; 190 $workshop2->{$field} = (bool) $workshop2->{$field}; 191 } 192 $expected1[$field] = $workshop1->{$field}; 193 $expected2[$field] = $workshop2->{$field}; 194 } 195 196 $expectedworkshops = array($expected2, $expected1); 197 198 // Call the external function passing course ids. 199 $result = mod_workshop_external::get_workshops_by_courses(array($course2->id, $this->course->id)); 200 $result = \external_api::clean_returnvalue($returndescription, $result); 201 202 $this->assertEquals($expectedworkshops, $result['workshops']); 203 $this->assertCount(0, $result['warnings']); 204 205 // Call the external function without passing course id. 206 $result = mod_workshop_external::get_workshops_by_courses(); 207 $result = \external_api::clean_returnvalue($returndescription, $result); 208 $this->assertEquals($expectedworkshops, $result['workshops']); 209 $this->assertCount(0, $result['warnings']); 210 211 // Unenrol user from second course and alter expected workshops. 212 $enrol->unenrol_user($instance2, $this->student->id); 213 array_shift($expectedworkshops); 214 215 // Call the external function without passing course id. 216 $result = mod_workshop_external::get_workshops_by_courses(); 217 $result = \external_api::clean_returnvalue($returndescription, $result); 218 $this->assertEquals($expectedworkshops, $result['workshops']); 219 220 // Call for the second course we unenrolled the user from, expected warning. 221 $result = mod_workshop_external::get_workshops_by_courses(array($course2->id)); 222 $this->assertCount(1, $result['warnings']); 223 $this->assertEquals('1', $result['warnings'][0]['warningcode']); 224 $this->assertEquals($course2->id, $result['warnings'][0]['itemid']); 225 } 226 227 /** 228 * Test mod_workshop_get_workshop_access_information for students. 229 */ 230 public function test_mod_workshop_get_workshop_access_information_student() { 231 232 self::setUser($this->student); 233 $result = mod_workshop_external::get_workshop_access_information($this->workshop->id); 234 $result = \external_api::clean_returnvalue(mod_workshop_external::get_workshop_access_information_returns(), $result); 235 // Check default values for capabilities. 236 $enabledcaps = array('canpeerassess', 'cansubmit', 'canview', 'canviewauthornames', 'canviewauthorpublished', 237 'canviewpublishedsubmissions', 'canexportsubmissions'); 238 239 foreach ($result as $capname => $capvalue) { 240 if (strpos($capname, 'can') !== 0) { 241 continue; 242 } 243 if (in_array($capname, $enabledcaps)) { 244 $this->assertTrue($capvalue); 245 } else { 246 $this->assertFalse($capvalue); 247 } 248 } 249 // Now, unassign some capabilities. 250 unassign_capability('mod/workshop:peerassess', $this->studentrole->id); 251 unassign_capability('mod/workshop:submit', $this->studentrole->id); 252 unset($enabledcaps[0]); 253 unset($enabledcaps[1]); 254 accesslib_clear_all_caches_for_unit_testing(); 255 256 $result = mod_workshop_external::get_workshop_access_information($this->workshop->id); 257 $result = \external_api::clean_returnvalue(mod_workshop_external::get_workshop_access_information_returns(), $result); 258 foreach ($result as $capname => $capvalue) { 259 if (strpos($capname, 'can') !== 0) { 260 continue; 261 } 262 if (in_array($capname, $enabledcaps)) { 263 $this->assertTrue($capvalue); 264 } else { 265 $this->assertFalse($capvalue); 266 } 267 } 268 269 // Now, specific functionalities. 270 $this->assertFalse($result['creatingsubmissionallowed']); 271 $this->assertFalse($result['modifyingsubmissionallowed']); 272 $this->assertFalse($result['assessingallowed']); 273 $this->assertFalse($result['assessingexamplesallowed']); 274 $this->assertTrue($result['examplesassessedbeforesubmission']); 275 $this->assertTrue($result['examplesassessedbeforeassessment']); 276 277 // Switch phase. 278 $workshop = new workshop($this->workshop, $this->cm, $this->course); 279 $workshop->switch_phase(workshop::PHASE_SUBMISSION); 280 $result = mod_workshop_external::get_workshop_access_information($this->workshop->id); 281 $result = \external_api::clean_returnvalue(mod_workshop_external::get_workshop_access_information_returns(), $result); 282 283 $this->assertTrue($result['creatingsubmissionallowed']); 284 $this->assertTrue($result['modifyingsubmissionallowed']); 285 $this->assertFalse($result['assessingallowed']); 286 $this->assertFalse($result['assessingexamplesallowed']); 287 $this->assertTrue($result['examplesassessedbeforesubmission']); 288 $this->assertTrue($result['examplesassessedbeforeassessment']); 289 290 // Switch to next (to assessment). 291 $workshop->switch_phase(workshop::PHASE_ASSESSMENT); 292 $result = mod_workshop_external::get_workshop_access_information($this->workshop->id); 293 $result = \external_api::clean_returnvalue(mod_workshop_external::get_workshop_access_information_returns(), $result); 294 295 $this->assertFalse($result['creatingsubmissionallowed']); 296 $this->assertFalse($result['modifyingsubmissionallowed']); 297 $this->assertTrue($result['assessingallowed']); 298 $this->assertFalse($result['assessingexamplesallowed']); 299 $this->assertTrue($result['examplesassessedbeforesubmission']); 300 $this->assertTrue($result['examplesassessedbeforeassessment']); 301 } 302 303 /** 304 * Test mod_workshop_get_workshop_access_information for teachers. 305 */ 306 public function test_mod_workshop_get_workshop_access_information_teacher() { 307 308 self::setUser($this->teacher); 309 $result = mod_workshop_external::get_workshop_access_information($this->workshop->id); 310 $result = \external_api::clean_returnvalue(mod_workshop_external::get_workshop_access_information_returns(), $result); 311 // Check default values. 312 $disabledcaps = array('canpeerassess', 'cansubmit'); 313 314 foreach ($result as $capname => $capvalue) { 315 if (strpos($capname, 'can') !== 0) { 316 continue; 317 } 318 if (in_array($capname, $disabledcaps)) { 319 $this->assertFalse($capvalue); 320 } else { 321 $this->assertTrue($capvalue); 322 } 323 } 324 325 // Now, specific functionalities. 326 $this->assertFalse($result['creatingsubmissionallowed']); 327 $this->assertFalse($result['modifyingsubmissionallowed']); 328 $this->assertFalse($result['assessingallowed']); 329 $this->assertFalse($result['assessingexamplesallowed']); 330 } 331 332 /** 333 * Test mod_workshop_get_user_plan for students. 334 */ 335 public function test_mod_workshop_get_user_plan_student() { 336 337 self::setUser($this->student); 338 $result = mod_workshop_external::get_user_plan($this->workshop->id); 339 $result = \external_api::clean_returnvalue(mod_workshop_external::get_user_plan_returns(), $result); 340 341 $this->assertCount(0, $result['userplan']['examples']); // No examples given. 342 $this->assertCount(5, $result['userplan']['phases']); // Always 5 phases. 343 $this->assertEquals(workshop::PHASE_SETUP, $result['userplan']['phases'][0]['code']); // First phase always setup. 344 $this->assertTrue($result['userplan']['phases'][0]['active']); // First phase "Setup" active in new workshops. 345 346 // Switch phase. 347 $workshop = new workshop($this->workshop, $this->cm, $this->course); 348 $workshop->switch_phase(workshop::PHASE_SUBMISSION); 349 350 $result = mod_workshop_external::get_user_plan($this->workshop->id); 351 $result = \external_api::clean_returnvalue(mod_workshop_external::get_user_plan_returns(), $result); 352 353 $this->assertEquals(workshop::PHASE_SUBMISSION, $result['userplan']['phases'][1]['code']); 354 $this->assertTrue($result['userplan']['phases'][1]['active']); // We are now in submission phase. 355 } 356 357 /** 358 * Test mod_workshop_get_user_plan for teachers. 359 */ 360 public function test_mod_workshop_get_user_plan_teacher() { 361 362 self::setUser($this->teacher); 363 $result = mod_workshop_external::get_user_plan($this->workshop->id); 364 $result = \external_api::clean_returnvalue(mod_workshop_external::get_user_plan_returns(), $result); 365 366 $this->assertCount(0, $result['userplan']['examples']); // No examples given. 367 $this->assertCount(5, $result['userplan']['phases']); // Always 5 phases. 368 $this->assertEquals(workshop::PHASE_SETUP, $result['userplan']['phases'][0]['code']); // First phase always setup. 369 $this->assertTrue($result['userplan']['phases'][0]['active']); // First phase "Setup" active in new workshops. 370 $this->assertCount(4, $result['userplan']['phases'][0]['tasks']); // For new empty workshops, always 4 tasks. 371 372 foreach ($result['userplan']['phases'][0]['tasks'] as $task) { 373 if ($task['code'] == 'intro' || $task['code'] == 'instructauthors' || $task['code'] == 'editform') { 374 $this->assertEquals(1, $task['completed']); 375 } else { 376 $this->assertEmpty($task['completed']); 377 } 378 } 379 380 // Do some of the tasks asked - switch phase. 381 $workshop = new workshop($this->workshop, $this->cm, $this->course); 382 $workshop->switch_phase(workshop::PHASE_SUBMISSION); 383 384 $result = mod_workshop_external::get_user_plan($this->workshop->id); 385 $result = \external_api::clean_returnvalue(mod_workshop_external::get_user_plan_returns(), $result); 386 foreach ($result['userplan']['phases'][0]['tasks'] as $task) { 387 if ($task['code'] == 'intro' || $task['code'] == 'instructauthors' || $task['code'] == 'editform' || 388 $task['code'] == 'switchtonextphase') { 389 $this->assertEquals(1, $task['completed']); 390 } else { 391 $this->assertEmpty($task['completed']); 392 } 393 } 394 395 $result = mod_workshop_external::get_user_plan($this->workshop->id); 396 $result = \external_api::clean_returnvalue(mod_workshop_external::get_user_plan_returns(), $result); 397 398 $this->assertEquals(workshop::PHASE_SUBMISSION, $result['userplan']['phases'][1]['code']); 399 $this->assertTrue($result['userplan']['phases'][1]['active']); // We are now in submission phase. 400 } 401 402 /** 403 * Test test_view_workshop invalid id. 404 */ 405 public function test_view_workshop_invalid_id() { 406 $this->expectException('moodle_exception'); 407 mod_workshop_external::view_workshop(0); 408 } 409 410 /** 411 * Test test_view_workshop user not enrolled. 412 */ 413 public function test_view_workshop_user_not_enrolled() { 414 // Test not-enrolled user. 415 $usernotenrolled = self::getDataGenerator()->create_user(); 416 $this->setUser($usernotenrolled); 417 $this->expectException('moodle_exception'); 418 mod_workshop_external::view_workshop($this->workshop->id); 419 } 420 421 /** 422 * Test test_view_workshop user student. 423 */ 424 public function test_view_workshop_user_student() { 425 // Test user with full capabilities. 426 $this->setUser($this->student); 427 428 // Trigger and capture the event. 429 $sink = $this->redirectEvents(); 430 431 $result = mod_workshop_external::view_workshop($this->workshop->id); 432 $result = \external_api::clean_returnvalue(mod_workshop_external::view_workshop_returns(), $result); 433 $this->assertTrue($result['status']); 434 435 $events = $sink->get_events(); 436 $this->assertCount(1, $events); 437 $event = array_shift($events); 438 439 // Checking that the event contains the expected values. 440 $this->assertInstanceOf('\mod_workshop\event\course_module_viewed', $event); 441 $this->assertEquals($this->context, $event->get_context()); 442 $moodleworkshop = new \moodle_url('/mod/workshop/view.php', array('id' => $this->cm->id)); 443 $this->assertEquals($moodleworkshop, $event->get_url()); 444 $this->assertEventContextNotUsed($event); 445 $this->assertNotEmpty($event->get_name()); 446 } 447 448 /** 449 * Test test_view_workshop user missing capabilities. 450 */ 451 public function test_view_workshop_user_missing_capabilities() { 452 // Test user with no capabilities. 453 // We need a explicit prohibit since this capability is only defined in authenticated user and guest roles. 454 assign_capability('mod/workshop:view', CAP_PROHIBIT, $this->studentrole->id, $this->context->id); 455 // Empty all the caches that may be affected by this change. 456 accesslib_clear_all_caches_for_unit_testing(); 457 \course_modinfo::clear_instance_cache(); 458 459 $this->setUser($this->student); 460 $this->expectException('moodle_exception'); 461 mod_workshop_external::view_workshop($this->workshop->id); 462 } 463 464 /** 465 * Test test_add_submission. 466 */ 467 public function test_add_submission() { 468 $fs = get_file_storage(); 469 470 // Test user with full capabilities. 471 $this->setUser($this->student); 472 473 $title = 'Submission title'; 474 $content = 'Submission contents'; 475 476 // Create a file in a draft area for inline attachments. 477 $draftidinlineattach = file_get_unused_draft_itemid(); 478 $usercontext = \context_user::instance($this->student->id); 479 $filenameimg = 'shouldbeanimage.txt'; 480 $filerecordinline = array( 481 'contextid' => $usercontext->id, 482 'component' => 'user', 483 'filearea' => 'draft', 484 'itemid' => $draftidinlineattach, 485 'filepath' => '/', 486 'filename' => $filenameimg, 487 ); 488 $fs->create_file_from_string($filerecordinline, 'image contents (not really)'); 489 490 // Create a file in a draft area for regular attachments. 491 $draftidattach = file_get_unused_draft_itemid(); 492 $filerecordattach = $filerecordinline; 493 $attachfilename = 'attachment.txt'; 494 $filerecordattach['filename'] = $attachfilename; 495 $filerecordattach['itemid'] = $draftidattach; 496 $fs->create_file_from_string($filerecordattach, 'simple text attachment'); 497 498 // Switch to submission phase. 499 $workshop = new workshop($this->workshop, $this->cm, $this->course); 500 $workshop->switch_phase(workshop::PHASE_SUBMISSION); 501 502 $result = mod_workshop_external::add_submission($this->workshop->id, $title, $content, FORMAT_MOODLE, $draftidinlineattach, 503 $draftidattach); 504 $result = \external_api::clean_returnvalue(mod_workshop_external::add_submission_returns(), $result); 505 $this->assertEmpty($result['warnings']); 506 507 // Check submission created. 508 $submission = $workshop->get_submission_by_author($this->student->id); 509 $this->assertTrue($result['status']); 510 $this->assertEquals($result['submissionid'], $submission->id); 511 $this->assertEquals($title, $submission->title); 512 $this->assertEquals($content, $submission->content); 513 514 // Check files. 515 $contentfiles = $fs->get_area_files($this->context->id, 'mod_workshop', 'submission_content', $submission->id); 516 $this->assertCount(2, $contentfiles); 517 foreach ($contentfiles as $file) { 518 if ($file->is_directory()) { 519 continue; 520 } else { 521 $this->assertEquals($filenameimg, $file->get_filename()); 522 } 523 } 524 $contentfiles = $fs->get_area_files($this->context->id, 'mod_workshop', 'submission_attachment', $submission->id); 525 $this->assertCount(2, $contentfiles); 526 foreach ($contentfiles as $file) { 527 if ($file->is_directory()) { 528 continue; 529 } else { 530 $this->assertEquals($attachfilename, $file->get_filename()); 531 } 532 } 533 } 534 535 /** 536 * Test test_add_submission invalid phase. 537 */ 538 public function test_add_submission_invalid_phase() { 539 $this->setUser($this->student); 540 541 $this->expectException('moodle_exception'); 542 mod_workshop_external::add_submission($this->workshop->id, 'Test'); 543 } 544 545 /** 546 * Test test_add_submission empty title. 547 */ 548 public function test_add_submission_empty_title() { 549 $this->setUser($this->student); 550 551 // Switch to submission phase. 552 $workshop = new workshop($this->workshop, $this->cm, $this->course); 553 $workshop->switch_phase(workshop::PHASE_SUBMISSION); 554 555 $this->expectException('moodle_exception'); 556 mod_workshop_external::add_submission($this->workshop->id, ''); 557 } 558 559 /** 560 * Test test_add_submission already added. 561 */ 562 public function test_add_submission_already_added() { 563 $this->setUser($this->student); 564 565 $usercontext = \context_user::instance($this->student->id); 566 $fs = get_file_storage(); 567 $draftidattach = file_get_unused_draft_itemid(); 568 $filerecordattach = [ 569 'contextid' => $usercontext->id, 570 'component' => 'user', 571 'filearea' => 'draft', 572 'itemid' => $draftidattach, 573 'filepath' => '/', 574 'filename' => 'attachement.txt' 575 ]; 576 $fs->create_file_from_string($filerecordattach, 'simple text attachment'); 577 578 // Switch to submission phase. 579 $workshop = new workshop($this->workshop, $this->cm, $this->course); 580 $workshop->switch_phase(workshop::PHASE_SUBMISSION); 581 582 // Create the submission. 583 $result = mod_workshop_external::add_submission($this->workshop->id, 'My submission', '', FORMAT_MOODLE, 0, $draftidattach); 584 $result = \external_api::clean_returnvalue(mod_workshop_external::add_submission_returns(), $result); 585 586 // Try to create it again. 587 $result = mod_workshop_external::add_submission($this->workshop->id, 'My submission', '', FORMAT_MOODLE, 0, $draftidattach); 588 $result = \external_api::clean_returnvalue(mod_workshop_external::add_submission_returns(), $result); 589 $this->assertFalse($result['status']); 590 $this->assertArrayNotHasKey('submissionid', $result); 591 $this->assertCount(1, $result['warnings']); 592 $this->assertEquals('fielderror', $result['warnings'][0]['warningcode']); 593 $this->assertEquals('title', $result['warnings'][0]['item']); 594 } 595 596 /** 597 * Helper method to create a submission for testing for the given user. 598 * 599 * @param int $user the submission will be created by this student. 600 * @return int the submission id 601 */ 602 protected function create_test_submission($user) { 603 // Test user with full capabilities. 604 $this->setUser($user); 605 606 $title = 'Submission title'; 607 $content = 'Submission contents'; 608 609 // Create a file in a draft area for inline attachments. 610 $fs = get_file_storage(); 611 $draftidinlineattach = file_get_unused_draft_itemid(); 612 $usercontext = \context_user::instance($user->id); 613 $filenameimg = 'shouldbeanimage.txt'; 614 $filerecordinline = array( 615 'contextid' => $usercontext->id, 616 'component' => 'user', 617 'filearea' => 'draft', 618 'itemid' => $draftidinlineattach, 619 'filepath' => '/', 620 'filename' => $filenameimg, 621 ); 622 $fs->create_file_from_string($filerecordinline, 'image contents (not really)'); 623 624 // Create a file in a draft area for regular attachments. 625 $draftidattach = file_get_unused_draft_itemid(); 626 $filerecordattach = $filerecordinline; 627 $attachfilename = 'attachment.txt'; 628 $filerecordattach['filename'] = $attachfilename; 629 $filerecordattach['itemid'] = $draftidattach; 630 $fs->create_file_from_string($filerecordattach, 'simple text attachment'); 631 632 // Switch to submission phase. 633 $workshop = new workshop($this->workshop, $this->cm, $this->course); 634 $workshop->switch_phase(workshop::PHASE_SUBMISSION); 635 636 $result = mod_workshop_external::add_submission($this->workshop->id, $title, $content, FORMAT_MOODLE, $draftidinlineattach, 637 $draftidattach); 638 return $result['submissionid']; 639 } 640 641 /** 642 * Test test_update_submission. 643 */ 644 public function test_update_submission() { 645 646 // Create the submission that will be updated. 647 $submissionid = $this->create_test_submission($this->student); 648 649 // Test user with full capabilities. 650 $this->setUser($this->student); 651 652 $title = 'Submission new title'; 653 $content = 'Submission new contents'; 654 655 // Create a different file in a draft area for inline attachments. 656 $fs = get_file_storage(); 657 $draftidinlineattach = file_get_unused_draft_itemid(); 658 $usercontext = \context_user::instance($this->student->id); 659 $filenameimg = 'shouldbeanimage_new.txt'; 660 $filerecordinline = array( 661 'contextid' => $usercontext->id, 662 'component' => 'user', 663 'filearea' => 'draft', 664 'itemid' => $draftidinlineattach, 665 'filepath' => '/', 666 'filename' => $filenameimg, 667 ); 668 $fs->create_file_from_string($filerecordinline, 'image contents (not really)'); 669 670 // Create a different file in a draft area for regular attachments. 671 $draftidattach = file_get_unused_draft_itemid(); 672 $filerecordattach = $filerecordinline; 673 $attachfilename = 'attachment_new.txt'; 674 $filerecordattach['filename'] = $attachfilename; 675 $filerecordattach['itemid'] = $draftidattach; 676 $fs->create_file_from_string($filerecordattach, 'simple text attachment'); 677 678 $result = mod_workshop_external::update_submission($submissionid, $title, $content, FORMAT_MOODLE, $draftidinlineattach, 679 $draftidattach); 680 $result = \external_api::clean_returnvalue(mod_workshop_external::update_submission_returns(), $result); 681 $this->assertEmpty($result['warnings']); 682 683 // Check submission updated. 684 $workshop = new workshop($this->workshop, $this->cm, $this->course); 685 $submission = $workshop->get_submission_by_id($submissionid); 686 $this->assertTrue($result['status']); 687 $this->assertEquals($title, $submission->title); 688 $this->assertEquals($content, $submission->content); 689 690 // Check files. 691 $contentfiles = $fs->get_area_files($this->context->id, 'mod_workshop', 'submission_content', $submission->id); 692 $this->assertCount(2, $contentfiles); 693 foreach ($contentfiles as $file) { 694 if ($file->is_directory()) { 695 continue; 696 } else { 697 $this->assertEquals($filenameimg, $file->get_filename()); 698 } 699 } 700 $contentfiles = $fs->get_area_files($this->context->id, 'mod_workshop', 'submission_attachment', $submission->id); 701 $this->assertCount(2, $contentfiles); 702 foreach ($contentfiles as $file) { 703 if ($file->is_directory()) { 704 continue; 705 } else { 706 $this->assertEquals($attachfilename, $file->get_filename()); 707 } 708 } 709 } 710 711 /** 712 * Test test_update_submission belonging to other user. 713 */ 714 public function test_update_submission_of_other_user() { 715 // Create the submission that will be updated. 716 $submissionid = $this->create_test_submission($this->student); 717 718 $this->setUser($this->teacher); 719 720 $this->expectException('moodle_exception'); 721 mod_workshop_external::update_submission($submissionid, 'Test'); 722 } 723 724 /** 725 * Test test_update_submission invalid phase. 726 */ 727 public function test_update_submission_invalid_phase() { 728 // Create the submission that will be updated. 729 $submissionid = $this->create_test_submission($this->student); 730 731 $this->setUser($this->student); 732 733 // Switch to assessment phase. 734 $workshop = new workshop($this->workshop, $this->cm, $this->course); 735 $workshop->switch_phase(workshop::PHASE_ASSESSMENT); 736 737 $this->expectException('moodle_exception'); 738 mod_workshop_external::update_submission($submissionid, 'Test'); 739 } 740 741 /** 742 * Test test_update_submission empty title. 743 */ 744 public function test_update_submission_empty_title() { 745 // Create the submission that will be updated. 746 $submissionid = $this->create_test_submission($this->student); 747 748 $this->setUser($this->student); 749 750 $this->expectException('moodle_exception'); 751 mod_workshop_external::update_submission($submissionid, ''); 752 } 753 754 /** 755 * Test test_delete_submission. 756 */ 757 public function test_delete_submission() { 758 759 // Create the submission that will be deleted. 760 $submissionid = $this->create_test_submission($this->student); 761 762 $this->setUser($this->student); 763 764 // Trigger and capture the event. 765 $sink = $this->redirectEvents(); 766 767 $result = mod_workshop_external::delete_submission($submissionid); 768 $result = \external_api::clean_returnvalue(mod_workshop_external::delete_submission_returns(), $result); 769 $this->assertEmpty($result['warnings']); 770 $this->assertTrue($result['status']); 771 $workshop = new workshop($this->workshop, $this->cm, $this->course); 772 $submission = $workshop->get_submission_by_author($this->student->id); 773 $this->assertFalse($submission); 774 775 $events = $sink->get_events(); 776 $this->assertCount(1, $events); 777 $event = array_shift($events); 778 779 // Checking event. 780 $this->assertInstanceOf('\mod_workshop\event\submission_deleted', $event); 781 $this->assertEquals($this->context, $event->get_context()); 782 } 783 784 /** 785 * Test test_delete_submission_with_assessments. 786 */ 787 public function test_delete_submission_with_assessments() { 788 789 // Create the submission that will be deleted. 790 $submissionid = $this->create_test_submission($this->student); 791 792 $workshopgenerator = $this->getDataGenerator()->get_plugin_generator('mod_workshop'); 793 $workshopgenerator->create_assessment($submissionid, $this->teacher->id, array( 794 'weight' => 3, 795 'grade' => 95.00000, 796 )); 797 798 $this->setUser($this->student); 799 $this->expectException('moodle_exception'); 800 mod_workshop_external::delete_submission($submissionid); 801 } 802 803 /** 804 * Test test_delete_submission_invalid_phase. 805 */ 806 public function test_delete_submission_invalid_phase() { 807 808 // Create the submission that will be deleted. 809 $submissionid = $this->create_test_submission($this->student); 810 811 // Switch to assessment phase. 812 $workshop = new workshop($this->workshop, $this->cm, $this->course); 813 $workshop->switch_phase(workshop::PHASE_ASSESSMENT); 814 815 $this->setUser($this->student); 816 $this->expectException('moodle_exception'); 817 mod_workshop_external::delete_submission($submissionid); 818 } 819 820 /** 821 * Test test_delete_submission_as_teacher. 822 */ 823 public function test_delete_submission_as_teacher() { 824 825 // Create the submission that will be deleted. 826 $submissionid = $this->create_test_submission($this->student); 827 828 $this->setUser($this->teacher); 829 $result = mod_workshop_external::delete_submission($submissionid); 830 $result = \external_api::clean_returnvalue(mod_workshop_external::delete_submission_returns(), $result); 831 $this->assertEmpty($result['warnings']); 832 $this->assertTrue($result['status']); 833 } 834 835 /** 836 * Test test_delete_submission_other_user. 837 */ 838 public function test_delete_submission_other_user() { 839 840 $anotheruser = self::getDataGenerator()->create_user(); 841 $this->getDataGenerator()->enrol_user($anotheruser->id, $this->course->id, $this->studentrole->id, 'manual'); 842 // Create the submission that will be deleted. 843 $submissionid = $this->create_test_submission($this->student); 844 845 $this->setUser($anotheruser); 846 $this->expectException('moodle_exception'); 847 mod_workshop_external::delete_submission($submissionid); 848 } 849 850 /** 851 * Test test_get_submissions_student. 852 */ 853 public function test_get_submissions_student() { 854 855 // Create a couple of submissions with files. 856 $firstsubmissionid = $this->create_test_submission($this->student); // Create submission with files. 857 $secondsubmissionid = $this->create_test_submission($this->anotherstudentg1); 858 859 $this->setUser($this->student); 860 $result = mod_workshop_external::get_submissions($this->workshop->id); 861 $result = \external_api::clean_returnvalue(mod_workshop_external::get_submissions_returns(), $result); 862 // We should get just our submission. 863 $this->assertCount(1, $result['submissions']); 864 $this->assertEquals(1, $result['totalcount']); 865 $this->assertEquals($firstsubmissionid, $result['submissions'][0]['id']); 866 $this->assertCount(1, $result['submissions'][0]['contentfiles']); // Check we retrieve submission text files. 867 $this->assertCount(1, $result['submissions'][0]['attachmentfiles']); // Check we retrieve attachment files. 868 // We shoul not see the grade or feedback information. 869 $properties = submission_exporter::properties_definition(); 870 foreach ($properties as $attribute => $settings) { 871 if (!empty($settings['optional'])) { 872 if (isset($result['submissions'][0][$attribute])) { 873 echo "error $attribute"; 874 } 875 $this->assertFalse(isset($result['submissions'][0][$attribute])); 876 } 877 } 878 } 879 880 /** 881 * Test test_get_submissions_published_student. 882 */ 883 public function test_get_submissions_published_student() { 884 885 $workshop = new workshop($this->workshop, $this->cm, $this->course); 886 $workshop->switch_phase(workshop::PHASE_CLOSED); 887 // Create a couple of submissions with files. 888 $workshopgenerator = $this->getDataGenerator()->get_plugin_generator('mod_workshop'); 889 $submission = array('published' => 1); 890 $submissionid = $workshopgenerator->create_submission($this->workshop->id, $this->anotherstudentg1->id, $submission); 891 892 $this->setUser($this->student); 893 $result = mod_workshop_external::get_submissions($this->workshop->id); 894 $result = \external_api::clean_returnvalue(mod_workshop_external::get_submissions_returns(), $result); 895 // We should get just our submission. 896 $this->assertCount(1, $result['submissions']); 897 $this->assertEquals(1, $result['totalcount']); 898 $this->assertEquals($submissionid, $result['submissions'][0]['id']); 899 900 // Check with group restrictions. 901 $this->setUser($this->anotherstudentg2); 902 $result = mod_workshop_external::get_submissions($this->workshop->id); 903 $result = \external_api::clean_returnvalue(mod_workshop_external::get_submissions_returns(), $result); 904 $this->assertCount(0, $result['submissions']); // I can't see other users in separated groups. 905 $this->assertEquals(0, $result['totalcount']); 906 } 907 908 /** 909 * Test test_get_submissions_from_student_with_feedback_from_teacher. 910 */ 911 public function test_get_submissions_from_student_with_feedback_from_teacher() { 912 global $DB; 913 914 // Create a couple of submissions with files. 915 $workshopgenerator = $this->getDataGenerator()->get_plugin_generator('mod_workshop'); 916 $submissionid = $workshopgenerator->create_submission($this->workshop->id, $this->student->id); 917 // Create teacher feedback for submission. 918 $record = new \stdClass(); 919 $record->id = $submissionid; 920 $record->gradeover = 9; 921 $record->gradeoverby = $this->teacher->id; 922 $record->feedbackauthor = 'Hey'; 923 $record->feedbackauthorformat = FORMAT_MOODLE; 924 $record->published = 1; 925 $DB->update_record('workshop_submissions', $record); 926 927 // Remove teacher caps. 928 assign_capability('mod/workshop:viewallsubmissions', CAP_PROHIBIT, $this->teacher->id, $this->context->id); 929 // Empty all the caches that may be affected by this change. 930 accesslib_clear_all_caches_for_unit_testing(); 931 \course_modinfo::clear_instance_cache(); 932 933 $this->setUser($this->teacher); 934 $result = mod_workshop_external::get_submissions($this->workshop->id, $this->student->id); 935 $result = \external_api::clean_returnvalue(mod_workshop_external::get_submissions_returns(), $result); 936 // We should get just our submission. 937 $this->assertEquals(1, $result['totalcount']); 938 $this->assertEquals($submissionid, $result['submissions'][0]['id']); 939 } 940 941 /** 942 * Test test_get_submissions_from_students_as_teacher. 943 */ 944 public function test_get_submissions_from_students_as_teacher() { 945 946 // Create a couple of submissions with files. 947 $workshopgenerator = $this->getDataGenerator()->get_plugin_generator('mod_workshop'); 948 $submissionid1 = $workshopgenerator->create_submission($this->workshop->id, $this->student->id); 949 $submissionid2 = $workshopgenerator->create_submission($this->workshop->id, $this->anotherstudentg1->id); 950 $submissionid3 = $workshopgenerator->create_submission($this->workshop->id, $this->anotherstudentg2->id); 951 952 $this->setUser($this->teacher); 953 $result = mod_workshop_external::get_submissions($this->workshop->id); // Get all. 954 $result = \external_api::clean_returnvalue(mod_workshop_external::get_submissions_returns(), $result); 955 $this->assertEquals(3, $result['totalcount']); 956 $this->assertCount(3, $result['submissions']); 957 958 $result = mod_workshop_external::get_submissions($this->workshop->id, 0, 0, 0, 2); // Check pagination. 959 $result = \external_api::clean_returnvalue(mod_workshop_external::get_submissions_returns(), $result); 960 $this->assertEquals(3, $result['totalcount']); 961 $this->assertCount(2, $result['submissions']); 962 963 $result = mod_workshop_external::get_submissions($this->workshop->id, 0, $this->group2->id); // Get group 2. 964 $result = \external_api::clean_returnvalue(mod_workshop_external::get_submissions_returns(), $result); 965 $this->assertEquals(1, $result['totalcount']); 966 $this->assertCount(1, $result['submissions']); 967 $this->assertEquals($submissionid3, $result['submissions'][0]['id']); 968 969 $result = mod_workshop_external::get_submissions($this->workshop->id, $this->anotherstudentg1->id); // Get one. 970 $result = \external_api::clean_returnvalue(mod_workshop_external::get_submissions_returns(), $result); 971 $this->assertEquals(1, $result['totalcount']); 972 $this->assertEquals($submissionid2, $result['submissions'][0]['id']); 973 } 974 975 /** 976 * Test test_get_submission_student. 977 */ 978 public function test_get_submission_student() { 979 980 // Create a couple of submissions with files. 981 $firstsubmissionid = $this->create_test_submission($this->student); // Create submission with files. 982 983 $workshop = new workshop($this->workshop, $this->cm, $this->course); 984 $workshop->switch_phase(workshop::PHASE_CLOSED); 985 $this->setUser($this->student); 986 $result = mod_workshop_external::get_submission($firstsubmissionid); 987 $result = \external_api::clean_returnvalue(mod_workshop_external::get_submission_returns(), $result); 988 $this->assertEquals($firstsubmissionid, $result['submission']['id']); 989 $this->assertCount(1, $result['submission']['contentfiles']); // Check we retrieve submission text files. 990 $this->assertCount(1, $result['submission']['attachmentfiles']); // Check we retrieve attachment files. 991 $this->assertArrayHasKey('feedbackauthor', $result['submission']); 992 $this->assertArrayNotHasKey('grade', $result['submission']); 993 $this->assertArrayNotHasKey('gradeover', $result['submission']); 994 $this->assertArrayHasKey('gradeoverby', $result['submission']); 995 $this->assertArrayNotHasKey('timegraded', $result['submission']); 996 997 // Switch to a different phase (where feedback won't be available). 998 $workshop->switch_phase(workshop::PHASE_EVALUATION); 999 $result = mod_workshop_external::get_submission($firstsubmissionid); 1000 $result = \external_api::clean_returnvalue(mod_workshop_external::get_submission_returns(), $result); 1001 $this->assertEquals($firstsubmissionid, $result['submission']['id']); 1002 $this->assertCount(1, $result['submission']['contentfiles']); // Check we retrieve submission text files. 1003 $this->assertCount(1, $result['submission']['attachmentfiles']); // Check we retrieve attachment files. 1004 $this->assertArrayNotHasKey('feedbackauthor', $result['submission']); 1005 $this->assertArrayNotHasKey('grade', $result['submission']); 1006 $this->assertArrayNotHasKey('gradeover', $result['submission']); 1007 $this->assertArrayNotHasKey('gradeoverby', $result['submission']); 1008 $this->assertArrayNotHasKey('timegraded', $result['submission']); 1009 } 1010 1011 /** 1012 * Test test_get_submission_i_reviewed. 1013 */ 1014 public function test_get_submission_i_reviewed() { 1015 1016 // Create a couple of submissions with files. 1017 $firstsubmissionid = $this->create_test_submission($this->student); // Create submission with files. 1018 $workshopgenerator = $this->getDataGenerator()->get_plugin_generator('mod_workshop'); 1019 $workshopgenerator->create_assessment($firstsubmissionid, $this->anotherstudentg1->id, array( 1020 'weight' => 3, 1021 'grade' => 95, 1022 )); 1023 // Now try to get the submission I just reviewed. 1024 $this->setUser($this->anotherstudentg1); 1025 $result = mod_workshop_external::get_submission($firstsubmissionid); 1026 $result = \external_api::clean_returnvalue(mod_workshop_external::get_submission_returns(), $result); 1027 $this->assertEquals($firstsubmissionid, $result['submission']['id']); 1028 $this->assertCount(1, $result['submission']['contentfiles']); // Check we retrieve submission text files. 1029 $this->assertCount(1, $result['submission']['attachmentfiles']); // Check we retrieve attachment files. 1030 $this->assertArrayNotHasKey('feedbackauthor', $result['submission']); 1031 $this->assertArrayNotHasKey('grade', $result['submission']); 1032 $this->assertArrayNotHasKey('gradeover', $result['submission']); 1033 $this->assertArrayNotHasKey('gradeoverby', $result['submission']); 1034 $this->assertArrayNotHasKey('timegraded', $result['submission']); 1035 } 1036 1037 /** 1038 * Test test_get_submission_other_student. 1039 */ 1040 public function test_get_submission_other_student() { 1041 1042 // Create a couple of submissions with files. 1043 $firstsubmissionid = $this->create_test_submission($this->student); // Create submission with files. 1044 // Expect failure. 1045 $this->setUser($this->anotherstudentg1); 1046 $this->expectException('moodle_exception'); 1047 $result = mod_workshop_external::get_submission($firstsubmissionid); 1048 } 1049 1050 /** 1051 * Test test_get_submission_published_student. 1052 */ 1053 public function test_get_submission_published_student() { 1054 1055 $workshop = new workshop($this->workshop, $this->cm, $this->course); 1056 $workshop->switch_phase(workshop::PHASE_CLOSED); 1057 // Create a couple of submissions with files. 1058 $workshopgenerator = $this->getDataGenerator()->get_plugin_generator('mod_workshop'); 1059 $submission = array('published' => 1); 1060 $submissionid = $workshopgenerator->create_submission($this->workshop->id, $this->anotherstudentg1->id, $submission); 1061 1062 $this->setUser($this->student); 1063 $result = mod_workshop_external::get_submission($submissionid); 1064 $result = \external_api::clean_returnvalue(mod_workshop_external::get_submission_returns(), $result); 1065 $this->assertEquals($submissionid, $result['submission']['id']); 1066 // Check that the student don't see the other student grade/feedback data even if is published. 1067 // We should not see the grade or feedback information. 1068 $properties = submission_exporter::properties_definition(); 1069 $this->assertArrayNotHasKey('feedbackauthor', $result['submission']); 1070 $this->assertArrayNotHasKey('grade', $result['submission']); 1071 $this->assertArrayNotHasKey('gradeover', $result['submission']); 1072 $this->assertArrayNotHasKey('gradeoverby', $result['submission']); 1073 $this->assertArrayNotHasKey('timegraded', $result['submission']); 1074 1075 // Check with group restrictions. 1076 $this->setUser($this->anotherstudentg2); 1077 $this->expectException('moodle_exception'); 1078 mod_workshop_external::get_submission($submissionid); 1079 } 1080 1081 /** 1082 * Test test_get_submission_from_student_with_feedback_from_teacher. 1083 */ 1084 public function test_get_submission_from_student_with_feedback_from_teacher() { 1085 global $DB; 1086 1087 // Create a couple of submissions with files. 1088 $workshopgenerator = $this->getDataGenerator()->get_plugin_generator('mod_workshop'); 1089 $submissionid = $workshopgenerator->create_submission($this->workshop->id, $this->student->id); 1090 $workshop = new workshop($this->workshop, $this->cm, $this->course); 1091 $workshop->switch_phase(workshop::PHASE_CLOSED); 1092 // Create teacher feedback for submission. 1093 $record = new \stdClass(); 1094 $record->id = $submissionid; 1095 $record->gradeover = 9; 1096 $record->gradeoverby = $this->teacher->id; 1097 $record->feedbackauthor = 'Hey'; 1098 $record->feedbackauthorformat = FORMAT_MOODLE; 1099 $record->published = 1; 1100 $record->timegraded = time(); 1101 $DB->update_record('workshop_submissions', $record); 1102 1103 $this->setUser($this->teacher); 1104 $result = mod_workshop_external::get_submission($submissionid); 1105 $result = \external_api::clean_returnvalue(mod_workshop_external::get_submission_returns(), $result); 1106 $this->assertEquals($submissionid, $result['submission']['id']); 1107 $this->assertEquals($record->feedbackauthor, $result['submission']['feedbackauthor']); 1108 $this->assertEquals($record->gradeover, $result['submission']['gradeover']); 1109 $this->assertEquals($record->gradeoverby, $result['submission']['gradeoverby']); 1110 $this->assertEquals($record->timegraded, $result['submission']['timegraded']); 1111 1112 // Go to phase where feedback and grades are not yet available. 1113 $workshop->switch_phase(workshop::PHASE_SUBMISSION); 1114 $result = mod_workshop_external::get_submission($submissionid); 1115 $result = \external_api::clean_returnvalue(mod_workshop_external::get_submission_returns(), $result); 1116 $this->assertArrayNotHasKey('feedbackauthor', $result['submission']); 1117 $this->assertArrayNotHasKey('grade', $result['submission']); 1118 $this->assertArrayNotHasKey('gradeover', $result['submission']); 1119 $this->assertArrayNotHasKey('gradeoverby', $result['submission']); 1120 $this->assertArrayNotHasKey('timegraded', $result['submission']); 1121 1122 // Remove teacher caps to view and go to valid phase. 1123 $workshop->switch_phase(workshop::PHASE_EVALUATION); 1124 unassign_capability('mod/workshop:viewallsubmissions', $this->teacherrole->id); 1125 // Empty all the caches that may be affected by this change. 1126 accesslib_clear_all_caches_for_unit_testing(); 1127 1128 $this->expectException('moodle_exception'); 1129 mod_workshop_external::get_submission($submissionid); 1130 } 1131 1132 /** 1133 * Test test_get_submission_from_students_as_teacher. 1134 */ 1135 public function test_get_submission_from_students_as_teacher() { 1136 // Create a couple of submissions with files. 1137 $workshopgenerator = $this->getDataGenerator()->get_plugin_generator('mod_workshop'); 1138 $submissionid1 = $workshopgenerator->create_submission($this->workshop->id, $this->student->id); 1139 $submissionid2 = $workshopgenerator->create_submission($this->workshop->id, $this->anotherstudentg1->id); 1140 $submissionid3 = $workshopgenerator->create_submission($this->workshop->id, $this->anotherstudentg2->id); 1141 1142 $this->setUser($this->teacher); 1143 $result = mod_workshop_external::get_submission($submissionid1); // Get all. 1144 $result = \external_api::clean_returnvalue(mod_workshop_external::get_submission_returns(), $result); 1145 $this->assertEquals($submissionid1, $result['submission']['id']); 1146 1147 $result = mod_workshop_external::get_submission($submissionid3); // Get group 2. 1148 $result = \external_api::clean_returnvalue(mod_workshop_external::get_submission_returns(), $result); 1149 $this->assertEquals($submissionid3, $result['submission']['id']); 1150 } 1151 1152 1153 /** 1154 * Test get_submission_assessments_student. 1155 */ 1156 public function test_get_submission_assessments_student() { 1157 1158 // Create the submission that will be deleted. 1159 $submissionid = $this->create_test_submission($this->student); 1160 1161 $workshopgenerator = $this->getDataGenerator()->get_plugin_generator('mod_workshop'); 1162 $workshopgenerator->create_assessment($submissionid, $this->anotherstudentg1->id, array( 1163 'weight' => 3, 1164 'grade' => 95, 1165 )); 1166 $workshopgenerator->create_assessment($submissionid, $this->student->id, array( 1167 'weight' => 2, 1168 'grade' => 90, 1169 )); 1170 1171 $workshop = new workshop($this->workshop, $this->cm, $this->course); 1172 $workshop->switch_phase(workshop::PHASE_CLOSED); 1173 $this->setUser($this->student); 1174 $result = mod_workshop_external::get_submission_assessments($submissionid); 1175 $result = \external_api::clean_returnvalue(mod_workshop_external::get_submission_assessments_returns(), $result); 1176 $this->assertCount(2, $result['assessments']); // I received my two assessments. 1177 foreach ($result['assessments'] as $assessment) { 1178 if ($assessment['grade'] == 90) { 1179 // My own assessment, I can see me. 1180 $this->assertEquals($this->student->id, $assessment['reviewerid']); 1181 } else { 1182 // Student's can't see who did the review. 1183 $this->assertEquals(0, $assessment['reviewerid']); 1184 } 1185 } 1186 } 1187 1188 /** 1189 * Test get_submission_assessments_invalid_phase. 1190 */ 1191 public function test_get_submission_assessments_invalid_phase() { 1192 1193 // Create the submission that will be deleted. 1194 $submissionid = $this->create_test_submission($this->student); 1195 1196 $workshopgenerator = $this->getDataGenerator()->get_plugin_generator('mod_workshop'); 1197 $workshopgenerator->create_assessment($submissionid, $this->anotherstudentg1->id, array( 1198 'weight' => 3, 1199 'grade' => 95, 1200 )); 1201 1202 $this->expectException('moodle_exception'); 1203 mod_workshop_external::get_submission_assessments($submissionid); 1204 } 1205 1206 /** 1207 * Test get_submission_assessments_teacher. 1208 */ 1209 public function test_get_submission_assessments_teacher() { 1210 1211 // Create the submission that will be deleted. 1212 $submissionid = $this->create_test_submission($this->student); 1213 1214 $workshopgenerator = $this->getDataGenerator()->get_plugin_generator('mod_workshop'); 1215 $assessmentid = $workshopgenerator->create_assessment($submissionid, $this->anotherstudentg1->id, array( 1216 'weight' => 1, 1217 'grade' => 50, 1218 )); 1219 1220 $this->setUser($this->teacher); 1221 $result = mod_workshop_external::get_submission_assessments($submissionid); 1222 $result = \external_api::clean_returnvalue(mod_workshop_external::get_submission_assessments_returns(), $result); 1223 $this->assertCount(1, $result['assessments']); 1224 $this->assertEquals(50, $result['assessments'][0]['grade']); 1225 $this->assertEquals($assessmentid, $result['assessments'][0]['id']); 1226 } 1227 1228 /** 1229 * Test get_assessment_author. 1230 */ 1231 public function test_get_assessment_author() { 1232 1233 // Create the submission. 1234 $submissionid = $this->create_test_submission($this->anotherstudentg1); 1235 1236 $workshopgenerator = $this->getDataGenerator()->get_plugin_generator('mod_workshop'); 1237 $assessmentid = $workshopgenerator->create_assessment($submissionid, $this->student->id, array( 1238 'weight' => 2, 1239 'grade' => 90, 1240 )); 1241 1242 // Switch to closed phase. 1243 $workshop = new workshop($this->workshop, $this->cm, $this->course); 1244 $workshop->switch_phase(workshop::PHASE_CLOSED); 1245 $this->setUser($this->anotherstudentg1); 1246 $result = mod_workshop_external::get_assessment($assessmentid); 1247 $result = \external_api::clean_returnvalue(mod_workshop_external::get_assessment_returns(), $result); 1248 $this->assertEquals($assessmentid, $result['assessment']['id']); 1249 $this->assertEquals(90, $result['assessment']['grade']); 1250 // I can't see the reviewer review. 1251 $this->assertFalse(isset($result['assessment']['feedbackreviewer'])); 1252 } 1253 1254 /** 1255 * Test get_assessment_reviewer. 1256 */ 1257 public function test_get_assessment_reviewer() { 1258 1259 // Create the submission. 1260 $submissionid = $this->create_test_submission($this->anotherstudentg1); 1261 1262 $workshopgenerator = $this->getDataGenerator()->get_plugin_generator('mod_workshop'); 1263 $assessmentid = $workshopgenerator->create_assessment($submissionid, $this->student->id, array( 1264 'weight' => 2, 1265 'grade' => 90, 1266 )); 1267 1268 // Switch to closed phase. 1269 $workshop = new workshop($this->workshop, $this->cm, $this->course); 1270 $workshop->switch_phase(workshop::PHASE_CLOSED); 1271 $this->setUser($this->student); 1272 $result = mod_workshop_external::get_assessment($assessmentid); 1273 $result = \external_api::clean_returnvalue(mod_workshop_external::get_assessment_returns(), $result); 1274 $this->assertEquals($assessmentid, $result['assessment']['id']); 1275 $this->assertEquals(90, $result['assessment']['grade']); 1276 // I can see the reviewer review. 1277 $this->assertTrue(isset($result['assessment']['feedbackreviewer'])); 1278 } 1279 1280 /** 1281 * Test get_assessment_teacher. 1282 */ 1283 public function test_get_assessment_teacher() { 1284 1285 // Create the submission. 1286 $submissionid = $this->create_test_submission($this->anotherstudentg1); 1287 1288 $workshopgenerator = $this->getDataGenerator()->get_plugin_generator('mod_workshop'); 1289 $assessmentid = $workshopgenerator->create_assessment($submissionid, $this->student->id, array( 1290 'weight' => 2, 1291 'grade' => 90, 1292 )); 1293 1294 // Switch to closed phase. 1295 $workshop = new workshop($this->workshop, $this->cm, $this->course); 1296 $workshop->switch_phase(workshop::PHASE_CLOSED); 1297 $this->setUser($this->teacher); 1298 $result = mod_workshop_external::get_assessment($assessmentid); 1299 $result = \external_api::clean_returnvalue(mod_workshop_external::get_assessment_returns(), $result); 1300 $this->assertEquals($assessmentid, $result['assessment']['id']); 1301 $this->assertEquals(90, $result['assessment']['grade']); 1302 } 1303 1304 /** 1305 * Test get_assessment_student_invalid_phase. 1306 */ 1307 public function test_get_assessment_student_invalid_phase() { 1308 1309 // Create the submission. 1310 $submissionid = $this->create_test_submission($this->anotherstudentg1); 1311 1312 $workshopgenerator = $this->getDataGenerator()->get_plugin_generator('mod_workshop'); 1313 $assessmentid = $workshopgenerator->create_assessment($submissionid, $this->student->id, array( 1314 'weight' => 2, 1315 'grade' => 90, 1316 )); 1317 1318 // Switch to closed phase. 1319 $this->setUser($this->anotherstudentg1); 1320 1321 $this->expectException('moodle_exception'); 1322 mod_workshop_external::get_assessment($assessmentid); 1323 } 1324 1325 /** 1326 * Test get_assessment_student_invalid_user. 1327 */ 1328 public function test_get_assessment_student_invalid_user() { 1329 1330 // Create the submission. 1331 $submissionid = $this->create_test_submission($this->anotherstudentg1); 1332 1333 $workshopgenerator = $this->getDataGenerator()->get_plugin_generator('mod_workshop'); 1334 $assessmentid = $workshopgenerator->create_assessment($submissionid, $this->student->id, array( 1335 'weight' => 2, 1336 'grade' => 90, 1337 )); 1338 1339 // Switch to closed phase. 1340 $workshop = new workshop($this->workshop, $this->cm, $this->course); 1341 $workshop->switch_phase(workshop::PHASE_CLOSED); 1342 $this->setUser($this->anotherstudentg2); 1343 1344 $this->expectException('moodle_exception'); 1345 mod_workshop_external::get_assessment($assessmentid); 1346 } 1347 1348 /** 1349 * Test get_assessment_form_definition_reviewer_new_assessment. 1350 */ 1351 public function test_get_assessment_form_definition_reviewer_new_assessment() { 1352 1353 // Create the submission. 1354 $submissionid = $this->create_test_submission($this->anotherstudentg1); 1355 1356 $workshop = new workshop($this->workshop, $this->cm, $this->course); 1357 $submission = $workshop->get_submission_by_id($submissionid); 1358 $assessmentid = $workshop->add_allocation($submission, $this->student->id); 1359 1360 // Switch to assessment phase. 1361 $workshop->switch_phase(workshop::PHASE_ASSESSMENT); 1362 $this->setUser($this->student); 1363 $result = mod_workshop_external::get_assessment_form_definition($assessmentid); 1364 $result = \external_api::clean_returnvalue(mod_workshop_external::get_assessment_form_definition_returns(), $result); 1365 $this->assertEquals(4, $result['dimenssionscount']); // We receive the expected 4 dimensions. 1366 $this->assertEmpty($result['current']); // Assessment not yet done. 1367 foreach ($result['fields'] as $field) { 1368 if (strpos($field['name'], 'grade__idx_') === 0) { 1369 $this->assertEquals(25, $field['value']); // Check one of the dimension fields attributes. 1370 } 1371 } 1372 // Check dimensions grading info. 1373 foreach ($result['dimensionsinfo'] as $dimension) { 1374 $this->assertEquals(0, $dimension['min']); 1375 $this->assertEquals(25, $dimension['max']); 1376 $this->assertEquals(25, $dimension['weight']); 1377 $this->assertFalse(isset($dimension['scale'])); 1378 } 1379 } 1380 1381 /** 1382 * Test get_assessment_form_definition_teacher_new_assessment. 1383 */ 1384 public function test_get_assessment_form_definition_teacher_new_assessment() { 1385 1386 // Create the submission. 1387 $submissionid = $this->create_test_submission($this->anotherstudentg1); 1388 1389 $workshop = new workshop($this->workshop, $this->cm, $this->course); 1390 $submission = $workshop->get_submission_by_id($submissionid); 1391 $assessmentid = $workshop->add_allocation($submission, $this->student->id); 1392 1393 // Switch to assessment phase. 1394 $workshop->switch_phase(workshop::PHASE_ASSESSMENT); 1395 // Teachers need to be able to view assessments. 1396 $this->setUser($this->teacher); 1397 $result = mod_workshop_external::get_assessment_form_definition($assessmentid); 1398 $result = \external_api::clean_returnvalue(mod_workshop_external::get_assessment_form_definition_returns(), $result); 1399 $this->assertEquals(4, $result['dimenssionscount']); 1400 } 1401 1402 /** 1403 * Test get_assessment_form_definition_invalid_phase. 1404 */ 1405 public function test_get_assessment_form_definition_invalid_phase() { 1406 1407 // Create the submission. 1408 $submissionid = $this->create_test_submission($this->anotherstudentg1); 1409 1410 $workshop = new workshop($this->workshop, $this->cm, $this->course); 1411 $submission = $workshop->get_submission_by_id($submissionid); 1412 $assessmentid = $workshop->add_allocation($submission, $this->anotherstudentg1->id); 1413 1414 $workshop->switch_phase(workshop::PHASE_EVALUATION); 1415 $this->setUser($this->student); 1416 // Since we are not reviewers we can't see the assessment until the workshop is closed. 1417 $this->expectException('moodle_exception'); 1418 mod_workshop_external::get_assessment_form_definition($assessmentid); 1419 } 1420 1421 /** 1422 * Test get_reviewer_assessments. 1423 */ 1424 public function test_get_reviewer_assessments() { 1425 1426 // Create the submission. 1427 $submissionid1 = $this->create_test_submission($this->student); 1428 $submissionid2 = $this->create_test_submission($this->anotherstudentg1); 1429 1430 $workshopgenerator = $this->getDataGenerator()->get_plugin_generator('mod_workshop'); 1431 $assessmentid1 = $workshopgenerator->create_assessment($submissionid1, $this->student->id, array( 1432 'weight' => 2, 1433 'grade' => 90, 1434 )); 1435 $assessmentid2 = $workshopgenerator->create_assessment($submissionid2, $this->student->id, array( 1436 'weight' => 3, 1437 'grade' => 80, 1438 )); 1439 1440 // Switch to assessment phase. 1441 $workshop = new workshop($this->workshop, $this->cm, $this->course); 1442 $workshop->switch_phase(workshop::PHASE_ASSESSMENT); 1443 $this->setUser($this->student); 1444 // Get my assessments. 1445 $result = mod_workshop_external::get_reviewer_assessments($this->workshop->id); 1446 $result = \external_api::clean_returnvalue(mod_workshop_external::get_reviewer_assessments_returns(), $result); 1447 $this->assertCount(2, $result['assessments']); 1448 foreach ($result['assessments'] as $assessment) { 1449 if ($assessment['id'] == $assessmentid1) { 1450 $this->assertEquals(90, $assessment['grade']); 1451 } else { 1452 $this->assertEquals($assessmentid2, $assessment['id']); 1453 $this->assertEquals(80, $assessment['grade']); 1454 } 1455 } 1456 1457 // Now, as teacher try to get the same student assessments. 1458 $result = mod_workshop_external::get_reviewer_assessments($this->workshop->id, $this->student->id); 1459 $result = \external_api::clean_returnvalue(mod_workshop_external::get_reviewer_assessments_returns(), $result); 1460 $this->assertCount(2, $result['assessments']); 1461 $this->assertArrayNotHasKey('feedbackreviewer', $result['assessments'][0]); 1462 } 1463 1464 /** 1465 * Test get_reviewer_assessments_other_student. 1466 */ 1467 public function test_get_reviewer_assessments_other_student() { 1468 1469 $workshop = new workshop($this->workshop, $this->cm, $this->course); 1470 $workshop->switch_phase(workshop::PHASE_ASSESSMENT); 1471 // Try to get other user assessments. 1472 $this->setUser($this->student); 1473 $this->expectException('moodle_exception'); 1474 mod_workshop_external::get_reviewer_assessments($this->workshop->id, $this->anotherstudentg1->id); 1475 } 1476 1477 /** 1478 * Test get_reviewer_assessments_invalid_phase. 1479 */ 1480 public function test_get_reviewer_assessments_invalid_phase() { 1481 1482 $workshop = new workshop($this->workshop, $this->cm, $this->course); 1483 $workshop->switch_phase(workshop::PHASE_SUBMISSION); 1484 // Try to get other user assessments. 1485 $this->setUser($this->student); 1486 $this->expectException('moodle_exception'); 1487 mod_workshop_external::get_reviewer_assessments($this->workshop->id, $this->anotherstudentg1->id); 1488 } 1489 1490 /** 1491 * Test update_assessment. 1492 */ 1493 public function test_update_assessment() { 1494 1495 // Create the submission. 1496 $submissionid = $this->create_test_submission($this->anotherstudentg1); 1497 1498 $workshop = new workshop($this->workshop, $this->cm, $this->course); 1499 $submission = $workshop->get_submission_by_id($submissionid); 1500 $assessmentid = $workshop->add_allocation($submission, $this->student->id); 1501 1502 // Switch to assessment phase. 1503 $workshop->switch_phase(workshop::PHASE_ASSESSMENT); 1504 $this->setUser($this->student); 1505 // Get the form definition. 1506 $result = mod_workshop_external::get_assessment_form_definition($assessmentid); 1507 $result = \external_api::clean_returnvalue(mod_workshop_external::get_assessment_form_definition_returns(), $result); 1508 1509 // Prepare the data to be sent. 1510 $data = $result['fields']; 1511 foreach ($data as $key => $param) { 1512 if (strpos($param['name'], 'peercomment__idx_') === 0) { 1513 $data[$key]['value'] = 'Some content'; 1514 } else if (strpos($param['name'], 'grade__idx_') === 0) { 1515 $data[$key]['value'] = 25; // Set all to 25. 1516 } 1517 } 1518 1519 // Required data. 1520 $data[] = array( 1521 'name' => 'nodims', 1522 'value' => $result['dimenssionscount'], 1523 ); 1524 1525 // General feedback. 1526 $data[] = array( 1527 'name' => 'feedbackauthor', 1528 'value' => 'Feedback for the author', 1529 ); 1530 $data[] = array( 1531 'name' => 'feedbackauthorformat', 1532 'value' => FORMAT_MOODLE, 1533 ); 1534 1535 // Create a file in a draft area for inline attachments. 1536 $fs = get_file_storage(); 1537 $draftidinlineattach = file_get_unused_draft_itemid(); 1538 $usercontext = \context_user::instance($this->student->id); 1539 $filenameimg = 'shouldbeanimage.txt'; 1540 $filerecordinline = array( 1541 'contextid' => $usercontext->id, 1542 'component' => 'user', 1543 'filearea' => 'draft', 1544 'itemid' => $draftidinlineattach, 1545 'filepath' => '/', 1546 'filename' => $filenameimg, 1547 ); 1548 $fs->create_file_from_string($filerecordinline, 'image contents (not really)'); 1549 1550 // Create a file in a draft area for regular attachments. 1551 $draftidattach = file_get_unused_draft_itemid(); 1552 $filerecordattach = $filerecordinline; 1553 $attachfilename = 'attachment.txt'; 1554 $filerecordattach['filename'] = $attachfilename; 1555 $filerecordattach['itemid'] = $draftidattach; 1556 $fs->create_file_from_string($filerecordattach, 'simple text attachment'); 1557 1558 $data[] = array( 1559 'name' => 'feedbackauthorinlineattachmentsid', 1560 'value' => $draftidinlineattach, 1561 ); 1562 $data[] = array( 1563 'name' => 'feedbackauthorattachmentsid', 1564 'value' => $draftidattach, 1565 ); 1566 1567 // Update the assessment. 1568 $result = mod_workshop_external::update_assessment($assessmentid, $data); 1569 $result = \external_api::clean_returnvalue(mod_workshop_external::update_assessment_returns(), $result); 1570 $this->assertEquals(100, $result['rawgrade']); 1571 $this->assertTrue($result['status']); 1572 1573 // Get the assessment and check it was updated properly. 1574 $result = mod_workshop_external::get_assessment($assessmentid); 1575 $result = \external_api::clean_returnvalue(mod_workshop_external::get_assessment_returns(), $result); 1576 $this->assertEquals(100, $result['assessment']['grade']); 1577 $this->assertEquals($this->student->id, $result['assessment']['reviewerid']); 1578 $this->assertEquals('Feedback for the author', $result['assessment']['feedbackauthor']); 1579 $this->assertCount(1, $result['assessment']['feedbackcontentfiles']); 1580 $this->assertCount(1, $result['assessment']['feedbackattachmentfiles']); 1581 1582 // Now, get again the form and check we received the data we already sent. 1583 $result = mod_workshop_external::get_assessment_form_definition($assessmentid); 1584 $result = \external_api::clean_returnvalue(mod_workshop_external::get_assessment_form_definition_returns(), $result); 1585 foreach ($result['current'] as $currentdata) { 1586 if (strpos($currentdata['name'], 'peercomment__idx_') === 0) { 1587 $this->assertEquals('Some content', $currentdata['value']); 1588 } else if (strpos($currentdata['name'], 'grade__idx_') === 0) { 1589 $this->assertEquals(25, (int) $currentdata['value']); 1590 } 1591 } 1592 } 1593 1594 /** 1595 * Test get_grades. 1596 */ 1597 public function test_get_grades() { 1598 1599 $timenow = time(); 1600 $submissiongrade = array( 1601 'userid' => $this->student->id, 1602 'rawgrade' => 40, 1603 'feedback' => '', 1604 'feedbackformat' => 1, 1605 'datesubmitted' => $timenow, 1606 'dategraded' => $timenow, 1607 ); 1608 $assessmentgrade = array( 1609 'userid' => $this->student->id, 1610 'rawgrade' => 10, 1611 'feedback' => '', 1612 'feedbackformat' => 1, 1613 'datesubmitted' => $timenow, 1614 'dategraded' => $timenow, 1615 ); 1616 1617 workshop_grade_item_update($this->workshop, (object) $submissiongrade, (object) $assessmentgrade); 1618 1619 // First retrieve my grades. 1620 $this->setUser($this->student); 1621 $result = mod_workshop_external::get_grades($this->workshop->id); 1622 $result = \external_api::clean_returnvalue(mod_workshop_external::get_grades_returns(), $result); 1623 $this->assertCount(0, $result['warnings']); 1624 $this->assertEquals($assessmentgrade['rawgrade'], $result['assessmentrawgrade']); 1625 $this->assertEquals($submissiongrade['rawgrade'], $result['submissionrawgrade']); 1626 $this->assertFalse($result['assessmentgradehidden']); 1627 $this->assertFalse($result['submissiongradehidden']); 1628 $this->assertEquals($assessmentgrade['rawgrade'] . ".00 / 20.00", $result['assessmentlongstrgrade']); 1629 $this->assertEquals($submissiongrade['rawgrade'] . ".00 / 80.00", $result['submissionlongstrgrade']); 1630 1631 // Second, teacher retrieve user grades. 1632 $this->setUser($this->teacher); 1633 $result = mod_workshop_external::get_grades($this->workshop->id, $this->student->id); 1634 $result = \external_api::clean_returnvalue(mod_workshop_external::get_grades_returns(), $result); 1635 $this->assertCount(0, $result['warnings']); 1636 $this->assertEquals($assessmentgrade['rawgrade'], $result['assessmentrawgrade']); 1637 $this->assertEquals($submissiongrade['rawgrade'], $result['submissionrawgrade']); 1638 $this->assertFalse($result['assessmentgradehidden']); 1639 $this->assertFalse($result['submissiongradehidden']); 1640 $this->assertEquals($assessmentgrade['rawgrade'] . ".00 / 20.00", $result['assessmentlongstrgrade']); 1641 $this->assertEquals($submissiongrade['rawgrade'] . ".00 / 80.00", $result['submissionlongstrgrade']); 1642 } 1643 1644 /** 1645 * Test get_grades_other_student. 1646 */ 1647 public function test_get_grades_other_student() { 1648 1649 // Create the submission that will be deleted. 1650 $submissionid = $this->create_test_submission($this->student); 1651 1652 $workshop = new workshop($this->workshop, $this->cm, $this->course); 1653 $workshop->switch_phase(workshop::PHASE_CLOSED); 1654 $this->setUser($this->anotherstudentg1); 1655 $this->expectException('moodle_exception'); 1656 mod_workshop_external::get_grades($this->workshop->id, $this->student->id); 1657 } 1658 1659 /** 1660 * Test evaluate_assessment. 1661 */ 1662 public function test_evaluate_assessment() { 1663 global $DB; 1664 1665 $workshopgenerator = $this->getDataGenerator()->get_plugin_generator('mod_workshop'); 1666 $submissionid = $workshopgenerator->create_submission($this->workshop->id, $this->student->id); 1667 $assessmentid = $workshopgenerator->create_assessment($submissionid, $this->anotherstudentg1->id, array( 1668 'weight' => 3, 1669 'grade' => 20, 1670 )); 1671 1672 $this->setUser($this->teacher); 1673 $feedbacktext = 'The feedback'; 1674 $feedbackformat = FORMAT_MOODLE; 1675 $weight = 10; 1676 $gradinggradeover = 10; 1677 $result = mod_workshop_external::evaluate_assessment($assessmentid, $feedbacktext, $feedbackformat, $weight, 1678 $gradinggradeover); 1679 $result = \external_api::clean_returnvalue(mod_workshop_external::evaluate_assessment_returns(), $result); 1680 $this->assertTrue($result['status']); 1681 1682 $assessment = $DB->get_record('workshop_assessments', array('id' => $assessmentid)); 1683 $this->assertEquals('The feedback', $assessment->feedbackreviewer); 1684 $this->assertEquals(10, $assessment->weight); 1685 1686 // Now test passing incorrect weight and grade values. 1687 $weight = 17; 1688 $gradinggradeover = 100; 1689 $result = mod_workshop_external::evaluate_assessment($assessmentid, $feedbacktext, $feedbackformat, $weight, 1690 $gradinggradeover); 1691 $result = \external_api::clean_returnvalue(mod_workshop_external::evaluate_assessment_returns(), $result); 1692 $this->assertFalse($result['status']); 1693 $this->assertCount(2, $result['warnings']); 1694 $found = 0; 1695 foreach ($result['warnings'] as $warning) { 1696 if ($warning['item'] == 'weight' || $warning['item'] == 'gradinggradeover') { 1697 $found++; 1698 } 1699 } 1700 $this->assertEquals(2, $found); 1701 } 1702 1703 /** 1704 * Test evaluate_assessment_ignore_parameters. 1705 */ 1706 public function test_evaluate_assessment_ignore_parameters() { 1707 $workshopgenerator = $this->getDataGenerator()->get_plugin_generator('mod_workshop'); 1708 $submissionid = $workshopgenerator->create_submission($this->workshop->id, $this->student->id); 1709 $assessmentid = $workshopgenerator->create_assessment($submissionid, $this->anotherstudentg1->id, array( 1710 'weight' => 3, 1711 'grade' => 20, 1712 )); 1713 1714 assign_capability('mod/workshop:allocate', CAP_PROHIBIT, $this->teacherrole->id, $this->context->id); 1715 // Empty all the caches that may be affected by this change. 1716 accesslib_clear_all_caches_for_unit_testing(); 1717 1718 $this->setUser($this->teacher); 1719 $feedbacktext = 'The feedback'; 1720 $feedbackformat = FORMAT_MOODLE; 1721 $weight = 10; 1722 $gradinggradeover = 19; 1723 $result = mod_workshop_external::evaluate_assessment($assessmentid, $feedbacktext, $feedbackformat, $weight, 1724 $gradinggradeover); 1725 $result = \external_api::clean_returnvalue(mod_workshop_external::evaluate_assessment_returns(), $result); 1726 $this->assertTrue($result['status']); 1727 1728 $result = mod_workshop_external::get_assessment($assessmentid); 1729 $result = \external_api::clean_returnvalue(mod_workshop_external::get_assessment_returns(), $result); 1730 $this->assertNotEquals(10, $result['assessment']['weight']); 1731 } 1732 1733 /** 1734 * Test evaluate_assessment_no_permissions. 1735 */ 1736 public function test_evaluate_assessment_no_permissions() { 1737 $workshopgenerator = $this->getDataGenerator()->get_plugin_generator('mod_workshop'); 1738 $submissionid = $workshopgenerator->create_submission($this->workshop->id, $this->student->id); 1739 $assessmentid = $workshopgenerator->create_assessment($submissionid, $this->anotherstudentg1->id, array( 1740 'weight' => 3, 1741 'grade' => 20, 1742 )); 1743 1744 $this->setUser($this->student); 1745 $feedbacktext = 'The feedback'; 1746 $feedbackformat = FORMAT_MOODLE; 1747 $weight = 10; 1748 $gradinggradeover = 50; 1749 $this->expectException('moodle_exception'); 1750 mod_workshop_external::evaluate_assessment($assessmentid, $feedbacktext, $feedbackformat, $weight, $gradinggradeover); 1751 } 1752 1753 /** 1754 * Test get_grades_report. 1755 */ 1756 public function test_get_grades_report() { 1757 1758 $workshop = new workshop($this->workshop, $this->cm, $this->course); 1759 $workshopgenerator = $this->getDataGenerator()->get_plugin_generator('mod_workshop'); 1760 $submissionid1 = $workshopgenerator->create_submission($this->workshop->id, $this->student->id); 1761 $submissionid2 = $workshopgenerator->create_submission($this->workshop->id, $this->anotherstudentg1->id); 1762 1763 $assessmentid1 = $workshopgenerator->create_assessment($submissionid2, $this->student->id, array( 1764 'weight' => 100, 1765 'grade' => 50, 1766 )); 1767 $assessmentid2 = $workshopgenerator->create_assessment($submissionid1, $this->anotherstudentg1->id, array( 1768 'weight' => 100, 1769 'grade' => 55, 1770 )); 1771 1772 $workshop->switch_phase(workshop::PHASE_CLOSED); 1773 $this->setUser($this->teacher); 1774 $result = mod_workshop_external::get_grades_report($this->workshop->id); 1775 $result = \external_api::clean_returnvalue(mod_workshop_external::get_grades_report_returns(), $result); 1776 $this->assertEquals(3, $result['report']['totalcount']); // Expect 3 potential submissions. 1777 1778 foreach ($result['report']['grades'] as $grade) { 1779 if ($grade['userid'] == $this->student->id) { 1780 $this->assertEquals($this->anotherstudentg1->id, $grade['reviewedby'][0]['userid']); // Check reviewer. 1781 $this->assertEquals($this->anotherstudentg1->id, $grade['reviewerof'][0]['userid']); // Check reviewer. 1782 $this->assertEquals($workshop->real_grade(50), $grade['reviewerof'][0]['grade']); // Check grade (converted). 1783 $this->assertEquals($workshop->real_grade(55), $grade['reviewedby'][0]['grade']); // Check grade (converted). 1784 } else if ($grade['userid'] == $this->anotherstudentg1->id) { 1785 $this->assertEquals($this->student->id, $grade['reviewedby'][0]['userid']); // Check reviewer. 1786 $this->assertEquals($this->student->id, $grade['reviewerof'][0]['userid']); // Check reviewer. 1787 $this->assertEquals($workshop->real_grade(55), $grade['reviewerof'][0]['grade']); // Check grade (converted). 1788 $this->assertEquals($workshop->real_grade(50), $grade['reviewedby'][0]['grade']); // Check grade (converted). 1789 } 1790 } 1791 // Now check pagination. 1792 $result = mod_workshop_external::get_grades_report($this->workshop->id, 0, 'lastname', 'ASC', 0, 1); 1793 $result = \external_api::clean_returnvalue(mod_workshop_external::get_grades_report_returns(), $result); 1794 $this->assertEquals(3, $result['report']['totalcount']); // Expect the total count. 1795 $this->assertCount(1, $result['report']['grades']); 1796 1797 // Groups filtering. 1798 $result = mod_workshop_external::get_grades_report($this->workshop->id, $this->group1->id); 1799 $result = \external_api::clean_returnvalue(mod_workshop_external::get_grades_report_returns(), $result); 1800 $this->assertEquals(2, $result['report']['totalcount']); // Expect the group count. 1801 } 1802 1803 /** 1804 * Test get_grades_report_invalid_phase. 1805 */ 1806 public function test_get_grades_report_invalid_phase() { 1807 $this->setUser($this->teacher); 1808 $this->expectException('moodle_exception'); 1809 $this->expectExceptionMessage(get_string('nothingfound', 'workshop')); 1810 mod_workshop_external::get_grades_report($this->workshop->id); 1811 } 1812 1813 /** 1814 * Test get_grades_report_missing_permissions. 1815 */ 1816 public function test_get_grades_report_missing_permissions() { 1817 $this->setUser($this->student); 1818 $this->expectException('required_capability_exception'); 1819 mod_workshop_external::get_grades_report($this->workshop->id); 1820 } 1821 1822 /** 1823 * Test test_view_submission. 1824 */ 1825 public function test_view_submission() { 1826 1827 // Create a couple of submissions with files. 1828 $firstsubmissionid = $this->create_test_submission($this->student); // Create submission with files. 1829 1830 // Trigger and capture the event. 1831 $sink = $this->redirectEvents(); 1832 1833 $this->setUser($this->student); 1834 $result = mod_workshop_external::view_submission($firstsubmissionid); 1835 $result = \external_api::clean_returnvalue(mod_workshop_external::view_submission_returns(), $result); 1836 1837 $events = $sink->get_events(); 1838 $this->assertCount(1, $events); 1839 $event = array_shift($events); 1840 1841 // Checking that the event contains the expected values. 1842 $this->assertInstanceOf('\mod_workshop\event\submission_viewed', $event); 1843 $this->assertEquals($this->context, $event->get_context()); 1844 $moodleworkshop = new \moodle_url('/mod/workshop/submission.php', array('id' => $firstsubmissionid, 1845 'cmid' => $this->cm->id)); 1846 $this->assertEquals($moodleworkshop, $event->get_url()); 1847 $this->assertEventContextNotUsed($event); 1848 $this->assertNotEmpty($event->get_name()); 1849 1850 } 1851 1852 /** 1853 * Test evaluate_submission. 1854 */ 1855 public function test_evaluate_submission() { 1856 global $DB; 1857 1858 $workshopgenerator = $this->getDataGenerator()->get_plugin_generator('mod_workshop'); 1859 $submissionid = $workshopgenerator->create_submission($this->workshop->id, $this->student->id); 1860 1861 $workshop = new workshop($this->workshop, $this->cm, $this->course); 1862 $workshop->switch_phase(workshop::PHASE_EVALUATION); 1863 1864 $this->setUser($this->teacher); 1865 $feedbacktext = 'The feedback'; 1866 $feedbackformat = FORMAT_MOODLE; 1867 $published = 1; 1868 $gradeover = 10; 1869 $result = mod_workshop_external::evaluate_submission($submissionid, $feedbacktext, $feedbackformat, $published, 1870 $gradeover); 1871 $result = \external_api::clean_returnvalue(mod_workshop_external::evaluate_submission_returns(), $result); 1872 $this->assertTrue($result['status']); 1873 1874 $submission = $DB->get_record('workshop_submissions', array('id' => $submissionid)); 1875 $this->assertEquals($feedbacktext, $submission->feedbackauthor); 1876 $this->assertEquals($workshop->raw_grade_value($gradeover, $workshop->grade), $submission->gradeover); // Expected grade. 1877 $this->assertEquals(1, $submission->published); // Submission published. 1878 } 1879 1880 /** 1881 * Test evaluate_submission_invalid_phase_for_override. 1882 */ 1883 public function test_evaluate_submission_invalid_phase_for_override() { 1884 global $DB; 1885 1886 $workshopgenerator = $this->getDataGenerator()->get_plugin_generator('mod_workshop'); 1887 $submissionid = $workshopgenerator->create_submission($this->workshop->id, $this->student->id); 1888 1889 $this->setUser($this->teacher); 1890 $feedbacktext = 'The feedback'; 1891 $feedbackformat = FORMAT_MOODLE; 1892 $published = 1; 1893 $gradeover = 10; 1894 $result = mod_workshop_external::evaluate_submission($submissionid, $feedbacktext, $feedbackformat, $published, 1895 $gradeover); 1896 $result = \external_api::clean_returnvalue(mod_workshop_external::evaluate_submission_returns(), $result); 1897 $this->assertTrue($result['status']); 1898 1899 $submission = $DB->get_record('workshop_submissions', array('id' => $submissionid)); 1900 $this->assertEquals('', $submission->feedbackauthor); // Feedback and grade not updated. 1901 $this->assertEquals(0, $submission->gradeover); 1902 $this->assertEquals(1, $submission->published); // Publishing status correctly updated. 1903 } 1904 1905 /** 1906 * Test evaluate_submission_no_permissions. 1907 */ 1908 public function test_evaluate_submission_no_permissions() { 1909 1910 $workshopgenerator = $this->getDataGenerator()->get_plugin_generator('mod_workshop'); 1911 $submissionid = $workshopgenerator->create_submission($this->workshop->id, $this->student->id); 1912 $workshop = new workshop($this->workshop, $this->cm, $this->course); 1913 $workshop->switch_phase(workshop::PHASE_EVALUATION); 1914 1915 $this->setUser($this->student); 1916 $feedbacktext = 'The feedback'; 1917 $feedbackformat = FORMAT_MOODLE; 1918 $published = 1; 1919 $gradeover = 50; 1920 $this->expectException('moodle_exception'); 1921 mod_workshop_external::evaluate_submission($submissionid, $feedbacktext, $feedbackformat, $published, $gradeover); 1922 } 1923 1924 /** 1925 * Test evaluate_submission_invalid_grade. 1926 */ 1927 public function test_evaluate_submission_invalid_grade() { 1928 1929 $workshopgenerator = $this->getDataGenerator()->get_plugin_generator('mod_workshop'); 1930 $submissionid = $workshopgenerator->create_submission($this->workshop->id, $this->student->id); 1931 $workshop = new workshop($this->workshop, $this->cm, $this->course); 1932 $workshop->switch_phase(workshop::PHASE_EVALUATION); 1933 1934 $this->setUser($this->teacher); 1935 $feedbacktext = 'The feedback'; 1936 $feedbackformat = FORMAT_MOODLE; 1937 $published = 1; 1938 $gradeover = 150; 1939 $result = mod_workshop_external::evaluate_submission($submissionid, $feedbacktext, $feedbackformat, $published, $gradeover); 1940 $result = \external_api::clean_returnvalue(mod_workshop_external::evaluate_submission_returns(), $result); 1941 $this->assertCount(1, $result['warnings']); 1942 $this->assertFalse($result['status']); 1943 $this->assertEquals('gradeover', $result['warnings'][0]['item']); 1944 } 1945 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body