a5ad1c4a1f5685055ccc7d92e79ee395f89c4082
[moodle.git] / mod / assign / externallib.php
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/>.
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  */
26 defined('MOODLE_INTERNAL') || die;
28 require_once("$CFG->libdir/externallib.php");
30 /**
31  * Assign functions
32  */
33 class mod_assign_external extends external_api {
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     }
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));
67         $assignments = array();
68         $warnings = array();
69         $requestedassignmentids = $params['assignmentids'];
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         }
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;
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;
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         }
146         $result = array();
147         $result['assignments'] = $assignments;
148         $result['warnings'] = $warnings;
149         return $result;
150     }
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     }
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('item is always \'assignment\'',
188                     'when errorcode is 3 then itemid is an assignment id. When errorcode is 1, itemid is a course module instance id',
189                     'errorcode can be 3 (no grades found) or 1 (no permission to get grades)')
190             )
191         );
192     }
194     /**
195      * Returns description of method parameters
196      *
197      * @return external_function_parameters
198      * @since  Moodle 2.4
199      */
200     public static function get_assignments_parameters() {
201         return new external_function_parameters(
202             array(
203                 'courseids' => new external_multiple_structure(
204                     new external_value(PARAM_INT, 'course id'),
205                     '0 or more course ids',
206                     VALUE_DEFAULT, array()
207                 ),
208                 'capabilities'  => new external_multiple_structure(
209                     new external_value(PARAM_CAPABILITY, 'capability'),
210                     'list of capabilities used to filter courses',
211                     VALUE_DEFAULT, array()
212                 )
213             )
214         );
215     }
217     /**
218      * Returns an array of courses the user is enrolled in, and for each course all of the assignments that the user can
219      * view within that course.
220      *
221      * @param array $courseids An optional array of course ids. If provided only assignments within the given course
222      * will be returned. If the user is not enrolled in a given course a warning will be generated and returned.
223      * @param array $capabilities An array of additional capability checks you wish to be made on the course context.
224      * @return An array of courses and warnings.
225      * @since  Moodle 2.4
226      */
227     public static function get_assignments($courseids = array(), $capabilities = array()) {
228         global $USER, $DB;
230         $params = self::validate_parameters(
231             self::get_assignments_parameters(),
232             array('courseids' => $courseids, 'capabilities' => $capabilities)
233         );
235         $warnings = array();
236         $fields = 'sortorder,shortname,fullname,timemodified';
237         $courses = enrol_get_users_courses($USER->id, true, $fields);
238         // Used to test for ids that have been requested but can't be returned.
239         if (count($params['courseids']) > 0) {
240             foreach ($params['courseids'] as $courseid) {
241                 if (!in_array($courseid, array_keys($courses))) {
242                     unset($courses[$courseid]);
243                     $warnings[] = array(
244                         'item' => 'course',
245                         'itemid' => $courseid,
246                         'warningcode' => '2',
247                         'message' => 'User is not enrolled or does not have requested capability'
248                     );
249                 }
250             }
251         }
252         foreach ($courses as $id => $course) {
253             if (count($params['courseids']) > 0 && !in_array($id, $params['courseids'])) {
254                 unset($courses[$id]);
255             }
256             $context = context_course::instance($id);
257             try {
258                 self::validate_context($context);
259             } catch (Exception $e) {
260                 unset($courses[$id]);
261                 $warnings[] = array(
262                     'item' => 'course',
263                     'itemid' => $id,
264                     'warningcode' => '1',
265                     'message' => 'No access rights in course context '.$e->getMessage().$e->getTraceAsString()
266                 );
267                 continue;
268             }
269             if (count($params['capabilities']) > 0 && !has_all_capabilities($params['capabilities'], $context)) {
270                 unset($courses[$id]);
271             }
272         }
273         $extrafields='m.id as assignmentid, m.course, m.nosubmissions, m.submissiondrafts, m.sendnotifications, '.
274                      'm.sendlatenotifications, m.duedate, m.allowsubmissionsfromdate, m.grade, m.timemodified, '.
275                      'm.completionsubmit, m.cutoffdate, m.teamsubmission, m.requireallteammemberssubmit, '.
276                      'm.teamsubmissiongroupingid, m.blindmarking, m.revealidentities, m.requiresubmissionstatement';
277         $coursearray = array();
278         foreach ($courses as $id => $course) {
279             $assignmentarray = array();
280             // Get a list of assignments for the course.
281             if ($modules = get_coursemodules_in_course('assign', $courses[$id]->id, $extrafields)) {
282                 foreach ($modules as $module) {
283                     $context = context_module::instance($module->id);
284                     try {
285                         self::validate_context($context);
286                         require_capability('mod/assign:view', $context);
287                     } catch (Exception $e) {
288                         $warnings[] = array(
289                             'item' => 'module',
290                             'itemid' => $module->id,
291                             'warningcode' => '1',
292                             'message' => 'No access rights in module context'
293                         );
294                         continue;
295                     }
296                     $configrecords = $DB->get_recordset('assign_plugin_config', array('assignment' => $module->assignmentid));
297                     $configarray = array();
298                     foreach ($configrecords as $configrecord) {
299                         $configarray[] = array(
300                             'id' => $configrecord->id,
301                             'assignment' => $configrecord->assignment,
302                             'plugin' => $configrecord->plugin,
303                             'subtype' => $configrecord->subtype,
304                             'name' => $configrecord->name,
305                             'value' => $configrecord->value
306                         );
307                     }
308                     $configrecords->close();
310                     $assignmentarray[]= array(
311                         'id' => $module->assignmentid,
312                         'cmid' => $module->id,
313                         'course' => $module->course,
314                         'name' => $module->name,
315                         'nosubmissions' => $module->nosubmissions,
316                         'submissiondrafts' => $module->submissiondrafts,
317                         'sendnotifications' => $module->sendnotifications,
318                         'sendlatenotifications' => $module->sendlatenotifications,
319                         'duedate' => $module->duedate,
320                         'allowsubmissionsfromdate' => $module->allowsubmissionsfromdate,
321                         'grade' => $module->grade,
322                         'timemodified' => $module->timemodified,
323                         'completionsubmit' => $module->completionsubmit,
324                         'cutoffdate' => $module->cutoffdate,
325                         'teamsubmission' => $module->teamsubmission,
326                         'requireallteammemberssubmit' => $module->requireallteammemberssubmit,
327                         'teamsubmissiongroupingid' => $module->teamsubmissiongroupingid,
328                         'blindmarking' => $module->blindmarking,
329                         'revealidentities' => $module->revealidentities,
330                         'requiresubmissionstatement' => $module->requiresubmissionstatement,
331                         'configs' => $configarray
332                     );
333                 }
334             }
335             $coursearray[]= array(
336                 'id' => $courses[$id]->id,
337                 'fullname' => $courses[$id]->fullname,
338                 'shortname' => $courses[$id]->shortname,
339                 'timemodified' => $courses[$id]->timemodified,
340                 'assignments' => $assignmentarray
341             );
342         }
344         $result = array(
345             'courses' => $coursearray,
346             'warnings' => $warnings
347         );
348         return $result;
349     }
351     /**
352      * Creates an assignment external_single_structure
353      *
354      * @return external_single_structure
355      * @since Moodle 2.4
356      */
357     private static function get_assignments_assignment_structure() {
358         return new external_single_structure(
359             array(
360                 'id' => new external_value(PARAM_INT, 'assignment id'),
361                 'course' => new external_value(PARAM_INT, 'course id'),
362                 'name' => new external_value(PARAM_TEXT, 'assignment name'),
363                 'nosubmissions' => new external_value(PARAM_INT, 'no submissions'),
364                 'submissiondrafts' => new external_value(PARAM_INT, 'submissions drafts'),
365                 'sendnotifications' => new external_value(PARAM_INT, 'send notifications'),
366                 'sendlatenotifications' => new external_value(PARAM_INT, 'send notifications'),
367                 'duedate' => new external_value(PARAM_INT, 'assignment due date'),
368                 'allowsubmissionsfromdate' => new external_value(PARAM_INT, 'allow submissions from date'),
369                 'grade' => new external_value(PARAM_INT, 'grade type'),
370                 'timemodified' => new external_value(PARAM_INT, 'last time assignment was modified'),
371                 'completionsubmit' => new external_value(PARAM_INT, 'if enabled, set activity as complete following submission'),
372                 'cutoffdate' => new external_value(PARAM_INT, 'date after which submission is not accepted without an extension'),
373                 'teamsubmission' => new external_value(PARAM_INT, 'if enabled, students submit as a team'),
374                 'requireallteammemberssubmit' => new external_value(PARAM_INT, 'if enabled, all team members must submit'),
375                 'teamsubmissiongroupingid' => new external_value(PARAM_INT, 'the grouping id for the team submission groups'),
376                 'blindmarking' => new external_value(PARAM_INT, 'if enabled, hide identities until reveal identities actioned'),
377                 'revealidentities' => new external_value(PARAM_INT, 'show identities for a blind marking assignment'),
378                 'requiresubmissionstatement' => new external_value(PARAM_INT, 'student must accept submission statement'),
379                 'configs' => new external_multiple_structure(self::get_assignments_config_structure(), 'configuration settings')
380             ), 'assignment information object');
381     }
383     /**
384      * Creates an assign_plugin_config external_single_structure
385      *
386      * @return external_single_structure
387      * @since Moodle 2.4
388      */
389     private static function get_assignments_config_structure() {
390         return new external_single_structure(
391             array(
392                 'id' => new external_value(PARAM_INT, 'assign_plugin_config id'),
393                 'assignment' => new external_value(PARAM_INT, 'assignment id'),
394                 'plugin' => new external_value(PARAM_TEXT, 'plugin'),
395                 'subtype' => new external_value(PARAM_TEXT, 'subtype'),
396                 'name' => new external_value(PARAM_TEXT, 'name'),
397                 'value' => new external_value(PARAM_TEXT, 'value')
398             ), 'assignment configuration object'
399         );
400     }
402     /**
403      * Creates a course external_single_structure
404      *
405      * @return external_single_structure
406      * @since Moodle 2.4
407      */
408     private static function get_assignments_course_structure() {
409         return new external_single_structure(
410             array(
411                 'id' => new external_value(PARAM_INT, 'course id'),
412                 'fullname' => new external_value(PARAM_TEXT, 'course full name'),
413                 'shortname' => new external_value(PARAM_TEXT, 'course short name'),
414                 'timemodified' => new external_value(PARAM_INT, 'last time modified'),
415                 'assignments' => new external_multiple_structure(self::get_assignments_assignment_structure(), 'assignment info')
416               ), 'course information object'
417         );
418     }
420     /**
421      * Describes the return value for get_assignments
422      *
423      * @return external_single_structure
424      * @since Moodle 2.4
425      */
426     public static function get_assignments_returns() {
427         return new external_single_structure(
428             array(
429                 'courses' => new external_multiple_structure(self::get_assignments_course_structure(), 'list of courses'),
430                 'warnings'  => new external_warnings('item can be \'course\' (errorcode 1 or 2) or \'module\' (errorcode 1)',
431                     'When item is a course then itemid is a course id. When the item is a module then itemid is a module id',
432                     'errorcode can be 1 (no access rights) or 2 (not enrolled or no permissions)')
433             )
434         );
435     }
437     /**
438      * Describes the parameters for get_submissions
439      *
440      * @return external_external_function_parameters
441      * @since Moodle 2.5
442      */
443     public static function get_submissions_parameters() {
444         return new external_function_parameters(
445             array(
446                 'assignmentids' => new external_multiple_structure(
447                     new external_value(PARAM_INT, 'assignment id'),
448                     '1 or more assignment ids',
449                     VALUE_REQUIRED),
450                 'status' => new external_value(PARAM_ALPHA, 'status', VALUE_DEFAULT, ''),
451                 'since' => new external_value(PARAM_INT, 'submitted since', VALUE_DEFAULT, 0),
452                 'before' => new external_value(PARAM_INT, 'submitted before', VALUE_DEFAULT, 0)
453             )
454         );
455     }
457     /**
458      * Returns submissions for the requested assignment ids
459      *
460      * @param array of ints $assignmentids
461      * @param string $status only return submissions with this status
462      * @param int $since only return submissions with timemodified >= since
463      * @param int $before only return submissions with timemodified <= before
464      * @return array of submissions for each requested assignment
465      * @since Moodle 2.5
466      */
467     public static function get_submissions($assignmentids, $status = '', $since = 0, $before = 0) {
468         global $DB, $CFG;
469         require_once("$CFG->dirroot/mod/assign/locallib.php");
470         $params = self::validate_parameters(self::get_submissions_parameters(),
471                         array('assignmentids' => $assignmentids,
472                               'status' => $status,
473                               'since' => $since,
474                               'before' => $before));
476         $warnings = array();
477         $assignments = array();
479         // Check the user is allowed to get the submissions for the assignments requested.
480         $placeholders = array();
481         list($inorequalsql, $placeholders) = $DB->get_in_or_equal($params['assignmentids'], SQL_PARAMS_NAMED);
482         $sql = "SELECT cm.id, cm.instance FROM {course_modules} cm JOIN {modules} md ON md.id = cm.module ".
483                "WHERE md.name = :modname AND cm.instance ".$inorequalsql;
484         $placeholders['modname'] = 'assign';
485         $cms = $DB->get_records_sql($sql, $placeholders);
486         $assigns = array();
487         foreach ($cms as $cm) {
488             try {
489                 $context = context_module::instance($cm->id);
490                 self::validate_context($context);
491                 require_capability('mod/assign:grade', $context);
492                 $assign = new assign($context, null, null);
493                 $assigns[] = $assign;
494             } catch (Exception $e) {
495                 $warnings[] = array(
496                     'item' => 'assignment',
497                     'itemid' => $cm->instance,
498                     'warningcode' => '1',
499                     'message' => 'No access rights in module context'
500                 );
501             }
502         }
504         foreach ($assigns as $assign) {
505             $submissions = array();
506             $submissionplugins = $assign->get_submission_plugins();
507             $placeholders = array('assignment' => $assign->get_instance()->id);
508             $sql = "SELECT mas.id, mas.assignment,mas.userid,".
509                    "mas.timecreated,mas.timemodified,mas.status,mas.groupid ".
510                    "FROM {assign_submission} mas ".
511                    "WHERE mas.assignment = :assignment";
513             if (!empty($params['status'])) {
514                 $placeholders['status'] = $params['status'];
515                 $sql = $sql." AND mas.status = :status";
516             }
517             if (!empty($params['before'])) {
518                 $placeholders['since'] = $params['since'];
519                 $placeholders['before'] = $params['before'];
520                 $sql = $sql." AND mas.timemodified BETWEEN :since AND :before";
521             } else {
522                 $placeholders['since'] = $params['since'];
523                 $sql = $sql." AND mas.timemodified >= :since";
524             }
526             $submissionrecords = $DB->get_records_sql($sql, $placeholders);
528             if (!empty($submissionrecords)) {
529                 $fs = get_file_storage();
530                 foreach ($submissionrecords as $submissionrecord) {
531                     $submission = array(
532                         'id' => $submissionrecord->id,
533                         'userid' => $submissionrecord->userid,
534                         'timecreated' => $submissionrecord->timecreated,
535                         'timemodified' => $submissionrecord->timemodified,
536                         'status' => $submissionrecord->status,
537                         'groupid' => $submissionrecord->groupid
538                     );
539                     foreach ($submissionplugins as $submissionplugin) {
540                         $plugin = array(
541                             'name' => $submissionplugin->get_name(),
542                             'type' => $submissionplugin->get_type()
543                         );
544                         // Subtype is 'assignsubmission', type is currently 'file' or 'onlinetext'.
545                         $component = $submissionplugin->get_subtype().'_'.$submissionplugin->get_type();
547                         $fileareas = $submissionplugin->get_file_areas();
548                         foreach ($fileareas as $filearea => $name) {
549                             $fileareainfo = array('area' => $filearea);
550                             $files = $fs->get_area_files(
551                                 $assign->get_context()->id,
552                                 $component,
553                                 $filearea,
554                                 $submissionrecord->id,
555                                 "timemodified",
556                                 false
557                             );
558                             foreach ($files as $file) {
559                                 $filepath = array('filepath' => $file->get_filepath().$file->get_filename());
560                                 $fileareainfo['files'][] = $filepath;
561                             }
562                             $plugin['fileareas'][] = $fileareainfo;
563                         }
565                         $editorfields = $submissionplugin->get_editor_fields();
566                         foreach ($editorfields as $name => $description) {
567                             $editorfieldinfo = array(
568                                 'name' => $name,
569                                 'description' => $description,
570                                 'text' => $submissionplugin->get_editor_text($name, $submissionrecord->id),
571                                 'format' => $submissionplugin->get_editor_format($name, $submissionrecord->id)
572                             );
573                             $plugin['editorfields'][] = $editorfieldinfo;
574                         }
576                         $submission['plugins'][] = $plugin;
577                     }
578                     $submissions[] = $submission;
579                 }
580             } else {
581                 $warnings[] = array(
582                     'item' => 'module',
583                     'itemid' => $assign->get_instance()->id,
584                     'warningcode' => '3',
585                     'message' => 'No submissions found'
586                 );
587             }
589             $assignments[] = array(
590                 'assignmentid' => $assign->get_instance()->id,
591                 'submissions' => $submissions
592             );
594         }
596         $result = array(
597             'assignments' => $assignments,
598             'warnings' => $warnings
599         );
600         return $result;
601     }
603     /**
604      * Creates an assign_submissions external_single_structure
605      *
606      * @return external_single_structure
607      * @since Moodle 2.5
608      */
609     private static function get_submissions_structure() {
610         return new external_single_structure(
611             array (
612                 'assignmentid' => new external_value(PARAM_INT, 'assignment id'),
613                 'submissions' => new external_multiple_structure(
614                     new external_single_structure(
615                         array(
616                             'id' => new external_value(PARAM_INT, 'submission id'),
617                             'userid' => new external_value(PARAM_INT, 'student id'),
618                             'timecreated' => new external_value(PARAM_INT, 'submission creation time'),
619                             'timemodified' => new external_value(PARAM_INT, 'submission last modified time'),
620                             'status' => new external_value(PARAM_TEXT, 'submission status'),
621                             'groupid' => new external_value(PARAM_INT, 'group id'),
622                             'plugins' => new external_multiple_structure(
623                                 new external_single_structure(
624                                     array(
625                                         'type' => new external_value(PARAM_TEXT, 'submission plugin type'),
626                                         'name' => new external_value(PARAM_TEXT, 'submission plugin name'),
627                                         'fileareas' => new external_multiple_structure(
628                                             new external_single_structure(
629                                                 array (
630                                                     'area' => new external_value (PARAM_TEXT, 'file area'),
631                                                     'files' => new external_multiple_structure(
632                                                         new external_single_structure(
633                                                             array (
634                                                                 'filepath' => new external_value (PARAM_TEXT, 'file path')
635                                                             )
636                                                         ), 'files', VALUE_OPTIONAL
637                                                     )
638                                                 )
639                                             ), 'fileareas', VALUE_OPTIONAL
640                                         ),
641                                         'editorfields' => new external_multiple_structure(
642                                             new external_single_structure(
643                                                 array(
644                                                     'name' => new external_value(PARAM_TEXT, 'field name'),
645                                                     'description' => new external_value(PARAM_TEXT, 'field description'),
646                                                     'text' => new external_value (PARAM_RAW, 'field value'),
647                                                     'format' => new external_format_value ('text')
648                                                 )
649                                             )
650                                             , 'editorfields', VALUE_OPTIONAL
651                                         )
652                                     )
653                                 )
654                                 , 'plugins', VALUE_OPTIONAL
655                             )
656                         )
657                     )
658                 )
659             )
660         );
661     }
663     /**
664      * Describes the get_submissions return value
665      *
666      * @return external_single_structure
667      * @since Moodle 2.5
668      */
669     public static function get_submissions_returns() {
670         return new external_single_structure(
671             array(
672                 'assignments' => new external_multiple_structure(self::get_submissions_structure(), 'assignment submissions'),
673                 'warnings' => new external_warnings()
674             )
675         );
676     }