MDL-59250 mod_workshop: New WS mod_workshop_update_assessment
authorJuan Leyva <juanleyvadelgado@gmail.com>
Wed, 28 Jun 2017 10:24:49 +0000 (11:24 +0100)
committerJuan Leyva <juanleyvadelgado@gmail.com>
Tue, 3 Oct 2017 15:31:30 +0000 (17:31 +0200)
mod/workshop/classes/external.php
mod/workshop/db/services.php
mod/workshop/tests/external_test.php
mod/workshop/version.php

index ae00327..220b216 100644 (file)
@@ -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()
+            )
+        );
+    }
 }
 }
index b97f3df..d262d15 100644 (file)
@@ -127,4 +127,11 @@ $functions = array(
         'type'          => 'read',
         'services'      => array(MOODLE_OFFICIAL_MOBILE_SERVICE)
     ),
         '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)
+    ),
 );
 );
index e64fd8c..860abd2 100644 (file)
@@ -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);
         $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);
 
         $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);
     }
         $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']);
+            }
+        }
+    }
 }
 }
index db0082c..72263d9 100644 (file)
@@ -24,7 +24,7 @@
 
 defined('MOODLE_INTERNAL') || die();
 
 
 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.
 $plugin->requires  = 2017050500;        // Requires this Moodle version.
 $plugin->component = 'mod_workshop';
 $plugin->cron      = 60;                // Give as a chance every minute.