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