From 1f8c8f6125bc9aa51ac385906131d669bc7e3132 Mon Sep 17 00:00:00 2001 From: Paul Charsley Date: Wed, 19 Sep 2012 08:32:32 +1200 Subject: [PATCH] MDL-31873 added mod_assign_get_grades web service function --- mod/assign/db/services.php | 34 +++++ mod/assign/externallib.php | 192 ++++++++++++++++++++++++++ mod/assign/tests/externallib_test.php | 104 ++++++++++++++ mod/assign/tests/generator/lib.php | 127 +++++++++++++++++ 4 files changed, 457 insertions(+) create mode 100644 mod/assign/db/services.php create mode 100644 mod/assign/externallib.php create mode 100644 mod/assign/tests/externallib_test.php create mode 100644 mod/assign/tests/generator/lib.php diff --git a/mod/assign/db/services.php b/mod/assign/db/services.php new file mode 100644 index 00000000000..40ce90de9b5 --- /dev/null +++ b/mod/assign/db/services.php @@ -0,0 +1,34 @@ +. + +/** + * 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 index 00000000000..4939099aa3e --- /dev/null +++ b/mod/assign/externallib.php @@ -0,0 +1,192 @@ +. + +/** + * 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 index 00000000000..a743ed4a09b --- /dev/null +++ b/mod/assign/tests/externallib_test.php @@ -0,0 +1,104 @@ +. + +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 index 00000000000..99907091d1c --- /dev/null +++ b/mod/assign/tests/generator/lib.php @@ -0,0 +1,127 @@ +. + +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); + } +} -- 2.43.0