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