Rev 1 | Ir a la última revisión | Autoría | Comparar con el anterior | Ultima modificación | Ver Log |
<?php// This file is part of Moodle - http://moodle.org///// Moodle is free software: you can redistribute it and/or modify// it under the terms of the GNU General Public License as published by// the Free Software Foundation, either version 3 of the License, or// (at your option) any later version.//// Moodle is distributed in the hope that it will be useful,// but WITHOUT ANY WARRANTY; without even the implied warranty of// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the// GNU General Public License for more details.//// You should have received a copy of the GNU General Public License// along with Moodle. If not, see <http://www.gnu.org/licenses/>./*** Workshop module external functions tests** @package mod_workshop* @category external* @copyright 2017 Juan Leyva <juan@moodle.com>* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later* @since Moodle 3.4*/namespace mod_workshop\external;use core_external\external_api;use externallib_advanced_testcase;use mod_workshop_external;use workshop;defined('MOODLE_INTERNAL') || die();global $CFG;require_once($CFG->dirroot . '/webservice/tests/helpers.php');require_once($CFG->dirroot . '/mod/workshop/lib.php');/*** Workshop module external functions tests** @package mod_workshop* @category external* @copyright 2017 Juan Leyva <juan@moodle.com>* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later* @since Moodle 3.4*/class external_test extends externallib_advanced_testcase {/** @var stdClass course object */private $course;/** @var stdClass workshop object */private $workshop;/** @var stdClass context object */private $context;/** @var stdClass cm object */private $cm;/** @var stdClass student object */private $student;/** @var stdClass teacher object */private $teacher;/** @var stdClass student role object */private $studentrole;/** @var stdClass teacher role object */private $teacherrole;/** @var \stdClass student object. */private $anotherstudentg1;/** @var \stdClass student object. */private $anotherstudentg2;/** @var \stdClass group object. */private $group1;/** @var \stdClass group object. */private $group2;/*** Set up for every test*/public function setUp(): void {global $DB;$this->resetAfterTest();$this->setAdminUser();// Setup test data.$course = new \stdClass();$course->groupmode = SEPARATEGROUPS;$course->groupmodeforce = true;$this->course = $this->getDataGenerator()->create_course($course);$this->workshop = $this->getDataGenerator()->create_module('workshop',array('course' => $this->course->id,'overallfeedbackfiles' => 1,));$this->context = \context_module::instance($this->workshop->cmid);$this->cm = get_coursemodule_from_instance('workshop', $this->workshop->id);// Add grading strategy data (accumulative is the default).$workshop = new workshop($this->workshop, $this->cm, $this->course);$strategy = $workshop->grading_strategy_instance();$data = array();for ($i = 0; $i < 4; $i++) {$data['dimensionid__idx_'.$i] = 0;$data['description__idx_'.$i.'_editor'] = array('text' => "Content $i", 'format' => FORMAT_MOODLE);$data['grade__idx_'.$i] = 25;$data['weight__idx_'.$i] = 25;}$data['workshopid'] = $workshop->id;$data['norepeats'] = 4;$strategy->save_edit_strategy_form((object) $data);// Create users.$this->student = self::getDataGenerator()->create_user();$this->anotherstudentg1 = self::getDataGenerator()->create_user();$this->anotherstudentg2 = self::getDataGenerator()->create_user();$this->teacher = self::getDataGenerator()->create_user();// Users enrolments.$this->studentrole = $DB->get_record('role', array('shortname' => 'student'));$this->teacherrole = $DB->get_record('role', array('shortname' => 'editingteacher'));$this->getDataGenerator()->enrol_user($this->student->id, $this->course->id, $this->studentrole->id, 'manual');$this->getDataGenerator()->enrol_user($this->anotherstudentg1->id, $this->course->id, $this->studentrole->id, 'manual');$this->getDataGenerator()->enrol_user($this->anotherstudentg2->id, $this->course->id, $this->studentrole->id, 'manual');$this->getDataGenerator()->enrol_user($this->teacher->id, $this->course->id, $this->teacherrole->id, 'manual');$this->group1 = $this->getDataGenerator()->create_group(array('courseid' => $this->course->id));$this->group2 = $this->getDataGenerator()->create_group(array('courseid' => $this->course->id));groups_add_member($this->group1, $this->student);groups_add_member($this->group1, $this->anotherstudentg1);groups_add_member($this->group2, $this->anotherstudentg2);}/*** Test test_mod_workshop_get_workshops_by_courses*/public function test_mod_workshop_get_workshops_by_courses(): void {// Create additional course.$course2 = self::getDataGenerator()->create_course();// Second workshop.$record = new \stdClass();$record->course = $course2->id;$workshop2 = self::getDataGenerator()->create_module('workshop', $record);// Execute real Moodle enrolment as we'll call unenrol() method on the instance later.$enrol = enrol_get_plugin('manual');$enrolinstances = enrol_get_instances($course2->id, true);foreach ($enrolinstances as $courseenrolinstance) {if ($courseenrolinstance->enrol == "manual") {$instance2 = $courseenrolinstance;break;}}$enrol->enrol_user($instance2, $this->student->id, $this->studentrole->id);self::setUser($this->student);$returndescription = mod_workshop_external::get_workshops_by_courses_returns();// Create what we expect to be returned when querying the two courses.$properties = workshop_summary_exporter::read_properties_definition();$expectedfields = array_keys($properties);// Add expected coursemodule and data.$workshop1 = $this->workshop;$workshop1->coursemodule = $workshop1->cmid;$workshop1->introformat = 1;$workshop1->introfiles = [];$workshop1->lang = '';$workshop1->instructauthorsfiles = [];$workshop1->instructauthorsformat = 1;$workshop1->instructreviewersfiles = [];$workshop1->instructreviewersformat = 1;$workshop1->conclusionfiles = [];$workshop1->conclusionformat = 1;$workshop1->submissiontypetext = 1;$workshop1->submissiontypefile = 1;$workshop2->coursemodule = $workshop2->cmid;$workshop2->introformat = 1;$workshop2->introfiles = [];$workshop2->lang = '';$workshop2->instructauthorsfiles = [];$workshop2->instructauthorsformat = 1;$workshop2->instructreviewersfiles = [];$workshop2->instructreviewersformat = 1;$workshop2->conclusionfiles = [];$workshop2->conclusionformat = 1;$workshop2->submissiontypetext = 1;$workshop2->submissiontypefile = 1;foreach ($expectedfields as $field) {if (!empty($properties[$field]) && $properties[$field]['type'] == PARAM_BOOL) {$workshop1->{$field} = (bool) $workshop1->{$field};$workshop2->{$field} = (bool) $workshop2->{$field};}$expected1[$field] = $workshop1->{$field};$expected2[$field] = $workshop2->{$field};}$expectedworkshops = array($expected2, $expected1);// Call the external function passing course ids.$result = mod_workshop_external::get_workshops_by_courses(array($course2->id, $this->course->id));$result = external_api::clean_returnvalue($returndescription, $result);$this->assertEquals($expectedworkshops, $result['workshops']);$this->assertCount(0, $result['warnings']);// Call the external function without passing course id.$result = mod_workshop_external::get_workshops_by_courses();$result = external_api::clean_returnvalue($returndescription, $result);$this->assertEquals($expectedworkshops, $result['workshops']);$this->assertCount(0, $result['warnings']);// Unenrol user from second course and alter expected workshops.$enrol->unenrol_user($instance2, $this->student->id);array_shift($expectedworkshops);// Call the external function without passing course id.$result = mod_workshop_external::get_workshops_by_courses();$result = external_api::clean_returnvalue($returndescription, $result);$this->assertEquals($expectedworkshops, $result['workshops']);// Call for the second course we unenrolled the user from, expected warning.$result = mod_workshop_external::get_workshops_by_courses(array($course2->id));$this->assertCount(1, $result['warnings']);$this->assertEquals('1', $result['warnings'][0]['warningcode']);$this->assertEquals($course2->id, $result['warnings'][0]['itemid']);}/*** Test mod_workshop_get_workshop_access_information for students.*/public function test_mod_workshop_get_workshop_access_information_student(): void {self::setUser($this->student);$result = mod_workshop_external::get_workshop_access_information($this->workshop->id);$result = external_api::clean_returnvalue(mod_workshop_external::get_workshop_access_information_returns(), $result);// Check default values for capabilities.$enabledcaps = array('canpeerassess', 'cansubmit', 'canview', 'canviewauthornames', 'canviewauthorpublished','canviewpublishedsubmissions', 'canexportsubmissions');foreach ($result as $capname => $capvalue) {if (strpos($capname, 'can') !== 0) {continue;}if (in_array($capname, $enabledcaps)) {$this->assertTrue($capvalue);} else {$this->assertFalse($capvalue);}}// Now, unassign some capabilities.unassign_capability('mod/workshop:peerassess', $this->studentrole->id);unassign_capability('mod/workshop:submit', $this->studentrole->id);unset($enabledcaps[0]);unset($enabledcaps[1]);accesslib_clear_all_caches_for_unit_testing();$result = mod_workshop_external::get_workshop_access_information($this->workshop->id);$result = external_api::clean_returnvalue(mod_workshop_external::get_workshop_access_information_returns(), $result);foreach ($result as $capname => $capvalue) {if (strpos($capname, 'can') !== 0) {continue;}if (in_array($capname, $enabledcaps)) {$this->assertTrue($capvalue);} else {$this->assertFalse($capvalue);}}// Now, specific functionalities.$this->assertFalse($result['creatingsubmissionallowed']);$this->assertFalse($result['modifyingsubmissionallowed']);$this->assertFalse($result['assessingallowed']);$this->assertFalse($result['assessingexamplesallowed']);$this->assertTrue($result['examplesassessedbeforesubmission']);$this->assertTrue($result['examplesassessedbeforeassessment']);// Switch phase.$workshop = new workshop($this->workshop, $this->cm, $this->course);$workshop->switch_phase(workshop::PHASE_SUBMISSION);$result = mod_workshop_external::get_workshop_access_information($this->workshop->id);$result = external_api::clean_returnvalue(mod_workshop_external::get_workshop_access_information_returns(), $result);$this->assertTrue($result['creatingsubmissionallowed']);$this->assertTrue($result['modifyingsubmissionallowed']);$this->assertFalse($result['assessingallowed']);$this->assertFalse($result['assessingexamplesallowed']);$this->assertTrue($result['examplesassessedbeforesubmission']);$this->assertTrue($result['examplesassessedbeforeassessment']);// Switch to next (to assessment).$workshop->switch_phase(workshop::PHASE_ASSESSMENT);$result = mod_workshop_external::get_workshop_access_information($this->workshop->id);$result = external_api::clean_returnvalue(mod_workshop_external::get_workshop_access_information_returns(), $result);$this->assertFalse($result['creatingsubmissionallowed']);$this->assertFalse($result['modifyingsubmissionallowed']);$this->assertTrue($result['assessingallowed']);$this->assertFalse($result['assessingexamplesallowed']);$this->assertTrue($result['examplesassessedbeforesubmission']);$this->assertTrue($result['examplesassessedbeforeassessment']);}/*** Test mod_workshop_get_workshop_access_information for teachers.*/public function test_mod_workshop_get_workshop_access_information_teacher(): void {self::setUser($this->teacher);$result = mod_workshop_external::get_workshop_access_information($this->workshop->id);$result = external_api::clean_returnvalue(mod_workshop_external::get_workshop_access_information_returns(), $result);// Check default values.$disabledcaps = array('canpeerassess', 'cansubmit');foreach ($result as $capname => $capvalue) {if (strpos($capname, 'can') !== 0) {continue;}if (in_array($capname, $disabledcaps)) {$this->assertFalse($capvalue);} else {$this->assertTrue($capvalue);}}// Now, specific functionalities.$this->assertFalse($result['creatingsubmissionallowed']);$this->assertFalse($result['modifyingsubmissionallowed']);$this->assertFalse($result['assessingallowed']);$this->assertFalse($result['assessingexamplesallowed']);}/*** Test mod_workshop_get_user_plan for students.*/public function test_mod_workshop_get_user_plan_student(): void {self::setUser($this->student);$result = mod_workshop_external::get_user_plan($this->workshop->id);$result = external_api::clean_returnvalue(mod_workshop_external::get_user_plan_returns(), $result);$this->assertCount(0, $result['userplan']['examples']); // No examples given.$this->assertCount(5, $result['userplan']['phases']); // Always 5 phases.$this->assertEquals(workshop::PHASE_SETUP, $result['userplan']['phases'][0]['code']); // First phase always setup.$this->assertTrue($result['userplan']['phases'][0]['active']); // First phase "Setup" active in new workshops.// Switch phase.$workshop = new workshop($this->workshop, $this->cm, $this->course);$workshop->switch_phase(workshop::PHASE_SUBMISSION);$result = mod_workshop_external::get_user_plan($this->workshop->id);$result = external_api::clean_returnvalue(mod_workshop_external::get_user_plan_returns(), $result);$this->assertEquals(workshop::PHASE_SUBMISSION, $result['userplan']['phases'][1]['code']);$this->assertTrue($result['userplan']['phases'][1]['active']); // We are now in submission phase.}/*** Test mod_workshop_get_user_plan for teachers.*/public function test_mod_workshop_get_user_plan_teacher(): void {self::setUser($this->teacher);$result = mod_workshop_external::get_user_plan($this->workshop->id);$result = external_api::clean_returnvalue(mod_workshop_external::get_user_plan_returns(), $result);$this->assertCount(0, $result['userplan']['examples']); // No examples given.$this->assertCount(5, $result['userplan']['phases']); // Always 5 phases.$this->assertEquals(workshop::PHASE_SETUP, $result['userplan']['phases'][0]['code']); // First phase always setup.$this->assertTrue($result['userplan']['phases'][0]['active']); // First phase "Setup" active in new workshops.$this->assertCount(4, $result['userplan']['phases'][0]['tasks']); // For new empty workshops, always 4 tasks.foreach ($result['userplan']['phases'][0]['tasks'] as $task) {if ($task['code'] == 'intro' || $task['code'] == 'instructauthors' || $task['code'] == 'editform') {$this->assertEquals(1, $task['completed']);} else {$this->assertEmpty($task['completed']);}}// Do some of the tasks asked - switch phase.$workshop = new workshop($this->workshop, $this->cm, $this->course);$workshop->switch_phase(workshop::PHASE_SUBMISSION);$result = mod_workshop_external::get_user_plan($this->workshop->id);$result = external_api::clean_returnvalue(mod_workshop_external::get_user_plan_returns(), $result);foreach ($result['userplan']['phases'][0]['tasks'] as $task) {if ($task['code'] == 'intro' || $task['code'] == 'instructauthors' || $task['code'] == 'editform' ||$task['code'] == 'switchtonextphase') {$this->assertEquals(1, $task['completed']);} else {$this->assertEmpty($task['completed']);}}$result = mod_workshop_external::get_user_plan($this->workshop->id);$result = external_api::clean_returnvalue(mod_workshop_external::get_user_plan_returns(), $result);$this->assertEquals(workshop::PHASE_SUBMISSION, $result['userplan']['phases'][1]['code']);$this->assertTrue($result['userplan']['phases'][1]['active']); // We are now in submission phase.}/*** Test test_view_workshop invalid id.*/public function test_view_workshop_invalid_id(): void {$this->expectException('moodle_exception');mod_workshop_external::view_workshop(0);}/*** Test test_view_workshop user not enrolled.*/public function test_view_workshop_user_not_enrolled(): void {// Test not-enrolled user.$usernotenrolled = self::getDataGenerator()->create_user();$this->setUser($usernotenrolled);$this->expectException('moodle_exception');mod_workshop_external::view_workshop($this->workshop->id);}/*** Test test_view_workshop user student.*/public function test_view_workshop_user_student(): void {// Test user with full capabilities.$this->setUser($this->student);// Trigger and capture the event.$sink = $this->redirectEvents();$result = mod_workshop_external::view_workshop($this->workshop->id);$result = external_api::clean_returnvalue(mod_workshop_external::view_workshop_returns(), $result);$this->assertTrue($result['status']);$events = $sink->get_events();$this->assertCount(1, $events);$event = array_shift($events);// Checking that the event contains the expected values.$this->assertInstanceOf('\mod_workshop\event\course_module_viewed', $event);$this->assertEquals($this->context, $event->get_context());$moodleworkshop = new \moodle_url('/mod/workshop/view.php', array('id' => $this->cm->id));$this->assertEquals($moodleworkshop, $event->get_url());$this->assertEventContextNotUsed($event);$this->assertNotEmpty($event->get_name());}/*** Test test_view_workshop user missing capabilities.*/public function test_view_workshop_user_missing_capabilities(): void {// Test user with no capabilities.// We need a explicit prohibit since this capability is only defined in authenticated user and guest roles.assign_capability('mod/workshop:view', CAP_PROHIBIT, $this->studentrole->id, $this->context->id);// Empty all the caches that may be affected by this change.accesslib_clear_all_caches_for_unit_testing();\course_modinfo::clear_instance_cache();$this->setUser($this->student);$this->expectException('moodle_exception');mod_workshop_external::view_workshop($this->workshop->id);}/*** Test test_add_submission.*/public function test_add_submission(): void {$fs = get_file_storage();// Test user with full capabilities.$this->setUser($this->student);$title = 'Submission title';$content = 'Submission contents';// Create a file in a draft area for inline attachments.$draftidinlineattach = file_get_unused_draft_itemid();$usercontext = \context_user::instance($this->student->id);$filenameimg = 'shouldbeanimage.txt';$filerecordinline = array('contextid' => $usercontext->id,'component' => 'user','filearea' => 'draft','itemid' => $draftidinlineattach,'filepath' => '/','filename' => $filenameimg,);$fs->create_file_from_string($filerecordinline, 'image contents (not really)');// Create a file in a draft area for regular attachments.$draftidattach = file_get_unused_draft_itemid();$filerecordattach = $filerecordinline;$attachfilename = 'attachment.txt';$filerecordattach['filename'] = $attachfilename;$filerecordattach['itemid'] = $draftidattach;$fs->create_file_from_string($filerecordattach, 'simple text attachment');// Switch to submission phase.$workshop = new workshop($this->workshop, $this->cm, $this->course);$workshop->switch_phase(workshop::PHASE_SUBMISSION);$result = mod_workshop_external::add_submission($this->workshop->id, $title, $content, FORMAT_MOODLE, $draftidinlineattach,$draftidattach);$result = external_api::clean_returnvalue(mod_workshop_external::add_submission_returns(), $result);$this->assertEmpty($result['warnings']);// Check submission created.$submission = $workshop->get_submission_by_author($this->student->id);$this->assertTrue($result['status']);$this->assertEquals($result['submissionid'], $submission->id);$this->assertEquals($title, $submission->title);$this->assertEquals($content, $submission->content);// Check files.$contentfiles = $fs->get_area_files($this->context->id, 'mod_workshop', 'submission_content', $submission->id);$this->assertCount(2, $contentfiles);foreach ($contentfiles as $file) {if ($file->is_directory()) {continue;} else {$this->assertEquals($filenameimg, $file->get_filename());}}$contentfiles = $fs->get_area_files($this->context->id, 'mod_workshop', 'submission_attachment', $submission->id);$this->assertCount(2, $contentfiles);foreach ($contentfiles as $file) {if ($file->is_directory()) {continue;} else {$this->assertEquals($attachfilename, $file->get_filename());}}}/*** Test test_add_submission invalid phase.*/public function test_add_submission_invalid_phase(): void {$this->setUser($this->student);$this->expectException('moodle_exception');mod_workshop_external::add_submission($this->workshop->id, 'Test');}/*** Test test_add_submission empty title.*/public function test_add_submission_empty_title(): void {$this->setUser($this->student);// Switch to submission phase.$workshop = new workshop($this->workshop, $this->cm, $this->course);$workshop->switch_phase(workshop::PHASE_SUBMISSION);$this->expectException('moodle_exception');mod_workshop_external::add_submission($this->workshop->id, '');}/*** Test test_add_submission already added.*/public function test_add_submission_already_added(): void {$this->setUser($this->student);$usercontext = \context_user::instance($this->student->id);$fs = get_file_storage();$draftidattach = file_get_unused_draft_itemid();$filerecordattach = ['contextid' => $usercontext->id,'component' => 'user','filearea' => 'draft','itemid' => $draftidattach,'filepath' => '/','filename' => 'attachement.txt'];$fs->create_file_from_string($filerecordattach, 'simple text attachment');// Switch to submission phase.$workshop = new workshop($this->workshop, $this->cm, $this->course);$workshop->switch_phase(workshop::PHASE_SUBMISSION);// Create the submission.$result = mod_workshop_external::add_submission($this->workshop->id, 'My submission', '', FORMAT_MOODLE, 0, $draftidattach);$result = external_api::clean_returnvalue(mod_workshop_external::add_submission_returns(), $result);// Try to create it again.$result = mod_workshop_external::add_submission($this->workshop->id, 'My submission', '', FORMAT_MOODLE, 0, $draftidattach);$result = external_api::clean_returnvalue(mod_workshop_external::add_submission_returns(), $result);$this->assertFalse($result['status']);$this->assertArrayNotHasKey('submissionid', $result);$this->assertCount(1, $result['warnings']);$this->assertEquals('fielderror', $result['warnings'][0]['warningcode']);$this->assertEquals('title', $result['warnings'][0]['item']);}/*** Helper method to create a submission for testing for the given user.** @param int $user the submission will be created by this student.* @return int the submission id*/protected function create_test_submission($user) {// Test user with full capabilities.$this->setUser($user);$title = 'Submission title';$content = 'Submission contents';// Create a file in a draft area for inline attachments.$fs = get_file_storage();$draftidinlineattach = file_get_unused_draft_itemid();$usercontext = \context_user::instance($user->id);$filenameimg = 'shouldbeanimage.txt';$filerecordinline = array('contextid' => $usercontext->id,'component' => 'user','filearea' => 'draft','itemid' => $draftidinlineattach,'filepath' => '/','filename' => $filenameimg,);$fs->create_file_from_string($filerecordinline, 'image contents (not really)');// Create a file in a draft area for regular attachments.$draftidattach = file_get_unused_draft_itemid();$filerecordattach = $filerecordinline;$attachfilename = 'attachment.txt';$filerecordattach['filename'] = $attachfilename;$filerecordattach['itemid'] = $draftidattach;$fs->create_file_from_string($filerecordattach, 'simple text attachment');// Switch to submission phase.$workshop = new workshop($this->workshop, $this->cm, $this->course);$workshop->switch_phase(workshop::PHASE_SUBMISSION);$result = mod_workshop_external::add_submission($this->workshop->id, $title, $content, FORMAT_MOODLE, $draftidinlineattach,$draftidattach);return $result['submissionid'];}/*** Test test_update_submission.*/public function test_update_submission(): void {// Create the submission that will be updated.$submissionid = $this->create_test_submission($this->student);// Test user with full capabilities.$this->setUser($this->student);$title = 'Submission new title';$content = 'Submission new contents';// Create a different file in a draft area for inline attachments.$fs = get_file_storage();$draftidinlineattach = file_get_unused_draft_itemid();$usercontext = \context_user::instance($this->student->id);$filenameimg = 'shouldbeanimage_new.txt';$filerecordinline = array('contextid' => $usercontext->id,'component' => 'user','filearea' => 'draft','itemid' => $draftidinlineattach,'filepath' => '/','filename' => $filenameimg,);$fs->create_file_from_string($filerecordinline, 'image contents (not really)');// Create a different file in a draft area for regular attachments.$draftidattach = file_get_unused_draft_itemid();$filerecordattach = $filerecordinline;$attachfilename = 'attachment_new.txt';$filerecordattach['filename'] = $attachfilename;$filerecordattach['itemid'] = $draftidattach;$fs->create_file_from_string($filerecordattach, 'simple text attachment');$result = mod_workshop_external::update_submission($submissionid, $title, $content, FORMAT_MOODLE, $draftidinlineattach,$draftidattach);$result = external_api::clean_returnvalue(mod_workshop_external::update_submission_returns(), $result);$this->assertEmpty($result['warnings']);// Check submission updated.$workshop = new workshop($this->workshop, $this->cm, $this->course);$submission = $workshop->get_submission_by_id($submissionid);$this->assertTrue($result['status']);$this->assertEquals($title, $submission->title);$this->assertEquals($content, $submission->content);// Check files.$contentfiles = $fs->get_area_files($this->context->id, 'mod_workshop', 'submission_content', $submission->id);$this->assertCount(2, $contentfiles);foreach ($contentfiles as $file) {if ($file->is_directory()) {continue;} else {$this->assertEquals($filenameimg, $file->get_filename());}}$contentfiles = $fs->get_area_files($this->context->id, 'mod_workshop', 'submission_attachment', $submission->id);$this->assertCount(2, $contentfiles);foreach ($contentfiles as $file) {if ($file->is_directory()) {continue;} else {$this->assertEquals($attachfilename, $file->get_filename());}}}/*** Test test_update_submission belonging to other user.*/public function test_update_submission_of_other_user(): void {// Create the submission that will be updated.$submissionid = $this->create_test_submission($this->student);$this->setUser($this->teacher);$this->expectException('moodle_exception');mod_workshop_external::update_submission($submissionid, 'Test');}/*** Test test_update_submission invalid phase.*/public function test_update_submission_invalid_phase(): void {// Create the submission that will be updated.$submissionid = $this->create_test_submission($this->student);$this->setUser($this->student);// Switch to assessment phase.$workshop = new workshop($this->workshop, $this->cm, $this->course);$workshop->switch_phase(workshop::PHASE_ASSESSMENT);$this->expectException('moodle_exception');mod_workshop_external::update_submission($submissionid, 'Test');}/*** Test test_update_submission empty title.*/public function test_update_submission_empty_title(): void {// Create the submission that will be updated.$submissionid = $this->create_test_submission($this->student);$this->setUser($this->student);$this->expectException('moodle_exception');mod_workshop_external::update_submission($submissionid, '');}/*** Test test_delete_submission.*/public function test_delete_submission(): void {// Create the submission that will be deleted.$submissionid = $this->create_test_submission($this->student);$this->setUser($this->student);// Trigger and capture the event.$sink = $this->redirectEvents();$result = mod_workshop_external::delete_submission($submissionid);$result = external_api::clean_returnvalue(mod_workshop_external::delete_submission_returns(), $result);$this->assertEmpty($result['warnings']);$this->assertTrue($result['status']);$workshop = new workshop($this->workshop, $this->cm, $this->course);$submission = $workshop->get_submission_by_author($this->student->id);$this->assertFalse($submission);$events = $sink->get_events();$this->assertCount(1, $events);$event = array_shift($events);// Checking event.$this->assertInstanceOf('\mod_workshop\event\submission_deleted', $event);$this->assertEquals($this->context, $event->get_context());}/*** Test test_delete_submission_with_assessments.*/public function test_delete_submission_with_assessments(): void {// Create the submission that will be deleted.$submissionid = $this->create_test_submission($this->student);$workshopgenerator = $this->getDataGenerator()->get_plugin_generator('mod_workshop');$workshopgenerator->create_assessment($submissionid, $this->teacher->id, array('weight' => 3,'grade' => 95.00000,));$this->setUser($this->student);$this->expectException('moodle_exception');mod_workshop_external::delete_submission($submissionid);}/*** Test test_delete_submission_invalid_phase.*/public function test_delete_submission_invalid_phase(): void {// Create the submission that will be deleted.$submissionid = $this->create_test_submission($this->student);// Switch to assessment phase.$workshop = new workshop($this->workshop, $this->cm, $this->course);$workshop->switch_phase(workshop::PHASE_ASSESSMENT);$this->setUser($this->student);$this->expectException('moodle_exception');mod_workshop_external::delete_submission($submissionid);}/*** Test test_delete_submission_as_teacher.*/public function test_delete_submission_as_teacher(): void {// Create the submission that will be deleted.$submissionid = $this->create_test_submission($this->student);$this->setUser($this->teacher);$result = mod_workshop_external::delete_submission($submissionid);$result = external_api::clean_returnvalue(mod_workshop_external::delete_submission_returns(), $result);$this->assertEmpty($result['warnings']);$this->assertTrue($result['status']);}/*** Test test_delete_submission_other_user.*/public function test_delete_submission_other_user(): void {$anotheruser = self::getDataGenerator()->create_user();$this->getDataGenerator()->enrol_user($anotheruser->id, $this->course->id, $this->studentrole->id, 'manual');// Create the submission that will be deleted.$submissionid = $this->create_test_submission($this->student);$this->setUser($anotheruser);$this->expectException('moodle_exception');mod_workshop_external::delete_submission($submissionid);}/*** Test test_get_submissions_student.*/public function test_get_submissions_student(): void {// Create a couple of submissions with files.$firstsubmissionid = $this->create_test_submission($this->student); // Create submission with files.$secondsubmissionid = $this->create_test_submission($this->anotherstudentg1);$this->setUser($this->student);$result = mod_workshop_external::get_submissions($this->workshop->id);$result = external_api::clean_returnvalue(mod_workshop_external::get_submissions_returns(), $result);// We should get just our submission.$this->assertCount(1, $result['submissions']);$this->assertEquals(1, $result['totalcount']);$this->assertEquals($firstsubmissionid, $result['submissions'][0]['id']);$this->assertCount(1, $result['submissions'][0]['contentfiles']); // Check we retrieve submission text files.$this->assertCount(1, $result['submissions'][0]['attachmentfiles']); // Check we retrieve attachment files.// We shoul not see the grade or feedback information.$properties = submission_exporter::properties_definition();foreach ($properties as $attribute => $settings) {if (!empty($settings['optional'])) {if (isset($result['submissions'][0][$attribute])) {echo "error $attribute";}$this->assertFalse(isset($result['submissions'][0][$attribute]));}}}/*** Test test_get_submissions_published_student.*/public function test_get_submissions_published_student(): void {$workshop = new workshop($this->workshop, $this->cm, $this->course);$workshop->switch_phase(workshop::PHASE_CLOSED);// Create a couple of submissions with files.$workshopgenerator = $this->getDataGenerator()->get_plugin_generator('mod_workshop');$submission = array('published' => 1);$submissionid = $workshopgenerator->create_submission($this->workshop->id, $this->anotherstudentg1->id, $submission);$this->setUser($this->student);$result = mod_workshop_external::get_submissions($this->workshop->id);$result = external_api::clean_returnvalue(mod_workshop_external::get_submissions_returns(), $result);// We should get just our submission.$this->assertCount(1, $result['submissions']);$this->assertEquals(1, $result['totalcount']);$this->assertEquals($submissionid, $result['submissions'][0]['id']);// Check with group restrictions.$this->setUser($this->anotherstudentg2);$result = mod_workshop_external::get_submissions($this->workshop->id);$result = external_api::clean_returnvalue(mod_workshop_external::get_submissions_returns(), $result);$this->assertCount(0, $result['submissions']); // I can't see other users in separated groups.$this->assertEquals(0, $result['totalcount']);}/*** Test test_get_submissions_from_student_with_feedback_from_teacher.*/public function test_get_submissions_from_student_with_feedback_from_teacher(): void {global $DB;// Create a couple of submissions with files.$workshopgenerator = $this->getDataGenerator()->get_plugin_generator('mod_workshop');$submissionid = $workshopgenerator->create_submission($this->workshop->id, $this->student->id);// Create teacher feedback for submission.$record = new \stdClass();$record->id = $submissionid;$record->gradeover = 9;$record->gradeoverby = $this->teacher->id;$record->feedbackauthor = 'Hey';$record->feedbackauthorformat = FORMAT_MOODLE;$record->published = 1;$DB->update_record('workshop_submissions', $record);// Remove teacher caps.assign_capability('mod/workshop:viewallsubmissions', CAP_PROHIBIT, $this->teacher->id, $this->context->id);// Empty all the caches that may be affected by this change.accesslib_clear_all_caches_for_unit_testing();\course_modinfo::clear_instance_cache();$this->setUser($this->teacher);$result = mod_workshop_external::get_submissions($this->workshop->id, $this->student->id);$result = external_api::clean_returnvalue(mod_workshop_external::get_submissions_returns(), $result);// We should get just our submission.$this->assertEquals(1, $result['totalcount']);$this->assertEquals($submissionid, $result['submissions'][0]['id']);}/*** Test test_get_submissions_from_students_as_teacher.*/public function test_get_submissions_from_students_as_teacher(): void {// Create a couple of submissions with files.$workshopgenerator = $this->getDataGenerator()->get_plugin_generator('mod_workshop');$submissionid1 = $workshopgenerator->create_submission($this->workshop->id, $this->student->id);$submissionid2 = $workshopgenerator->create_submission($this->workshop->id, $this->anotherstudentg1->id);$submissionid3 = $workshopgenerator->create_submission($this->workshop->id, $this->anotherstudentg2->id);$this->setUser($this->teacher);$result = mod_workshop_external::get_submissions($this->workshop->id); // Get all.$result = external_api::clean_returnvalue(mod_workshop_external::get_submissions_returns(), $result);$this->assertEquals(3, $result['totalcount']);$this->assertCount(3, $result['submissions']);$result = mod_workshop_external::get_submissions($this->workshop->id, 0, 0, 0, 2); // Check pagination.$result = external_api::clean_returnvalue(mod_workshop_external::get_submissions_returns(), $result);$this->assertEquals(3, $result['totalcount']);$this->assertCount(2, $result['submissions']);$result = mod_workshop_external::get_submissions($this->workshop->id, 0, $this->group2->id); // Get group 2.$result = external_api::clean_returnvalue(mod_workshop_external::get_submissions_returns(), $result);$this->assertEquals(1, $result['totalcount']);$this->assertCount(1, $result['submissions']);$this->assertEquals($submissionid3, $result['submissions'][0]['id']);$result = mod_workshop_external::get_submissions($this->workshop->id, $this->anotherstudentg1->id); // Get one.$result = external_api::clean_returnvalue(mod_workshop_external::get_submissions_returns(), $result);$this->assertEquals(1, $result['totalcount']);$this->assertEquals($submissionid2, $result['submissions'][0]['id']);}/*** Test test_get_submission_student.*/public function test_get_submission_student(): void {// Create a couple of submissions with files.$firstsubmissionid = $this->create_test_submission($this->student); // Create submission with files.$workshop = new workshop($this->workshop, $this->cm, $this->course);$workshop->switch_phase(workshop::PHASE_CLOSED);$this->setUser($this->student);$result = mod_workshop_external::get_submission($firstsubmissionid);$result = external_api::clean_returnvalue(mod_workshop_external::get_submission_returns(), $result);$this->assertEquals($firstsubmissionid, $result['submission']['id']);$this->assertCount(1, $result['submission']['contentfiles']); // Check we retrieve submission text files.$this->assertCount(1, $result['submission']['attachmentfiles']); // Check we retrieve attachment files.$this->assertArrayHasKey('feedbackauthor', $result['submission']);$this->assertArrayNotHasKey('grade', $result['submission']);$this->assertArrayNotHasKey('gradeover', $result['submission']);$this->assertArrayHasKey('gradeoverby', $result['submission']);$this->assertArrayNotHasKey('timegraded', $result['submission']);// Switch to a different phase (where feedback won't be available).$workshop->switch_phase(workshop::PHASE_EVALUATION);$result = mod_workshop_external::get_submission($firstsubmissionid);$result = external_api::clean_returnvalue(mod_workshop_external::get_submission_returns(), $result);$this->assertEquals($firstsubmissionid, $result['submission']['id']);$this->assertCount(1, $result['submission']['contentfiles']); // Check we retrieve submission text files.$this->assertCount(1, $result['submission']['attachmentfiles']); // Check we retrieve attachment files.$this->assertArrayNotHasKey('feedbackauthor', $result['submission']);$this->assertArrayNotHasKey('grade', $result['submission']);$this->assertArrayNotHasKey('gradeover', $result['submission']);$this->assertArrayNotHasKey('gradeoverby', $result['submission']);$this->assertArrayNotHasKey('timegraded', $result['submission']);}/*** Test test_get_submission_i_reviewed.*/public function test_get_submission_i_reviewed(): void {// Create a couple of submissions with files.$firstsubmissionid = $this->create_test_submission($this->student); // Create submission with files.$workshopgenerator = $this->getDataGenerator()->get_plugin_generator('mod_workshop');$workshopgenerator->create_assessment($firstsubmissionid, $this->anotherstudentg1->id, array('weight' => 3,'grade' => 95,));// Now try to get the submission I just reviewed.$this->setUser($this->anotherstudentg1);$result = mod_workshop_external::get_submission($firstsubmissionid);$result = external_api::clean_returnvalue(mod_workshop_external::get_submission_returns(), $result);$this->assertEquals($firstsubmissionid, $result['submission']['id']);$this->assertCount(1, $result['submission']['contentfiles']); // Check we retrieve submission text files.$this->assertCount(1, $result['submission']['attachmentfiles']); // Check we retrieve attachment files.$this->assertArrayNotHasKey('feedbackauthor', $result['submission']);$this->assertArrayNotHasKey('grade', $result['submission']);$this->assertArrayNotHasKey('gradeover', $result['submission']);$this->assertArrayNotHasKey('gradeoverby', $result['submission']);$this->assertArrayNotHasKey('timegraded', $result['submission']);}/*** Test test_get_submission_other_student.*/public function test_get_submission_other_student(): void {// Create a couple of submissions with files.$firstsubmissionid = $this->create_test_submission($this->student); // Create submission with files.// Expect failure.$this->setUser($this->anotherstudentg1);$this->expectException('moodle_exception');$result = mod_workshop_external::get_submission($firstsubmissionid);}/*** Test test_get_submission_published_student.*/public function test_get_submission_published_student(): void {$workshop = new workshop($this->workshop, $this->cm, $this->course);$workshop->switch_phase(workshop::PHASE_CLOSED);// Create a couple of submissions with files.$workshopgenerator = $this->getDataGenerator()->get_plugin_generator('mod_workshop');$submission = array('published' => 1);$submissionid = $workshopgenerator->create_submission($this->workshop->id, $this->anotherstudentg1->id, $submission);$this->setUser($this->student);$result = mod_workshop_external::get_submission($submissionid);$result = external_api::clean_returnvalue(mod_workshop_external::get_submission_returns(), $result);$this->assertEquals($submissionid, $result['submission']['id']);// Check that the student don't see the other student grade/feedback data even if is published.// We should not see the grade or feedback information.$properties = submission_exporter::properties_definition();$this->assertArrayNotHasKey('feedbackauthor', $result['submission']);$this->assertArrayNotHasKey('grade', $result['submission']);$this->assertArrayNotHasKey('gradeover', $result['submission']);$this->assertArrayNotHasKey('gradeoverby', $result['submission']);$this->assertArrayNotHasKey('timegraded', $result['submission']);// Check with group restrictions.$this->setUser($this->anotherstudentg2);$this->expectException('moodle_exception');mod_workshop_external::get_submission($submissionid);}/*** Test test_get_submission_from_student_with_feedback_from_teacher.*/public function test_get_submission_from_student_with_feedback_from_teacher(): void {global $DB;// Create a couple of submissions with files.$workshopgenerator = $this->getDataGenerator()->get_plugin_generator('mod_workshop');$submissionid = $workshopgenerator->create_submission($this->workshop->id, $this->student->id);$workshop = new workshop($this->workshop, $this->cm, $this->course);$workshop->switch_phase(workshop::PHASE_CLOSED);// Create teacher feedback for submission.$record = new \stdClass();$record->id = $submissionid;$record->gradeover = 9;$record->gradeoverby = $this->teacher->id;$record->feedbackauthor = 'Hey';$record->feedbackauthorformat = FORMAT_MOODLE;$record->published = 1;$record->timegraded = time();$DB->update_record('workshop_submissions', $record);$this->setUser($this->teacher);$result = mod_workshop_external::get_submission($submissionid);$result = external_api::clean_returnvalue(mod_workshop_external::get_submission_returns(), $result);$this->assertEquals($submissionid, $result['submission']['id']);$this->assertEquals($record->feedbackauthor, $result['submission']['feedbackauthor']);$this->assertEquals($record->gradeover, $result['submission']['gradeover']);$this->assertEquals($record->gradeoverby, $result['submission']['gradeoverby']);$this->assertEquals($record->timegraded, $result['submission']['timegraded']);// Go to phase where feedback and grades are not yet available.$workshop->switch_phase(workshop::PHASE_SUBMISSION);$result = mod_workshop_external::get_submission($submissionid);$result = external_api::clean_returnvalue(mod_workshop_external::get_submission_returns(), $result);$this->assertArrayNotHasKey('feedbackauthor', $result['submission']);$this->assertArrayNotHasKey('grade', $result['submission']);$this->assertArrayNotHasKey('gradeover', $result['submission']);$this->assertArrayNotHasKey('gradeoverby', $result['submission']);$this->assertArrayNotHasKey('timegraded', $result['submission']);// Remove teacher caps to view and go to valid phase.$workshop->switch_phase(workshop::PHASE_EVALUATION);unassign_capability('mod/workshop:viewallsubmissions', $this->teacherrole->id);// Empty all the caches that may be affected by this change.accesslib_clear_all_caches_for_unit_testing();$this->expectException('moodle_exception');mod_workshop_external::get_submission($submissionid);}/*** Test test_get_submission_from_students_as_teacher.*/public function test_get_submission_from_students_as_teacher(): void {// Create a couple of submissions with files.$workshopgenerator = $this->getDataGenerator()->get_plugin_generator('mod_workshop');$submissionid1 = $workshopgenerator->create_submission($this->workshop->id, $this->student->id);$submissionid2 = $workshopgenerator->create_submission($this->workshop->id, $this->anotherstudentg1->id);$submissionid3 = $workshopgenerator->create_submission($this->workshop->id, $this->anotherstudentg2->id);$this->setUser($this->teacher);$result = mod_workshop_external::get_submission($submissionid1); // Get all.$result = external_api::clean_returnvalue(mod_workshop_external::get_submission_returns(), $result);$this->assertEquals($submissionid1, $result['submission']['id']);$result = mod_workshop_external::get_submission($submissionid3); // Get group 2.$result = external_api::clean_returnvalue(mod_workshop_external::get_submission_returns(), $result);$this->assertEquals($submissionid3, $result['submission']['id']);}/*** Test get_submission_assessments_student.*/public function test_get_submission_assessments_student(): void {// Create the submission that will be deleted.$submissionid = $this->create_test_submission($this->student);$workshopgenerator = $this->getDataGenerator()->get_plugin_generator('mod_workshop');$workshopgenerator->create_assessment($submissionid, $this->anotherstudentg1->id, array('weight' => 3,'grade' => 95,));$workshopgenerator->create_assessment($submissionid, $this->student->id, array('weight' => 2,'grade' => 90,));$workshop = new workshop($this->workshop, $this->cm, $this->course);$workshop->switch_phase(workshop::PHASE_CLOSED);$this->setUser($this->student);$result = mod_workshop_external::get_submission_assessments($submissionid);$result = external_api::clean_returnvalue(mod_workshop_external::get_submission_assessments_returns(), $result);$this->assertCount(2, $result['assessments']); // I received my two assessments.foreach ($result['assessments'] as $assessment) {if ($assessment['grade'] == 90) {// My own assessment, I can see me.$this->assertEquals($this->student->id, $assessment['reviewerid']);} else {// Student's can't see who did the review.$this->assertEquals(0, $assessment['reviewerid']);}}}/*** Test get_submission_assessments_invalid_phase.*/public function test_get_submission_assessments_invalid_phase(): void {// Create the submission that will be deleted.$submissionid = $this->create_test_submission($this->student);$workshopgenerator = $this->getDataGenerator()->get_plugin_generator('mod_workshop');$workshopgenerator->create_assessment($submissionid, $this->anotherstudentg1->id, array('weight' => 3,'grade' => 95,));$this->expectException('moodle_exception');mod_workshop_external::get_submission_assessments($submissionid);}/*** Test get_submission_assessments_teacher.*/public function test_get_submission_assessments_teacher(): void {// Create the submission that will be deleted.$submissionid = $this->create_test_submission($this->student);$workshopgenerator = $this->getDataGenerator()->get_plugin_generator('mod_workshop');$assessmentid = $workshopgenerator->create_assessment($submissionid, $this->anotherstudentg1->id, array('weight' => 1,'grade' => 50,));$this->setUser($this->teacher);$result = mod_workshop_external::get_submission_assessments($submissionid);$result = external_api::clean_returnvalue(mod_workshop_external::get_submission_assessments_returns(), $result);$this->assertCount(1, $result['assessments']);$this->assertEquals(50, $result['assessments'][0]['grade']);$this->assertEquals($assessmentid, $result['assessments'][0]['id']);}/*** Test get_assessment_author.*/public function test_get_assessment_author(): void {// Create the submission.$submissionid = $this->create_test_submission($this->anotherstudentg1);$workshopgenerator = $this->getDataGenerator()->get_plugin_generator('mod_workshop');$assessmentid = $workshopgenerator->create_assessment($submissionid, $this->student->id, array('weight' => 2,'grade' => 90,));// Switch to closed phase.$workshop = new workshop($this->workshop, $this->cm, $this->course);$workshop->switch_phase(workshop::PHASE_CLOSED);$this->setUser($this->anotherstudentg1);$result = mod_workshop_external::get_assessment($assessmentid);$result = external_api::clean_returnvalue(mod_workshop_external::get_assessment_returns(), $result);$this->assertEquals($assessmentid, $result['assessment']['id']);$this->assertEquals(90, $result['assessment']['grade']);// I can't see the reviewer review.$this->assertFalse(isset($result['assessment']['feedbackreviewer']));}/*** Test get_assessment_reviewer.*/public function test_get_assessment_reviewer(): void {// Create the submission.$submissionid = $this->create_test_submission($this->anotherstudentg1);$workshopgenerator = $this->getDataGenerator()->get_plugin_generator('mod_workshop');$assessmentid = $workshopgenerator->create_assessment($submissionid, $this->student->id, array('weight' => 2,'grade' => 90,));// Switch to closed phase.$workshop = new workshop($this->workshop, $this->cm, $this->course);$workshop->switch_phase(workshop::PHASE_CLOSED);$this->setUser($this->student);$result = mod_workshop_external::get_assessment($assessmentid);$result = external_api::clean_returnvalue(mod_workshop_external::get_assessment_returns(), $result);$this->assertEquals($assessmentid, $result['assessment']['id']);$this->assertEquals(90, $result['assessment']['grade']);// I can see the reviewer review.$this->assertTrue(isset($result['assessment']['feedbackreviewer']));}/*** Test get_assessment_teacher.*/public function test_get_assessment_teacher(): void {// Create the submission.$submissionid = $this->create_test_submission($this->anotherstudentg1);$workshopgenerator = $this->getDataGenerator()->get_plugin_generator('mod_workshop');$assessmentid = $workshopgenerator->create_assessment($submissionid, $this->student->id, array('weight' => 2,'grade' => 90,));// Switch to closed phase.$workshop = new workshop($this->workshop, $this->cm, $this->course);$workshop->switch_phase(workshop::PHASE_CLOSED);$this->setUser($this->teacher);$result = mod_workshop_external::get_assessment($assessmentid);$result = external_api::clean_returnvalue(mod_workshop_external::get_assessment_returns(), $result);$this->assertEquals($assessmentid, $result['assessment']['id']);$this->assertEquals(90, $result['assessment']['grade']);}/*** Test get_assessment_student_invalid_phase.*/public function test_get_assessment_student_invalid_phase(): void {// Create the submission.$submissionid = $this->create_test_submission($this->anotherstudentg1);$workshopgenerator = $this->getDataGenerator()->get_plugin_generator('mod_workshop');$assessmentid = $workshopgenerator->create_assessment($submissionid, $this->student->id, array('weight' => 2,'grade' => 90,));// Switch to closed phase.$this->setUser($this->anotherstudentg1);$this->expectException('moodle_exception');mod_workshop_external::get_assessment($assessmentid);}/*** Test get_assessment_student_invalid_user.*/public function test_get_assessment_student_invalid_user(): void {// Create the submission.$submissionid = $this->create_test_submission($this->anotherstudentg1);$workshopgenerator = $this->getDataGenerator()->get_plugin_generator('mod_workshop');$assessmentid = $workshopgenerator->create_assessment($submissionid, $this->student->id, array('weight' => 2,'grade' => 90,));// Switch to closed phase.$workshop = new workshop($this->workshop, $this->cm, $this->course);$workshop->switch_phase(workshop::PHASE_CLOSED);$this->setUser($this->anotherstudentg2);$this->expectException('moodle_exception');mod_workshop_external::get_assessment($assessmentid);}/*** Test get_assessment_form_definition_reviewer_new_assessment.*/public function test_get_assessment_form_definition_reviewer_new_assessment(): void {// Create the submission.$submissionid = $this->create_test_submission($this->anotherstudentg1);$workshop = new workshop($this->workshop, $this->cm, $this->course);$submission = $workshop->get_submission_by_id($submissionid);$assessmentid = $workshop->add_allocation($submission, $this->student->id);// Switch to assessment phase.$workshop->switch_phase(workshop::PHASE_ASSESSMENT);$this->setUser($this->student);$result = mod_workshop_external::get_assessment_form_definition($assessmentid);$result = external_api::clean_returnvalue(mod_workshop_external::get_assessment_form_definition_returns(), $result);$this->assertEquals(4, $result['dimenssionscount']); // We receive the expected 4 dimensions.$this->assertEmpty($result['current']); // Assessment not yet done.foreach ($result['fields'] as $field) {if (strpos($field['name'], 'grade__idx_') === 0) {$this->assertEquals(25, $field['value']); // Check one of the dimension fields attributes.}}// Check dimensions grading info.foreach ($result['dimensionsinfo'] as $dimension) {$this->assertEquals(0, $dimension['min']);$this->assertEquals(25, $dimension['max']);$this->assertEquals(25, $dimension['weight']);$this->assertFalse(isset($dimension['scale']));}}/*** Test get_assessment_form_definition_teacher_new_assessment.*/public function test_get_assessment_form_definition_teacher_new_assessment(): void {// Create the submission.$submissionid = $this->create_test_submission($this->anotherstudentg1);$workshop = new workshop($this->workshop, $this->cm, $this->course);$submission = $workshop->get_submission_by_id($submissionid);$assessmentid = $workshop->add_allocation($submission, $this->student->id);// Switch to assessment phase.$workshop->switch_phase(workshop::PHASE_ASSESSMENT);// Teachers need to be able to view assessments.$this->setUser($this->teacher);$result = mod_workshop_external::get_assessment_form_definition($assessmentid);$result = external_api::clean_returnvalue(mod_workshop_external::get_assessment_form_definition_returns(), $result);$this->assertEquals(4, $result['dimenssionscount']);}/*** Test get_assessment_form_definition_invalid_phase.*/public function test_get_assessment_form_definition_invalid_phase(): void {// Create the submission.$submissionid = $this->create_test_submission($this->anotherstudentg1);$workshop = new workshop($this->workshop, $this->cm, $this->course);$submission = $workshop->get_submission_by_id($submissionid);$assessmentid = $workshop->add_allocation($submission, $this->anotherstudentg1->id);$workshop->switch_phase(workshop::PHASE_EVALUATION);$this->setUser($this->student);// Since we are not reviewers we can't see the assessment until the workshop is closed.$this->expectException('moodle_exception');mod_workshop_external::get_assessment_form_definition($assessmentid);}/*** Test get_reviewer_assessments.*/public function test_get_reviewer_assessments(): void {// Create the submission.$submissionid1 = $this->create_test_submission($this->student);$submissionid2 = $this->create_test_submission($this->anotherstudentg1);$workshopgenerator = $this->getDataGenerator()->get_plugin_generator('mod_workshop');$assessmentid1 = $workshopgenerator->create_assessment($submissionid1, $this->student->id, array('weight' => 2,'grade' => 90,));$assessmentid2 = $workshopgenerator->create_assessment($submissionid2, $this->student->id, array('weight' => 3,'grade' => 80,));// Switch to assessment phase.$workshop = new workshop($this->workshop, $this->cm, $this->course);$workshop->switch_phase(workshop::PHASE_ASSESSMENT);$this->setUser($this->student);// Get my assessments.$result = mod_workshop_external::get_reviewer_assessments($this->workshop->id);$result = external_api::clean_returnvalue(mod_workshop_external::get_reviewer_assessments_returns(), $result);$this->assertCount(2, $result['assessments']);foreach ($result['assessments'] as $assessment) {if ($assessment['id'] == $assessmentid1) {$this->assertEquals(90, $assessment['grade']);} else {$this->assertEquals($assessmentid2, $assessment['id']);$this->assertEquals(80, $assessment['grade']);}}// Now, as teacher try to get the same student assessments.$result = mod_workshop_external::get_reviewer_assessments($this->workshop->id, $this->student->id);$result = external_api::clean_returnvalue(mod_workshop_external::get_reviewer_assessments_returns(), $result);$this->assertCount(2, $result['assessments']);$this->assertArrayNotHasKey('feedbackreviewer', $result['assessments'][0]);}/*** Test get_reviewer_assessments_other_student.*/public function test_get_reviewer_assessments_other_student(): void {$workshop = new workshop($this->workshop, $this->cm, $this->course);$workshop->switch_phase(workshop::PHASE_ASSESSMENT);// Try to get other user assessments.$this->setUser($this->student);$this->expectException('moodle_exception');mod_workshop_external::get_reviewer_assessments($this->workshop->id, $this->anotherstudentg1->id);}/*** Test get_reviewer_assessments_invalid_phase.*/public function test_get_reviewer_assessments_invalid_phase(): void {$workshop = new workshop($this->workshop, $this->cm, $this->course);$workshop->switch_phase(workshop::PHASE_SUBMISSION);// Try to get other user assessments.$this->setUser($this->student);$this->expectException('moodle_exception');mod_workshop_external::get_reviewer_assessments($this->workshop->id, $this->anotherstudentg1->id);}/*** Test update_assessment.*/public function test_update_assessment(): void {// Create the submission.$submissionid = $this->create_test_submission($this->anotherstudentg1);$workshop = new workshop($this->workshop, $this->cm, $this->course);$submission = $workshop->get_submission_by_id($submissionid);$assessmentid = $workshop->add_allocation($submission, $this->student->id);// Switch to assessment phase.$workshop->switch_phase(workshop::PHASE_ASSESSMENT);$this->setUser($this->student);// Get the form definition.$result = mod_workshop_external::get_assessment_form_definition($assessmentid);$result = external_api::clean_returnvalue(mod_workshop_external::get_assessment_form_definition_returns(), $result);// Prepare the data to be sent.$data = $result['fields'];foreach ($data as $key => $param) {if (strpos($param['name'], 'peercomment__idx_') === 0) {$data[$key]['value'] = 'Some content';} else if (strpos($param['name'], 'grade__idx_') === 0) {$data[$key]['value'] = 25; // Set all to 25.}}// Required data.$data[] = array('name' => 'nodims','value' => $result['dimenssionscount'],);// General feedback.$data[] = array('name' => 'feedbackauthor','value' => 'Feedback for the author',);$data[] = array('name' => 'feedbackauthorformat','value' => FORMAT_MOODLE,);// Create a file in a draft area for inline attachments.$fs = get_file_storage();$draftidinlineattach = file_get_unused_draft_itemid();$usercontext = \context_user::instance($this->student->id);$filenameimg = 'shouldbeanimage.txt';$filerecordinline = array('contextid' => $usercontext->id,'component' => 'user','filearea' => 'draft','itemid' => $draftidinlineattach,'filepath' => '/','filename' => $filenameimg,);$fs->create_file_from_string($filerecordinline, 'image contents (not really)');// Create a file in a draft area for regular attachments.$draftidattach = file_get_unused_draft_itemid();$filerecordattach = $filerecordinline;$attachfilename = 'attachment.txt';$filerecordattach['filename'] = $attachfilename;$filerecordattach['itemid'] = $draftidattach;$fs->create_file_from_string($filerecordattach, 'simple text attachment');$data[] = array('name' => 'feedbackauthorinlineattachmentsid','value' => $draftidinlineattach,);$data[] = array('name' => 'feedbackauthorattachmentsid','value' => $draftidattach,);// Update the assessment.$result = mod_workshop_external::update_assessment($assessmentid, $data);$result = external_api::clean_returnvalue(mod_workshop_external::update_assessment_returns(), $result);$this->assertEquals(100, $result['rawgrade']);$this->assertTrue($result['status']);// Get the assessment and check it was updated properly.$result = mod_workshop_external::get_assessment($assessmentid);$result = external_api::clean_returnvalue(mod_workshop_external::get_assessment_returns(), $result);$this->assertEquals(100, $result['assessment']['grade']);$this->assertEquals($this->student->id, $result['assessment']['reviewerid']);$this->assertEquals('Feedback for the author', $result['assessment']['feedbackauthor']);$this->assertCount(1, $result['assessment']['feedbackcontentfiles']);$this->assertCount(1, $result['assessment']['feedbackattachmentfiles']);// Now, get again the form and check we received the data we already sent.$result = mod_workshop_external::get_assessment_form_definition($assessmentid);$result = external_api::clean_returnvalue(mod_workshop_external::get_assessment_form_definition_returns(), $result);foreach ($result['current'] as $currentdata) {if (strpos($currentdata['name'], 'peercomment__idx_') === 0) {$this->assertEquals('Some content', $currentdata['value']);} else if (strpos($currentdata['name'], 'grade__idx_') === 0) {$this->assertEquals(25, (int) $currentdata['value']);}}}/*** Test get_grades.*/public function test_get_grades(): void {$timenow = time();$submissiongrade = array('userid' => $this->student->id,'rawgrade' => 40,'feedback' => '','feedbackformat' => 1,'datesubmitted' => $timenow,'dategraded' => $timenow,);$assessmentgrade = array('userid' => $this->student->id,'rawgrade' => 10,'feedback' => '','feedbackformat' => 1,'datesubmitted' => $timenow,'dategraded' => $timenow,);workshop_grade_item_update($this->workshop, (object) $submissiongrade, (object) $assessmentgrade);// First retrieve my grades.$this->setUser($this->student);$result = mod_workshop_external::get_grades($this->workshop->id);$result = external_api::clean_returnvalue(mod_workshop_external::get_grades_returns(), $result);$this->assertCount(0, $result['warnings']);$this->assertEquals($assessmentgrade['rawgrade'], $result['assessmentrawgrade']);$this->assertEquals($submissiongrade['rawgrade'], $result['submissionrawgrade']);$this->assertFalse($result['assessmentgradehidden']);$this->assertFalse($result['submissiongradehidden']);$this->assertEquals($assessmentgrade['rawgrade'] . ".00 / 20.00", $result['assessmentlongstrgrade']);$this->assertEquals($submissiongrade['rawgrade'] . ".00 / 80.00", $result['submissionlongstrgrade']);// Second, teacher retrieve user grades.$this->setUser($this->teacher);$result = mod_workshop_external::get_grades($this->workshop->id, $this->student->id);$result = external_api::clean_returnvalue(mod_workshop_external::get_grades_returns(), $result);$this->assertCount(0, $result['warnings']);$this->assertEquals($assessmentgrade['rawgrade'], $result['assessmentrawgrade']);$this->assertEquals($submissiongrade['rawgrade'], $result['submissionrawgrade']);$this->assertFalse($result['assessmentgradehidden']);$this->assertFalse($result['submissiongradehidden']);$this->assertEquals($assessmentgrade['rawgrade'] . ".00 / 20.00", $result['assessmentlongstrgrade']);$this->assertEquals($submissiongrade['rawgrade'] . ".00 / 80.00", $result['submissionlongstrgrade']);}/*** Test get_grades_other_student.*/public function test_get_grades_other_student(): void {// Create the submission that will be deleted.$submissionid = $this->create_test_submission($this->student);$workshop = new workshop($this->workshop, $this->cm, $this->course);$workshop->switch_phase(workshop::PHASE_CLOSED);$this->setUser($this->anotherstudentg1);$this->expectException('moodle_exception');mod_workshop_external::get_grades($this->workshop->id, $this->student->id);}/*** Test evaluate_assessment.*/public function test_evaluate_assessment(): void {global $DB;$workshopgenerator = $this->getDataGenerator()->get_plugin_generator('mod_workshop');$submissionid = $workshopgenerator->create_submission($this->workshop->id, $this->student->id);$assessmentid = $workshopgenerator->create_assessment($submissionid, $this->anotherstudentg1->id, array('weight' => 3,'grade' => 20,));$this->setUser($this->teacher);$feedbacktext = 'The feedback';$feedbackformat = FORMAT_MOODLE;$weight = 10;$gradinggradeover = 10;$result = mod_workshop_external::evaluate_assessment($assessmentid, $feedbacktext, $feedbackformat, $weight,$gradinggradeover);$result = external_api::clean_returnvalue(mod_workshop_external::evaluate_assessment_returns(), $result);$this->assertTrue($result['status']);$assessment = $DB->get_record('workshop_assessments', array('id' => $assessmentid));$this->assertEquals('The feedback', $assessment->feedbackreviewer);$this->assertEquals(10, $assessment->weight);// Now test passing incorrect weight and grade values.$weight = 17;$gradinggradeover = 100;$result = mod_workshop_external::evaluate_assessment($assessmentid, $feedbacktext, $feedbackformat, $weight,$gradinggradeover);$result = external_api::clean_returnvalue(mod_workshop_external::evaluate_assessment_returns(), $result);$this->assertFalse($result['status']);$this->assertCount(2, $result['warnings']);$found = 0;foreach ($result['warnings'] as $warning) {if ($warning['item'] == 'weight' || $warning['item'] == 'gradinggradeover') {$found++;}}$this->assertEquals(2, $found);}/*** Test evaluate_assessment_ignore_parameters.*/public function test_evaluate_assessment_ignore_parameters(): void {$workshopgenerator = $this->getDataGenerator()->get_plugin_generator('mod_workshop');$submissionid = $workshopgenerator->create_submission($this->workshop->id, $this->student->id);$assessmentid = $workshopgenerator->create_assessment($submissionid, $this->anotherstudentg1->id, array('weight' => 3,'grade' => 20,));assign_capability('mod/workshop:allocate', CAP_PROHIBIT, $this->teacherrole->id, $this->context->id);// Empty all the caches that may be affected by this change.accesslib_clear_all_caches_for_unit_testing();$this->setUser($this->teacher);$feedbacktext = 'The feedback';$feedbackformat = FORMAT_MOODLE;$weight = 10;$gradinggradeover = 19;$result = mod_workshop_external::evaluate_assessment($assessmentid, $feedbacktext, $feedbackformat, $weight,$gradinggradeover);$result = external_api::clean_returnvalue(mod_workshop_external::evaluate_assessment_returns(), $result);$this->assertTrue($result['status']);$result = mod_workshop_external::get_assessment($assessmentid);$result = external_api::clean_returnvalue(mod_workshop_external::get_assessment_returns(), $result);$this->assertNotEquals(10, $result['assessment']['weight']);}/*** Test evaluate_assessment_no_permissions.*/public function test_evaluate_assessment_no_permissions(): void {$workshopgenerator = $this->getDataGenerator()->get_plugin_generator('mod_workshop');$submissionid = $workshopgenerator->create_submission($this->workshop->id, $this->student->id);$assessmentid = $workshopgenerator->create_assessment($submissionid, $this->anotherstudentg1->id, array('weight' => 3,'grade' => 20,));$this->setUser($this->student);$feedbacktext = 'The feedback';$feedbackformat = FORMAT_MOODLE;$weight = 10;$gradinggradeover = 50;$this->expectException('moodle_exception');mod_workshop_external::evaluate_assessment($assessmentid, $feedbacktext, $feedbackformat, $weight, $gradinggradeover);}/*** Test get_grades_report.*/public function test_get_grades_report(): void {$workshop = new workshop($this->workshop, $this->cm, $this->course);$workshopgenerator = $this->getDataGenerator()->get_plugin_generator('mod_workshop');$submissionid1 = $workshopgenerator->create_submission($this->workshop->id, $this->student->id);$submissionid2 = $workshopgenerator->create_submission($this->workshop->id, $this->anotherstudentg1->id);$assessmentid1 = $workshopgenerator->create_assessment($submissionid2, $this->student->id, array('weight' => 100,'grade' => 50,));$assessmentid2 = $workshopgenerator->create_assessment($submissionid1, $this->anotherstudentg1->id, array('weight' => 100,'grade' => 55,));$workshop->switch_phase(workshop::PHASE_CLOSED);$this->setUser($this->teacher);$result = mod_workshop_external::get_grades_report($this->workshop->id);$result = external_api::clean_returnvalue(mod_workshop_external::get_grades_report_returns(), $result);$this->assertEquals(3, $result['report']['totalcount']); // Expect 3 potential submissions.foreach ($result['report']['grades'] as $grade) {if ($grade['userid'] == $this->student->id) {$this->assertEquals($this->anotherstudentg1->id, $grade['reviewedby'][0]['userid']); // Check reviewer.$this->assertEquals($this->anotherstudentg1->id, $grade['reviewerof'][0]['userid']); // Check reviewer.$this->assertEquals($workshop->real_grade(50), $grade['reviewerof'][0]['grade']); // Check grade (converted).$this->assertEquals($workshop->real_grade(55), $grade['reviewedby'][0]['grade']); // Check grade (converted).} else if ($grade['userid'] == $this->anotherstudentg1->id) {$this->assertEquals($this->student->id, $grade['reviewedby'][0]['userid']); // Check reviewer.$this->assertEquals($this->student->id, $grade['reviewerof'][0]['userid']); // Check reviewer.$this->assertEquals($workshop->real_grade(55), $grade['reviewerof'][0]['grade']); // Check grade (converted).$this->assertEquals($workshop->real_grade(50), $grade['reviewedby'][0]['grade']); // Check grade (converted).}}// Now check pagination.$result = mod_workshop_external::get_grades_report($this->workshop->id, 0, 'lastname', 'ASC', 0, 1);$result = external_api::clean_returnvalue(mod_workshop_external::get_grades_report_returns(), $result);$this->assertEquals(3, $result['report']['totalcount']); // Expect the total count.$this->assertCount(1, $result['report']['grades']);// Groups filtering.$result = mod_workshop_external::get_grades_report($this->workshop->id, $this->group1->id);$result = external_api::clean_returnvalue(mod_workshop_external::get_grades_report_returns(), $result);$this->assertEquals(2, $result['report']['totalcount']); // Expect the group count.}/*** Test get_grades_report_invalid_phase.*/public function test_get_grades_report_invalid_phase(): void {$this->setUser($this->teacher);$this->expectException('moodle_exception');$this->expectExceptionMessage(get_string('nothingfound', 'workshop'));mod_workshop_external::get_grades_report($this->workshop->id);}/*** Test get_grades_report_missing_permissions.*/public function test_get_grades_report_missing_permissions(): void {$this->setUser($this->student);$this->expectException('required_capability_exception');mod_workshop_external::get_grades_report($this->workshop->id);}/*** Test test_view_submission.*/public function test_view_submission(): void {// Create a couple of submissions with files.$firstsubmissionid = $this->create_test_submission($this->student); // Create submission with files.// Trigger and capture the event.$sink = $this->redirectEvents();$this->setUser($this->student);$result = mod_workshop_external::view_submission($firstsubmissionid);$result = external_api::clean_returnvalue(mod_workshop_external::view_submission_returns(), $result);$events = $sink->get_events();$this->assertCount(1, $events);$event = array_shift($events);// Checking that the event contains the expected values.$this->assertInstanceOf('\mod_workshop\event\submission_viewed', $event);$this->assertEquals($this->context, $event->get_context());$moodleworkshop = new \moodle_url('/mod/workshop/submission.php', array('id' => $firstsubmissionid,'cmid' => $this->cm->id));$this->assertEquals($moodleworkshop, $event->get_url());$this->assertEventContextNotUsed($event);$this->assertNotEmpty($event->get_name());}/*** Test evaluate_submission.*/public function test_evaluate_submission(): void {global $DB;$workshopgenerator = $this->getDataGenerator()->get_plugin_generator('mod_workshop');$submissionid = $workshopgenerator->create_submission($this->workshop->id, $this->student->id);$workshop = new workshop($this->workshop, $this->cm, $this->course);$workshop->switch_phase(workshop::PHASE_EVALUATION);$this->setUser($this->teacher);$feedbacktext = 'The feedback';$feedbackformat = FORMAT_MOODLE;$published = 1;$gradeover = 10;$result = mod_workshop_external::evaluate_submission($submissionid, $feedbacktext, $feedbackformat, $published,$gradeover);$result = external_api::clean_returnvalue(mod_workshop_external::evaluate_submission_returns(), $result);$this->assertTrue($result['status']);$submission = $DB->get_record('workshop_submissions', array('id' => $submissionid));$this->assertEquals($feedbacktext, $submission->feedbackauthor);$this->assertEquals($workshop->raw_grade_value($gradeover, $workshop->grade), $submission->gradeover); // Expected grade.$this->assertEquals(1, $submission->published); // Submission published.}/*** Test evaluate_submission_invalid_phase_for_override.*/public function test_evaluate_submission_invalid_phase_for_override(): void {global $DB;$workshopgenerator = $this->getDataGenerator()->get_plugin_generator('mod_workshop');$submissionid = $workshopgenerator->create_submission($this->workshop->id, $this->student->id);$this->setUser($this->teacher);$feedbacktext = 'The feedback';$feedbackformat = FORMAT_MOODLE;$published = 1;$gradeover = 10;$result = mod_workshop_external::evaluate_submission($submissionid, $feedbacktext, $feedbackformat, $published,$gradeover);$result = external_api::clean_returnvalue(mod_workshop_external::evaluate_submission_returns(), $result);$this->assertTrue($result['status']);$submission = $DB->get_record('workshop_submissions', array('id' => $submissionid));$this->assertEquals('', $submission->feedbackauthor); // Feedback and grade not updated.$this->assertEquals(0, $submission->gradeover);$this->assertEquals(1, $submission->published); // Publishing status correctly updated.}/*** Test evaluate_submission_no_permissions.*/public function test_evaluate_submission_no_permissions(): void {$workshopgenerator = $this->getDataGenerator()->get_plugin_generator('mod_workshop');$submissionid = $workshopgenerator->create_submission($this->workshop->id, $this->student->id);$workshop = new workshop($this->workshop, $this->cm, $this->course);$workshop->switch_phase(workshop::PHASE_EVALUATION);$this->setUser($this->student);$feedbacktext = 'The feedback';$feedbackformat = FORMAT_MOODLE;$published = 1;$gradeover = 50;$this->expectException('moodle_exception');mod_workshop_external::evaluate_submission($submissionid, $feedbacktext, $feedbackformat, $published, $gradeover);}/*** Test evaluate_submission_invalid_grade.*/public function test_evaluate_submission_invalid_grade(): void {$workshopgenerator = $this->getDataGenerator()->get_plugin_generator('mod_workshop');$submissionid = $workshopgenerator->create_submission($this->workshop->id, $this->student->id);$workshop = new workshop($this->workshop, $this->cm, $this->course);$workshop->switch_phase(workshop::PHASE_EVALUATION);$this->setUser($this->teacher);$feedbacktext = 'The feedback';$feedbackformat = FORMAT_MOODLE;$published = 1;$gradeover = 150;$result = mod_workshop_external::evaluate_submission($submissionid, $feedbacktext, $feedbackformat, $published, $gradeover);$result = external_api::clean_returnvalue(mod_workshop_external::evaluate_submission_returns(), $result);$this->assertCount(1, $result['warnings']);$this->assertFalse($result['status']);$this->assertEquals('gradeover', $result['warnings'][0]['item']);}}