MDL-37028 Fixed bug, orphaned modules are moved to the 0-section
[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);
a13fbf5f
DW
98 list($inorequalsql2, $placeholders2) = $DB->get_in_or_equal($requestedassignmentids, SQL_PARAMS_NAMED);
99
100 $grademaxattempt = 'SELECT mxg.userid, MAX(mxg.attemptnumber) AS maxattempt
101 FROM {assign_grades} mxg
102 WHERE mxg.assignment ' . $inorequalsql2 . ' GROUP BY mxg.userid';
103
1f8c8f61 104 $sql = "SELECT ag.id,ag.assignment,ag.userid,ag.timecreated,ag.timemodified,".
df211804 105 "ag.grader,ag.grade ".
1f8c8f61 106 "FROM {assign_grades} ag ".
a13fbf5f
DW
107 "JOIN ( " . $grademaxattempt . " ) gmx ON ag.userid = gmx.userid".
108 " WHERE ag.assignment ".$inorequalsql.
1f8c8f61 109 " AND ag.timemodified >= :since".
a13fbf5f 110 " AND ag.attemptnumber = gmx.maxattempt" .
1f8c8f61
PC
111 " ORDER BY ag.assignment, ag.id";
112 $placeholders['since'] = $params['since'];
a13fbf5f
DW
113 // Combine the parameters.
114 $placeholders += $placeholders2;
1f8c8f61
PC
115 $rs = $DB->get_recordset_sql($sql, $placeholders);
116 $currentassignmentid = null;
117 $assignment = null;
118 foreach ($rs as $rd) {
119 $grade = array();
120 $grade['id'] = $rd->id;
121 $grade['userid'] = $rd->userid;
122 $grade['timecreated'] = $rd->timecreated;
123 $grade['timemodified'] = $rd->timemodified;
124 $grade['grader'] = $rd->grader;
125 $grade['grade'] = (string)$rd->grade;
1f8c8f61
PC
126
127 if (is_null($currentassignmentid) || ($rd->assignment != $currentassignmentid )) {
128 if (!is_null($assignment)) {
129 $assignments[] = $assignment;
130 }
131 $assignment = array();
132 $assignment['assignmentid'] = $rd->assignment;
133 $assignment['grades'] = array();
134 $requestedassignmentids = array_diff($requestedassignmentids, array($rd->assignment));
135 }
136 $assignment['grades'][] = $grade;
137
138 $currentassignmentid = $rd->assignment;
139 }
140 if (!is_null($assignment)) {
141 $assignments[] = $assignment;
142 }
143 $rs->close();
144 }
145 foreach ($requestedassignmentids as $assignmentid) {
146 $warning = array();
147 $warning['item'] = 'assignment';
148 $warning['itemid'] = $assignmentid;
149 $warning['warningcode'] = '3';
150 $warning['message'] = 'No grades found';
151 $warnings[] = $warning;
152 }
153
154 $result = array();
155 $result['assignments'] = $assignments;
156 $result['warnings'] = $warnings;
157 return $result;
158 }
159
160 /**
161 * Creates an assign_grades external_single_structure
162 * @return external_single_structure
163 * @since Moodle 2.4
164 */
165 private static function assign_grades() {
166 return new external_single_structure(
167 array (
168 'assignmentid' => new external_value(PARAM_INT, 'assignment id'),
169 'grades' => new external_multiple_structure(new external_single_structure(
170 array(
171 'id' => new external_value(PARAM_INT, 'grade id'),
172 'userid' => new external_value(PARAM_INT, 'student id'),
173 'timecreated' => new external_value(PARAM_INT, 'grade creation time'),
174 'timemodified' => new external_value(PARAM_INT, 'grade last modified time'),
175 'grader' => new external_value(PARAM_INT, 'grader'),
df211804 176 'grade' => new external_value(PARAM_TEXT, 'grade')
1f8c8f61
PC
177 )
178 )
179 )
180 )
181 );
182 }
183
184 /**
185 * Describes the get_grades return value
186 * @return external_single_structure
187 * @since Moodle 2.4
188 */
189 public static function get_grades_returns() {
190 return new external_single_structure(
191 array(
192 'assignments' => new external_multiple_structure(self::assign_grades(), 'list of assignment grade information'),
8118dbd0 193 'warnings' => new external_warnings('item is always \'assignment\'',
b0da618b 194 'when errorcode is 3 then itemid is an assignment id. When errorcode is 1, itemid is a course module id',
8118dbd0 195 'errorcode can be 3 (no grades found) or 1 (no permission to get grades)')
1f8c8f61
PC
196 )
197 );
198 }
199
1378838e
PC
200 /**
201 * Returns description of method parameters
2ea4312a 202 *
1378838e
PC
203 * @return external_function_parameters
204 * @since Moodle 2.4
205 */
206 public static function get_assignments_parameters() {
207 return new external_function_parameters(
208 array(
209 'courseids' => new external_multiple_structure(
210 new external_value(PARAM_INT, 'course id'),
211 '0 or more course ids',
212 VALUE_DEFAULT, array()
213 ),
214 'capabilities' => new external_multiple_structure(
215 new external_value(PARAM_CAPABILITY, 'capability'),
216 'list of capabilities used to filter courses',
217 VALUE_DEFAULT, array()
218 )
219 )
220 );
221 }
222
223 /**
224 * Returns an array of courses the user is enrolled in, and for each course all of the assignments that the user can
225 * view within that course.
2ea4312a 226 *
1378838e
PC
227 * @param array $courseids An optional array of course ids. If provided only assignments within the given course
228 * will be returned. If the user is not enrolled in a given course a warning will be generated and returned.
229 * @param array $capabilities An array of additional capability checks you wish to be made on the course context.
230 * @return An array of courses and warnings.
231 * @since Moodle 2.4
232 */
233 public static function get_assignments($courseids = array(), $capabilities = array()) {
234 global $USER, $DB;
235
236 $params = self::validate_parameters(
237 self::get_assignments_parameters(),
238 array('courseids' => $courseids, 'capabilities' => $capabilities)
239 );
240
241 $warnings = array();
242 $fields = 'sortorder,shortname,fullname,timemodified';
243 $courses = enrol_get_users_courses($USER->id, true, $fields);
244 // Used to test for ids that have been requested but can't be returned.
245 if (count($params['courseids']) > 0) {
246 foreach ($params['courseids'] as $courseid) {
247 if (!in_array($courseid, array_keys($courses))) {
248 unset($courses[$courseid]);
249 $warnings[] = array(
250 'item' => 'course',
251 'itemid' => $courseid,
252 'warningcode' => '2',
253 'message' => 'User is not enrolled or does not have requested capability'
254 );
255 }
256 }
257 }
258 foreach ($courses as $id => $course) {
259 if (count($params['courseids']) > 0 && !in_array($id, $params['courseids'])) {
260 unset($courses[$id]);
261 }
262 $context = context_course::instance($id);
263 try {
264 self::validate_context($context);
1378838e
PC
265 } catch (Exception $e) {
266 unset($courses[$id]);
267 $warnings[] = array(
268 'item' => 'course',
269 'itemid' => $id,
270 'warningcode' => '1',
271 'message' => 'No access rights in course context '.$e->getMessage().$e->getTraceAsString()
272 );
273 continue;
274 }
275 if (count($params['capabilities']) > 0 && !has_all_capabilities($params['capabilities'], $context)) {
276 unset($courses[$id]);
277 }
278 }
279 $extrafields='m.id as assignmentid, m.course, m.nosubmissions, m.submissiondrafts, m.sendnotifications, '.
280 'm.sendlatenotifications, m.duedate, m.allowsubmissionsfromdate, m.grade, m.timemodified, '.
281 'm.completionsubmit, m.cutoffdate, m.teamsubmission, m.requireallteammemberssubmit, '.
912cbaf1
PC
282 'm.teamsubmissiongroupingid, m.blindmarking, m.revealidentities, m.attemptreopenmethod, '.
283 'm.maxattempts, m.markingworkflow, m.markingallocation, m.requiresubmissionstatement';
1378838e
PC
284 $coursearray = array();
285 foreach ($courses as $id => $course) {
286 $assignmentarray = array();
287 // Get a list of assignments for the course.
288 if ($modules = get_coursemodules_in_course('assign', $courses[$id]->id, $extrafields)) {
289 foreach ($modules as $module) {
290 $context = context_module::instance($module->id);
291 try {
292 self::validate_context($context);
293 require_capability('mod/assign:view', $context);
294 } catch (Exception $e) {
295 $warnings[] = array(
296 'item' => 'module',
297 'itemid' => $module->id,
298 'warningcode' => '1',
299 'message' => 'No access rights in module context'
300 );
301 continue;
302 }
303 $configrecords = $DB->get_recordset('assign_plugin_config', array('assignment' => $module->assignmentid));
304 $configarray = array();
305 foreach ($configrecords as $configrecord) {
306 $configarray[] = array(
307 'id' => $configrecord->id,
308 'assignment' => $configrecord->assignment,
309 'plugin' => $configrecord->plugin,
310 'subtype' => $configrecord->subtype,
311 'name' => $configrecord->name,
312 'value' => $configrecord->value
313 );
314 }
315 $configrecords->close();
316
317 $assignmentarray[]= array(
318 'id' => $module->assignmentid,
319 'cmid' => $module->id,
320 'course' => $module->course,
321 'name' => $module->name,
322 'nosubmissions' => $module->nosubmissions,
323 'submissiondrafts' => $module->submissiondrafts,
324 'sendnotifications' => $module->sendnotifications,
325 'sendlatenotifications' => $module->sendlatenotifications,
326 'duedate' => $module->duedate,
327 'allowsubmissionsfromdate' => $module->allowsubmissionsfromdate,
328 'grade' => $module->grade,
329 'timemodified' => $module->timemodified,
330 'completionsubmit' => $module->completionsubmit,
331 'cutoffdate' => $module->cutoffdate,
332 'teamsubmission' => $module->teamsubmission,
333 'requireallteammemberssubmit' => $module->requireallteammemberssubmit,
334 'teamsubmissiongroupingid' => $module->teamsubmissiongroupingid,
335 'blindmarking' => $module->blindmarking,
336 'revealidentities' => $module->revealidentities,
912cbaf1
PC
337 'attemptreopenmethod' => $module->attemptreopenmethod,
338 'maxattempts' => $module->maxattempts,
339 'markingworkflow' => $module->markingworkflow,
340 'markingallocation' => $module->markingallocation,
1378838e
PC
341 'requiresubmissionstatement' => $module->requiresubmissionstatement,
342 'configs' => $configarray
343 );
344 }
345 }
346 $coursearray[]= array(
347 'id' => $courses[$id]->id,
348 'fullname' => $courses[$id]->fullname,
349 'shortname' => $courses[$id]->shortname,
350 'timemodified' => $courses[$id]->timemodified,
351 'assignments' => $assignmentarray
352 );
353 }
354
355 $result = array(
356 'courses' => $coursearray,
357 'warnings' => $warnings
358 );
359 return $result;
360 }
361
362 /**
363 * Creates an assignment external_single_structure
2ea4312a 364 *
1378838e
PC
365 * @return external_single_structure
366 * @since Moodle 2.4
367 */
368 private static function get_assignments_assignment_structure() {
369 return new external_single_structure(
370 array(
371 'id' => new external_value(PARAM_INT, 'assignment id'),
912cbaf1 372 'cmid' => new external_value(PARAM_INT, 'course module id'),
1378838e
PC
373 'course' => new external_value(PARAM_INT, 'course id'),
374 'name' => new external_value(PARAM_TEXT, 'assignment name'),
375 'nosubmissions' => new external_value(PARAM_INT, 'no submissions'),
376 'submissiondrafts' => new external_value(PARAM_INT, 'submissions drafts'),
377 'sendnotifications' => new external_value(PARAM_INT, 'send notifications'),
378 'sendlatenotifications' => new external_value(PARAM_INT, 'send notifications'),
379 'duedate' => new external_value(PARAM_INT, 'assignment due date'),
380 'allowsubmissionsfromdate' => new external_value(PARAM_INT, 'allow submissions from date'),
381 'grade' => new external_value(PARAM_INT, 'grade type'),
382 'timemodified' => new external_value(PARAM_INT, 'last time assignment was modified'),
383 'completionsubmit' => new external_value(PARAM_INT, 'if enabled, set activity as complete following submission'),
384 'cutoffdate' => new external_value(PARAM_INT, 'date after which submission is not accepted without an extension'),
385 'teamsubmission' => new external_value(PARAM_INT, 'if enabled, students submit as a team'),
386 'requireallteammemberssubmit' => new external_value(PARAM_INT, 'if enabled, all team members must submit'),
387 'teamsubmissiongroupingid' => new external_value(PARAM_INT, 'the grouping id for the team submission groups'),
388 'blindmarking' => new external_value(PARAM_INT, 'if enabled, hide identities until reveal identities actioned'),
389 'revealidentities' => new external_value(PARAM_INT, 'show identities for a blind marking assignment'),
912cbaf1
PC
390 'attemptreopenmethod' => new external_value(PARAM_TEXT, 'method used to control opening new attempts'),
391 'maxattempts' => new external_value(PARAM_INT, 'maximum number of attempts allowed'),
392 'markingworkflow' => new external_value(PARAM_INT, 'enable marking workflow'),
393 'markingallocation' => new external_value(PARAM_INT, 'enable marking allocation'),
1378838e
PC
394 'requiresubmissionstatement' => new external_value(PARAM_INT, 'student must accept submission statement'),
395 'configs' => new external_multiple_structure(self::get_assignments_config_structure(), 'configuration settings')
396 ), 'assignment information object');
397 }
398
399 /**
400 * Creates an assign_plugin_config external_single_structure
2ea4312a 401 *
1378838e
PC
402 * @return external_single_structure
403 * @since Moodle 2.4
404 */
405 private static function get_assignments_config_structure() {
406 return new external_single_structure(
407 array(
408 'id' => new external_value(PARAM_INT, 'assign_plugin_config id'),
409 'assignment' => new external_value(PARAM_INT, 'assignment id'),
410 'plugin' => new external_value(PARAM_TEXT, 'plugin'),
411 'subtype' => new external_value(PARAM_TEXT, 'subtype'),
412 'name' => new external_value(PARAM_TEXT, 'name'),
413 'value' => new external_value(PARAM_TEXT, 'value')
414 ), 'assignment configuration object'
415 );
416 }
417
418 /**
419 * Creates a course external_single_structure
2ea4312a 420 *
1378838e 421 * @return external_single_structure
2ea4312a 422 * @since Moodle 2.4
1378838e
PC
423 */
424 private static function get_assignments_course_structure() {
425 return new external_single_structure(
426 array(
427 'id' => new external_value(PARAM_INT, 'course id'),
428 'fullname' => new external_value(PARAM_TEXT, 'course full name'),
429 'shortname' => new external_value(PARAM_TEXT, 'course short name'),
430 'timemodified' => new external_value(PARAM_INT, 'last time modified'),
431 'assignments' => new external_multiple_structure(self::get_assignments_assignment_structure(), 'assignment info')
432 ), 'course information object'
433 );
434 }
435
2ea4312a 436 /**
1378838e 437 * Describes the return value for get_assignments
2ea4312a 438 *
1378838e
PC
439 * @return external_single_structure
440 * @since Moodle 2.4
441 */
442 public static function get_assignments_returns() {
443 return new external_single_structure(
444 array(
445 'courses' => new external_multiple_structure(self::get_assignments_course_structure(), 'list of courses'),
8118dbd0
JM
446 'warnings' => new external_warnings('item can be \'course\' (errorcode 1 or 2) or \'module\' (errorcode 1)',
447 'When item is a course then itemid is a course id. When the item is a module then itemid is a module id',
448 'errorcode can be 1 (no access rights) or 2 (not enrolled or no permissions)')
1378838e
PC
449 )
450 );
451 }
c144959c
PC
452
453 /**
454 * Describes the parameters for get_submissions
455 *
456 * @return external_external_function_parameters
2d971403 457 * @since Moodle 2.5
c144959c
PC
458 */
459 public static function get_submissions_parameters() {
460 return new external_function_parameters(
461 array(
462 'assignmentids' => new external_multiple_structure(
463 new external_value(PARAM_INT, 'assignment id'),
464 '1 or more assignment ids',
465 VALUE_REQUIRED),
466 'status' => new external_value(PARAM_ALPHA, 'status', VALUE_DEFAULT, ''),
467 'since' => new external_value(PARAM_INT, 'submitted since', VALUE_DEFAULT, 0),
468 'before' => new external_value(PARAM_INT, 'submitted before', VALUE_DEFAULT, 0)
469 )
470 );
471 }
472
473 /**
474 * Returns submissions for the requested assignment ids
475 *
476 * @param array of ints $assignmentids
477 * @param string $status only return submissions with this status
478 * @param int $since only return submissions with timemodified >= since
479 * @param int $before only return submissions with timemodified <= before
480 * @return array of submissions for each requested assignment
2d971403 481 * @since Moodle 2.5
c144959c
PC
482 */
483 public static function get_submissions($assignmentids, $status = '', $since = 0, $before = 0) {
484 global $DB, $CFG;
485 require_once("$CFG->dirroot/mod/assign/locallib.php");
486 $params = self::validate_parameters(self::get_submissions_parameters(),
487 array('assignmentids' => $assignmentids,
488 'status' => $status,
489 'since' => $since,
490 'before' => $before));
491
492 $warnings = array();
493 $assignments = array();
494
495 // Check the user is allowed to get the submissions for the assignments requested.
496 $placeholders = array();
497 list($inorequalsql, $placeholders) = $DB->get_in_or_equal($params['assignmentids'], SQL_PARAMS_NAMED);
498 $sql = "SELECT cm.id, cm.instance FROM {course_modules} cm JOIN {modules} md ON md.id = cm.module ".
499 "WHERE md.name = :modname AND cm.instance ".$inorequalsql;
500 $placeholders['modname'] = 'assign';
501 $cms = $DB->get_records_sql($sql, $placeholders);
502 $assigns = array();
503 foreach ($cms as $cm) {
504 try {
505 $context = context_module::instance($cm->id);
506 self::validate_context($context);
507 require_capability('mod/assign:grade', $context);
508 $assign = new assign($context, null, null);
509 $assigns[] = $assign;
510 } catch (Exception $e) {
511 $warnings[] = array(
512 'item' => 'assignment',
513 'itemid' => $cm->instance,
514 'warningcode' => '1',
515 'message' => 'No access rights in module context'
516 );
517 }
518 }
519
520 foreach ($assigns as $assign) {
521 $submissions = array();
522 $submissionplugins = $assign->get_submission_plugins();
a13fbf5f
DW
523 $placeholders = array('assignid1' => $assign->get_instance()->id,
524 'assignid2' => $assign->get_instance()->id);
525
526 $submissionmaxattempt = 'SELECT mxs.userid, MAX(mxs.attemptnumber) AS maxattempt
527 FROM {assign_submission} mxs
528 WHERE mxs.assignment = :assignid1 GROUP BY mxs.userid';
529
c144959c
PC
530 $sql = "SELECT mas.id, mas.assignment,mas.userid,".
531 "mas.timecreated,mas.timemodified,mas.status,mas.groupid ".
532 "FROM {assign_submission} mas ".
a13fbf5f
DW
533 "JOIN ( " . $submissionmaxattempt . " ) smx ON mas.userid = smx.userid ".
534 "WHERE mas.assignment = :assignid2 AND mas.attemptnumber = smx.maxattempt";
c144959c
PC
535
536 if (!empty($params['status'])) {
537 $placeholders['status'] = $params['status'];
538 $sql = $sql." AND mas.status = :status";
539 }
540 if (!empty($params['before'])) {
541 $placeholders['since'] = $params['since'];
542 $placeholders['before'] = $params['before'];
543 $sql = $sql." AND mas.timemodified BETWEEN :since AND :before";
544 } else {
545 $placeholders['since'] = $params['since'];
546 $sql = $sql." AND mas.timemodified >= :since";
547 }
548
549 $submissionrecords = $DB->get_records_sql($sql, $placeholders);
550
551 if (!empty($submissionrecords)) {
552 $fs = get_file_storage();
553 foreach ($submissionrecords as $submissionrecord) {
554 $submission = array(
555 'id' => $submissionrecord->id,
556 'userid' => $submissionrecord->userid,
557 'timecreated' => $submissionrecord->timecreated,
558 'timemodified' => $submissionrecord->timemodified,
559 'status' => $submissionrecord->status,
560 'groupid' => $submissionrecord->groupid
561 );
562 foreach ($submissionplugins as $submissionplugin) {
563 $plugin = array(
564 'name' => $submissionplugin->get_name(),
565 'type' => $submissionplugin->get_type()
566 );
567 // Subtype is 'assignsubmission', type is currently 'file' or 'onlinetext'.
568 $component = $submissionplugin->get_subtype().'_'.$submissionplugin->get_type();
569
570 $fileareas = $submissionplugin->get_file_areas();
571 foreach ($fileareas as $filearea => $name) {
572 $fileareainfo = array('area' => $filearea);
573 $files = $fs->get_area_files(
574 $assign->get_context()->id,
575 $component,
576 $filearea,
577 $submissionrecord->id,
578 "timemodified",
579 false
580 );
581 foreach ($files as $file) {
582 $filepath = array('filepath' => $file->get_filepath().$file->get_filename());
583 $fileareainfo['files'][] = $filepath;
584 }
585 $plugin['fileareas'][] = $fileareainfo;
586 }
587
588 $editorfields = $submissionplugin->get_editor_fields();
589 foreach ($editorfields as $name => $description) {
590 $editorfieldinfo = array(
591 'name' => $name,
592 'description' => $description,
593 'text' => $submissionplugin->get_editor_text($name, $submissionrecord->id),
594 'format' => $submissionplugin->get_editor_format($name, $submissionrecord->id)
595 );
596 $plugin['editorfields'][] = $editorfieldinfo;
597 }
598
599 $submission['plugins'][] = $plugin;
600 }
601 $submissions[] = $submission;
602 }
603 } else {
604 $warnings[] = array(
605 'item' => 'module',
606 'itemid' => $assign->get_instance()->id,
607 'warningcode' => '3',
608 'message' => 'No submissions found'
609 );
610 }
611
612 $assignments[] = array(
613 'assignmentid' => $assign->get_instance()->id,
614 'submissions' => $submissions
615 );
616
617 }
618
619 $result = array(
620 'assignments' => $assignments,
621 'warnings' => $warnings
622 );
623 return $result;
624 }
625
626 /**
627 * Creates an assign_submissions external_single_structure
628 *
629 * @return external_single_structure
2d971403 630 * @since Moodle 2.5
c144959c
PC
631 */
632 private static function get_submissions_structure() {
633 return new external_single_structure(
634 array (
635 'assignmentid' => new external_value(PARAM_INT, 'assignment id'),
636 'submissions' => new external_multiple_structure(
637 new external_single_structure(
638 array(
639 'id' => new external_value(PARAM_INT, 'submission id'),
640 'userid' => new external_value(PARAM_INT, 'student id'),
641 'timecreated' => new external_value(PARAM_INT, 'submission creation time'),
642 'timemodified' => new external_value(PARAM_INT, 'submission last modified time'),
643 'status' => new external_value(PARAM_TEXT, 'submission status'),
644 'groupid' => new external_value(PARAM_INT, 'group id'),
645 'plugins' => new external_multiple_structure(
646 new external_single_structure(
647 array(
648 'type' => new external_value(PARAM_TEXT, 'submission plugin type'),
649 'name' => new external_value(PARAM_TEXT, 'submission plugin name'),
650 'fileareas' => new external_multiple_structure(
651 new external_single_structure(
652 array (
653 'area' => new external_value (PARAM_TEXT, 'file area'),
654 'files' => new external_multiple_structure(
655 new external_single_structure(
656 array (
657 'filepath' => new external_value (PARAM_TEXT, 'file path')
658 )
659 ), 'files', VALUE_OPTIONAL
660 )
661 )
662 ), 'fileareas', VALUE_OPTIONAL
663 ),
664 'editorfields' => new external_multiple_structure(
665 new external_single_structure(
666 array(
667 'name' => new external_value(PARAM_TEXT, 'field name'),
668 'description' => new external_value(PARAM_TEXT, 'field description'),
9f780282
DP
669 'text' => new external_value (PARAM_RAW, 'field value'),
670 'format' => new external_format_value ('text')
c144959c
PC
671 )
672 )
673 , 'editorfields', VALUE_OPTIONAL
674 )
675 )
676 )
677 , 'plugins', VALUE_OPTIONAL
678 )
679 )
680 )
681 )
682 )
683 );
684 }
685
686 /**
687 * Describes the get_submissions return value
688 *
689 * @return external_single_structure
2d971403 690 * @since Moodle 2.5
c144959c
PC
691 */
692 public static function get_submissions_returns() {
693 return new external_single_structure(
694 array(
695 'assignments' => new external_multiple_structure(self::get_submissions_structure(), 'assignment submissions'),
696 'warnings' => new external_warnings()
697 )
698 );
699 }
07df8c38
PC
700
701 /**
702 * Describes the parameters for get_user_flags
703 * @return external_function_parameters
704 * @since Moodle 2.6
705 */
706 public static function get_user_flags_parameters() {
707 return new external_function_parameters(
708 array(
709 'assignmentids' => new external_multiple_structure(
710 new external_value(PARAM_INT, 'assignment id'),
711 '1 or more assignment ids',
712 VALUE_REQUIRED)
713 )
714 );
715 }
716
717 /**
718 * Returns user flag information from assign_user_flags for the requested assignment ids
719 * @param array of ints $assignmentids
720 * @return array of user flag records for each requested assignment
721 * @since Moodle 2.6
722 */
723 public static function get_user_flags($assignmentids) {
724 global $DB;
725 $params = self::validate_parameters(self::get_user_flags_parameters(),
726 array('assignmentids' => $assignmentids));
727
728 $assignments = array();
729 $warnings = array();
730 $requestedassignmentids = $params['assignmentids'];
731
732 // Check the user is allowed to get the user flags for the assignments requested.
733 $placeholders = array();
734 list($sqlassignmentids, $placeholders) = $DB->get_in_or_equal($requestedassignmentids, SQL_PARAMS_NAMED);
735 $sql = "SELECT cm.id, cm.instance FROM {course_modules} cm JOIN {modules} md ON md.id = cm.module ".
736 "WHERE md.name = :modname AND cm.instance ".$sqlassignmentids;
737 $placeholders['modname'] = 'assign';
738 $cms = $DB->get_records_sql($sql, $placeholders);
739 foreach ($cms as $cm) {
740 try {
741 $context = context_module::instance($cm->id);
742 self::validate_context($context);
743 require_capability('mod/assign:grade', $context);
744 } catch (Exception $e) {
745 $requestedassignmentids = array_diff($requestedassignmentids, array($cm->instance));
746 $warning = array();
747 $warning['item'] = 'assignment';
748 $warning['itemid'] = $cm->instance;
749 $warning['warningcode'] = '1';
750 $warning['message'] = 'No access rights in module context';
751 $warnings[] = $warning;
752 }
753 }
754
755 // Create the query and populate an array of assign_user_flags records from the recordset results.
756 if (count ($requestedassignmentids) > 0) {
757 $placeholders = array();
758 list($inorequalsql, $placeholders) = $DB->get_in_or_equal($requestedassignmentids, SQL_PARAMS_NAMED);
759
760 $sql = "SELECT auf.id,auf.assignment,auf.userid,auf.locked,auf.mailed,".
761 "auf.extensionduedate,auf.workflowstate,auf.allocatedmarker ".
762 "FROM {assign_user_flags} auf ".
763 "WHERE auf.assignment ".$inorequalsql.
764 " ORDER BY auf.assignment, auf.id";
765
766 $rs = $DB->get_recordset_sql($sql, $placeholders);
767 $currentassignmentid = null;
768 $assignment = null;
769 foreach ($rs as $rd) {
770 $userflag = array();
771 $userflag['id'] = $rd->id;
772 $userflag['userid'] = $rd->userid;
773 $userflag['locked'] = $rd->locked;
774 $userflag['mailed'] = $rd->mailed;
775 $userflag['extensionduedate'] = $rd->extensionduedate;
776 $userflag['workflowstate'] = $rd->workflowstate;
777 $userflag['allocatedmarker'] = $rd->allocatedmarker;
778
779 if (is_null($currentassignmentid) || ($rd->assignment != $currentassignmentid )) {
780 if (!is_null($assignment)) {
781 $assignments[] = $assignment;
782 }
783 $assignment = array();
784 $assignment['assignmentid'] = $rd->assignment;
785 $assignment['userflags'] = array();
786 $requestedassignmentids = array_diff($requestedassignmentids, array($rd->assignment));
787 }
788 $assignment['userflags'][] = $userflag;
789
790 $currentassignmentid = $rd->assignment;
791 }
792 if (!is_null($assignment)) {
793 $assignments[] = $assignment;
794 }
795 $rs->close();
796
797 }
798
799 foreach ($requestedassignmentids as $assignmentid) {
800 $warning = array();
801 $warning['item'] = 'assignment';
802 $warning['itemid'] = $assignmentid;
803 $warning['warningcode'] = '3';
804 $warning['message'] = 'No user flags found';
805 $warnings[] = $warning;
806 }
807
808 $result = array();
809 $result['assignments'] = $assignments;
810 $result['warnings'] = $warnings;
811 return $result;
812 }
813
814 /**
815 * Creates an assign_user_flags external_single_structure
816 * @return external_single_structure
817 * @since Moodle 2.6
818 */
819 private static function assign_user_flags() {
820 return new external_single_structure(
821 array (
822 'assignmentid' => new external_value(PARAM_INT, 'assignment id'),
823 'userflags' => new external_multiple_structure(new external_single_structure(
824 array(
825 'id' => new external_value(PARAM_INT, 'user flag id'),
826 'userid' => new external_value(PARAM_INT, 'student id'),
827 'locked' => new external_value(PARAM_INT, 'locked'),
828 'mailed' => new external_value(PARAM_INT, 'mailed'),
829 'extensionduedate' => new external_value(PARAM_INT, 'extension due date'),
830 'workflowstate' => new external_value(PARAM_TEXT, 'marking workflow state', VALUE_OPTIONAL),
831 'allocatedmarker' => new external_value(PARAM_INT, 'allocated marker')
832 )
833 )
834 )
835 )
836 );
837 }
838
839 /**
840 * Describes the get_user_flags return value
841 * @return external_single_structure
842 * @since Moodle 2.6
843 */
844 public static function get_user_flags_returns() {
845 return new external_single_structure(
846 array(
847 'assignments' => new external_multiple_structure(self::assign_user_flags(), 'list of assign user flag information'),
848 'warnings' => new external_warnings('item is always \'assignment\'',
849 'when errorcode is 3 then itemid is an assignment id. When errorcode is 1, itemid is a course module id',
850 'errorcode can be 3 (no user flags found) or 1 (no permission to get user flags)')
851 )
852 );
853 }
854
855 /**
856 * Describes the parameters for get_user_mappings
857 * @return external_function_parameters
858 * @since Moodle 2.6
859 */
860 public static function get_user_mappings_parameters() {
861 return new external_function_parameters(
862 array(
863 'assignmentids' => new external_multiple_structure(
864 new external_value(PARAM_INT, 'assignment id'),
865 '1 or more assignment ids',
866 VALUE_REQUIRED)
867 )
868 );
869 }
870
871 /**
872 * Returns user mapping information from assign_user_mapping for the requested assignment ids
873 * @param array of ints $assignmentids
874 * @return array of user mapping records for each requested assignment
875 * @since Moodle 2.6
876 */
877 public static function get_user_mappings($assignmentids) {
878 global $DB;
879 $params = self::validate_parameters(self::get_user_mappings_parameters(),
880 array('assignmentids' => $assignmentids));
881
882 $assignments = array();
883 $warnings = array();
884 $requestedassignmentids = $params['assignmentids'];
885
886 // Check the user is allowed to get the mappings for the assignments requested.
887 $placeholders = array();
888 list($sqlassignmentids, $placeholders) = $DB->get_in_or_equal($requestedassignmentids, SQL_PARAMS_NAMED);
889 $sql = "SELECT cm.id, cm.instance FROM {course_modules} cm JOIN {modules} md ON md.id = cm.module ".
890 "WHERE md.name = :modname AND cm.instance ".$sqlassignmentids;
891 $placeholders['modname'] = 'assign';
892 $cms = $DB->get_records_sql($sql, $placeholders);
893 foreach ($cms as $cm) {
894 try {
895 $context = context_module::instance($cm->id);
896 self::validate_context($context);
897 require_capability('mod/assign:revealidentities', $context);
898 } catch (Exception $e) {
899 $requestedassignmentids = array_diff($requestedassignmentids, array($cm->instance));
900 $warning = array();
901 $warning['item'] = 'assignment';
902 $warning['itemid'] = $cm->instance;
903 $warning['warningcode'] = '1';
904 $warning['message'] = 'No access rights in module context';
905 $warnings[] = $warning;
906 }
907 }
908
909 // Create the query and populate an array of assign_user_mapping records from the recordset results.
910 if (count ($requestedassignmentids) > 0) {
911 $placeholders = array();
912 list($inorequalsql, $placeholders) = $DB->get_in_or_equal($requestedassignmentids, SQL_PARAMS_NAMED);
913
914 $sql = "SELECT aum.id,aum.assignment,aum.userid ".
915 "FROM {assign_user_mapping} aum ".
916 "WHERE aum.assignment ".$inorequalsql.
917 " ORDER BY aum.assignment, aum.id";
918
919 $rs = $DB->get_recordset_sql($sql, $placeholders);
920 $currentassignmentid = null;
921 $assignment = null;
922 foreach ($rs as $rd) {
923 $mapping = array();
924 $mapping['id'] = $rd->id;
925 $mapping['userid'] = $rd->userid;
926
927 if (is_null($currentassignmentid) || ($rd->assignment != $currentassignmentid )) {
928 if (!is_null($assignment)) {
929 $assignments[] = $assignment;
930 }
931 $assignment = array();
932 $assignment['assignmentid'] = $rd->assignment;
933 $assignment['mappings'] = array();
934 $requestedassignmentids = array_diff($requestedassignmentids, array($rd->assignment));
935 }
936 $assignment['mappings'][] = $mapping;
937
938 $currentassignmentid = $rd->assignment;
939 }
940 if (!is_null($assignment)) {
941 $assignments[] = $assignment;
942 }
943 $rs->close();
944
945 }
946
947 foreach ($requestedassignmentids as $assignmentid) {
948 $warning = array();
949 $warning['item'] = 'assignment';
950 $warning['itemid'] = $assignmentid;
951 $warning['warningcode'] = '3';
952 $warning['message'] = 'No mappings found';
953 $warnings[] = $warning;
954 }
955
956 $result = array();
957 $result['assignments'] = $assignments;
958 $result['warnings'] = $warnings;
959 return $result;
960 }
961
962 /**
963 * Creates an assign_user_mappings external_single_structure
964 * @return external_single_structure
965 * @since Moodle 2.6
966 */
967 private static function assign_user_mappings() {
968 return new external_single_structure(
969 array (
970 'assignmentid' => new external_value(PARAM_INT, 'assignment id'),
971 'mappings' => new external_multiple_structure(new external_single_structure(
972 array(
973 'id' => new external_value(PARAM_INT, 'user mapping id'),
974 'userid' => new external_value(PARAM_INT, 'student id')
975 )
976 )
977 )
978 )
979 );
980 }
981
982 /**
983 * Describes the get_user_mappings return value
984 * @return external_single_structure
985 * @since Moodle 2.6
986 */
987 public static function get_user_mappings_returns() {
988 return new external_single_structure(
989 array(
990 'assignments' => new external_multiple_structure(self::assign_user_mappings(), 'list of assign user mapping data'),
991 'warnings' => new external_warnings('item is always \'assignment\'',
992 'when errorcode is 3 then itemid is an assignment id. When errorcode is 1, itemid is a course module id',
993 'errorcode can be 3 (no user mappings found) or 1 (no permission to get user mappings)')
994 )
995 );
996 }
997
1f8c8f61 998}