From fe966a27208e2f229c41592342e67d2e1c601b4f Mon Sep 17 00:00:00 2001 From: Juan Leyva Date: Wed, 28 Jun 2017 11:24:49 +0100 Subject: [PATCH] MDL-59250 mod_workshop: New WS mod_workshop_update_assessment --- mod/workshop/classes/external.php | 128 +++++++++++++++++++++++++++ mod/workshop/db/services.php | 7 ++ mod/workshop/tests/external_test.php | 112 ++++++++++++++++++++++- mod/workshop/version.php | 2 +- 4 files changed, 247 insertions(+), 2 deletions(-) diff --git a/mod/workshop/classes/external.php b/mod/workshop/classes/external.php index ae003271919..220b216a784 100644 --- a/mod/workshop/classes/external.php +++ b/mod/workshop/classes/external.php @@ -1412,4 +1412,132 @@ class mod_workshop_external extends external_api { ) ); } + + /** + * Returns the description of the external function parameters. + * + * @return external_function_parameters + * @since Moodle 3.4 + */ + public static function update_assessment_parameters() { + return new external_function_parameters( + array( + 'assessmentid' => new external_value(PARAM_INT, 'Assessment id.'), + 'data' => new external_multiple_structure ( + new external_single_structure( + array( + 'name' => new external_value(PARAM_ALPHANUMEXT, + 'The assessment data (use WS get_assessment_form_definition for obtaining the data to sent). + Apart from that data, you can optionally send: + feedbackauthor (str); the feedback for the submission author + feedbackauthorformat (int); the format of the feedbackauthor + feedbackauthorinlineattachmentsid (int); the draft file area for the editor attachments + feedbackauthorattachmentsid (int); the draft file area id for the feedback attachments' + ), + 'value' => new external_value(PARAM_RAW, 'The value of the option.') + ) + ), 'Assessment data' + ) + ) + ); + } + + + /** + * Updates an assessment. + * + * @param int $assessmentid the assessment id + * @param array $data the assessment data + * @return array indicates if the assessment was updated, the new raw grade and possible warnings. + * @since Moodle 3.4 + * @throws moodle_exception + */ + public static function update_assessment($assessmentid, $data) { + global $DB, $USER; + + $params = self::validate_parameters( + self::update_assessment_parameters(), array('assessmentid' => $assessmentid, 'data' => $data) + ); + $warnings = array(); + + // Get and validate the assessment, submission and workshop. + $assessment = $DB->get_record('workshop_assessments', array('id' => $params['assessmentid']), '*', MUST_EXIST); + $submission = $DB->get_record('workshop_submissions', array('id' => $assessment->submissionid), '*', MUST_EXIST); + list($workshop, $course, $cm, $context) = self::validate_workshop($submission->workshopid); + + // Check we can edit the assessment. + $workshop->check_edit_assessment($assessment, $submission); + + // Process data. + $data = new stdClass; + $data->feedbackauthor_editor = array(); + + foreach ($params['data'] as $wsdata) { + $name = trim($wsdata['name']); + switch ($name) { + case 'feedbackauthor': + $data->feedbackauthor_editor['text'] = $wsdata['value']; + break; + case 'feedbackauthorformat': + $data->feedbackauthor_editor['format'] = clean_param($wsdata['value'], PARAM_FORMAT); + break; + case 'feedbackauthorinlineattachmentsid': + $data->feedbackauthor_editor['itemid'] = clean_param($wsdata['value'], PARAM_INT); + break; + case 'feedbackauthorattachmentsid': + $data->feedbackauthorattachment_filemanager = clean_param($wsdata['value'], PARAM_INT); + break; + default: + $data->{$wsdata['name']} = $wsdata['value']; // Validation will be done in the form->validation. + } + } + + $cansetassessmentweight = has_capability('mod/workshop:allocate', $context); + $pending = $workshop->get_pending_assessments_by_reviewer($assessment->reviewerid, $assessment->id); + // Retrieve the data from the strategy plugin. + $strategy = $workshop->grading_strategy_instance(); + $mform = $strategy->get_assessment_form(null, 'assessment', $assessment, true, + array('editableweight' => $cansetassessmentweight, 'pending' => !empty($pending))); + + $errors = $mform->validation((array) $data, array()); + // We can get several errors, return them in warnings. + if (!empty($errors)) { + $status = false; + $rawgrade = null; + foreach ($errors as $itemname => $message) { + $warnings[] = array( + 'item' => $itemname, + 'itemid' => 0, + 'warningcode' => 'fielderror', + 'message' => s($message) + ); + } + } else { + $rawgrade = $workshop->edit_assessment($assessment, $submission, $data, $strategy); + $status = true; + } + + return array( + 'status' => $status, + 'rawgrade' => $rawgrade, + 'warnings' => $warnings, + ); + } + + /** + * Returns description of method result value + * + * @return external_description + * @since Moodle 3.4 + */ + public static function update_assessment_returns() { + return new external_single_structure( + array( + 'status' => new external_value(PARAM_BOOL, 'status: true if the assessment was added or updated false otherwise.'), + 'rawgrade' => new external_value(PARAM_FLOAT, 'Raw percentual grade (0.00000 to 100.00000) for submission.', + VALUE_OPTIONAL), + 'warnings' => new external_warnings() + ) + ); + } } diff --git a/mod/workshop/db/services.php b/mod/workshop/db/services.php index b97f3dfdf70..d262d1598a9 100644 --- a/mod/workshop/db/services.php +++ b/mod/workshop/db/services.php @@ -127,4 +127,11 @@ $functions = array( 'type' => 'read', 'services' => array(MOODLE_OFFICIAL_MOBILE_SERVICE) ), + 'mod_workshop_update_assessment' => array( + 'classname' => 'mod_workshop_external', + 'methodname' => 'update_assessment', + 'description' => 'Add information to an allocated assessment.', + 'type' => 'write', + 'services' => array(MOODLE_OFFICIAL_MOBILE_SERVICE) + ), ); diff --git a/mod/workshop/tests/external_test.php b/mod/workshop/tests/external_test.php index e64fd8c41da..860abd2210d 100644 --- a/mod/workshop/tests/external_test.php +++ b/mod/workshop/tests/external_test.php @@ -75,7 +75,12 @@ class mod_workshop_external_testcase extends externallib_advanced_testcase { $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)); + $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); @@ -1414,4 +1419,109 @@ class mod_workshop_external_testcase extends externallib_advanced_testcase { $this->setExpectedException('moodle_exception'); mod_workshop_external::get_reviewer_assessments($this->workshop->id, $this->anotherstudentg1->id); } + + /** + * Test update_assessment. + */ + public function test_update_assessment() { + global $DB; + + // 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. + $DB->set_field('workshop', 'phase', workshop::PHASE_ASSESSMENT, array('id' => $this->workshop->id)); + $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']); + } + } + } } diff --git a/mod/workshop/version.php b/mod/workshop/version.php index db0082c04e1..72263d982b8 100644 --- a/mod/workshop/version.php +++ b/mod/workshop/version.php @@ -24,7 +24,7 @@ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2017051513; // The current module version (YYYYMMDDXX) +$plugin->version = 2017051514; // The current module version (YYYYMMDDXX) $plugin->requires = 2017050500; // Requires this Moodle version. $plugin->component = 'mod_workshop'; $plugin->cron = 60; // Give as a chance every minute. -- 2.43.0