weekly on-sync release 2.5dev
[moodle.git] / mod / assign / externallib.php
CommitLineData
1f8c8f61
PC
1<?php
2// This file is part of Moodle - http://moodle.org/
3//
4// Moodle is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8//
9// Moodle is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12// GNU General Public License for more details.
13//
14// You should have received a copy of the GNU General Public License
15// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
16
17/**
18 * External assign API
19 *
20 * @package mod_assign
21 * @since Moodle 2.4
22 * @copyright 2012 Paul Charsley
23 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
24 */
25
26defined('MOODLE_INTERNAL') || die;
27
28require_once("$CFG->libdir/externallib.php");
29
30/**
31 * Assign functions
32 */
33class mod_assign_external extends external_api {
34
35 /**
36 * Describes the parameters for get_grades
37 * @return external_external_function_parameters
38 * @since Moodle 2.4
39 */
40 public static function get_grades_parameters() {
41 return new external_function_parameters(
42 array(
43 'assignmentids' => new external_multiple_structure(
44 new external_value(PARAM_INT, 'assignment id'),
45 '1 or more assignment ids',
46 VALUE_REQUIRED),
47 'since' => new external_value(PARAM_INT,
48 'timestamp, only return records where timemodified >= since',
49 VALUE_DEFAULT, 0)
50 )
51 );
52 }
53
54 /**
55 * Returns grade information from assign_grades for the requested assignment ids
56 * @param array of ints $assignmentids
57 * @param int $since only return records with timemodified >= since
58 * @return array of grade records for each requested assignment
59 * @since Moodle 2.4
60 */
61 public static function get_grades($assignmentids, $since = 0) {
62 global $DB;
63 $params = self::validate_parameters(self::get_grades_parameters(),
64 array('assignmentids' => $assignmentids,
65 'since' => $since));
66
67 $assignments = array();
68 $warnings = array();
69 $requestedassignmentids = $params['assignmentids'];
70
71 // Check the user is allowed to get the grades for the assignments requested.
72 $placeholders = array();
73 list($sqlassignmentids, $placeholders) = $DB->get_in_or_equal($requestedassignmentids, SQL_PARAMS_NAMED);
74 $sql = "SELECT cm.id, cm.instance FROM {course_modules} cm JOIN {modules} md ON md.id = cm.module ".
75 "WHERE md.name = :modname AND cm.instance ".$sqlassignmentids;
76 $placeholders['modname'] = 'assign';
77 $cms = $DB->get_records_sql($sql, $placeholders);
78 foreach ($cms as $cm) {
79 try {
80 $context = context_module::instance($cm->id);
81 self::validate_context($context);
82 require_capability('mod/assign:grade', $context);
83 } catch (Exception $e) {
84 $requestedassignmentids = array_diff($requestedassignmentids, array($cm->instance));
85 $warning = array();
86 $warning['item'] = 'assignment';
87 $warning['itemid'] = $cm->instance;
88 $warning['warningcode'] = '1';
89 $warning['message'] = 'No access rights in module context';
90 $warnings[] = $warning;
91 }
92 }
93
94 // Create the query and populate an array of grade records from the recordset results.
95 if (count ($requestedassignmentids) > 0) {
96 $placeholders = array();
97 list($inorequalsql, $placeholders) = $DB->get_in_or_equal($requestedassignmentids, SQL_PARAMS_NAMED);
98 $sql = "SELECT ag.id,ag.assignment,ag.userid,ag.timecreated,ag.timemodified,".
99 "ag.grader,ag.grade,ag.locked,ag.mailed ".
100 "FROM {assign_grades} ag ".
101 "WHERE ag.assignment ".$inorequalsql.
102 " AND ag.timemodified >= :since".
103 " ORDER BY ag.assignment, ag.id";
104 $placeholders['since'] = $params['since'];
105 $rs = $DB->get_recordset_sql($sql, $placeholders);
106 $currentassignmentid = null;
107 $assignment = null;
108 foreach ($rs as $rd) {
109 $grade = array();
110 $grade['id'] = $rd->id;
111 $grade['userid'] = $rd->userid;
112 $grade['timecreated'] = $rd->timecreated;
113 $grade['timemodified'] = $rd->timemodified;
114 $grade['grader'] = $rd->grader;
115 $grade['grade'] = (string)$rd->grade;
116 $grade['locked'] = $rd->locked;
117 $grade['mailed'] = $rd->mailed;
118
119 if (is_null($currentassignmentid) || ($rd->assignment != $currentassignmentid )) {
120 if (!is_null($assignment)) {
121 $assignments[] = $assignment;
122 }
123 $assignment = array();
124 $assignment['assignmentid'] = $rd->assignment;
125 $assignment['grades'] = array();
126 $requestedassignmentids = array_diff($requestedassignmentids, array($rd->assignment));
127 }
128 $assignment['grades'][] = $grade;
129
130 $currentassignmentid = $rd->assignment;
131 }
132 if (!is_null($assignment)) {
133 $assignments[] = $assignment;
134 }
135 $rs->close();
136 }
137 foreach ($requestedassignmentids as $assignmentid) {
138 $warning = array();
139 $warning['item'] = 'assignment';
140 $warning['itemid'] = $assignmentid;
141 $warning['warningcode'] = '3';
142 $warning['message'] = 'No grades found';
143 $warnings[] = $warning;
144 }
145
146 $result = array();
147 $result['assignments'] = $assignments;
148 $result['warnings'] = $warnings;
149 return $result;
150 }
151
152 /**
153 * Creates an assign_grades external_single_structure
154 * @return external_single_structure
155 * @since Moodle 2.4
156 */
157 private static function assign_grades() {
158 return new external_single_structure(
159 array (
160 'assignmentid' => new external_value(PARAM_INT, 'assignment id'),
161 'grades' => new external_multiple_structure(new external_single_structure(
162 array(
163 'id' => new external_value(PARAM_INT, 'grade id'),
164 'userid' => new external_value(PARAM_INT, 'student id'),
165 'timecreated' => new external_value(PARAM_INT, 'grade creation time'),
166 'timemodified' => new external_value(PARAM_INT, 'grade last modified time'),
167 'grader' => new external_value(PARAM_INT, 'grader'),
168 'grade' => new external_value(PARAM_TEXT, 'grade'),
169 'locked' => new external_value(PARAM_BOOL, 'locked'),
170 'mailed' => new external_value(PARAM_BOOL, 'mailed')
171 )
172 )
173 )
174 )
175 );
176 }
177
178 /**
179 * Describes the get_grades return value
180 * @return external_single_structure
181 * @since Moodle 2.4
182 */
183 public static function get_grades_returns() {
184 return new external_single_structure(
185 array(
186 'assignments' => new external_multiple_structure(self::assign_grades(), 'list of assignment grade information'),
187 'warnings' => new external_warnings()
188 )
189 );
190 }
191
1378838e
PC
192 /**
193 * Returns description of method parameters
2ea4312a 194 *
1378838e
PC
195 * @return external_function_parameters
196 * @since Moodle 2.4
197 */
198 public static function get_assignments_parameters() {
199 return new external_function_parameters(
200 array(
201 'courseids' => new external_multiple_structure(
202 new external_value(PARAM_INT, 'course id'),
203 '0 or more course ids',
204 VALUE_DEFAULT, array()
205 ),
206 'capabilities' => new external_multiple_structure(
207 new external_value(PARAM_CAPABILITY, 'capability'),
208 'list of capabilities used to filter courses',
209 VALUE_DEFAULT, array()
210 )
211 )
212 );
213 }
214
215 /**
216 * Returns an array of courses the user is enrolled in, and for each course all of the assignments that the user can
217 * view within that course.
2ea4312a 218 *
1378838e
PC
219 * @param array $courseids An optional array of course ids. If provided only assignments within the given course
220 * will be returned. If the user is not enrolled in a given course a warning will be generated and returned.
221 * @param array $capabilities An array of additional capability checks you wish to be made on the course context.
222 * @return An array of courses and warnings.
223 * @since Moodle 2.4
224 */
225 public static function get_assignments($courseids = array(), $capabilities = array()) {
226 global $USER, $DB;
227
228 $params = self::validate_parameters(
229 self::get_assignments_parameters(),
230 array('courseids' => $courseids, 'capabilities' => $capabilities)
231 );
232
233 $warnings = array();
234 $fields = 'sortorder,shortname,fullname,timemodified';
235 $courses = enrol_get_users_courses($USER->id, true, $fields);
236 // Used to test for ids that have been requested but can't be returned.
237 if (count($params['courseids']) > 0) {
238 foreach ($params['courseids'] as $courseid) {
239 if (!in_array($courseid, array_keys($courses))) {
240 unset($courses[$courseid]);
241 $warnings[] = array(
242 'item' => 'course',
243 'itemid' => $courseid,
244 'warningcode' => '2',
245 'message' => 'User is not enrolled or does not have requested capability'
246 );
247 }
248 }
249 }
250 foreach ($courses as $id => $course) {
251 if (count($params['courseids']) > 0 && !in_array($id, $params['courseids'])) {
252 unset($courses[$id]);
253 }
254 $context = context_course::instance($id);
255 try {
256 self::validate_context($context);
1378838e
PC
257 } catch (Exception $e) {
258 unset($courses[$id]);
259 $warnings[] = array(
260 'item' => 'course',
261 'itemid' => $id,
262 'warningcode' => '1',
263 'message' => 'No access rights in course context '.$e->getMessage().$e->getTraceAsString()
264 );
265 continue;
266 }
267 if (count($params['capabilities']) > 0 && !has_all_capabilities($params['capabilities'], $context)) {
268 unset($courses[$id]);
269 }
270 }
271 $extrafields='m.id as assignmentid, m.course, m.nosubmissions, m.submissiondrafts, m.sendnotifications, '.
272 'm.sendlatenotifications, m.duedate, m.allowsubmissionsfromdate, m.grade, m.timemodified, '.
273 'm.completionsubmit, m.cutoffdate, m.teamsubmission, m.requireallteammemberssubmit, '.
274 'm.teamsubmissiongroupingid, m.blindmarking, m.revealidentities, m.requiresubmissionstatement';
275 $coursearray = array();
276 foreach ($courses as $id => $course) {
277 $assignmentarray = array();
278 // Get a list of assignments for the course.
279 if ($modules = get_coursemodules_in_course('assign', $courses[$id]->id, $extrafields)) {
280 foreach ($modules as $module) {
281 $context = context_module::instance($module->id);
282 try {
283 self::validate_context($context);
284 require_capability('mod/assign:view', $context);
285 } catch (Exception $e) {
286 $warnings[] = array(
287 'item' => 'module',
288 'itemid' => $module->id,
289 'warningcode' => '1',
290 'message' => 'No access rights in module context'
291 );
292 continue;
293 }
294 $configrecords = $DB->get_recordset('assign_plugin_config', array('assignment' => $module->assignmentid));
295 $configarray = array();
296 foreach ($configrecords as $configrecord) {
297 $configarray[] = array(
298 'id' => $configrecord->id,
299 'assignment' => $configrecord->assignment,
300 'plugin' => $configrecord->plugin,
301 'subtype' => $configrecord->subtype,
302 'name' => $configrecord->name,
303 'value' => $configrecord->value
304 );
305 }
306 $configrecords->close();
307
308 $assignmentarray[]= array(
309 'id' => $module->assignmentid,
310 'cmid' => $module->id,
311 'course' => $module->course,
312 'name' => $module->name,
313 'nosubmissions' => $module->nosubmissions,
314 'submissiondrafts' => $module->submissiondrafts,
315 'sendnotifications' => $module->sendnotifications,
316 'sendlatenotifications' => $module->sendlatenotifications,
317 'duedate' => $module->duedate,
318 'allowsubmissionsfromdate' => $module->allowsubmissionsfromdate,
319 'grade' => $module->grade,
320 'timemodified' => $module->timemodified,
321 'completionsubmit' => $module->completionsubmit,
322 'cutoffdate' => $module->cutoffdate,
323 'teamsubmission' => $module->teamsubmission,
324 'requireallteammemberssubmit' => $module->requireallteammemberssubmit,
325 'teamsubmissiongroupingid' => $module->teamsubmissiongroupingid,
326 'blindmarking' => $module->blindmarking,
327 'revealidentities' => $module->revealidentities,
328 'requiresubmissionstatement' => $module->requiresubmissionstatement,
329 'configs' => $configarray
330 );
331 }
332 }
333 $coursearray[]= array(
334 'id' => $courses[$id]->id,
335 'fullname' => $courses[$id]->fullname,
336 'shortname' => $courses[$id]->shortname,
337 'timemodified' => $courses[$id]->timemodified,
338 'assignments' => $assignmentarray
339 );
340 }
341
342 $result = array(
343 'courses' => $coursearray,
344 'warnings' => $warnings
345 );
346 return $result;
347 }
348
349 /**
350 * Creates an assignment external_single_structure
2ea4312a 351 *
1378838e
PC
352 * @return external_single_structure
353 * @since Moodle 2.4
354 */
355 private static function get_assignments_assignment_structure() {
356 return new external_single_structure(
357 array(
358 'id' => new external_value(PARAM_INT, 'assignment id'),
359 'course' => new external_value(PARAM_INT, 'course id'),
360 'name' => new external_value(PARAM_TEXT, 'assignment name'),
361 'nosubmissions' => new external_value(PARAM_INT, 'no submissions'),
362 'submissiondrafts' => new external_value(PARAM_INT, 'submissions drafts'),
363 'sendnotifications' => new external_value(PARAM_INT, 'send notifications'),
364 'sendlatenotifications' => new external_value(PARAM_INT, 'send notifications'),
365 'duedate' => new external_value(PARAM_INT, 'assignment due date'),
366 'allowsubmissionsfromdate' => new external_value(PARAM_INT, 'allow submissions from date'),
367 'grade' => new external_value(PARAM_INT, 'grade type'),
368 'timemodified' => new external_value(PARAM_INT, 'last time assignment was modified'),
369 'completionsubmit' => new external_value(PARAM_INT, 'if enabled, set activity as complete following submission'),
370 'cutoffdate' => new external_value(PARAM_INT, 'date after which submission is not accepted without an extension'),
371 'teamsubmission' => new external_value(PARAM_INT, 'if enabled, students submit as a team'),
372 'requireallteammemberssubmit' => new external_value(PARAM_INT, 'if enabled, all team members must submit'),
373 'teamsubmissiongroupingid' => new external_value(PARAM_INT, 'the grouping id for the team submission groups'),
374 'blindmarking' => new external_value(PARAM_INT, 'if enabled, hide identities until reveal identities actioned'),
375 'revealidentities' => new external_value(PARAM_INT, 'show identities for a blind marking assignment'),
376 'requiresubmissionstatement' => new external_value(PARAM_INT, 'student must accept submission statement'),
377 'configs' => new external_multiple_structure(self::get_assignments_config_structure(), 'configuration settings')
378 ), 'assignment information object');
379 }
380
381 /**
382 * Creates an assign_plugin_config external_single_structure
2ea4312a 383 *
1378838e
PC
384 * @return external_single_structure
385 * @since Moodle 2.4
386 */
387 private static function get_assignments_config_structure() {
388 return new external_single_structure(
389 array(
390 'id' => new external_value(PARAM_INT, 'assign_plugin_config id'),
391 'assignment' => new external_value(PARAM_INT, 'assignment id'),
392 'plugin' => new external_value(PARAM_TEXT, 'plugin'),
393 'subtype' => new external_value(PARAM_TEXT, 'subtype'),
394 'name' => new external_value(PARAM_TEXT, 'name'),
395 'value' => new external_value(PARAM_TEXT, 'value')
396 ), 'assignment configuration object'
397 );
398 }
399
400 /**
401 * Creates a course external_single_structure
2ea4312a 402 *
1378838e 403 * @return external_single_structure
2ea4312a 404 * @since Moodle 2.4
1378838e
PC
405 */
406 private static function get_assignments_course_structure() {
407 return new external_single_structure(
408 array(
409 'id' => new external_value(PARAM_INT, 'course id'),
410 'fullname' => new external_value(PARAM_TEXT, 'course full name'),
411 'shortname' => new external_value(PARAM_TEXT, 'course short name'),
412 'timemodified' => new external_value(PARAM_INT, 'last time modified'),
413 'assignments' => new external_multiple_structure(self::get_assignments_assignment_structure(), 'assignment info')
414 ), 'course information object'
415 );
416 }
417
2ea4312a 418 /**
1378838e 419 * Describes the return value for get_assignments
2ea4312a 420 *
1378838e
PC
421 * @return external_single_structure
422 * @since Moodle 2.4
423 */
424 public static function get_assignments_returns() {
425 return new external_single_structure(
426 array(
427 'courses' => new external_multiple_structure(self::get_assignments_course_structure(), 'list of courses'),
428 'warnings' => new external_warnings()
429 )
430 );
431 }
1f8c8f61 432}