MDL-31873 added mod_assign_get_grades web service function
authorPaul Charsley <p.charsley@massey.ac.nz>
Tue, 18 Sep 2012 20:32:32 +0000 (08:32 +1200)
committerPaul Charsley <p.charsley@massey.ac.nz>
Thu, 20 Sep 2012 22:29:15 +0000 (10:29 +1200)
mod/assign/db/services.php [new file with mode: 0644]
mod/assign/externallib.php [new file with mode: 0644]
mod/assign/tests/externallib_test.php [new file with mode: 0644]
mod/assign/tests/generator/lib.php [new file with mode: 0644]

diff --git a/mod/assign/db/services.php b/mod/assign/db/services.php
new file mode 100644 (file)
index 0000000..40ce90d
--- /dev/null
@@ -0,0 +1,34 @@
+<?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/>.
+
+/**
+ * Web service for mod assign
+ * @package    mod_assign
+ * @subpackage db
+ * @since      Moodle 2.4
+ * @copyright  2012 Paul Charsley
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+$functions = array(
+        'mod_assign_get_grades' => array(
+                'classname'   => 'mod_assign_external',
+                'methodname'  => 'get_grades',
+                'classpath'   => 'mod/assign/externallib.php',
+                'description' => 'Returns grades from the assignment',
+                'type'        => 'read',
+        )
+);
diff --git a/mod/assign/externallib.php b/mod/assign/externallib.php
new file mode 100644 (file)
index 0000000..4939099
--- /dev/null
@@ -0,0 +1,192 @@
+<?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/>.
+
+/**
+ * External assign API
+ *
+ * @package    mod_assign
+ * @since      Moodle 2.4
+ * @copyright  2012 Paul Charsley
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+defined('MOODLE_INTERNAL') || die;
+
+require_once("$CFG->libdir/externallib.php");
+
+/**
+ * Assign functions
+ */
+class mod_assign_external extends external_api {
+
+    /**
+     * Describes the parameters for get_grades
+     * @return external_external_function_parameters
+     * @since  Moodle 2.4
+     */
+    public static function get_grades_parameters() {
+        return new external_function_parameters(
+            array(
+                'assignmentids' => new external_multiple_structure(
+                    new external_value(PARAM_INT, 'assignment id'),
+                    '1 or more assignment ids',
+                    VALUE_REQUIRED),
+                'since' => new external_value(PARAM_INT,
+                          'timestamp, only return records where timemodified >= since',
+                          VALUE_DEFAULT, 0)
+            )
+        );
+    }
+
+    /**
+     * Returns grade information from assign_grades for the requested assignment ids
+     * @param array of ints $assignmentids
+     * @param int $since only return records with timemodified >= since
+     * @return array of grade records for each requested assignment
+     * @since  Moodle 2.4
+     */
+    public static function get_grades($assignmentids, $since = 0) {
+        global $DB;
+        $params = self::validate_parameters(self::get_grades_parameters(),
+                        array('assignmentids' => $assignmentids,
+                              'since' => $since));
+
+        $assignments = array();
+        $warnings = array();
+        $requestedassignmentids = $params['assignmentids'];
+
+        // Check the user is allowed to get the grades for the assignments requested.
+        $placeholders = array();
+        list($sqlassignmentids, $placeholders) = $DB->get_in_or_equal($requestedassignmentids, SQL_PARAMS_NAMED);
+        $sql = "SELECT cm.id, cm.instance FROM {course_modules} cm JOIN {modules} md ON md.id = cm.module ".
+               "WHERE md.name = :modname AND cm.instance ".$sqlassignmentids;
+        $placeholders['modname'] = 'assign';
+        $cms = $DB->get_records_sql($sql, $placeholders);
+        foreach ($cms as $cm) {
+            try {
+                $context = context_module::instance($cm->id);
+                self::validate_context($context);
+                require_capability('mod/assign:grade', $context);
+            } catch (Exception $e) {
+                $requestedassignmentids = array_diff($requestedassignmentids, array($cm->instance));
+                $warning = array();
+                $warning['item'] = 'assignment';
+                $warning['itemid'] = $cm->instance;
+                $warning['warningcode'] = '1';
+                $warning['message'] = 'No access rights in module context';
+                $warnings[] = $warning;
+            }
+        }
+
+        // Create the query and populate an array of grade records from the recordset results.
+        if (count ($requestedassignmentids) > 0) {
+            $placeholders = array();
+            list($inorequalsql, $placeholders) = $DB->get_in_or_equal($requestedassignmentids, SQL_PARAMS_NAMED);
+            $sql = "SELECT ag.id,ag.assignment,ag.userid,ag.timecreated,ag.timemodified,".
+                   "ag.grader,ag.grade,ag.locked,ag.mailed ".
+                   "FROM {assign_grades} ag ".
+                   "WHERE ag.assignment ".$inorequalsql.
+                   " AND ag.timemodified  >= :since".
+                   " ORDER BY ag.assignment, ag.id";
+            $placeholders['since'] = $params['since'];
+            $rs = $DB->get_recordset_sql($sql, $placeholders);
+            $currentassignmentid = null;
+            $assignment = null;
+            foreach ($rs as $rd) {
+                $grade = array();
+                $grade['id'] = $rd->id;
+                $grade['userid'] = $rd->userid;
+                $grade['timecreated'] = $rd->timecreated;
+                $grade['timemodified'] = $rd->timemodified;
+                $grade['grader'] = $rd->grader;
+                $grade['grade'] = (string)$rd->grade;
+                $grade['locked'] = $rd->locked;
+                $grade['mailed'] = $rd->mailed;
+
+                if (is_null($currentassignmentid) || ($rd->assignment != $currentassignmentid )) {
+                    if (!is_null($assignment)) {
+                        $assignments[] = $assignment;
+                    }
+                    $assignment = array();
+                    $assignment['assignmentid'] = $rd->assignment;
+                    $assignment['grades'] = array();
+                    $requestedassignmentids = array_diff($requestedassignmentids, array($rd->assignment));
+                }
+                $assignment['grades'][] = $grade;
+
+                $currentassignmentid = $rd->assignment;
+            }
+            if (!is_null($assignment)) {
+                $assignments[] = $assignment;
+            }
+            $rs->close();
+        }
+        foreach ($requestedassignmentids as $assignmentid) {
+            $warning = array();
+            $warning['item'] = 'assignment';
+            $warning['itemid'] = $assignmentid;
+            $warning['warningcode'] = '3';
+            $warning['message'] = 'No grades found';
+            $warnings[] = $warning;
+        }
+
+        $result = array();
+        $result['assignments'] = $assignments;
+        $result['warnings'] = $warnings;
+        return $result;
+    }
+
+    /**
+     * Creates an assign_grades external_single_structure
+     * @return external_single_structure
+     * @since  Moodle 2.4
+     */
+    private static function assign_grades() {
+        return new external_single_structure(
+            array (
+                'assignmentid'    => new external_value(PARAM_INT, 'assignment id'),
+                'grades'   => new external_multiple_structure(new external_single_structure(
+                        array(
+                            'id'            => new external_value(PARAM_INT, 'grade id'),
+                            'userid'        => new external_value(PARAM_INT, 'student id'),
+                            'timecreated'   => new external_value(PARAM_INT, 'grade creation time'),
+                            'timemodified'  => new external_value(PARAM_INT, 'grade last modified time'),
+                            'grader'        => new external_value(PARAM_INT, 'grader'),
+                            'grade'         => new external_value(PARAM_TEXT, 'grade'),
+                            'locked'        => new external_value(PARAM_BOOL, 'locked'),
+                            'mailed'        => new external_value(PARAM_BOOL, 'mailed')
+                        )
+                    )
+                )
+            )
+        );
+    }
+
+    /**
+     * Describes the get_grades return value
+     * @return external_single_structure
+     * @since  Moodle 2.4
+     */
+    public static function get_grades_returns() {
+        return new external_single_structure(
+            array(
+                'assignments' => new external_multiple_structure(self::assign_grades(), 'list of assignment grade information'),
+                'warnings'      => new external_warnings()
+            )
+        );
+    }
+
+}
diff --git a/mod/assign/tests/externallib_test.php b/mod/assign/tests/externallib_test.php
new file mode 100644 (file)
index 0000000..a743ed4
--- /dev/null
@@ -0,0 +1,104 @@
+<?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/>.
+
+defined('MOODLE_INTERNAL') || die();
+
+global $CFG;
+
+require_once($CFG->dirroot . '/webservice/tests/helpers.php');
+
+/**
+ * External mod assign functions unit tests
+ *
+ * @package mod_assign
+ * @category external
+ * @copyright 2012 Paul Charsley
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class mod_assign_external_testcase extends externallib_advanced_testcase {
+
+    /**
+     * Tests set up
+     */
+    protected function setUp() {
+        global $CFG;
+        require_once($CFG->dirroot . '/mod/assign/externallib.php');
+    }
+
+    /**
+     * Test get_grades
+     */
+    public function test_get_grades () {
+        global $DB, $USER;
+
+        $this->resetAfterTest(true);
+        // Create a course and assignment.
+        $coursedata['idnumber'] = 'idnumbercourse';
+        $coursedata['fullname'] = 'Lightwork Course';
+        $coursedata['summary'] = 'Lightwork Course description';
+        $coursedata['summaryformat'] = FORMAT_MOODLE;
+        $course = self::getDataGenerator()->create_course($coursedata);
+
+        $assigndata['course'] = $course->id;
+        $assigndata['name'] = 'lightwork assignment';
+
+        $assign = self::getDataGenerator()->create_module('assign', $assigndata);
+
+        // Create a manual enrolment record.
+        $manual_enrol_data['enrol'] = 'manual';
+        $manual_enrol_data['status'] = 0;
+        $manual_enrol_data['courseid'] = $course->id;
+        $enrolid = $DB->insert_record('enrol', $manual_enrol_data);
+
+        // Create a teacher and give them capabilities.
+        $context = context_course::instance($course->id);
+        $roleid = $this->assignUserCapability('moodle/course:viewparticipants', $context->id, 3);
+        $context = context_module::instance($assign->id);
+        $this->assignUserCapability('mod/assign:grade', $context->id, $roleid);
+
+        // Create the teacher's enrolment record.
+        $user_enrolment_data['status'] = 0;
+        $user_enrolment_data['enrolid'] = $enrolid;
+        $user_enrolment_data['userid'] = $USER->id;
+        $DB->insert_record('user_enrolments', $user_enrolment_data);
+
+        // Create a student and give them a grade.
+        $student = self::getDataGenerator()->create_user();
+        $grade = new stdClass();
+        $grade->assignment = $assign->id;
+        $grade->userid = $student->id;
+        $grade->timecreated = time();
+        $grade->timemodified = $grade->timecreated;
+        $grade->grader = $USER->id;
+        $grade->grade = 75;
+        $grade->locked = false;
+        $grade->mailed = true;
+        $DB->insert_record('assign_grades', $grade);
+
+        $assignmentids[] = $assign->id;
+        $result = mod_assign_external::get_grades($assignmentids);
+
+        // Check that the correct grade information for the student is returned.
+        $this->assertEquals(1, count($result['assignments']));
+        $assignment = $result['assignments'][0];
+        $this->assertEquals($assign->id, $assignment['assignmentid']);
+        $this->assertEquals(1, count($assignment['grades']));
+        $grade = $assignment['grades'][0];
+        $this->assertEquals($student->id, $grade['userid']);
+        $this->assertEquals(75, $grade['grade']);
+    }
+
+}
diff --git a/mod/assign/tests/generator/lib.php b/mod/assign/tests/generator/lib.php
new file mode 100644 (file)
index 0000000..9990709
--- /dev/null
@@ -0,0 +1,127 @@
+<?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/>.
+
+defined('MOODLE_INTERNAL') || die();
+
+/**
+ * assign module PHPUnit data generator class
+ *
+ * @package mod_assign
+ * @category phpunit
+ * @copyright 2012 Paul Charsley
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class mod_assign_generator extends phpunit_module_generator {
+
+    /**
+     * Create new assign module instance
+     * @param array|stdClass $record
+     * @param array $options (mostly course_module properties)
+     * @return stdClass activity record with extra cmid field
+     */
+    public function create_instance($record = null, array $options = null) {
+        global $CFG;
+        require_once("$CFG->dirroot/mod/assign/lib.php");
+
+        $this->instancecount++;
+        $i = $this->instancecount;
+
+        $record = (object)(array)$record;
+        $options = (array)$options;
+
+        if (empty($record->course)) {
+            throw new coding_exception('module generator requires $record->course');
+        }
+        if (!isset($record->name)) {
+            $record->name = get_string('pluginname', 'data').' '.$i;
+        }
+        if (!isset($record->intro)) {
+            $record->intro = 'Test database '.$i;
+        }
+        if (!isset($record->introformat)) {
+            $record->introformat = FORMAT_MOODLE;
+        }
+        if (!isset($record->alwaysshowdescription)) {
+            $record->alwaysshowdescription = 1;
+        }
+        if (!isset($record->nosubmissions)) {
+            $record->nosubmissions = 0;
+        }
+        if (!isset($record->submissiondrafts)) {
+            $record->submissiondrafts = 1;
+        }
+        if (!isset($record->requiresubmissionstatement)) {
+            $record->requiresubmissionstatement = 0;
+        }
+        if (!isset($record->sendnotifications)) {
+            $record->sendnotifications = 0;
+        }
+        if (!isset($record->sendlatenotifications)) {
+            $record->sendlatenotifications = 0;
+        }
+        if (!isset($record->duedate)) {
+            $record->duedate = 0;
+        }
+        if (!isset($record->allowsubmissionsfromdate)) {
+            $record->allowsubmissionsfromdate = 0;
+        }
+        if (!isset($record->assignsubmission_onlinetext_enabled)) {
+            $record->assignsubmission_onlinetext_enabled = 0;
+        }
+        if (!isset($record->assignsubmission_file_enabled)) {
+            $record->assignsubmission_file_enabled = 0;
+        }
+        if (!isset($record->assignsubmission_comments_enabled)) {
+            $record->assignsubmission_comments_enabled = 0;
+        }
+        if (!isset($record->assignfeedback_comments_enabled)) {
+            $record->assignfeedback_comments_enabled = 0;
+        }
+        if (!isset($record->assignfeedback_file_enabled)) {
+            $record->assignfeedback_file_enabled = 0;
+        }
+        if (!isset($record->assignfeedback_offline_enabled)) {
+            $record->assignfeedback_offline_enabled = 0;
+        }
+        if (!isset($record->grade)) {
+            $record->grade = 100;
+        }
+        if (!isset($record->cutoffdate)) {
+            $record->cutoffdate = 0;
+        }
+        if (!isset($record->teamsubmission)) {
+            $record->teamsubmission = 0;
+        }
+        if (!isset($record->requireallteammemberssubmit)) {
+            $record->requireallteammemberssubmit = 0;
+        }
+        if (!isset($record->teamsubmissiongroupingid)) {
+            $record->teamsubmissiongroupingid = 0;
+        }
+        if (!isset($record->blindmarking)) {
+            $record->blindmarking = 0;
+        }
+        if (isset($options['idnumber'])) {
+            $record->cmidnumber = $options['idnumber'];
+        } else {
+            $record->cmidnumber = '';
+        }
+
+        $record->coursemodule = $this->precreate_course_module($record->course, $options);
+        $id = assign_add_instance($record, null);
+        return $this->post_add_instance($id, $record->coursemodule);
+    }
+}