diff --git a/mod/workshop/classes/external.php b/mod/workshop/classes/external.php index 70063c43039..e79bef40d33 100644 --- a/mod/workshop/classes/external.php +++ b/mod/workshop/classes/external.php @@ -1976,4 +1976,120 @@ 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 evaluate_submission_parameters() { + return new external_function_parameters( + array( + 'submissionid' => new external_value(PARAM_INT, 'submission id.'), + 'feedbacktext' => new external_value(PARAM_RAW, 'The feedback for the author.', VALUE_DEFAULT, ''), + 'feedbackformat' => new external_value(PARAM_INT, 'The feedback format for text.', VALUE_DEFAULT, FORMAT_MOODLE), + 'published' => new external_value(PARAM_BOOL, 'Publish the submission for others?.', VALUE_DEFAULT, false), + 'gradeover' => new external_value(PARAM_ALPHANUMEXT, 'The new submission grade.', VALUE_DEFAULT, ''), + ) + ); + } + + + /** + * Evaluates a submission (used by teachers for provide feedback or override the submission grade). + * + * @param int $submissionid the submission id + * @param str $feedbacktext the feedback for the author + * @param int $feedbackformat the feedback format for the reviewer text + * @param bool $published whether to publish the submission for other users + * @param mixed $gradeover the new submission grade (empty for no overriding the grade) + * @return array containing the status and warnings. + * @since Moodle 3.4 + * @throws moodle_exception + */ + public static function evaluate_submission($submissionid, $feedbacktext = '', $feedbackformat = FORMAT_MOODLE, $published = 1, + $gradeover = '') { + global $DB; + + $params = self::validate_parameters( + self::evaluate_submission_parameters(), + array( + 'submissionid' => $submissionid, + 'feedbacktext' => $feedbacktext, + 'feedbackformat' => $feedbackformat, + 'published' => $published, + 'gradeover' => $gradeover, + ) + ); + $warnings = array(); + + // Get and validate the submission, submission and workshop. + $submission = $DB->get_record('workshop_submissions', array('id' => $params['submissionid']), '*', MUST_EXIST); + list($workshop, $course, $cm, $context) = self::validate_workshop($submission->workshopid); + + // Check we can evaluate the submission. + self::validate_submission($submission, $workshop); + $canpublish = has_capability('mod/workshop:publishsubmissions', $context); + $canoverride = ($workshop->phase == workshop::PHASE_EVALUATION && + has_capability('mod/workshop:overridegrades', $context)); + + if (!$canpublish && !$canoverride) { + throw new moodle_exception('nopermissions', 'error', '', 'evaluate submission'); + } + + // Process data. + $data = new stdClass; + $data->id = $submission->id; + $data->feedbackauthor_editor = array( + 'text' => $params['feedbacktext'], + 'format' => $params['feedbackformat'], + ); + $data->published = $params['published']; + $data->gradeover = $params['gradeover']; + + $options = array( + 'editable' => true, + 'editablepublished' => $canpublish, + 'overridablegrade' => $canoverride + ); + $feedbackform = $workshop->get_feedbackauthor_form(null, $submission, $options); + + $errors = $feedbackform->validation((array) $data, array()); + // We can get several errors, return them in warnings. + if (!empty($errors)) { + $status = false; + foreach ($errors as $itemname => $message) { + $warnings[] = array( + 'item' => $itemname, + 'itemid' => 0, + 'warningcode' => 'fielderror', + 'message' => s($message) + ); + } + } else { + $workshop->evaluate_submission($submission, $data, $canpublish, $canoverride); + $status = true; + } + + return array( + 'status' => $status, + 'warnings' => $warnings, + ); + } + + /** + * Returns description of method result value + * + * @return external_description + * @since Moodle 3.4 + */ + public static function evaluate_submission_returns() { + return new external_single_structure( + array( + 'status' => new external_value(PARAM_BOOL, 'status: true if the submission was evaluated, false otherwise.'), + 'warnings' => new external_warnings() + ) + ); + } } diff --git a/mod/workshop/db/services.php b/mod/workshop/db/services.php index d25ce624ada..bbe4a90babf 100644 --- a/mod/workshop/db/services.php +++ b/mod/workshop/db/services.php @@ -163,4 +163,11 @@ $functions = array( 'capabilities' => 'mod/workshop:view', 'services' => array(MOODLE_OFFICIAL_MOBILE_SERVICE) ), + 'mod_workshop_evaluate_submission' => array( + 'classname' => 'mod_workshop_external', + 'methodname' => 'evaluate_submission', + 'description' => 'Evaluates a submission (used by teachers for provide feedback or override the submission grade).', + '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 2ccc99ee051..fa43ebc2e2c 100644 --- a/mod/workshop/tests/external_test.php +++ b/mod/workshop/tests/external_test.php @@ -1768,4 +1768,76 @@ class mod_workshop_external_testcase extends externallib_advanced_testcase { $this->assertNotEmpty($event->get_name()); } + + /** + * Test evaluate_submission. + */ + public function test_evaluate_submission() { + global $DB; + + $workshopgenerator = $this->getDataGenerator()->get_plugin_generator('mod_workshop'); + $submissionid = $workshopgenerator->create_submission($this->workshop->id, $this->student->id); + + $DB->set_field('workshop', 'phase', workshop::PHASE_EVALUATION, array('id' => $this->workshop->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']); + + $workshop = new workshop($this->workshop, $this->cm, $this->course); + $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() { + 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() { + global $DB; + + $workshopgenerator = $this->getDataGenerator()->get_plugin_generator('mod_workshop'); + $submissionid = $workshopgenerator->create_submission($this->workshop->id, $this->student->id); + $DB->set_field('workshop', 'phase', workshop::PHASE_EVALUATION, array('id' => $this->workshop->id)); + + $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); + } } diff --git a/mod/workshop/version.php b/mod/workshop/version.php index d3cb91ce37f..617de0a470a 100644 --- a/mod/workshop/version.php +++ b/mod/workshop/version.php @@ -24,7 +24,7 @@ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2017051518; // The current module version (YYYYMMDDXX) +$plugin->version = 2017051519; // 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.