MDL-59242 mod_workshop: New WS mod_workshop_get_submission
[moodle.git] / mod / workshop / classes / external.php
CommitLineData
9f1ab2db
JL
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 * Workshop external API
19 *
20 * @package mod_workshop
21 * @category external
22 * @copyright 2017 Juan Leyva <juan@moodle.com>
23 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
24 * @since Moodle 3.4
25 */
26
27defined('MOODLE_INTERNAL') || die;
28
29require_once("$CFG->libdir/externallib.php");
977fdfa3 30require_once($CFG->dirroot . '/mod/workshop/locallib.php');
9f1ab2db
JL
31
32use mod_workshop\external\workshop_summary_exporter;
3f08cfc5 33use mod_workshop\external\submission_exporter;
9f1ab2db
JL
34
35/**
36 * Workshop external functions
37 *
38 * @package mod_workshop
39 * @category external
40 * @copyright 2017 Juan Leyva <juan@moodle.com>
41 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
42 * @since Moodle 3.4
43 */
44class mod_workshop_external extends external_api {
45
46 /**
47 * Describes the parameters for get_workshops_by_courses.
48 *
49 * @return external_function_parameters
50 * @since Moodle 3.4
51 */
52 public static function get_workshops_by_courses_parameters() {
53 return new external_function_parameters (
54 array(
55 'courseids' => new external_multiple_structure(
56 new external_value(PARAM_INT, 'Course id'), 'Array of course ids', VALUE_DEFAULT, array()
57 ),
58 )
59 );
60 }
61
62 /**
63 * Returns a list of workshops in a provided list of courses.
64 * If no list is provided all workshops that the user can view will be returned.
65 *
66 * @param array $courseids course ids
67 * @return array of warnings and workshops
68 * @since Moodle 3.4
69 */
70 public static function get_workshops_by_courses($courseids = array()) {
71 global $PAGE;
72
73 $warnings = array();
74 $returnedworkshops = array();
75
76 $params = array(
77 'courseids' => $courseids,
78 );
79 $params = self::validate_parameters(self::get_workshops_by_courses_parameters(), $params);
80
81 $mycourses = array();
82 if (empty($params['courseids'])) {
83 $mycourses = enrol_get_my_courses();
84 $params['courseids'] = array_keys($mycourses);
85 }
86
87 // Ensure there are courseids to loop through.
88 if (!empty($params['courseids'])) {
89
90 list($courses, $warnings) = external_util::validate_courses($params['courseids'], $mycourses);
91 $output = $PAGE->get_renderer('core');
92
93 // Get the workshops in this course, this function checks users visibility permissions.
94 // We can avoid then additional validate_context calls.
95 $workshops = get_all_instances_in_courses("workshop", $courses);
96 foreach ($workshops as $workshop) {
97
98 $context = context_module::instance($workshop->coursemodule);
99 // Remove fields that are not from the workshop (added by get_all_instances_in_courses).
100 unset($workshop->coursemodule, $workshop->context, $workshop->visible, $workshop->section, $workshop->groupmode,
101 $workshop->groupingid);
102
103 $exporter = new workshop_summary_exporter($workshop, array('context' => $context));
104 $returnedworkshops[] = $exporter->export($output);
105 }
106 }
107
108 $result = array(
109 'workshops' => $returnedworkshops,
110 'warnings' => $warnings
111 );
112 return $result;
113 }
114
115 /**
116 * Describes the get_workshops_by_courses return value.
117 *
118 * @return external_single_structure
119 * @since Moodle 3.4
120 */
121 public static function get_workshops_by_courses_returns() {
122 return new external_single_structure(
123 array(
124 'workshops' => new external_multiple_structure(
125 workshop_summary_exporter::get_read_structure()
126 ),
127 'warnings' => new external_warnings(),
128 )
129 );
130 }
977fdfa3
JL
131
132 /**
133 * Utility function for validating a workshop.
134 *
135 * @param int $workshopid workshop instance id
136 * @return array array containing the workshop object, course, context and course module objects
137 * @since Moodle 3.4
138 */
139 protected static function validate_workshop($workshopid) {
140 global $DB, $USER;
141
142 // Request and permission validation.
143 $workshop = $DB->get_record('workshop', array('id' => $workshopid), '*', MUST_EXIST);
144 list($course, $cm) = get_course_and_cm_from_instance($workshop, 'workshop');
145
146 $context = context_module::instance($cm->id);
147 self::validate_context($context);
148
149 $workshop = new workshop($workshop, $cm, $course);
150
151 return array($workshop, $course, $cm, $context);
152 }
153
154
155 /**
156 * Describes the parameters for get_workshop_access_information.
157 *
158 * @return external_external_function_parameters
159 * @since Moodle 3.4
160 */
161 public static function get_workshop_access_information_parameters() {
162 return new external_function_parameters (
163 array(
164 'workshopid' => new external_value(PARAM_INT, 'Workshop instance id.')
165 )
166 );
167 }
168
169 /**
170 * Return access information for a given workshop.
171 *
172 * @param int $workshopid workshop instance id
173 * @return array of warnings and the access information
174 * @since Moodle 3.4
175 * @throws moodle_exception
176 */
177 public static function get_workshop_access_information($workshopid) {
178 global $USER;
179
180 $params = self::validate_parameters(self::get_workshop_access_information_parameters(), array('workshopid' => $workshopid));
181
182 list($workshop, $course, $cm, $context) = self::validate_workshop($params['workshopid']);
183
184 $result = array();
185 // Return all the available capabilities.
186 $capabilities = load_capability_def('mod_workshop');
187 foreach ($capabilities as $capname => $capdata) {
188 // Get fields like cansubmit so it is consistent with the access_information function implemented in other modules.
189 $field = 'can' . str_replace('mod/workshop:', '', $capname);
190 $result[$field] = has_capability($capname, $context);
191 }
192
193 // Now, specific features access information.
194 $result['creatingsubmissionallowed'] = $workshop->creating_submission_allowed($USER->id);
195 $result['modifyingsubmissionallowed'] = $workshop->modifying_submission_allowed($USER->id);
196 $result['assessingallowed'] = $workshop->assessing_allowed($USER->id);
197 $result['assessingexamplesallowed'] = $workshop->assessing_examples_allowed();
198 if (is_null($result['assessingexamplesallowed'])) {
199 $result['assessingexamplesallowed'] = false;
200 }
c2cf2450 201 $result['examplesassessed'] = $workshop->check_examples_assessed($USER->id);
977fdfa3
JL
202
203 $result['warnings'] = array();
204 return $result;
205 }
206
207 /**
208 * Describes the get_workshop_access_information return value.
209 *
210 * @return external_single_structure
211 * @since Moodle 3.4
212 */
213 public static function get_workshop_access_information_returns() {
214
215 $structure = array(
216 'creatingsubmissionallowed' => new external_value(PARAM_BOOL,
217 'Is the given user allowed to create their submission?'),
218 'modifyingsubmissionallowed' => new external_value(PARAM_BOOL,
219 'Is the user allowed to modify his existing submission?'),
220 'assessingallowed' => new external_value(PARAM_BOOL,
221 'Is the user allowed to create/edit his assessments?'),
222 'assessingexamplesallowed' => new external_value(PARAM_BOOL,
223 'Are reviewers allowed to create/edit their assessments of the example submissions?.'),
c2cf2450
JL
224 'examplesassessed' => new external_value(PARAM_BOOL,
225 'Whether the given user has assessed all his required examples (always true if there are no examples to assess).'),
977fdfa3
JL
226 'warnings' => new external_warnings()
227 );
228
229 $capabilities = load_capability_def('mod_workshop');
230 foreach ($capabilities as $capname => $capdata) {
231 // Get fields like cansubmit so it is consistent with the access_information function implemented in other modules.
232 $field = 'can' . str_replace('mod/workshop:', '', $capname);
233 $structure[$field] = new external_value(PARAM_BOOL, 'Whether the user has the capability ' . $capname . ' allowed.');
234 }
235
236 return new external_single_structure($structure);
237 }
cd495029
JL
238
239 /**
240 * Describes the parameters for get_user_plan.
241 *
242 * @return external_external_function_parameters
243 * @since Moodle 3.4
244 */
245 public static function get_user_plan_parameters() {
246 return new external_function_parameters (
247 array(
248 'workshopid' => new external_value(PARAM_INT, 'Workshop instance id.'),
249 'userid' => new external_value(PARAM_INT, 'User id (empty or 0 for current user).', VALUE_DEFAULT, 0),
250 )
251 );
252 }
253
254 /**
255 * Return the planner information for the given user.
256 *
257 * @param int $workshopid workshop instance id
258 * @param int $userid user id
259 * @return array of warnings and the user plan
260 * @since Moodle 3.4
261 * @throws moodle_exception
262 */
263 public static function get_user_plan($workshopid, $userid = 0) {
264 global $USER;
265
266 $params = array(
267 'workshopid' => $workshopid,
268 'userid' => $userid,
269 );
270 $params = self::validate_parameters(self::get_user_plan_parameters(), $params);
271
272 list($workshop, $course, $cm, $context) = self::validate_workshop($params['workshopid']);
273
274 // Extra checks so only users with permissions can view other users plans.
275 if (empty($params['userid']) || $params['userid'] == $USER->id) {
276 $userid = $USER->id;
277 } else {
278 require_capability('moodle/course:manageactivities', $context);
279 $user = core_user::get_user($params['userid'], '*', MUST_EXIST);
280 core_user::require_active_user($user);
281 if (!$workshop->check_group_membership($user->id)) {
282 throw new moodle_exception('notingroup');
283 }
284 $userid = $user->id;
285 }
286
287 // Get the user plan information ready for external functions.
288 $userplan = new workshop_user_plan($workshop, $userid);
289 $userplan = array('phases' => $userplan->phases, 'examples' => $userplan->get_examples());
290 foreach ($userplan['phases'] as $phasecode => $phase) {
291 $phase->code = $phasecode;
292 $userplan['phases'][$phasecode] = (array) $phase;
293 foreach ($userplan['phases'][$phasecode]['tasks'] as $taskcode => $task) {
294 $task->code = $taskcode;
295 if ($task->link instanceof moodle_url) {
296 $task->link = $task->link->out(false);
297 }
298 $userplan['phases'][$phasecode]['tasks'][$taskcode] = (array) $task;
299 }
300 foreach ($userplan['phases'][$phasecode]['actions'] as $actioncode => $action) {
301 if ($action->url instanceof moodle_url) {
302 $action->url = $action->url->out(false);
303 }
304 $userplan['phases'][$phasecode]['actions'][$actioncode] = (array) $action;
305 }
306 }
307
308 $result['userplan'] = $userplan;
309 $result['warnings'] = array();
310 return $result;
311 }
312
313 /**
314 * Describes the get_user_plan return value.
315 *
316 * @return external_single_structure
317 * @since Moodle 3.4
318 */
319 public static function get_user_plan_returns() {
320 return new external_single_structure(
321 array(
322 'userplan' => new external_single_structure(
323 array(
324 'phases' => new external_multiple_structure(
325 new external_single_structure(
326 array(
327 'code' => new external_value(PARAM_INT, 'Phase code.'),
328 'title' => new external_value(PARAM_NOTAGS, 'Phase title.'),
329 'active' => new external_value(PARAM_BOOL, 'Whether is the active task.'),
330 'tasks' => new external_multiple_structure(
331 new external_single_structure(
332 array(
333 'code' => new external_value(PARAM_ALPHA, 'Task code.'),
334 'title' => new external_value(PARAM_RAW, 'Task title.'),
335 'link' => new external_value(PARAM_URL, 'Link to task.'),
336 'details' => new external_value(PARAM_RAW, 'Task details.', VALUE_OPTIONAL),
337 'completed' => new external_value(PARAM_NOTAGS,
338 'Completion information (maybe empty, maybe a boolean or generic info.'),
339 )
340 )
341 ),
342 'actions' => new external_multiple_structure(
343 new external_single_structure(
344 array(
345 'type' => new external_value(PARAM_ALPHA, 'Action type.', VALUE_OPTIONAL),
346 'label' => new external_value(PARAM_RAW, 'Action label.', VALUE_OPTIONAL),
347 'url' => new external_value(PARAM_URL, 'Link to action.'),
348 'method' => new external_value(PARAM_ALPHA, 'Get or post.', VALUE_OPTIONAL),
349 )
350 )
351 ),
352 )
353 )
354 ),
355 'examples' => new external_multiple_structure(
356 new external_single_structure(
357 array(
358 'id' => new external_value(PARAM_INT, 'Example submission id.'),
359 'title' => new external_value(PARAM_RAW, 'Example submission title.'),
360 'assessmentid' => new external_value(PARAM_INT, 'Example submission assessment id.'),
361 'grade' => new external_value(PARAM_FLOAT, 'The submission grade.'),
362 'gradinggrade' => new external_value(PARAM_FLOAT, 'The assessment grade.'),
363 )
364 )
365 ),
366 )
367 ),
368 'warnings' => new external_warnings(),
369 )
370 );
371 }
291645f7
JL
372
373 /**
374 * Describes the parameters for view_workshop.
375 *
376 * @return external_function_parameters
377 * @since Moodle 3.4
378 */
379 public static function view_workshop_parameters() {
380 return new external_function_parameters (
381 array(
382 'workshopid' => new external_value(PARAM_INT, 'Workshop instance id'),
383 )
384 );
385 }
386
387 /**
388 * Trigger the course module viewed event and update the module completion status.
389 *
390 * @param int $workshopid workshop instance id
391 * @return array of warnings and status result
392 * @since Moodle 3.4
393 * @throws moodle_exception
394 */
395 public static function view_workshop($workshopid) {
396
397 $params = array('workshopid' => $workshopid);
398 $params = self::validate_parameters(self::view_workshop_parameters(), $params);
399 $warnings = array();
400
401 list($workshop, $course, $cm, $context) = self::validate_workshop($params['workshopid']);
402
403 $workshop->set_module_viewed();
404
405 $result = array(
406 'status' => true,
407 'warnings' => $warnings,
408 );
409 return $result;
410 }
411
412 /**
413 * Describes the view_workshop return value.
414 *
415 * @return external_single_structure
416 * @since Moodle 3.4
417 */
418 public static function view_workshop_returns() {
419 return new external_single_structure(
420 array(
421 'status' => new external_value(PARAM_BOOL, 'status: true if success'),
422 'warnings' => new external_warnings(),
423 )
424 );
425 }
c2cf2450
JL
426
427 /**
428 * Returns the description of the external function parameters.
429 *
430 * @return external_function_parameters
431 * @since Moodle 3.4
432 */
433 public static function add_submission_parameters() {
434 return new external_function_parameters(array(
435 'workshopid' => new external_value(PARAM_INT, 'Workshop id'),
436 'title' => new external_value(PARAM_TEXT, 'Submission title'),
437 'content' => new external_value(PARAM_RAW, 'Submission text content', VALUE_DEFAULT, ''),
438 'contentformat' => new external_value(PARAM_INT, 'The format used for the content', VALUE_DEFAULT, FORMAT_MOODLE),
439 'inlineattachmentsid' => new external_value(PARAM_INT, 'The draft file area id for inline attachments in the content',
440 VALUE_DEFAULT, 0),
441 'attachmentsid' => new external_value(PARAM_INT, 'The draft file area id for attachments', VALUE_DEFAULT, 0),
442 ));
443 }
444
445 /**
446 * Add a new submission to a given workshop.
447 *
448 * @param int $workshopid the workshop id
449 * @param string $title the submission title
450 * @param string $content the submission text content
451 * @param int $contentformat the format used for the content
452 * @param int $inlineattachmentsid the draft file area id for inline attachments in the content
453 * @param int $attachmentsid the draft file area id for attachments
454 * @return array Containing the new created submission id and warnings.
455 * @since Moodle 3.4
456 * @throws moodle_exception
457 */
458 public static function add_submission($workshopid, $title, $content = '', $contentformat = FORMAT_MOODLE,
459 $inlineattachmentsid = 0, $attachmentsid = 0) {
460 global $USER;
461
462 $params = self::validate_parameters(self::add_submission_parameters(), array(
463 'workshopid' => $workshopid,
464 'title' => $title,
465 'content' => $content,
466 'contentformat' => $contentformat,
467 'inlineattachmentsid' => $inlineattachmentsid,
468 'attachmentsid' => $attachmentsid,
469 ));
470 $warnings = array();
471
472 // Get and validate the workshop.
473 list($workshop, $course, $cm, $context) = self::validate_workshop($params['workshopid']);
474 require_capability('mod/workshop:submit', $context);
475
476 // Check if we can submit now.
477 $canaddsubmission = $workshop->creating_submission_allowed($USER->id);
478 $canaddsubmission = $canaddsubmission && $workshop->check_examples_assessed($USER->id);
479 if (!$canaddsubmission) {
480 throw new moodle_exception('nopermissions', 'error', '', 'add submission');
481 }
482
483 // Prepare the submission object.
484 $submission = new stdClass;
485 $submission->id = null;
486 $submission->cmid = $cm->id;
487 $submission->example = 0;
488 $submission->title = trim($params['title']);
489 $submission->content_editor = array(
490 'text' => $params['content'],
491 'format' => $params['contentformat'],
492 'itemid' => $params['inlineattachmentsid'],
493 );
494 $submission->attachment_filemanager = $params['attachmentsid'];
495
496 if (empty($submission->title)) {
497 throw new moodle_exception('errorinvalidparam', 'webservice', '', 'title');
498 }
499
500 $errors = $workshop->validate_submission_data((array) $submission);
501 // We can get several errors, return them in warnings.
502 if (!empty($errors)) {
503 $submission->id = 0;
504 foreach ($errors as $itemname => $message) {
505 $warnings[] = array(
506 'item' => $itemname,
507 'itemid' => 0,
508 'warningcode' => 'fielderror',
509 'message' => s($message)
510 );
511 }
4834e127
JL
512 return array(
513 'status' => false,
514 'warnings' => $warnings
515 );
c2cf2450
JL
516 } else {
517 $submission->id = $workshop->edit_submission($submission);
4834e127
JL
518 return array(
519 'status' => true,
520 'submissionid' => $submission->id,
521 'warnings' => $warnings
522 );
c2cf2450 523 }
c2cf2450
JL
524 }
525
526 /**
527 * Returns the description of the external function return value.
528 *
529 * @return external_description
530 * @since Moodle 3.4
531 */
532 public static function add_submission_returns() {
533 return new external_single_structure(array(
4834e127
JL
534 'status' => new external_value(PARAM_BOOL, 'True if the submission was created false otherwise.'),
535 'submissionid' => new external_value(PARAM_INT, 'New workshop submission id.', VALUE_OPTIONAL),
c2cf2450
JL
536 'warnings' => new external_warnings()
537 ));
538 }
c1698a37
JL
539
540 /**
541 * Returns the description of the external function parameters.
542 *
543 * @return external_function_parameters
544 * @since Moodle 3.4
545 */
546 public static function update_submission_parameters() {
547 return new external_function_parameters(array(
548 'submissionid' => new external_value(PARAM_INT, 'Submission id'),
549 'title' => new external_value(PARAM_TEXT, 'Submission title'),
550 'content' => new external_value(PARAM_RAW, 'Submission text content', VALUE_DEFAULT, ''),
551 'contentformat' => new external_value(PARAM_INT, 'The format used for the content', VALUE_DEFAULT, FORMAT_MOODLE),
552 'inlineattachmentsid' => new external_value(PARAM_INT, 'The draft file area id for inline attachments in the content',
553 VALUE_DEFAULT, 0),
554 'attachmentsid' => new external_value(PARAM_INT, 'The draft file area id for attachments', VALUE_DEFAULT, 0),
555 ));
556 }
557
558
559 /**
560 * Updates the given submission.
561 *
562 * @param int $submissionid the submission id
563 * @param string $title the submission title
564 * @param string $content the submission text content
565 * @param int $contentformat the format used for the content
566 * @param int $inlineattachmentsid the draft file area id for inline attachments in the content
567 * @param int $attachmentsid the draft file area id for attachments
568 * @return array whether the submission was updated and warnings.
569 * @since Moodle 3.4
570 * @throws moodle_exception
571 */
572 public static function update_submission($submissionid, $title, $content = '', $contentformat = FORMAT_MOODLE,
573 $inlineattachmentsid = 0, $attachmentsid = 0) {
574 global $USER, $DB;
575
576 $params = self::validate_parameters(self::update_submission_parameters(), array(
577 'submissionid' => $submissionid,
578 'title' => $title,
579 'content' => $content,
580 'contentformat' => $contentformat,
581 'inlineattachmentsid' => $inlineattachmentsid,
582 'attachmentsid' => $attachmentsid,
583 ));
584 $warnings = array();
585
586 // Get and validate the submission and workshop.
587 $submission = $DB->get_record('workshop_submissions', array('id' => $params['submissionid']), '*', MUST_EXIST);
588 list($workshop, $course, $cm, $context) = self::validate_workshop($submission->workshopid);
589 require_capability('mod/workshop:submit', $context);
590
591 // Check if we can update the submission.
592 $canupdatesubmission = $submission->authorid == $USER->id;
593 $canupdatesubmission = $canupdatesubmission && $workshop->modifying_submission_allowed($USER->id);
594 $canupdatesubmission = $canupdatesubmission && $workshop->check_examples_assessed($USER->id);
595 if (!$canupdatesubmission) {
596 throw new moodle_exception('nopermissions', 'error', '', 'update submission');
597 }
598
599 // Prepare the submission object.
600 $submission->title = trim($params['title']);
601 if (empty($submission->title)) {
602 throw new moodle_exception('errorinvalidparam', 'webservice', '', 'title');
603 }
604 $submission->content_editor = array(
605 'text' => $params['content'],
606 'format' => $params['contentformat'],
607 'itemid' => $params['inlineattachmentsid'],
608 );
609 $submission->attachment_filemanager = $params['attachmentsid'];
610
611 $errors = $workshop->validate_submission_data((array) $submission);
612 // We can get several errors, return them in warnings.
613 if (!empty($errors)) {
614 $status = false;
615 foreach ($errors as $itemname => $message) {
616 $warnings[] = array(
617 'item' => $itemname,
618 'itemid' => 0,
619 'warningcode' => 'fielderror',
620 'message' => s($message)
621 );
622 }
623 } else {
624 $status = true;
625 $submission->id = $workshop->edit_submission($submission);
626 }
627
628 return array(
629 'status' => $status,
630 'warnings' => $warnings
631 );
632 }
633
634 /**
635 * Returns the description of the external function return value.
636 *
637 * @return external_description
638 * @since Moodle 3.4
639 */
640 public static function update_submission_returns() {
641 return new external_single_structure(array(
642 'status' => new external_value(PARAM_BOOL, 'True if the submission was updated false otherwise.'),
643 'warnings' => new external_warnings()
644 ));
645 }
bde5631d
JL
646
647 /**
648 * Returns the description of the external function parameters.
649 *
650 * @return external_function_parameters
651 * @since Moodle 3.4
652 */
653 public static function delete_submission_parameters() {
654 return new external_function_parameters(
655 array(
656 'submissionid' => new external_value(PARAM_INT, 'Submission id'),
657 )
658 );
659 }
660
661
662 /**
663 * Deletes the given submission.
664 *
665 * @param int $submissionid the submission id.
666 * @return array containing the result status and warnings.
667 * @since Moodle 3.4
668 * @throws moodle_exception
669 */
670 public static function delete_submission($submissionid) {
671 global $USER, $DB;
672
673 $params = self::validate_parameters(self::delete_submission_parameters(), array('submissionid' => $submissionid));
674 $warnings = array();
675
676 // Get and validate the submission and workshop.
677 $submission = $DB->get_record('workshop_submissions', array('id' => $params['submissionid']), '*', MUST_EXIST);
678 list($workshop, $course, $cm, $context) = self::validate_workshop($submission->workshopid);
679
680 // Check if we can delete the submission.
681 if (!has_capability('mod/workshop:deletesubmissions', $context)) {
682 require_capability('mod/workshop:submit', $context);
683 // We can delete our own submission, on time and not yet assessed.
684 $candeletesubmission = $submission->authorid == $USER->id;
685 $candeletesubmission = $candeletesubmission && $workshop->modifying_submission_allowed($USER->id);
686 $candeletesubmission = $candeletesubmission && count($workshop->get_assessments_of_submission($submission->id)) == 0;
687 if (!$candeletesubmission) {
688 throw new moodle_exception('nopermissions', 'error', '', 'delete submission');
689 }
690 }
691
692 $workshop->delete_submission($submission);
693
694 return array(
695 'status' => true,
696 'warnings' => $warnings
697 );
698 }
699
700 /**
701 * Returns the description of the external function return value.
702 *
703 * @return external_description
704 * @since Moodle 3.4
705 */
706 public static function delete_submission_returns() {
707 return new external_single_structure(array(
708 'status' => new external_value(PARAM_BOOL, 'True if the submission was deleted.'),
709 'warnings' => new external_warnings()
710 ));
711 }
3f08cfc5
JL
712
713 /**
714 * Helper method for returning the submission data according the current user capabilities and current phase.
715 *
716 * @param stdClass $submission the submission data
717 * @param workshop $workshop the workshop class
718 * @param bool $canviewauthorpublished whether the user has the capability mod/workshop:viewauthorpublished on
719 * @param bool $canviewauthornames whether the user has the capability mod/workshop:vviewauthornames on
720 * @param bool $canviewallsubmissions whether the user has the capability mod/workshop:viewallsubmissions on
721 * @return stdClass object with the submission data filtered
722 * @since Moodle 3.4
723 */
724 protected static function prepare_submission_for_external($submission, workshop $workshop, $canviewauthorpublished = null,
725 $canviewauthornames = null, $canviewallsubmissions = null) {
726 global $USER;
727
728 if (is_null($canviewauthorpublished)) {
729 $canviewauthorpublished = has_capability('mod/workshop:viewauthorpublished', $workshop->context);
730 }
731 if (is_null($canviewauthornames)) {
732 $canviewauthornames = has_capability('mod/workshop:viewauthornames', $workshop->context);
733 }
734 if (is_null($canviewallsubmissions)) {
735 $canviewallsubmissions = has_capability('mod/workshop:viewallsubmissions', $workshop->context);
736 }
737
738 $ownsubmission = $submission->authorid == $USER->id;
739 if (!$canviewauthornames && !$ownsubmission) {
740 $submission->authorid = 0;
741 }
742
743 $isworkshopclosed = $workshop->phase == workshop::PHASE_CLOSED;
744 $canviewsubmissiondetail = $ownsubmission || $canviewallsubmissions;
745 // If the workshop is not closed or the user can't see the submission detail: remove grading or feedback information.
746 if (!$isworkshopclosed || !$canviewsubmissiondetail) {
747 $properties = submission_exporter::properties_definition();
748 foreach ($properties as $attribute => $settings) {
749 if (!empty($settings['optional'])) {
750 unset($submission->{$attribute});
751 }
752 }
753 }
754 return $submission;
755 }
756
757 /**
758 * Returns description of method parameters
759 *
760 * @return external_function_parameters
761 * @since Moodle 3.4
762 */
763 public static function get_submissions_parameters() {
764 return new external_function_parameters(
765 array(
766 'workshopid' => new external_value(PARAM_INT, 'Workshop instance id.'),
767 'userid' => new external_value(PARAM_INT, 'Get submissions done by this user. Use 0 or empty for the current user',
768 VALUE_DEFAULT, 0),
769 'groupid' => new external_value(PARAM_INT, 'Group id, 0 means that the function will determine the user group.
770 It will return submissions done by users in the given group.',
771 VALUE_DEFAULT, 0),
772 'page' => new external_value(PARAM_INT, 'The page of records to return.', VALUE_DEFAULT, 0),
773 'perpage' => new external_value(PARAM_INT, 'The number of records to return per page.', VALUE_DEFAULT, 0),
774 )
775 );
776 }
777
778 /**
779 * Retrieves all the workshop submissions visible by the current user or the one done by the given user.
780 *
781 * @param int $workshopid the workshop instance id
782 * @param int $userid get submissions done by this user
783 * @param int $groupid (optional) group id, 0 means that the function will determine the user group
784 * @param int $page page of records to return
785 * @param int $perpage number of records to return per page
786 * @return array of warnings and the entries
787 * @since Moodle 3.4
788 * @throws moodle_exception
789 */
790 public static function get_submissions($workshopid, $userid = 0, $groupid = 0, $page = 0, $perpage = 0) {
791 global $PAGE, $USER;
792
793 $params = array('workshopid' => $workshopid, 'userid' => $userid, 'groupid' => $groupid,
794 'page' => $page, 'perpage' => $perpage);
795 $params = self::validate_parameters(self::get_submissions_parameters(), $params);
796 $submissions = $warnings = array();
797
798 list($workshop, $course, $cm, $context) = self::validate_workshop($params['workshopid']);
799
800 if (empty($params['groupid'])) {
801 // Check to see if groups are being used here.
802 if ($groupmode = groups_get_activity_groupmode($cm)) {
803 $groupid = groups_get_activity_group($cm);
804 // Determine is the group is visible to user (this is particullary for the group 0 -> all groups).
805 if (!groups_group_visible($groupid, $course, $cm)) {
806 throw new moodle_exception('notingroup');
807 }
808 } else {
809 $groupid = 0;
810 }
811 }
812
813 if (!empty($params['userid']) && $params['userid'] != $USER->id) {
814 $user = core_user::get_user($params['userid'], '*', MUST_EXIST);
815 core_user::require_active_user($user);
816 if (!$workshop->check_group_membership($user->id)) {
817 throw new moodle_exception('notingroup');
818 }
819 }
820
821 $totalfilesize = 0;
822 list($submissionsrecords, $totalcount) =
823 $workshop->get_visible_submissions($params['userid'], $groupid, $params['page'], $params['perpage']);
824
825 if ($totalcount) {
826
827 $canviewauthorpublished = has_capability('mod/workshop:viewauthorpublished', $context);
828 $canviewauthornames = has_capability('mod/workshop:viewauthornames', $context);
829 $canviewallsubmissions = has_capability('mod/workshop:viewallsubmissions', $context);
830
831 $related = array('context' => $context);
832 foreach ($submissionsrecords as $submission) {
833 $submission = self::prepare_submission_for_external($submission, $workshop, $canviewauthorpublished,
834 $canviewauthornames, $canviewallsubmissions);
835
836 $exporter = new submission_exporter($submission, $related);
837 $submissions[] = $exporter->export($PAGE->get_renderer('core'));
838 }
839
840 // Retrieve total files size for the submissions (so external clients know how many data they'd need to download).
841 $fs = get_file_storage();
842 $files = $fs->get_area_files($context->id, 'mod_workshop', array('submission_content', 'submission_attachment'));
843 foreach ($files as $file) {
844 if ($file->is_directory() || !isset($submissionsrecords[$file->get_itemid()])) {
845 continue;
846 }
847 $totalfilesize += $file->get_filesize();
848 }
849 }
850
851 return array(
852 'submissions' => $submissions,
853 'totalcount' => $totalcount,
854 'totalfilesize' => $totalfilesize,
855 );
856 }
857
858 /**
859 * Returns description of method result value
860 *
861 * @return external_description
862 * @since Moodle 3.4
863 */
864 public static function get_submissions_returns() {
865 return new external_single_structure(
866 array(
867 'submissions' => new external_multiple_structure(
868 submission_exporter::get_read_structure()
869 ),
870 'totalcount' => new external_value(PARAM_INT, 'Total count of submissions.'),
871 'totalfilesize' => new external_value(PARAM_INT, 'Total size (bytes) of the files included in the submissions.'),
872 'warnings' => new external_warnings()
873 )
874 );
875 }
6e2f4866
JL
876
877 /**
878 * Returns the description of the external function parameters.
879 *
880 * @return external_function_parameters
881 * @since Moodle 3.4
882 */
883 public static function get_submission_parameters() {
884 return new external_function_parameters(
885 array(
886 'submissionid' => new external_value(PARAM_INT, 'Submission id'),
887 )
888 );
889 }
890
891
892 /**
893 * Retrieves the given submission.
894 *
895 * @param int $submissionid the submission id
896 * @return array containing the submission and warnings.
897 * @since Moodle 3.4
898 * @throws moodle_exception
899 */
900 public static function get_submission($submissionid) {
901 global $USER, $DB, $PAGE;
902
903 $params = self::validate_parameters(self::get_submission_parameters(), array('submissionid' => $submissionid));
904 $warnings = array();
905
906 // Get and validate the submission and workshop.
907 $submission = $DB->get_record('workshop_submissions', array('id' => $params['submissionid']), '*', MUST_EXIST);
908 list($workshop, $course, $cm, $context) = self::validate_workshop($submission->workshopid);
909
910 $workshopclosed = $workshop->phase == workshop::PHASE_CLOSED;
911 $canviewpublished = has_capability('mod/workshop:viewpublishedsubmissions', $context);
912
913 $canview = $submission->authorid == $USER->id; // I did it.
914 $canview = $canview || !empty($workshop->get_assessment_of_submission_by_user($submission->id, $USER->id)); // I reviewed.
915 $canview = $canview || has_capability('mod/workshop:viewallsubmissions', $context); // I can view all.
916 $canview = $canview || ($submission->published && $workshopclosed && $canviewpublished); // It has been published.
917
918 if ($canview) {
919 // Here we should check if the user share group.
920 if ($submission->authorid != $USER->id && !groups_user_groups_visible($course, $submission->authorid, $cm)) {
921 throw new moodle_exception('notingroup');
922 }
923 } else {
924 throw new moodle_exception('nopermissions', 'error', '', 'view submission');
925 }
926
927 $submission = self::prepare_submission_for_external($submission, $workshop);
928
929 $related = array('context' => $context);
930 $exporter = new submission_exporter($submission, $related);
931 return array(
932 'submission' => $exporter->export($PAGE->get_renderer('core')),
933 'warnings' => $warnings
934 );
935 }
936
937 /**
938 * Returns description of method result value
939 *
940 * @return external_description
941 * @since Moodle 3.4
942 */
943 public static function get_submission_returns() {
944 return new external_single_structure(
945 array(
946 'submission' => submission_exporter::get_read_structure(),
947 'warnings' => new external_warnings()
948 )
949 );
950 }
9f1ab2db 951}