MDL-59241 mod_workshop: Fix testing found issues
[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;
30b54b82 34use mod_workshop\external\assessment_exporter;
9f1ab2db
JL
35
36/**
37 * Workshop external functions
38 *
39 * @package mod_workshop
40 * @category external
41 * @copyright 2017 Juan Leyva <juan@moodle.com>
42 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
43 * @since Moodle 3.4
44 */
45class mod_workshop_external extends external_api {
46
47 /**
48 * Describes the parameters for get_workshops_by_courses.
49 *
50 * @return external_function_parameters
51 * @since Moodle 3.4
52 */
53 public static function get_workshops_by_courses_parameters() {
54 return new external_function_parameters (
55 array(
56 'courseids' => new external_multiple_structure(
57 new external_value(PARAM_INT, 'Course id'), 'Array of course ids', VALUE_DEFAULT, array()
58 ),
59 )
60 );
61 }
62
63 /**
64 * Returns a list of workshops in a provided list of courses.
65 * If no list is provided all workshops that the user can view will be returned.
66 *
67 * @param array $courseids course ids
68 * @return array of warnings and workshops
69 * @since Moodle 3.4
70 */
71 public static function get_workshops_by_courses($courseids = array()) {
72 global $PAGE;
73
74 $warnings = array();
75 $returnedworkshops = array();
76
77 $params = array(
78 'courseids' => $courseids,
79 );
80 $params = self::validate_parameters(self::get_workshops_by_courses_parameters(), $params);
81
82 $mycourses = array();
83 if (empty($params['courseids'])) {
84 $mycourses = enrol_get_my_courses();
85 $params['courseids'] = array_keys($mycourses);
86 }
87
88 // Ensure there are courseids to loop through.
89 if (!empty($params['courseids'])) {
90
91 list($courses, $warnings) = external_util::validate_courses($params['courseids'], $mycourses);
92 $output = $PAGE->get_renderer('core');
93
94 // Get the workshops in this course, this function checks users visibility permissions.
95 // We can avoid then additional validate_context calls.
96 $workshops = get_all_instances_in_courses("workshop", $courses);
97 foreach ($workshops as $workshop) {
98
99 $context = context_module::instance($workshop->coursemodule);
100 // Remove fields that are not from the workshop (added by get_all_instances_in_courses).
101 unset($workshop->coursemodule, $workshop->context, $workshop->visible, $workshop->section, $workshop->groupmode,
102 $workshop->groupingid);
103
104 $exporter = new workshop_summary_exporter($workshop, array('context' => $context));
105 $returnedworkshops[] = $exporter->export($output);
106 }
107 }
108
109 $result = array(
110 'workshops' => $returnedworkshops,
111 'warnings' => $warnings
112 );
113 return $result;
114 }
115
116 /**
117 * Describes the get_workshops_by_courses return value.
118 *
119 * @return external_single_structure
120 * @since Moodle 3.4
121 */
122 public static function get_workshops_by_courses_returns() {
123 return new external_single_structure(
124 array(
125 'workshops' => new external_multiple_structure(
126 workshop_summary_exporter::get_read_structure()
127 ),
128 'warnings' => new external_warnings(),
129 )
130 );
131 }
977fdfa3
JL
132
133 /**
134 * Utility function for validating a workshop.
135 *
136 * @param int $workshopid workshop instance id
137 * @return array array containing the workshop object, course, context and course module objects
138 * @since Moodle 3.4
139 */
140 protected static function validate_workshop($workshopid) {
141 global $DB, $USER;
142
143 // Request and permission validation.
144 $workshop = $DB->get_record('workshop', array('id' => $workshopid), '*', MUST_EXIST);
145 list($course, $cm) = get_course_and_cm_from_instance($workshop, 'workshop');
146
147 $context = context_module::instance($cm->id);
148 self::validate_context($context);
149
150 $workshop = new workshop($workshop, $cm, $course);
151
152 return array($workshop, $course, $cm, $context);
153 }
154
155
156 /**
157 * Describes the parameters for get_workshop_access_information.
158 *
159 * @return external_external_function_parameters
160 * @since Moodle 3.4
161 */
162 public static function get_workshop_access_information_parameters() {
163 return new external_function_parameters (
164 array(
165 'workshopid' => new external_value(PARAM_INT, 'Workshop instance id.')
166 )
167 );
168 }
169
170 /**
171 * Return access information for a given workshop.
172 *
173 * @param int $workshopid workshop instance id
174 * @return array of warnings and the access information
175 * @since Moodle 3.4
176 * @throws moodle_exception
177 */
178 public static function get_workshop_access_information($workshopid) {
179 global $USER;
180
181 $params = self::validate_parameters(self::get_workshop_access_information_parameters(), array('workshopid' => $workshopid));
182
183 list($workshop, $course, $cm, $context) = self::validate_workshop($params['workshopid']);
184
185 $result = array();
186 // Return all the available capabilities.
187 $capabilities = load_capability_def('mod_workshop');
188 foreach ($capabilities as $capname => $capdata) {
189 // Get fields like cansubmit so it is consistent with the access_information function implemented in other modules.
190 $field = 'can' . str_replace('mod/workshop:', '', $capname);
191 $result[$field] = has_capability($capname, $context);
192 }
193
194 // Now, specific features access information.
195 $result['creatingsubmissionallowed'] = $workshop->creating_submission_allowed($USER->id);
196 $result['modifyingsubmissionallowed'] = $workshop->modifying_submission_allowed($USER->id);
197 $result['assessingallowed'] = $workshop->assessing_allowed($USER->id);
198 $result['assessingexamplesallowed'] = $workshop->assessing_examples_allowed();
199 if (is_null($result['assessingexamplesallowed'])) {
200 $result['assessingexamplesallowed'] = false;
201 }
86928d2a
JL
202 $result['examplesassessedbeforesubmission'] = $workshop->check_examples_assessed_before_submission($USER->id);
203 list($result['examplesassessedbeforeassessment'], $code) = $workshop->check_examples_assessed_before_assessment($USER->id);
977fdfa3
JL
204
205 $result['warnings'] = array();
206 return $result;
207 }
208
209 /**
210 * Describes the get_workshop_access_information return value.
211 *
212 * @return external_single_structure
213 * @since Moodle 3.4
214 */
215 public static function get_workshop_access_information_returns() {
216
217 $structure = array(
218 'creatingsubmissionallowed' => new external_value(PARAM_BOOL,
219 'Is the given user allowed to create their submission?'),
220 'modifyingsubmissionallowed' => new external_value(PARAM_BOOL,
221 'Is the user allowed to modify his existing submission?'),
222 'assessingallowed' => new external_value(PARAM_BOOL,
223 'Is the user allowed to create/edit his assessments?'),
224 'assessingexamplesallowed' => new external_value(PARAM_BOOL,
225 'Are reviewers allowed to create/edit their assessments of the example submissions?.'),
86928d2a
JL
226 'examplesassessedbeforesubmission' => new external_value(PARAM_BOOL,
227 'Whether the given user has assessed all his required examples before submission
228 (always true if there are not examples to assess or not configured to check before submission).'),
229 'examplesassessedbeforeassessment' => new external_value(PARAM_BOOL,
230 'Whether the given user has assessed all his required examples before assessment
231 (always true if there are not examples to assessor not configured to check before assessment).'),
977fdfa3
JL
232 'warnings' => new external_warnings()
233 );
234
235 $capabilities = load_capability_def('mod_workshop');
236 foreach ($capabilities as $capname => $capdata) {
237 // Get fields like cansubmit so it is consistent with the access_information function implemented in other modules.
238 $field = 'can' . str_replace('mod/workshop:', '', $capname);
239 $structure[$field] = new external_value(PARAM_BOOL, 'Whether the user has the capability ' . $capname . ' allowed.');
240 }
241
242 return new external_single_structure($structure);
243 }
cd495029
JL
244
245 /**
246 * Describes the parameters for get_user_plan.
247 *
248 * @return external_external_function_parameters
249 * @since Moodle 3.4
250 */
251 public static function get_user_plan_parameters() {
252 return new external_function_parameters (
253 array(
254 'workshopid' => new external_value(PARAM_INT, 'Workshop instance id.'),
255 'userid' => new external_value(PARAM_INT, 'User id (empty or 0 for current user).', VALUE_DEFAULT, 0),
256 )
257 );
258 }
259
260 /**
261 * Return the planner information for the given user.
262 *
263 * @param int $workshopid workshop instance id
264 * @param int $userid user id
265 * @return array of warnings and the user plan
266 * @since Moodle 3.4
267 * @throws moodle_exception
268 */
269 public static function get_user_plan($workshopid, $userid = 0) {
270 global $USER;
271
272 $params = array(
273 'workshopid' => $workshopid,
274 'userid' => $userid,
275 );
276 $params = self::validate_parameters(self::get_user_plan_parameters(), $params);
277
278 list($workshop, $course, $cm, $context) = self::validate_workshop($params['workshopid']);
279
280 // Extra checks so only users with permissions can view other users plans.
281 if (empty($params['userid']) || $params['userid'] == $USER->id) {
282 $userid = $USER->id;
283 } else {
284 require_capability('moodle/course:manageactivities', $context);
285 $user = core_user::get_user($params['userid'], '*', MUST_EXIST);
286 core_user::require_active_user($user);
287 if (!$workshop->check_group_membership($user->id)) {
288 throw new moodle_exception('notingroup');
289 }
290 $userid = $user->id;
291 }
292
293 // Get the user plan information ready for external functions.
294 $userplan = new workshop_user_plan($workshop, $userid);
295 $userplan = array('phases' => $userplan->phases, 'examples' => $userplan->get_examples());
296 foreach ($userplan['phases'] as $phasecode => $phase) {
297 $phase->code = $phasecode;
298 $userplan['phases'][$phasecode] = (array) $phase;
299 foreach ($userplan['phases'][$phasecode]['tasks'] as $taskcode => $task) {
300 $task->code = $taskcode;
301 if ($task->link instanceof moodle_url) {
302 $task->link = $task->link->out(false);
303 }
304 $userplan['phases'][$phasecode]['tasks'][$taskcode] = (array) $task;
305 }
306 foreach ($userplan['phases'][$phasecode]['actions'] as $actioncode => $action) {
307 if ($action->url instanceof moodle_url) {
308 $action->url = $action->url->out(false);
309 }
310 $userplan['phases'][$phasecode]['actions'][$actioncode] = (array) $action;
311 }
312 }
313
314 $result['userplan'] = $userplan;
315 $result['warnings'] = array();
316 return $result;
317 }
318
319 /**
320 * Describes the get_user_plan return value.
321 *
322 * @return external_single_structure
323 * @since Moodle 3.4
324 */
325 public static function get_user_plan_returns() {
326 return new external_single_structure(
327 array(
328 'userplan' => new external_single_structure(
329 array(
330 'phases' => new external_multiple_structure(
331 new external_single_structure(
332 array(
333 'code' => new external_value(PARAM_INT, 'Phase code.'),
334 'title' => new external_value(PARAM_NOTAGS, 'Phase title.'),
335 'active' => new external_value(PARAM_BOOL, 'Whether is the active task.'),
336 'tasks' => new external_multiple_structure(
337 new external_single_structure(
338 array(
339 'code' => new external_value(PARAM_ALPHA, 'Task code.'),
340 'title' => new external_value(PARAM_RAW, 'Task title.'),
341 'link' => new external_value(PARAM_URL, 'Link to task.'),
342 'details' => new external_value(PARAM_RAW, 'Task details.', VALUE_OPTIONAL),
343 'completed' => new external_value(PARAM_NOTAGS,
344 'Completion information (maybe empty, maybe a boolean or generic info.'),
345 )
346 )
347 ),
348 'actions' => new external_multiple_structure(
349 new external_single_structure(
350 array(
351 'type' => new external_value(PARAM_ALPHA, 'Action type.', VALUE_OPTIONAL),
352 'label' => new external_value(PARAM_RAW, 'Action label.', VALUE_OPTIONAL),
353 'url' => new external_value(PARAM_URL, 'Link to action.'),
354 'method' => new external_value(PARAM_ALPHA, 'Get or post.', VALUE_OPTIONAL),
355 )
356 )
357 ),
358 )
359 )
360 ),
361 'examples' => new external_multiple_structure(
362 new external_single_structure(
363 array(
364 'id' => new external_value(PARAM_INT, 'Example submission id.'),
365 'title' => new external_value(PARAM_RAW, 'Example submission title.'),
366 'assessmentid' => new external_value(PARAM_INT, 'Example submission assessment id.'),
367 'grade' => new external_value(PARAM_FLOAT, 'The submission grade.'),
368 'gradinggrade' => new external_value(PARAM_FLOAT, 'The assessment grade.'),
369 )
370 )
371 ),
372 )
373 ),
374 'warnings' => new external_warnings(),
375 )
376 );
377 }
291645f7
JL
378
379 /**
380 * Describes the parameters for view_workshop.
381 *
382 * @return external_function_parameters
383 * @since Moodle 3.4
384 */
385 public static function view_workshop_parameters() {
386 return new external_function_parameters (
387 array(
388 'workshopid' => new external_value(PARAM_INT, 'Workshop instance id'),
389 )
390 );
391 }
392
393 /**
394 * Trigger the course module viewed event and update the module completion status.
395 *
396 * @param int $workshopid workshop instance id
397 * @return array of warnings and status result
398 * @since Moodle 3.4
399 * @throws moodle_exception
400 */
401 public static function view_workshop($workshopid) {
402
403 $params = array('workshopid' => $workshopid);
404 $params = self::validate_parameters(self::view_workshop_parameters(), $params);
405 $warnings = array();
406
407 list($workshop, $course, $cm, $context) = self::validate_workshop($params['workshopid']);
408
409 $workshop->set_module_viewed();
410
411 $result = array(
412 'status' => true,
413 'warnings' => $warnings,
414 );
415 return $result;
416 }
417
418 /**
419 * Describes the view_workshop return value.
420 *
421 * @return external_single_structure
422 * @since Moodle 3.4
423 */
424 public static function view_workshop_returns() {
425 return new external_single_structure(
426 array(
427 'status' => new external_value(PARAM_BOOL, 'status: true if success'),
428 'warnings' => new external_warnings(),
429 )
430 );
431 }
c2cf2450
JL
432
433 /**
434 * Returns the description of the external function parameters.
435 *
436 * @return external_function_parameters
437 * @since Moodle 3.4
438 */
439 public static function add_submission_parameters() {
440 return new external_function_parameters(array(
441 'workshopid' => new external_value(PARAM_INT, 'Workshop id'),
442 'title' => new external_value(PARAM_TEXT, 'Submission title'),
443 'content' => new external_value(PARAM_RAW, 'Submission text content', VALUE_DEFAULT, ''),
444 'contentformat' => new external_value(PARAM_INT, 'The format used for the content', VALUE_DEFAULT, FORMAT_MOODLE),
445 'inlineattachmentsid' => new external_value(PARAM_INT, 'The draft file area id for inline attachments in the content',
446 VALUE_DEFAULT, 0),
447 'attachmentsid' => new external_value(PARAM_INT, 'The draft file area id for attachments', VALUE_DEFAULT, 0),
448 ));
449 }
450
451 /**
452 * Add a new submission to a given workshop.
453 *
454 * @param int $workshopid the workshop id
455 * @param string $title the submission title
456 * @param string $content the submission text content
457 * @param int $contentformat the format used for the content
458 * @param int $inlineattachmentsid the draft file area id for inline attachments in the content
459 * @param int $attachmentsid the draft file area id for attachments
460 * @return array Containing the new created submission id and warnings.
461 * @since Moodle 3.4
462 * @throws moodle_exception
463 */
464 public static function add_submission($workshopid, $title, $content = '', $contentformat = FORMAT_MOODLE,
465 $inlineattachmentsid = 0, $attachmentsid = 0) {
466 global $USER;
467
468 $params = self::validate_parameters(self::add_submission_parameters(), array(
469 'workshopid' => $workshopid,
470 'title' => $title,
471 'content' => $content,
472 'contentformat' => $contentformat,
473 'inlineattachmentsid' => $inlineattachmentsid,
474 'attachmentsid' => $attachmentsid,
475 ));
476 $warnings = array();
477
478 // Get and validate the workshop.
479 list($workshop, $course, $cm, $context) = self::validate_workshop($params['workshopid']);
480 require_capability('mod/workshop:submit', $context);
481
482 // Check if we can submit now.
483 $canaddsubmission = $workshop->creating_submission_allowed($USER->id);
86928d2a 484 $canaddsubmission = $canaddsubmission && $workshop->check_examples_assessed_before_submission($USER->id);
c2cf2450
JL
485 if (!$canaddsubmission) {
486 throw new moodle_exception('nopermissions', 'error', '', 'add submission');
487 }
488
489 // Prepare the submission object.
490 $submission = new stdClass;
491 $submission->id = null;
492 $submission->cmid = $cm->id;
493 $submission->example = 0;
494 $submission->title = trim($params['title']);
495 $submission->content_editor = array(
496 'text' => $params['content'],
497 'format' => $params['contentformat'],
498 'itemid' => $params['inlineattachmentsid'],
499 );
500 $submission->attachment_filemanager = $params['attachmentsid'];
501
502 if (empty($submission->title)) {
503 throw new moodle_exception('errorinvalidparam', 'webservice', '', 'title');
504 }
505
506 $errors = $workshop->validate_submission_data((array) $submission);
507 // We can get several errors, return them in warnings.
508 if (!empty($errors)) {
509 $submission->id = 0;
510 foreach ($errors as $itemname => $message) {
511 $warnings[] = array(
512 'item' => $itemname,
513 'itemid' => 0,
514 'warningcode' => 'fielderror',
515 'message' => s($message)
516 );
517 }
4834e127
JL
518 return array(
519 'status' => false,
520 'warnings' => $warnings
521 );
c2cf2450
JL
522 } else {
523 $submission->id = $workshop->edit_submission($submission);
4834e127
JL
524 return array(
525 'status' => true,
526 'submissionid' => $submission->id,
527 'warnings' => $warnings
528 );
c2cf2450 529 }
c2cf2450
JL
530 }
531
532 /**
533 * Returns the description of the external function return value.
534 *
535 * @return external_description
536 * @since Moodle 3.4
537 */
538 public static function add_submission_returns() {
539 return new external_single_structure(array(
4834e127
JL
540 'status' => new external_value(PARAM_BOOL, 'True if the submission was created false otherwise.'),
541 'submissionid' => new external_value(PARAM_INT, 'New workshop submission id.', VALUE_OPTIONAL),
c2cf2450
JL
542 'warnings' => new external_warnings()
543 ));
544 }
c1698a37
JL
545
546 /**
547 * Returns the description of the external function parameters.
548 *
549 * @return external_function_parameters
550 * @since Moodle 3.4
551 */
552 public static function update_submission_parameters() {
553 return new external_function_parameters(array(
554 'submissionid' => new external_value(PARAM_INT, 'Submission id'),
555 'title' => new external_value(PARAM_TEXT, 'Submission title'),
556 'content' => new external_value(PARAM_RAW, 'Submission text content', VALUE_DEFAULT, ''),
557 'contentformat' => new external_value(PARAM_INT, 'The format used for the content', VALUE_DEFAULT, FORMAT_MOODLE),
558 'inlineattachmentsid' => new external_value(PARAM_INT, 'The draft file area id for inline attachments in the content',
559 VALUE_DEFAULT, 0),
560 'attachmentsid' => new external_value(PARAM_INT, 'The draft file area id for attachments', VALUE_DEFAULT, 0),
561 ));
562 }
563
564
565 /**
566 * Updates the given submission.
567 *
568 * @param int $submissionid the submission id
569 * @param string $title the submission title
570 * @param string $content the submission text content
571 * @param int $contentformat the format used for the content
572 * @param int $inlineattachmentsid the draft file area id for inline attachments in the content
573 * @param int $attachmentsid the draft file area id for attachments
574 * @return array whether the submission was updated and warnings.
575 * @since Moodle 3.4
576 * @throws moodle_exception
577 */
578 public static function update_submission($submissionid, $title, $content = '', $contentformat = FORMAT_MOODLE,
579 $inlineattachmentsid = 0, $attachmentsid = 0) {
580 global $USER, $DB;
581
582 $params = self::validate_parameters(self::update_submission_parameters(), array(
583 'submissionid' => $submissionid,
584 'title' => $title,
585 'content' => $content,
586 'contentformat' => $contentformat,
587 'inlineattachmentsid' => $inlineattachmentsid,
588 'attachmentsid' => $attachmentsid,
589 ));
590 $warnings = array();
591
592 // Get and validate the submission and workshop.
593 $submission = $DB->get_record('workshop_submissions', array('id' => $params['submissionid']), '*', MUST_EXIST);
594 list($workshop, $course, $cm, $context) = self::validate_workshop($submission->workshopid);
595 require_capability('mod/workshop:submit', $context);
596
597 // Check if we can update the submission.
598 $canupdatesubmission = $submission->authorid == $USER->id;
599 $canupdatesubmission = $canupdatesubmission && $workshop->modifying_submission_allowed($USER->id);
86928d2a 600 $canupdatesubmission = $canupdatesubmission && $workshop->check_examples_assessed_before_submission($USER->id);
c1698a37
JL
601 if (!$canupdatesubmission) {
602 throw new moodle_exception('nopermissions', 'error', '', 'update submission');
603 }
604
605 // Prepare the submission object.
606 $submission->title = trim($params['title']);
607 if (empty($submission->title)) {
608 throw new moodle_exception('errorinvalidparam', 'webservice', '', 'title');
609 }
610 $submission->content_editor = array(
611 'text' => $params['content'],
612 'format' => $params['contentformat'],
613 'itemid' => $params['inlineattachmentsid'],
614 );
615 $submission->attachment_filemanager = $params['attachmentsid'];
616
617 $errors = $workshop->validate_submission_data((array) $submission);
618 // We can get several errors, return them in warnings.
619 if (!empty($errors)) {
620 $status = false;
621 foreach ($errors as $itemname => $message) {
622 $warnings[] = array(
623 'item' => $itemname,
624 'itemid' => 0,
625 'warningcode' => 'fielderror',
626 'message' => s($message)
627 );
628 }
629 } else {
630 $status = true;
631 $submission->id = $workshop->edit_submission($submission);
632 }
633
634 return array(
635 'status' => $status,
636 'warnings' => $warnings
637 );
638 }
639
640 /**
641 * Returns the description of the external function return value.
642 *
643 * @return external_description
644 * @since Moodle 3.4
645 */
646 public static function update_submission_returns() {
647 return new external_single_structure(array(
648 'status' => new external_value(PARAM_BOOL, 'True if the submission was updated false otherwise.'),
649 'warnings' => new external_warnings()
650 ));
651 }
bde5631d
JL
652
653 /**
654 * Returns the description of the external function parameters.
655 *
656 * @return external_function_parameters
657 * @since Moodle 3.4
658 */
659 public static function delete_submission_parameters() {
660 return new external_function_parameters(
661 array(
662 'submissionid' => new external_value(PARAM_INT, 'Submission id'),
663 )
664 );
665 }
666
667
668 /**
669 * Deletes the given submission.
670 *
671 * @param int $submissionid the submission id.
672 * @return array containing the result status and warnings.
673 * @since Moodle 3.4
674 * @throws moodle_exception
675 */
676 public static function delete_submission($submissionid) {
677 global $USER, $DB;
678
679 $params = self::validate_parameters(self::delete_submission_parameters(), array('submissionid' => $submissionid));
680 $warnings = array();
681
682 // Get and validate the submission and workshop.
683 $submission = $DB->get_record('workshop_submissions', array('id' => $params['submissionid']), '*', MUST_EXIST);
684 list($workshop, $course, $cm, $context) = self::validate_workshop($submission->workshopid);
685
686 // Check if we can delete the submission.
687 if (!has_capability('mod/workshop:deletesubmissions', $context)) {
688 require_capability('mod/workshop:submit', $context);
689 // We can delete our own submission, on time and not yet assessed.
690 $candeletesubmission = $submission->authorid == $USER->id;
691 $candeletesubmission = $candeletesubmission && $workshop->modifying_submission_allowed($USER->id);
692 $candeletesubmission = $candeletesubmission && count($workshop->get_assessments_of_submission($submission->id)) == 0;
693 if (!$candeletesubmission) {
694 throw new moodle_exception('nopermissions', 'error', '', 'delete submission');
695 }
696 }
697
698 $workshop->delete_submission($submission);
699
700 return array(
701 'status' => true,
702 'warnings' => $warnings
703 );
704 }
705
706 /**
707 * Returns the description of the external function return value.
708 *
709 * @return external_description
710 * @since Moodle 3.4
711 */
712 public static function delete_submission_returns() {
713 return new external_single_structure(array(
714 'status' => new external_value(PARAM_BOOL, 'True if the submission was deleted.'),
715 'warnings' => new external_warnings()
716 ));
717 }
3f08cfc5
JL
718
719 /**
720 * Helper method for returning the submission data according the current user capabilities and current phase.
721 *
722 * @param stdClass $submission the submission data
723 * @param workshop $workshop the workshop class
724 * @param bool $canviewauthorpublished whether the user has the capability mod/workshop:viewauthorpublished on
725 * @param bool $canviewauthornames whether the user has the capability mod/workshop:vviewauthornames on
726 * @param bool $canviewallsubmissions whether the user has the capability mod/workshop:viewallsubmissions on
727 * @return stdClass object with the submission data filtered
728 * @since Moodle 3.4
729 */
730 protected static function prepare_submission_for_external($submission, workshop $workshop, $canviewauthorpublished = null,
731 $canviewauthornames = null, $canviewallsubmissions = null) {
732 global $USER;
733
734 if (is_null($canviewauthorpublished)) {
735 $canviewauthorpublished = has_capability('mod/workshop:viewauthorpublished', $workshop->context);
736 }
737 if (is_null($canviewauthornames)) {
738 $canviewauthornames = has_capability('mod/workshop:viewauthornames', $workshop->context);
739 }
740 if (is_null($canviewallsubmissions)) {
741 $canviewallsubmissions = has_capability('mod/workshop:viewallsubmissions', $workshop->context);
742 }
743
744 $ownsubmission = $submission->authorid == $USER->id;
745 if (!$canviewauthornames && !$ownsubmission) {
746 $submission->authorid = 0;
747 }
748
749 $isworkshopclosed = $workshop->phase == workshop::PHASE_CLOSED;
750 $canviewsubmissiondetail = $ownsubmission || $canviewallsubmissions;
751 // If the workshop is not closed or the user can't see the submission detail: remove grading or feedback information.
752 if (!$isworkshopclosed || !$canviewsubmissiondetail) {
753 $properties = submission_exporter::properties_definition();
754 foreach ($properties as $attribute => $settings) {
755 if (!empty($settings['optional'])) {
756 unset($submission->{$attribute});
757 }
758 }
759 }
760 return $submission;
761 }
762
763 /**
764 * Returns description of method parameters
765 *
766 * @return external_function_parameters
767 * @since Moodle 3.4
768 */
769 public static function get_submissions_parameters() {
770 return new external_function_parameters(
771 array(
772 'workshopid' => new external_value(PARAM_INT, 'Workshop instance id.'),
773 'userid' => new external_value(PARAM_INT, 'Get submissions done by this user. Use 0 or empty for the current user',
774 VALUE_DEFAULT, 0),
775 'groupid' => new external_value(PARAM_INT, 'Group id, 0 means that the function will determine the user group.
776 It will return submissions done by users in the given group.',
777 VALUE_DEFAULT, 0),
778 'page' => new external_value(PARAM_INT, 'The page of records to return.', VALUE_DEFAULT, 0),
779 'perpage' => new external_value(PARAM_INT, 'The number of records to return per page.', VALUE_DEFAULT, 0),
780 )
781 );
782 }
783
784 /**
4c2a2bd7
JL
785 * Retrieves all the workshop submissions visible by the current user or the one done by the given user
786 * (except example submissions).
3f08cfc5
JL
787 *
788 * @param int $workshopid the workshop instance id
789 * @param int $userid get submissions done by this user
790 * @param int $groupid (optional) group id, 0 means that the function will determine the user group
791 * @param int $page page of records to return
792 * @param int $perpage number of records to return per page
793 * @return array of warnings and the entries
794 * @since Moodle 3.4
795 * @throws moodle_exception
796 */
797 public static function get_submissions($workshopid, $userid = 0, $groupid = 0, $page = 0, $perpage = 0) {
798 global $PAGE, $USER;
799
800 $params = array('workshopid' => $workshopid, 'userid' => $userid, 'groupid' => $groupid,
801 'page' => $page, 'perpage' => $perpage);
802 $params = self::validate_parameters(self::get_submissions_parameters(), $params);
803 $submissions = $warnings = array();
804
805 list($workshop, $course, $cm, $context) = self::validate_workshop($params['workshopid']);
806
807 if (empty($params['groupid'])) {
808 // Check to see if groups are being used here.
809 if ($groupmode = groups_get_activity_groupmode($cm)) {
810 $groupid = groups_get_activity_group($cm);
811 // Determine is the group is visible to user (this is particullary for the group 0 -> all groups).
812 if (!groups_group_visible($groupid, $course, $cm)) {
813 throw new moodle_exception('notingroup');
814 }
815 } else {
816 $groupid = 0;
817 }
818 }
819
820 if (!empty($params['userid']) && $params['userid'] != $USER->id) {
821 $user = core_user::get_user($params['userid'], '*', MUST_EXIST);
822 core_user::require_active_user($user);
823 if (!$workshop->check_group_membership($user->id)) {
824 throw new moodle_exception('notingroup');
825 }
826 }
827
828 $totalfilesize = 0;
829 list($submissionsrecords, $totalcount) =
830 $workshop->get_visible_submissions($params['userid'], $groupid, $params['page'], $params['perpage']);
831
832 if ($totalcount) {
833
834 $canviewauthorpublished = has_capability('mod/workshop:viewauthorpublished', $context);
835 $canviewauthornames = has_capability('mod/workshop:viewauthornames', $context);
836 $canviewallsubmissions = has_capability('mod/workshop:viewallsubmissions', $context);
837
838 $related = array('context' => $context);
839 foreach ($submissionsrecords as $submission) {
840 $submission = self::prepare_submission_for_external($submission, $workshop, $canviewauthorpublished,
841 $canviewauthornames, $canviewallsubmissions);
842
843 $exporter = new submission_exporter($submission, $related);
844 $submissions[] = $exporter->export($PAGE->get_renderer('core'));
845 }
846
847 // Retrieve total files size for the submissions (so external clients know how many data they'd need to download).
848 $fs = get_file_storage();
849 $files = $fs->get_area_files($context->id, 'mod_workshop', array('submission_content', 'submission_attachment'));
850 foreach ($files as $file) {
4c2a2bd7 851 if ($file->is_directory()) {
3f08cfc5
JL
852 continue;
853 }
854 $totalfilesize += $file->get_filesize();
855 }
856 }
857
858 return array(
859 'submissions' => $submissions,
860 'totalcount' => $totalcount,
861 'totalfilesize' => $totalfilesize,
862 );
863 }
864
865 /**
866 * Returns description of method result value
867 *
868 * @return external_description
869 * @since Moodle 3.4
870 */
871 public static function get_submissions_returns() {
872 return new external_single_structure(
873 array(
874 'submissions' => new external_multiple_structure(
875 submission_exporter::get_read_structure()
876 ),
877 'totalcount' => new external_value(PARAM_INT, 'Total count of submissions.'),
4c2a2bd7
JL
878 'totalfilesize' => new external_value(PARAM_INT, 'Total size (bytes) of the files attached to all the
879 submissions (even the ones not returned due to pagination).'),
3f08cfc5
JL
880 'warnings' => new external_warnings()
881 )
882 );
883 }
6e2f4866 884
30b54b82
JL
885 /**
886 * Helper method for validating a submission.
887 *
888 * @param stdClass $submission submission object
889 * @param workshop $workshop workshop instance
890 * @return void
891 * @since Moodle 3.4
892 */
893 protected static function validate_submission($submission, workshop $workshop) {
894 global $USER;
895
896 $workshopclosed = $workshop->phase == workshop::PHASE_CLOSED;
897 $canviewpublished = has_capability('mod/workshop:viewpublishedsubmissions', $workshop->context);
898
899 $canview = $submission->authorid == $USER->id; // I did it.
900 $canview = $canview || !empty($workshop->get_assessment_of_submission_by_user($submission->id, $USER->id)); // I reviewed.
901 $canview = $canview || has_capability('mod/workshop:viewallsubmissions', $workshop->context); // I can view all.
902 $canview = $canview || ($submission->published && $workshopclosed && $canviewpublished); // It has been published.
903
904 if ($canview) {
905 // Here we should check if the user share group.
906 if ($submission->authorid != $USER->id &&
907 !groups_user_groups_visible($workshop->course, $submission->authorid, $workshop->cm)) {
908 throw new moodle_exception('notingroup');
909 }
910 } else {
911 throw new moodle_exception('nopermissions', 'error', '', 'view submission');
912 }
913 }
914
6e2f4866
JL
915 /**
916 * Returns the description of the external function parameters.
917 *
918 * @return external_function_parameters
919 * @since Moodle 3.4
920 */
921 public static function get_submission_parameters() {
922 return new external_function_parameters(
923 array(
924 'submissionid' => new external_value(PARAM_INT, 'Submission id'),
925 )
926 );
927 }
928
929
930 /**
931 * Retrieves the given submission.
932 *
933 * @param int $submissionid the submission id
934 * @return array containing the submission and warnings.
935 * @since Moodle 3.4
936 * @throws moodle_exception
937 */
938 public static function get_submission($submissionid) {
939 global $USER, $DB, $PAGE;
940
941 $params = self::validate_parameters(self::get_submission_parameters(), array('submissionid' => $submissionid));
942 $warnings = array();
943
944 // Get and validate the submission and workshop.
945 $submission = $DB->get_record('workshop_submissions', array('id' => $params['submissionid']), '*', MUST_EXIST);
946 list($workshop, $course, $cm, $context) = self::validate_workshop($submission->workshopid);
947
30b54b82 948 self::validate_submission($submission, $workshop);
6e2f4866 949
30b54b82
JL
950 $submission = self::prepare_submission_for_external($submission, $workshop);
951
952 $related = array('context' => $context);
953 $exporter = new submission_exporter($submission, $related);
954 return array(
955 'submission' => $exporter->export($PAGE->get_renderer('core')),
956 'warnings' => $warnings
957 );
958 }
959
960 /**
961 * Returns description of method result value
962 *
963 * @return external_description
964 * @since Moodle 3.4
965 */
966 public static function get_submission_returns() {
967 return new external_single_structure(
968 array(
969 'submission' => submission_exporter::get_read_structure(),
970 'warnings' => new external_warnings()
971 )
972 );
973 }
974
975 /**
976 * Helper method for validating if the current user can view the submission assessments.
977 *
978 * @param stdClass $submission submission object
979 * @param workshop $workshop workshop instance
980 * @return void
981 * @since Moodle 3.4
982 */
983 protected static function check_view_submission_assessments($submission, workshop $workshop) {
984 global $USER;
985
986 $ownsubmission = $submission->authorid == $USER->id;
987 $canview = has_capability('mod/workshop:viewallassessments', $workshop->context) ||
988 ($ownsubmission && $workshop->assessments_available());
6e2f4866
JL
989
990 if ($canview) {
991 // Here we should check if the user share group.
30b54b82
JL
992 if ($submission->authorid != $USER->id &&
993 !groups_user_groups_visible($workshop->course, $submission->authorid, $workshop->cm)) {
6e2f4866
JL
994 throw new moodle_exception('notingroup');
995 }
996 } else {
30b54b82 997 throw new moodle_exception('nopermissions', 'error', '', 'view assessment');
6e2f4866 998 }
30b54b82 999 }
6e2f4866 1000
30b54b82
JL
1001 /**
1002 * Helper method for returning the assessment data according the current user capabilities and current phase.
1003 *
1004 * @param stdClass $assessment the assessment data
1005 * @param workshop $workshop the workshop class
1006 * @return stdClass object with the assessment data filtered or null if is not viewable yet
1007 * @since Moodle 3.4
1008 */
1009 protected static function prepare_assessment_for_external($assessment, workshop $workshop) {
1010 global $USER;
1011 static $canviewallassessments = null;
1012 static $canviewreviewers = null;
1013 static $canoverridegrades = null;
1014
1015 // Remove all the properties that does not belong to the assessment table.
1016 $properties = assessment_exporter::properties_definition();
1017 foreach ($assessment as $key => $value) {
1018 if (!isset($properties[$key])) {
1019 unset($assessment->{$key});
1020 }
1021 }
1022
1023 if (is_null($canviewallassessments)) {
1024 $canviewallassessments = has_capability('mod/workshop:viewallassessments', $workshop->context);
1025 }
1026 if (is_null($canviewreviewers)) {
1027 $canviewreviewers = has_capability('mod/workshop:viewreviewernames', $workshop->context);
1028 }
1029 if (is_null($canoverridegrades)) {
1030 $canoverridegrades = has_capability('mod/workshop:overridegrades', $workshop->context);
1031 }
1032
1033 $isreviewer = $assessment->reviewerid == $USER->id;
1034
1035 if (!$isreviewer && is_null($assessment->grade) && !$canviewallassessments) {
1036 // Students do not see peer-assessment that are not graded yet.
1037 return null;
1038 }
1039
9e58617a
JL
1040 // Remove the feedback for the reviewer if the feedback phase is not valid or if we don't have enough permissions to see it.
1041 if ($workshop->phase < workshop::PHASE_EVALUATION || !($isreviewer || $canviewallassessments)) {
30b54b82
JL
1042 // Remove all the feedback information (all the optional fields).
1043 foreach ($properties as $attribute => $settings) {
1044 if (!empty($settings['optional'])) {
1045 unset($assessment->{$attribute});
1046 }
1047 }
1048 }
1049
1050 if (!$isreviewer && !$canviewreviewers) {
1051 $assessment->reviewerid = 0;
1052 }
1053
1054 return $assessment;
1055 }
1056
1057 /**
1058 * Returns the description of the external function parameters.
1059 *
1060 * @return external_function_parameters
1061 * @since Moodle 3.4
1062 */
1063 public static function get_submission_assessments_parameters() {
1064 return new external_function_parameters(
1065 array(
1066 'submissionid' => new external_value(PARAM_INT, 'Submission id'),
1067 )
1068 );
1069 }
1070
1071
1072 /**
1073 * Retrieves the given submission assessments.
1074 *
1075 * @param int $submissionid the submission id
1076 * @return array containing the assessments and warnings.
1077 * @since Moodle 3.4
1078 * @throws moodle_exception
1079 */
1080 public static function get_submission_assessments($submissionid) {
1081 global $USER, $DB, $PAGE;
1082
1083 $params = self::validate_parameters(self::get_submission_assessments_parameters(), array('submissionid' => $submissionid));
1084 $warnings = $assessments = array();
1085
1086 // Get and validate the submission and workshop.
1087 $submission = $DB->get_record('workshop_submissions', array('id' => $params['submissionid']), '*', MUST_EXIST);
1088 list($workshop, $course, $cm, $context) = self::validate_workshop($submission->workshopid);
1089
1090 // Check that we can get the assessments and get them.
1091 self::check_view_submission_assessments($submission, $workshop);
1092 $assessmentsrecords = $workshop->get_assessments_of_submission($submission->id);
6e2f4866
JL
1093
1094 $related = array('context' => $context);
30b54b82
JL
1095 foreach ($assessmentsrecords as $assessment) {
1096 $assessment = self::prepare_assessment_for_external($assessment, $workshop);
1097 if (empty($assessment)) {
1098 continue;
1099 }
1100 $exporter = new assessment_exporter($assessment, $related);
1101 $assessments[] = $exporter->export($PAGE->get_renderer('core'));
1102 }
1103
6e2f4866 1104 return array(
30b54b82 1105 'assessments' => $assessments,
6e2f4866
JL
1106 'warnings' => $warnings
1107 );
1108 }
1109
1110 /**
1111 * Returns description of method result value
1112 *
1113 * @return external_description
1114 * @since Moodle 3.4
1115 */
30b54b82 1116 public static function get_submission_assessments_returns() {
6e2f4866
JL
1117 return new external_single_structure(
1118 array(
30b54b82
JL
1119 'assessments' => new external_multiple_structure(
1120 assessment_exporter::get_read_structure()
1121 ),
6e2f4866
JL
1122 'warnings' => new external_warnings()
1123 )
1124 );
1125 }
b1e896cf
JL
1126
1127 /**
1128 * Returns the description of the external function parameters.
1129 *
1130 * @return external_function_parameters
1131 * @since Moodle 3.4
1132 */
1133 public static function get_assessment_parameters() {
1134 return new external_function_parameters(
1135 array(
1136 'assessmentid' => new external_value(PARAM_INT, 'Assessment id'),
1137 )
1138 );
1139 }
1140
1141
1142 /**
1143 * Retrieves the given assessment.
1144 *
1145 * @param int $assessmentid the assessment id
1146 * @return array containing the assessment and warnings.
1147 * @since Moodle 3.4
1148 * @throws moodle_exception
1149 */
1150 public static function get_assessment($assessmentid) {
1151 global $DB, $PAGE;
1152
1153 $params = self::validate_parameters(self::get_assessment_parameters(), array('assessmentid' => $assessmentid));
1154 $warnings = array();
1155
1156 // Get and validate the assessment, submission and workshop.
1157 $assessment = $DB->get_record('workshop_assessments', array('id' => $params['assessmentid']), '*', MUST_EXIST);
1158 $submission = $DB->get_record('workshop_submissions', array('id' => $assessment->submissionid), '*', MUST_EXIST);
1159 list($workshop, $course, $cm, $context) = self::validate_workshop($submission->workshopid);
1160
1161 // Check that we can get the assessment.
1162 $workshop->check_view_assessment($assessment, $submission);
1163
1164 $assessment = $workshop->get_assessment_by_id($assessment->id);
1165 $assessment = self::prepare_assessment_for_external($assessment, $workshop);
1166 if (empty($assessment)) {
1167 throw new moodle_exception('nopermissions', 'error', '', 'view assessment');
1168 }
1169 $related = array('context' => $context);
1170 $exporter = new assessment_exporter($assessment, $related);
1171
1172 return array(
1173 'assessment' => $exporter->export($PAGE->get_renderer('core')),
1174 'warnings' => $warnings
1175 );
1176 }
1177
1178 /**
1179 * Returns description of method result value
1180 *
1181 * @return external_description
1182 * @since Moodle 3.4
1183 */
1184 public static function get_assessment_returns() {
1185 return new external_single_structure(
1186 array(
1187 'assessment' => assessment_exporter::get_read_structure(),
1188 'warnings' => new external_warnings()
1189 )
1190 );
1191 }
46f5e9a0
JL
1192
1193 /**
1194 * Returns the description of the external function parameters.
1195 *
1196 * @return external_function_parameters
1197 * @since Moodle 3.4
1198 */
1199 public static function get_assessment_form_definition_parameters() {
1200 return new external_function_parameters(
1201 array(
1202 'assessmentid' => new external_value(PARAM_INT, 'Assessment id'),
1203 'mode' => new external_value(PARAM_ALPHA, 'The form mode (assessment or preview)', VALUE_DEFAULT, 'assessment'),
1204 )
1205 );
1206 }
1207
1208
1209 /**
1210 * Retrieves the assessment form definition (data required to be able to display the assessment form).
1211 *
1212 * @param int $assessmentid the assessment id
1213 * @param string $mode the form mode (assessment or preview)
1214 * @return array containing the assessment and warnings.
1215 * @since Moodle 3.4
1216 * @throws moodle_exception
1217 */
1218 public static function get_assessment_form_definition($assessmentid, $mode = 'assessment') {
1219 global $DB, $USER;
1220
1221 $params = self::validate_parameters(
1222 self::get_assessment_form_definition_parameters(), array('assessmentid' => $assessmentid, 'mode' => $mode)
1223 );
1224 $warnings = $pending = array();
1225
1226 if ($params['mode'] != 'assessment' && $params['mode'] != 'preview') {
1227 throw new invalid_parameter_exception('Invalid value for mode parameter (value: ' . $params['mode'] . ')');
1228 }
1229
1230 // Get and validate the assessment, submission and workshop.
1231 $assessment = $DB->get_record('workshop_assessments', array('id' => $params['assessmentid']), '*', MUST_EXIST);
1232 $submission = $DB->get_record('workshop_submissions', array('id' => $assessment->submissionid), '*', MUST_EXIST);
1233 list($workshop, $course, $cm, $context) = self::validate_workshop($submission->workshopid);
1234
2973f643
JL
1235 // Check we can view the assessment (so we can get the form data).
1236 $workshop->check_view_assessment($assessment, $submission);
46f5e9a0
JL
1237
1238 $cansetassessmentweight = has_capability('mod/workshop:allocate', $context);
1239 $pending = $workshop->get_pending_assessments_by_reviewer($assessment->reviewerid, $assessment->id);
1240
1241 // Retrieve the data from the strategy plugin.
1242 $strategy = $workshop->grading_strategy_instance();
1243 $strategyname = str_replace('_strategy', '', get_class($strategy)); // Get strategy name.
1244 $mform = $strategy->get_assessment_form(null, $params['mode'], $assessment, true,
1245 array('editableweight' => $cansetassessmentweight, 'pending' => !empty($pending)));
1246 $formdata = $mform->get_customdata();
1247
1248 $result = array(
1249 'dimenssionscount' => $formdata['nodims'],
1250 'descriptionfiles' => external_util::get_area_files($context->id, $strategyname, 'description'),
1251 'warnings' => $warnings
1252 );
1253 // Include missing dimension fields.
1254 for ($i = 0; $i < $formdata['nodims']; $i++) {
1255 $formdata['fields']->{'gradeid__idx_' . $i} = 0;
1256 $formdata['fields']->{'peercomment__idx_' . $i} = '';
1257 }
1258
1259 // Convert all the form data for external.
1260 foreach (array('options', 'fields', 'current') as $typeofdata) {
1261 $result[$typeofdata] = array();
1262
1263 if (!empty($formdata[$typeofdata])) {
1264 $alldata = (array) $formdata[$typeofdata];
1265 foreach ($alldata as $key => $val) {
1266 if (strpos($key, 'peercomment__idx_') === 0) {
1267 // Format reviewer comment.
1268 list($val, $format) = external_format_text($val, FORMAT_MOODLE, $context->id);
1269 } else if (strpos($key, 'description__idx_')) {
1270 // Format dimension description.
1271 $id = str_replace('description__idx_', '', $key);
1272 list($val, $format) = external_format_text($val, $alldata['dimensionid__idx_' . $id . 'format'],
1273 $context->id, $strategyname, 'description', $alldata['dimensionid__idx_' . $id]);
1274 }
1275 $result[$typeofdata][] = array(
1276 'name' => $key,
1277 'value' => $val
1278 );
1279 }
1280 }
1281 }
1282
1283 return $result;
1284 }
1285
1286 /**
1287 * Returns description of method result value
1288 *
1289 * @return external_description
1290 * @since Moodle 3.4
1291 */
1292 public static function get_assessment_form_definition_returns() {
1293 return new external_single_structure(
1294 array(
1295 'dimenssionscount' => new external_value(PARAM_INT, 'The number of dimenssions used by the form.'),
1296 'descriptionfiles' => new external_files('Files in the description text'),
1297 'options' => new external_multiple_structure(
1298 new external_single_structure(
1299 array(
1300 'name' => new external_value(PARAM_ALPHANUMEXT, 'Option name.'),
1301 'value' => new external_value(PARAM_NOTAGS, 'Option value.')
1302 )
1303 ), 'The form options.'
1304 ),
1305 'fields' => new external_multiple_structure(
1306 new external_single_structure(
1307 array(
1308 'name' => new external_value(PARAM_ALPHANUMEXT, 'Field name.'),
1309 'value' => new external_value(PARAM_RAW, 'Field default value.')
1310 )
1311 ), 'The form fields.'
1312 ),
1313 'current' => new external_multiple_structure(
1314 new external_single_structure(
1315 array(
1316 'name' => new external_value(PARAM_ALPHANUMEXT, 'Field name.'),
1317 'value' => new external_value(PARAM_RAW, 'Current field value.')
1318 )
1319 ), 'The current field values.'
1320 ),
1321 'warnings' => new external_warnings()
1322 )
1323 );
1324 }
aac70425
JL
1325
1326 /**
1327 * Returns the description of the external function parameters.
1328 *
1329 * @return external_function_parameters
1330 * @since Moodle 3.4
1331 */
1332 public static function get_reviewer_assessments_parameters() {
1333 return new external_function_parameters(
1334 array(
1335 'workshopid' => new external_value(PARAM_INT, 'Workshop instance id.'),
1336 'userid' => new external_value(PARAM_INT, 'User id who did the assessment review (empty or 0 for current user).',
1337 VALUE_DEFAULT, 0),
1338 )
1339 );
1340 }
1341
1342
1343 /**
1344 * Retrieves all the assessments reviewed by the given user.
1345 *
1346 * @param int $workshopid the workshop instance id
1347 * @param int $userid the reviewer user id
1348 * @return array containing the user assessments and warnings.
1349 * @since Moodle 3.4
1350 * @throws moodle_exception
1351 */
1352 public static function get_reviewer_assessments($workshopid, $userid = 0) {
1353 global $USER, $DB, $PAGE;
1354
1355 $params = self::validate_parameters(
1356 self::get_reviewer_assessments_parameters(), array('workshopid' => $workshopid, 'userid' => $userid)
1357 );
1358 $warnings = $assessments = array();
1359
1360 // Get and validate the submission and workshop.
1361 list($workshop, $course, $cm, $context) = self::validate_workshop($params['workshopid']);
1362
1363 // Extra checks so only users with permissions can view other users assessments.
1364 if (empty($params['userid']) || $params['userid'] == $USER->id) {
1365 $userid = $USER->id;
1366 list($assessed, $notice) = $workshop->check_examples_assessed_before_assessment($userid);
1367 if (!$assessed) {
1368 throw new moodle_exception($notice, 'mod_workshop');
1369 }
1370 if ($workshop->phase < workshop::PHASE_ASSESSMENT) { // Can view assessments only in assessment phase onwards.
1371 throw new moodle_exception('nopermissions', 'error', '', 'view assessments');
1372 }
1373 } else {
1374 require_capability('mod/workshop:viewallassessments', $context);
1375 $user = core_user::get_user($params['userid'], '*', MUST_EXIST);
1376 core_user::require_active_user($user);
1377 if (!$workshop->check_group_membership($user->id)) {
1378 throw new moodle_exception('notingroup');
1379 }
1380 $userid = $user->id;
1381 }
1382 // Now get all my assessments (includes those pending review).
1383 $assessmentsrecords = $workshop->get_assessments_by_reviewer($userid);
1384
1385 $related = array('context' => $context);
1386 foreach ($assessmentsrecords as $assessment) {
1387 $assessment = self::prepare_assessment_for_external($assessment, $workshop);
1388 if (empty($assessment)) {
1389 continue;
1390 }
1391 $exporter = new assessment_exporter($assessment, $related);
1392 $assessments[] = $exporter->export($PAGE->get_renderer('core'));
1393 }
1394
1395 return array(
1396 'assessments' => $assessments,
1397 'warnings' => $warnings
1398 );
1399 }
1400
1401 /**
1402 * Returns description of method result value
1403 *
1404 * @return external_description
1405 * @since Moodle 3.4
1406 */
1407 public static function get_reviewer_assessments_returns() {
1408 return new external_single_structure(
1409 array(
1410 'assessments' => new external_multiple_structure(
1411 assessment_exporter::get_read_structure()
1412 ),
1413 'warnings' => new external_warnings()
1414 )
1415 );
1416 }
fe966a27
JL
1417
1418 /**
1419 * Returns the description of the external function parameters.
1420 *
1421 * @return external_function_parameters
1422 * @since Moodle 3.4
1423 */
1424 public static function update_assessment_parameters() {
1425 return new external_function_parameters(
1426 array(
1427 'assessmentid' => new external_value(PARAM_INT, 'Assessment id.'),
1428 'data' => new external_multiple_structure (
1429 new external_single_structure(
1430 array(
1431 'name' => new external_value(PARAM_ALPHANUMEXT,
1432 'The assessment data (use WS get_assessment_form_definition for obtaining the data to sent).
1433 Apart from that data, you can optionally send:
1434 feedbackauthor (str); the feedback for the submission author
1435 feedbackauthorformat (int); the format of the feedbackauthor
1436 feedbackauthorinlineattachmentsid (int); the draft file area for the editor attachments
1437 feedbackauthorattachmentsid (int); the draft file area id for the feedback attachments'
1438 ),
1439 'value' => new external_value(PARAM_RAW, 'The value of the option.')
1440 )
1441 ), 'Assessment data'
1442 )
1443 )
1444 );
1445 }
1446
1447
1448 /**
1449 * Updates an assessment.
1450 *
1451 * @param int $assessmentid the assessment id
1452 * @param array $data the assessment data
1453 * @return array indicates if the assessment was updated, the new raw grade and possible warnings.
1454 * @since Moodle 3.4
1455 * @throws moodle_exception
1456 */
1457 public static function update_assessment($assessmentid, $data) {
1458 global $DB, $USER;
1459
1460 $params = self::validate_parameters(
1461 self::update_assessment_parameters(), array('assessmentid' => $assessmentid, 'data' => $data)
1462 );
1463 $warnings = array();
1464
1465 // Get and validate the assessment, submission and workshop.
1466 $assessment = $DB->get_record('workshop_assessments', array('id' => $params['assessmentid']), '*', MUST_EXIST);
1467 $submission = $DB->get_record('workshop_submissions', array('id' => $assessment->submissionid), '*', MUST_EXIST);
1468 list($workshop, $course, $cm, $context) = self::validate_workshop($submission->workshopid);
1469
1470 // Check we can edit the assessment.
1471 $workshop->check_edit_assessment($assessment, $submission);
1472
1473 // Process data.
1474 $data = new stdClass;
1475 $data->feedbackauthor_editor = array();
1476
1477 foreach ($params['data'] as $wsdata) {
1478 $name = trim($wsdata['name']);
1479 switch ($name) {
1480 case 'feedbackauthor':
1481 $data->feedbackauthor_editor['text'] = $wsdata['value'];
1482 break;
1483 case 'feedbackauthorformat':
1484 $data->feedbackauthor_editor['format'] = clean_param($wsdata['value'], PARAM_FORMAT);
1485 break;
1486 case 'feedbackauthorinlineattachmentsid':
1487 $data->feedbackauthor_editor['itemid'] = clean_param($wsdata['value'], PARAM_INT);
1488 break;
1489 case 'feedbackauthorattachmentsid':
1490 $data->feedbackauthorattachment_filemanager = clean_param($wsdata['value'], PARAM_INT);
1491 break;
1492 default:
1493 $data->{$wsdata['name']} = $wsdata['value']; // Validation will be done in the form->validation.
1494 }
1495 }
1496
1497 $cansetassessmentweight = has_capability('mod/workshop:allocate', $context);
1498 $pending = $workshop->get_pending_assessments_by_reviewer($assessment->reviewerid, $assessment->id);
1499 // Retrieve the data from the strategy plugin.
1500 $strategy = $workshop->grading_strategy_instance();
1501 $mform = $strategy->get_assessment_form(null, 'assessment', $assessment, true,
1502 array('editableweight' => $cansetassessmentweight, 'pending' => !empty($pending)));
1503
1504 $errors = $mform->validation((array) $data, array());
1505 // We can get several errors, return them in warnings.
1506 if (!empty($errors)) {
1507 $status = false;
1508 $rawgrade = null;
1509 foreach ($errors as $itemname => $message) {
1510 $warnings[] = array(
1511 'item' => $itemname,
1512 'itemid' => 0,
1513 'warningcode' => 'fielderror',
1514 'message' => s($message)
1515 );
1516 }
1517 } else {
1518 $rawgrade = $workshop->edit_assessment($assessment, $submission, $data, $strategy);
1519 $status = true;
1520 }
1521
1522 return array(
1523 'status' => $status,
1524 'rawgrade' => $rawgrade,
1525 'warnings' => $warnings,
1526 );
1527 }
1528
1529 /**
1530 * Returns description of method result value
1531 *
1532 * @return external_description
1533 * @since Moodle 3.4
1534 */
1535 public static function update_assessment_returns() {
1536 return new external_single_structure(
1537 array(
1538 'status' => new external_value(PARAM_BOOL, 'status: true if the assessment was added or updated false otherwise.'),
1539 'rawgrade' => new external_value(PARAM_FLOAT, 'Raw percentual grade (0.00000 to 100.00000) for submission.',
1540 VALUE_OPTIONAL),
1541 'warnings' => new external_warnings()
1542 )
1543 );
1544 }
d769f871
JL
1545
1546 /**
1547 * Returns the description of the external function parameters.
1548 *
1549 * @return external_external_function_parameters
1550 * @since Moodle 3.4
1551 */
1552 public static function get_grades_parameters() {
1553 return new external_function_parameters (
1554 array(
1555 'workshopid' => new external_value(PARAM_INT, 'Workshop instance id.'),
1556 'userid' => new external_value(PARAM_INT, 'User id (empty or 0 for current user).', VALUE_DEFAULT, 0),
1557 )
1558 );
1559 }
1560
1561 /**
1562 * Returns the grades information for the given workshop and user.
1563 *
1564 * @param int $workshopid workshop instance id
1565 * @param int $userid user id
1566 * @return array of warnings and the user plan
1567 * @since Moodle 3.4
1568 * @throws moodle_exception
1569 */
1570 public static function get_grades($workshopid, $userid = 0) {
1571 global $USER;
1572
1573 $params = array(
1574 'workshopid' => $workshopid,
1575 'userid' => $userid,
1576 );
1577 $params = self::validate_parameters(self::get_grades_parameters(), $params);
1578 $warnings = array();
1579
1580 list($workshop, $course, $cm, $context) = self::validate_workshop($params['workshopid']);
1581
1582 // Extra checks so only users with permissions can view other users plans.
1583 if (empty($params['userid']) || $params['userid'] == $USER->id) {
1584 $userid = $USER->id;
1585 } else {
1586 require_capability('mod/workshop:viewallassessments', $context);
1587 $user = core_user::get_user($params['userid'], '*', MUST_EXIST);
1588 core_user::require_active_user($user);
1589 if (!$workshop->check_group_membership($user->id)) {
1590 throw new moodle_exception('notingroup');
1591 }
1592 $userid = $user->id;
1593 }
1594
1595 $finalgrades = $workshop->get_gradebook_grades($userid);
1596
1597 $result = array('warnings' => $warnings);
1598 if ($finalgrades !== false) {
1599 if (!empty($finalgrades->submissiongrade)) {
1600 if (is_numeric($finalgrades->submissiongrade->grade)) {
1601 $result['submissionrawgrade'] = $finalgrades->submissiongrade->grade;
1602 }
1603 $result['submissionlongstrgrade'] = $finalgrades->submissiongrade->str_long_grade;
1604 $result['submissiongradehidden'] = $finalgrades->submissiongrade->hidden;
1605 }
1606 if (!empty($finalgrades->assessmentgrade)) {
1607 if (is_numeric($finalgrades->assessmentgrade->grade)) {
1608 $result['assessmentrawgrade'] = $finalgrades->assessmentgrade->grade;
1609 }
1610 $result['assessmentlongstrgrade'] = $finalgrades->assessmentgrade->str_long_grade;
1611 $result['assessmentgradehidden'] = $finalgrades->assessmentgrade->hidden;
1612 }
1613 }
1614
1615 return $result;
1616 }
1617
1618 /**
1619 * Returns description of method result value.
1620 *
1621 * @return external_single_structure
1622 * @since Moodle 3.4
1623 */
1624 public static function get_grades_returns() {
1625 return new external_single_structure(
1626 array(
1627 'assessmentrawgrade' => new external_value(PARAM_FLOAT, 'The assessment raw (numeric) grade.', VALUE_OPTIONAL),
1628 'assessmentlongstrgrade' => new external_value(PARAM_NOTAGS, 'The assessment string grade.', VALUE_OPTIONAL),
1629 'assessmentgradehidden' => new external_value(PARAM_BOOL, 'Whether the grade is hidden or not.', VALUE_OPTIONAL),
1630 'submissionrawgrade' => new external_value(PARAM_FLOAT, 'The submission raw (numeric) grade.', VALUE_OPTIONAL),
1631 'submissionlongstrgrade' => new external_value(PARAM_NOTAGS, 'The submission string grade.', VALUE_OPTIONAL),
1632 'submissiongradehidden' => new external_value(PARAM_BOOL, 'Whether the grade is hidden or not.', VALUE_OPTIONAL),
1633 'warnings' => new external_warnings(),
1634 )
1635 );
1636 }
9e58617a
JL
1637
1638 /**
1639 * Returns the description of the external function parameters.
1640 *
1641 * @return external_function_parameters
1642 * @since Moodle 3.4
1643 */
1644 public static function evaluate_assessment_parameters() {
1645 return new external_function_parameters(
1646 array(
1647 'assessmentid' => new external_value(PARAM_INT, 'Assessment id.'),
1648 'feedbacktext' => new external_value(PARAM_RAW, 'The feedback for the reviewer.', VALUE_DEFAULT, ''),
1649 'feedbackformat' => new external_value(PARAM_INT, 'The feedback format for text.', VALUE_DEFAULT, FORMAT_MOODLE),
1650 'weight' => new external_value(PARAM_INT, 'The new weight for the assessment.', VALUE_DEFAULT, 1),
1651 'gradinggradeover' => new external_value(PARAM_ALPHANUMEXT, 'The new grading grade.', VALUE_DEFAULT, ''),
1652 )
1653 );
1654 }
1655
1656
1657 /**
1658 * Evaluates an assessment (used by teachers for provide feedback to the reviewer).
1659 *
1660 * @param int $assessmentid the assessment id
1661 * @param str $feedbacktext the feedback for the reviewer
1662 * @param int $feedbackformat the feedback format for the reviewer text
1663 * @param int $weight the new weight for the assessment
1664 * @param mixed $gradinggradeover the new grading grade (empty for no overriding the grade)
1665 * @return array containing the status and warnings.
1666 * @since Moodle 3.4
1667 * @throws moodle_exception
1668 */
1669 public static function evaluate_assessment($assessmentid, $feedbacktext = '', $feedbackformat = FORMAT_MOODLE, $weight = 1,
1670 $gradinggradeover = '') {
1671 global $DB;
1672
1673 $params = self::validate_parameters(
1674 self::evaluate_assessment_parameters(),
1675 array(
1676 'assessmentid' => $assessmentid,
1677 'feedbacktext' => $feedbacktext,
1678 'feedbackformat' => $feedbackformat,
1679 'weight' => $weight,
1680 'gradinggradeover' => $gradinggradeover,
1681 )
1682 );
1683 $warnings = array();
1684
1685 // Get and validate the assessment, submission and workshop.
1686 $assessment = $DB->get_record('workshop_assessments', array('id' => $params['assessmentid']), '*', MUST_EXIST);
1687 $submission = $DB->get_record('workshop_submissions', array('id' => $assessment->submissionid), '*', MUST_EXIST);
1688 list($workshop, $course, $cm, $context) = self::validate_workshop($submission->workshopid);
1689
1690 // Check we can evaluate the assessment.
1691 $workshop->check_view_assessment($assessment, $submission);
1692 $cansetassessmentweight = has_capability('mod/workshop:allocate', $context);
1693 $canoverridegrades = has_capability('mod/workshop:overridegrades', $context);
1694 if (!$canoverridegrades && !$cansetassessmentweight) {
1695 throw new moodle_exception('nopermissions', 'error', '', 'evaluate assessments');
1696 }
1697
1698 // Process data.
1699 $data = new stdClass;
1700 $data->asid = $assessment->id;
1701 $data->feedbackreviewer_editor = array(
1702 'text' => $params['feedbacktext'],
1703 'format' => $params['feedbackformat'],
1704 );
1705 $data->weight = $params['weight'];
1706 $data->gradinggradeover = $params['gradinggradeover'];
1707
1708 $options = array(
1709 'editable' => true,
1710 'editableweight' => $cansetassessmentweight,
1711 'overridablegradinggrade' => $canoverridegrades
1712 );
1713 $feedbackform = $workshop->get_feedbackreviewer_form(null, $assessment, $options);
1714
1715 $errors = $feedbackform->validation((array) $data, array());
1716 // We can get several errors, return them in warnings.
1717 if (!empty($errors)) {
1718 $status = false;
1719 foreach ($errors as $itemname => $message) {
1720 $warnings[] = array(
1721 'item' => $itemname,
1722 'itemid' => 0,
1723 'warningcode' => 'fielderror',
1724 'message' => s($message)
1725 );
1726 }
1727 } else {
1728 $workshop->evaluate_assessment($assessment, $data, $cansetassessmentweight, $canoverridegrades);
1729 $status = true;
1730 }
1731
1732 return array(
1733 'status' => $status,
1734 'warnings' => $warnings,
1735 );
1736 }
1737
1738 /**
1739 * Returns description of method result value
1740 *
1741 * @return external_description
1742 * @since Moodle 3.4
1743 */
1744 public static function evaluate_assessment_returns() {
1745 return new external_single_structure(
1746 array(
1747 'status' => new external_value(PARAM_BOOL, 'status: true if the assessment was evaluated, false otherwise.'),
1748 'warnings' => new external_warnings()
1749 )
1750 );
1751 }
4d201b82
JL
1752
1753 /**
1754 * Returns description of method parameters
1755 *
1756 * @return external_function_parameters
1757 * @since Moodle 3.4
1758 */
1759 public static function get_grades_report_parameters() {
1760 return new external_function_parameters(
1761 array(
1762 'workshopid' => new external_value(PARAM_INT, 'Workshop instance id.'),
1763 'groupid' => new external_value(PARAM_INT, 'Group id, 0 means that the function will determine the user group.',
1764 VALUE_DEFAULT, 0),
1765 'sortby' => new external_value(PARAM_ALPHA, 'sort by this element: lastname, firstname, submissiontitle,
1766 submissionmodified, submissiongrade, gradinggrade.', VALUE_DEFAULT, 'lastname'),
1767 'sortdirection' => new external_value(PARAM_ALPHA, 'sort direction: ASC or DESC', VALUE_DEFAULT, 'ASC'),
1768 'page' => new external_value(PARAM_INT, 'The page of records to return.', VALUE_DEFAULT, 0),
1769 'perpage' => new external_value(PARAM_INT, 'The number of records to return per page.', VALUE_DEFAULT, 0),
1770 )
1771 );
1772 }
1773
1774 /**
1775 * Retrieves the assessment grades report.
1776 *
1777 * @param int $workshopid the workshop instance id
1778 * @param int $groupid (optional) group id, 0 means that the function will determine the user group
1779 * @param string $sortby sort by this element
1780 * @param string $sortdirection sort direction: ASC or DESC
1781 * @param int $page page of records to return
1782 * @param int $perpage number of records to return per page
1783 * @return array of warnings and the report data
1784 * @since Moodle 3.4
1785 * @throws moodle_exception
1786 */
1787 public static function get_grades_report($workshopid, $groupid = 0, $sortby = 'lastname', $sortdirection = 'ASC',
1788 $page = 0, $perpage = 0) {
1789 global $USER;
1790
1791 $params = array('workshopid' => $workshopid, 'groupid' => $groupid, 'sortby' => $sortby, 'sortdirection' => $sortdirection,
1792 'page' => $page, 'perpage' => $perpage);
1793 $params = self::validate_parameters(self::get_grades_report_parameters(), $params);
1794 $submissions = $warnings = array();
1795
1796 $sortallowedvalues = array('lastname', 'firstname', 'submissiontitle', 'submissionmodified', 'submissiongrade',
1797 'gradinggrade');
1798 if (!in_array($params['sortby'], $sortallowedvalues)) {
1799 throw new invalid_parameter_exception('Invalid value for sortby parameter (value: ' . $sortby . '),' .
1800 'allowed values are: ' . implode(',', $sortallowedvalues));
1801 }
1802
1803 $sortdirection = strtoupper($params['sortdirection']);
1804 $directionallowedvalues = array('ASC', 'DESC');
1805 if (!in_array($sortdirection, $directionallowedvalues)) {
1806 throw new invalid_parameter_exception('Invalid value for sortdirection parameter (value: ' . $sortdirection . '),' .
1807 'allowed values are: ' . implode(',', $directionallowedvalues));
1808 }
1809
1810 list($workshop, $course, $cm, $context) = self::validate_workshop($params['workshopid']);
1811 require_capability('mod/workshop:viewallassessments', $context);
1812
1813 if (!empty($params['groupid'])) {
1814 $groupid = $params['groupid'];
1815 // Determine is the group is visible to user.
1816 if (!groups_group_visible($groupid, $course, $cm)) {
1817 throw new moodle_exception('notingroup');
1818 }
1819 } else {
1820 // Check to see if groups are being used here.
1821 if ($groupmode = groups_get_activity_groupmode($cm)) {
1822 $groupid = groups_get_activity_group($cm);
1823 // Determine is the group is visible to user (this is particullary for the group 0 -> all groups).
1824 if (!groups_group_visible($groupid, $course, $cm)) {
1825 throw new moodle_exception('notingroup');
1826 }
1827 } else {
1828 $groupid = 0;
1829 }
1830 }
1831
1832 if ($workshop->phase >= workshop::PHASE_SUBMISSION) {
1833 $showauthornames = has_capability('mod/workshop:viewauthornames', $context);
1834 $showreviewernames = has_capability('mod/workshop:viewreviewernames', $context);
1835
1836 if ($workshop->phase >= workshop::PHASE_EVALUATION) {
1837 $showsubmissiongrade = true;
1838 $showgradinggrade = true;
1839 } else {
1840 $showsubmissiongrade = false;
1841 $showgradinggrade = false;
1842 }
1843
1844 $data = $workshop->prepare_grading_report_data($USER->id, $groupid, $params['page'], $params['perpage'],
1845 $params['sortby'], $sortdirection);
1846
1847 if (!empty($data)) {
1848 // Populate the display options for the submissions report.
1849 $reportopts = new stdclass();
1850 $reportopts->showauthornames = $showauthornames;
1851 $reportopts->showreviewernames = $showreviewernames;
1852 $reportopts->sortby = $params['sortby'];
1853 $reportopts->sorthow = $sortdirection;
1854 $reportopts->showsubmissiongrade = $showsubmissiongrade;
1855 $reportopts->showgradinggrade = $showgradinggrade;
1856 $reportopts->workshopphase = $workshop->phase;
1857
1858 $report = new workshop_grading_report($data, $reportopts);
1859 return array(
1860 'report' => $report->export_data_for_external(),
1861 'warnings' => array(),
1862 );
1863 }
1864 }
1865 throw new moodle_exception('nothingfound', 'workshop');
1866 }
1867
1868 /**
1869 * Returns description of method result value
1870 *
1871 * @return external_description
1872 * @since Moodle 3.4
1873 */
1874 public static function get_grades_report_returns() {
1875
1876 $reviewstructure = new external_single_structure(
1877 array(
1878 'userid' => new external_value(PARAM_INT, 'The id of the user (0 when is configured to do not display names).'),
1879 'assessmentid' => new external_value(PARAM_INT, 'The id of the assessment.'),
1880 'submissionid' => new external_value(PARAM_INT, 'The id of the submission assessed.'),
1881 'grade' => new external_value(PARAM_FLOAT, 'The grade for submission.'),
1882 'gradinggrade' => new external_value(PARAM_FLOAT, 'The grade for assessment.'),
1883 'gradinggradeover' => new external_value(PARAM_FLOAT, 'The aggregated grade overrided.'),
1884 'weight' => new external_value(PARAM_INT, 'The weight of the assessment for aggregation.'),
1885 )
1886 );
1887
1888 return new external_single_structure(
1889 array(
1890 'report' => new external_single_structure(
1891 array(
1892 'grades' => new external_multiple_structure(
1893 new external_single_structure(
1894 array(
1895 'userid' => new external_value(PARAM_INT, 'The id of the user being displayed in the report.'),
1896 'submissionid' => new external_value(PARAM_INT, 'Submission id.'),
1897 'submissiontitle' => new external_value(PARAM_RAW, 'Submission title.'),
1898 'submissionmodified' => new external_value(PARAM_INT, 'Timestamp submission was updated.'),
1899 'submissiongrade' => new external_value(PARAM_FLOAT, 'Aggregated grade for the submission.',
1900 VALUE_OPTIONAL),
1901 'gradinggrade' => new external_value(PARAM_FLOAT, 'Computed grade for the assessment.',
1902 VALUE_OPTIONAL),
1903 'submissiongradeover' => new external_value(PARAM_FLOAT, 'Grade for the assessment overrided
1904 by the teacher.', VALUE_OPTIONAL),
1905 'submissiongradeoverby' => new external_value(PARAM_INT, 'The id of the user who overrided
1906 the grade.', VALUE_OPTIONAL),
1907 'submissionpublished' => new external_value(PARAM_INT, 'Whether is a submission published.',
1908 VALUE_OPTIONAL),
1909 'reviewedby' => new external_multiple_structure($reviewstructure, 'The users who reviewed the
1910 user submission.', VALUE_OPTIONAL),
1911 'reviewerof' => new external_multiple_structure($reviewstructure, 'The assessments the user
1912 reviewed.', VALUE_OPTIONAL),
1913 )
1914 )
1915 ),
1916 'totalcount' => new external_value(PARAM_INT, 'Number of total submissions.'),
1917 )
1918 ),
1919 'warnings' => new external_warnings()
1920 )
1921 );
1922 }
b99070b9
JL
1923
1924 /**
1925 * Describes the parameters for view_submission.
1926 *
1927 * @return external_function_parameters
1928 * @since Moodle 3.4
1929 */
1930 public static function view_submission_parameters() {
1931 return new external_function_parameters (
1932 array(
1933 'submissionid' => new external_value(PARAM_INT, 'Submission id'),
1934 )
1935 );
1936 }
1937
1938 /**
1939 * Trigger the submission viewed event.
1940 *
1941 * @param int $submissionid submission id
1942 * @return array of warnings and status result
1943 * @since Moodle 3.4
1944 * @throws moodle_exception
1945 */
1946 public static function view_submission($submissionid) {
1947 global $DB;
1948
1949 $params = self::validate_parameters(self::view_submission_parameters(), array('submissionid' => $submissionid));
1950 $warnings = array();
1951
1952 // Get and validate the submission and workshop.
1953 $submission = $DB->get_record('workshop_submissions', array('id' => $params['submissionid']), '*', MUST_EXIST);
1954 list($workshop, $course, $cm, $context) = self::validate_workshop($submission->workshopid);
1955
1956 self::validate_submission($submission, $workshop);
1957
1958 $workshop->set_submission_viewed($submission);
1959
1960 $result = array(
1961 'status' => true,
1962 'warnings' => $warnings,
1963 );
1964 return $result;
1965 }
1966
1967 /**
1968 * Describes the view_submission return value.
1969 *
1970 * @return external_single_structure
1971 * @since Moodle 3.4
1972 */
1973 public static function view_submission_returns() {
1974 return new external_single_structure(
1975 array(
1976 'status' => new external_value(PARAM_BOOL, 'status: true if success'),
1977 'warnings' => new external_warnings(),
1978 )
1979 );
1980 }
012c2b84
JL
1981
1982 /**
1983 * Returns the description of the external function parameters.
1984 *
1985 * @return external_function_parameters
1986 * @since Moodle 3.4
1987 */
1988 public static function evaluate_submission_parameters() {
1989 return new external_function_parameters(
1990 array(
1991 'submissionid' => new external_value(PARAM_INT, 'submission id.'),
1992 'feedbacktext' => new external_value(PARAM_RAW, 'The feedback for the author.', VALUE_DEFAULT, ''),
1993 'feedbackformat' => new external_value(PARAM_INT, 'The feedback format for text.', VALUE_DEFAULT, FORMAT_MOODLE),
1994 'published' => new external_value(PARAM_BOOL, 'Publish the submission for others?.', VALUE_DEFAULT, false),
1995 'gradeover' => new external_value(PARAM_ALPHANUMEXT, 'The new submission grade.', VALUE_DEFAULT, ''),
1996 )
1997 );
1998 }
1999
2000
2001 /**
2002 * Evaluates a submission (used by teachers for provide feedback or override the submission grade).
2003 *
2004 * @param int $submissionid the submission id
2005 * @param str $feedbacktext the feedback for the author
2006 * @param int $feedbackformat the feedback format for the reviewer text
2007 * @param bool $published whether to publish the submission for other users
2008 * @param mixed $gradeover the new submission grade (empty for no overriding the grade)
2009 * @return array containing the status and warnings.
2010 * @since Moodle 3.4
2011 * @throws moodle_exception
2012 */
2013 public static function evaluate_submission($submissionid, $feedbacktext = '', $feedbackformat = FORMAT_MOODLE, $published = 1,
2014 $gradeover = '') {
2015 global $DB;
2016
2017 $params = self::validate_parameters(
2018 self::evaluate_submission_parameters(),
2019 array(
2020 'submissionid' => $submissionid,
2021 'feedbacktext' => $feedbacktext,
2022 'feedbackformat' => $feedbackformat,
2023 'published' => $published,
2024 'gradeover' => $gradeover,
2025 )
2026 );
2027 $warnings = array();
2028
2029 // Get and validate the submission, submission and workshop.
2030 $submission = $DB->get_record('workshop_submissions', array('id' => $params['submissionid']), '*', MUST_EXIST);
2031 list($workshop, $course, $cm, $context) = self::validate_workshop($submission->workshopid);
2032
2033 // Check we can evaluate the submission.
2034 self::validate_submission($submission, $workshop);
2035 $canpublish = has_capability('mod/workshop:publishsubmissions', $context);
2036 $canoverride = ($workshop->phase == workshop::PHASE_EVALUATION &&
2037 has_capability('mod/workshop:overridegrades', $context));
2038
2039 if (!$canpublish && !$canoverride) {
2040 throw new moodle_exception('nopermissions', 'error', '', 'evaluate submission');
2041 }
2042
2043 // Process data.
2044 $data = new stdClass;
2045 $data->id = $submission->id;
2046 $data->feedbackauthor_editor = array(
2047 'text' => $params['feedbacktext'],
2048 'format' => $params['feedbackformat'],
2049 );
2050 $data->published = $params['published'];
2051 $data->gradeover = $params['gradeover'];
2052
2053 $options = array(
2054 'editable' => true,
2055 'editablepublished' => $canpublish,
2056 'overridablegrade' => $canoverride
2057 );
2058 $feedbackform = $workshop->get_feedbackauthor_form(null, $submission, $options);
2059
2060 $errors = $feedbackform->validation((array) $data, array());
2061 // We can get several errors, return them in warnings.
2062 if (!empty($errors)) {
2063 $status = false;
2064 foreach ($errors as $itemname => $message) {
2065 $warnings[] = array(
2066 'item' => $itemname,
2067 'itemid' => 0,
2068 'warningcode' => 'fielderror',
2069 'message' => s($message)
2070 );
2071 }
2072 } else {
2073 $workshop->evaluate_submission($submission, $data, $canpublish, $canoverride);
2074 $status = true;
2075 }
2076
2077 return array(
2078 'status' => $status,
2079 'warnings' => $warnings,
2080 );
2081 }
2082
2083 /**
2084 * Returns description of method result value
2085 *
2086 * @return external_description
2087 * @since Moodle 3.4
2088 */
2089 public static function evaluate_submission_returns() {
2090 return new external_single_structure(
2091 array(
2092 'status' => new external_value(PARAM_BOOL, 'status: true if the submission was evaluated, false otherwise.'),
2093 'warnings' => new external_warnings()
2094 )
2095 );
2096 }
9f1ab2db 2097}