MDL-59253 mod_workshop: New WS mod_workshop_get_grades_report
authorJuan Leyva <juanleyvadelgado@gmail.com>
Fri, 30 Jun 2017 15:08:18 +0000 (16:08 +0100)
committerEloy Lafuente (stronk7) <stronk7@moodle.org>
Tue, 3 Oct 2017 17:22:09 +0000 (19:22 +0200)
mod/workshop/classes/external.php
mod/workshop/db/services.php
mod/workshop/locallib.php
mod/workshop/tests/external_test.php
mod/workshop/version.php

index 0d5404d..2f0145d 100644 (file)
@@ -1747,4 +1747,175 @@ class mod_workshop_external extends external_api {
             )
         );
     }
+
+    /**
+     * Returns description of method parameters
+     *
+     * @return external_function_parameters
+     * @since Moodle 3.4
+     */
+    public static function get_grades_report_parameters() {
+        return new external_function_parameters(
+            array(
+                'workshopid' => new external_value(PARAM_INT, 'Workshop instance id.'),
+                'groupid' => new external_value(PARAM_INT, 'Group id, 0 means that the function will determine the user group.',
+                                                   VALUE_DEFAULT, 0),
+                'sortby' => new external_value(PARAM_ALPHA, 'sort by this element: lastname, firstname, submissiontitle,
+                    submissionmodified, submissiongrade, gradinggrade.', VALUE_DEFAULT, 'lastname'),
+                'sortdirection' => new external_value(PARAM_ALPHA, 'sort direction: ASC or DESC', VALUE_DEFAULT, 'ASC'),
+                'page' => new external_value(PARAM_INT, 'The page of records to return.', VALUE_DEFAULT, 0),
+                'perpage' => new external_value(PARAM_INT, 'The number of records to return per page.', VALUE_DEFAULT, 0),
+            )
+        );
+    }
+
+    /**
+     * Retrieves the assessment grades report.
+     *
+     * @param int $workshopid       the workshop instance id
+     * @param int $groupid          (optional) group id, 0 means that the function will determine the user group
+     * @param string $sortby        sort by this element
+     * @param string $sortdirection sort direction: ASC or DESC
+     * @param int $page             page of records to return
+     * @param int $perpage          number of records to return per page
+     * @return array of warnings and the report data
+     * @since Moodle 3.4
+     * @throws moodle_exception
+     */
+    public static function get_grades_report($workshopid, $groupid = 0, $sortby = 'lastname', $sortdirection = 'ASC',
+            $page = 0, $perpage = 0) {
+        global $USER;
+
+        $params = array('workshopid' => $workshopid, 'groupid' => $groupid, 'sortby' => $sortby, 'sortdirection' => $sortdirection,
+            'page' => $page, 'perpage' => $perpage);
+        $params = self::validate_parameters(self::get_grades_report_parameters(), $params);
+        $submissions = $warnings = array();
+
+        $sortallowedvalues = array('lastname', 'firstname', 'submissiontitle', 'submissionmodified', 'submissiongrade',
+            'gradinggrade');
+        if (!in_array($params['sortby'], $sortallowedvalues)) {
+            throw new invalid_parameter_exception('Invalid value for sortby parameter (value: ' . $sortby . '),' .
+                'allowed values are: ' . implode(',', $sortallowedvalues));
+        }
+
+        $sortdirection = strtoupper($params['sortdirection']);
+        $directionallowedvalues = array('ASC', 'DESC');
+        if (!in_array($sortdirection, $directionallowedvalues)) {
+            throw new invalid_parameter_exception('Invalid value for sortdirection parameter (value: ' . $sortdirection . '),' .
+                'allowed values are: ' . implode(',', $directionallowedvalues));
+        }
+
+        list($workshop, $course, $cm, $context) = self::validate_workshop($params['workshopid']);
+        require_capability('mod/workshop:viewallassessments', $context);
+
+        if (!empty($params['groupid'])) {
+            $groupid = $params['groupid'];
+            // Determine is the group is visible to user.
+            if (!groups_group_visible($groupid, $course, $cm)) {
+                throw new moodle_exception('notingroup');
+            }
+        } else {
+            // Check to see if groups are being used here.
+            if ($groupmode = groups_get_activity_groupmode($cm)) {
+                $groupid = groups_get_activity_group($cm);
+                // Determine is the group is visible to user (this is particullary for the group 0 -> all groups).
+                if (!groups_group_visible($groupid, $course, $cm)) {
+                    throw new moodle_exception('notingroup');
+                }
+            } else {
+                $groupid = 0;
+            }
+        }
+
+        if ($workshop->phase >= workshop::PHASE_SUBMISSION) {
+            $showauthornames = has_capability('mod/workshop:viewauthornames', $context);
+            $showreviewernames = has_capability('mod/workshop:viewreviewernames', $context);
+
+            if ($workshop->phase >= workshop::PHASE_EVALUATION) {
+                $showsubmissiongrade = true;
+                $showgradinggrade = true;
+            } else {
+                $showsubmissiongrade = false;
+                $showgradinggrade = false;
+            }
+
+            $data = $workshop->prepare_grading_report_data($USER->id, $groupid, $params['page'], $params['perpage'],
+                $params['sortby'], $sortdirection);
+
+            if (!empty($data)) {
+                // Populate the display options for the submissions report.
+                $reportopts                      = new stdclass();
+                $reportopts->showauthornames     = $showauthornames;
+                $reportopts->showreviewernames   = $showreviewernames;
+                $reportopts->sortby              = $params['sortby'];
+                $reportopts->sorthow             = $sortdirection;
+                $reportopts->showsubmissiongrade = $showsubmissiongrade;
+                $reportopts->showgradinggrade    = $showgradinggrade;
+                $reportopts->workshopphase       = $workshop->phase;
+
+                $report = new workshop_grading_report($data, $reportopts);
+                return array(
+                    'report' => $report->export_data_for_external(),
+                    'warnings' => array(),
+                );
+            }
+        }
+        throw new moodle_exception('nothingfound', 'workshop');
+    }
+
+    /**
+     * Returns description of method result value
+     *
+     * @return external_description
+     * @since Moodle 3.4
+     */
+    public static function get_grades_report_returns() {
+
+        $reviewstructure = new external_single_structure(
+            array(
+                'userid' => new external_value(PARAM_INT, 'The id of the user (0 when is configured to do not display names).'),
+                'assessmentid' => new external_value(PARAM_INT, 'The id of the assessment.'),
+                'submissionid' => new external_value(PARAM_INT, 'The id of the submission assessed.'),
+                'grade' => new external_value(PARAM_FLOAT, 'The grade for submission.'),
+                'gradinggrade' => new external_value(PARAM_FLOAT, 'The grade for assessment.'),
+                'gradinggradeover' => new external_value(PARAM_FLOAT, 'The aggregated grade overrided.'),
+                'weight' => new external_value(PARAM_INT, 'The weight of the assessment for aggregation.'),
+            )
+        );
+
+        return new external_single_structure(
+            array(
+                'report' => new external_single_structure(
+                    array(
+                        'grades' => new external_multiple_structure(
+                            new external_single_structure(
+                                array(
+                                    'userid' => new external_value(PARAM_INT, 'The id of the user being displayed in the report.'),
+                                    'submissionid' => new external_value(PARAM_INT, 'Submission id.'),
+                                    'submissiontitle' => new external_value(PARAM_RAW, 'Submission title.'),
+                                    'submissionmodified' => new external_value(PARAM_INT, 'Timestamp submission was updated.'),
+                                    'submissiongrade' => new external_value(PARAM_FLOAT, 'Aggregated grade for the submission.',
+                                        VALUE_OPTIONAL),
+                                    'gradinggrade' => new external_value(PARAM_FLOAT, 'Computed grade for the assessment.',
+                                        VALUE_OPTIONAL),
+                                    'submissiongradeover' => new external_value(PARAM_FLOAT, 'Grade for the assessment overrided
+                                        by the teacher.', VALUE_OPTIONAL),
+                                    'submissiongradeoverby' => new external_value(PARAM_INT, 'The id of the user who overrided
+                                        the grade.', VALUE_OPTIONAL),
+                                    'submissionpublished' => new external_value(PARAM_INT, 'Whether is a submission published.',
+                                        VALUE_OPTIONAL),
+                                    'reviewedby' => new external_multiple_structure($reviewstructure, 'The users who reviewed the
+                                        user submission.', VALUE_OPTIONAL),
+                                    'reviewerof' => new external_multiple_structure($reviewstructure, 'The assessments the user
+                                        reviewed.', VALUE_OPTIONAL),
+                                )
+                            )
+                        ),
+                        'totalcount' => new external_value(PARAM_INT, 'Number of total submissions.'),
+                    )
+                ),
+                'warnings' => new external_warnings()
+            )
+        );
+    }
 }
index 0e76683..e9bf366 100644 (file)
@@ -148,4 +148,11 @@ $functions = array(
         'type'          => 'write',
         'services'      => array(MOODLE_OFFICIAL_MOBILE_SERVICE)
     ),
+    'mod_workshop_get_grades_report' => array(
+        'classname'     => 'mod_workshop_external',
+        'methodname'    => 'get_grades_report',
+        'description'   => 'Retrieves the assessment grades report.',
+        'type'          => 'read',
+        'services'      => array(MOODLE_OFFICIAL_MOBILE_SERVICE)
+    ),
 );
index 966e268..926ef7d 100644 (file)
@@ -4504,6 +4504,54 @@ class workshop_grading_report implements renderable {
     public function get_options() {
         return $this->options;
     }
+
+    /**
+     * Prepare the data to be exported to a external system via Web Services.
+     *
+     * This function applies extra capabilities checks.
+     * @return stdClass the data ready for external systems
+     */
+    public function export_data_for_external() {
+        $data = $this->get_data();
+        $options = $this->get_options();
+
+        foreach ($data->grades as $reportdata) {
+            // If we are in submission phase ignore the following data.
+            if ($options->workshopphase == workshop::PHASE_SUBMISSION) {
+                unset($reportdata->submissiongrade);
+                unset($reportdata->gradinggrade);
+                unset($reportdata->submissiongradeover);
+                unset($reportdata->submissiongradeoverby);
+                unset($reportdata->submissionpublished);
+                unset($reportdata->reviewedby);
+                unset($reportdata->reviewerof);
+                continue;
+            }
+
+            if (!$options->showsubmissiongrade) {
+                unset($reportdata->submissiongrade);
+                unset($reportdata->submissiongradeover);
+            }
+
+            if (!$options->showgradinggrade and $tr == 0) {
+                unset($reportdata->gradinggrade);
+            }
+
+            if (!$options->showreviewernames) {
+                foreach ($reportdata->reviewedby as $reviewedby) {
+                    $reviewedby->userid = 0;
+                }
+            }
+
+            if (!$options->showauthornames) {
+                foreach ($reportdata->reviewerof as $reviewerof) {
+                    $reviewerof->userid = 0;
+                }
+            }
+        }
+
+        return $data;
+    }
 }
 
 
index dbe229c..2657a96 100644 (file)
@@ -1668,4 +1668,74 @@ class mod_workshop_external_testcase extends externallib_advanced_testcase {
         $this->expectException('moodle_exception');
         mod_workshop_external::evaluate_assessment($assessmentid, $feedbacktext, $feedbackformat, $weight, $gradinggradeover);
     }
+
+    /**
+     * Test get_grades_report.
+     */
+    public function test_get_grades_report() {
+        global $DB;
+
+        $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,
+        ));
+
+        $DB->set_field('workshop', 'phase', workshop::PHASE_CLOSED, array('id' => $this->workshop->id));
+        $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() {
+        $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() {
+        $this->setUser($this->student);
+        $this->expectException('required_capability_exception');
+        mod_workshop_external::get_grades_report($this->workshop->id);
+    }
 }
index 001cf8a..bb1bc3a 100644 (file)
@@ -24,7 +24,7 @@
 
 defined('MOODLE_INTERNAL') || die();
 
-$plugin->version   = 2017051516;        // The current module version (YYYYMMDDXX)
+$plugin->version   = 2017051517;        // 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.