2 // This file is part of Moodle - http://moodle.org/
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.
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.
14 // You should have received a copy of the GNU General Public License
15 // along with Moodle. If not, see <http://www.gnu.org/licenses/>.
17 use mod_feedback\external\feedback_summary_exporter
;
18 use mod_feedback\external\feedback_completedtmp_exporter
;
19 use mod_feedback\external\feedback_item_exporter
;
20 use mod_feedback\external\feedback_valuetmp_exporter
;
21 use mod_feedback\external\feedback_value_exporter
;
22 use mod_feedback\external\feedback_completed_exporter
;
23 use core_external\external_api
;
24 use core_external\external_function_parameters
;
25 use core_external\external_multiple_structure
;
26 use core_external\external_single_structure
;
27 use core_external\external_value
;
28 use core_external\external_warnings
;
29 use core_external\util
;
32 * Feedback external functions
34 * @package mod_feedback
36 * @copyright 2017 Juan Leyva <juan@moodle.com>
37 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
40 class mod_feedback_external
extends external_api
{
43 * Describes the parameters for get_feedbacks_by_courses.
45 * @return external_function_parameters
48 public static function get_feedbacks_by_courses_parameters() {
49 return new external_function_parameters (
51 'courseids' => new external_multiple_structure(
52 new external_value(PARAM_INT
, 'Course id'), 'Array of course ids', VALUE_DEFAULT
, array()
59 * Returns a list of feedbacks in a provided list of courses.
60 * If no list is provided all feedbacks that the user can view will be returned.
62 * @param array $courseids course ids
63 * @return array of warnings and feedbacks
66 public static function get_feedbacks_by_courses($courseids = array()) {
70 $returnedfeedbacks = array();
73 'courseids' => $courseids,
75 $params = self
::validate_parameters(self
::get_feedbacks_by_courses_parameters(), $params);
78 if (empty($params['courseids'])) {
79 $mycourses = enrol_get_my_courses();
80 $params['courseids'] = array_keys($mycourses);
83 // Ensure there are courseids to loop through.
84 if (!empty($params['courseids'])) {
86 list($courses, $warnings) = util
::validate_courses($params['courseids'], $mycourses);
87 $output = $PAGE->get_renderer('core');
89 // Get the feedbacks in this course, this function checks users visibility permissions.
90 // We can avoid then additional validate_context calls.
91 $feedbacks = get_all_instances_in_courses("feedback", $courses);
92 foreach ($feedbacks as $feedback) {
94 $context = context_module
::instance($feedback->coursemodule
);
96 // Remove fields that are not from the feedback (added by get_all_instances_in_courses).
97 unset($feedback->coursemodule
, $feedback->context
, $feedback->visible
, $feedback->section
, $feedback->groupmode
,
98 $feedback->groupingid
);
100 // Check permissions.
101 if (!has_capability('mod/feedback:edititems', $context)) {
102 // Don't return the optional properties.
103 $properties = feedback_summary_exporter
::properties_definition();
104 foreach ($properties as $property => $config) {
105 if (!empty($config['optional'])) {
106 unset($feedback->{$property});
110 $exporter = new feedback_summary_exporter($feedback, array('context' => $context));
111 $returnedfeedbacks[] = $exporter->export($output);
116 'feedbacks' => $returnedfeedbacks,
117 'warnings' => $warnings
123 * Describes the get_feedbacks_by_courses return value.
125 * @return external_single_structure
128 public static function get_feedbacks_by_courses_returns() {
129 return new external_single_structure(
131 'feedbacks' => new external_multiple_structure(
132 feedback_summary_exporter
::get_read_structure()
134 'warnings' => new external_warnings(),
140 * Utility function for validating a feedback.
142 * @param int $feedbackid feedback instance id
143 * @param int $courseid courseid course where user completes the feedback (for site feedbacks only)
144 * @return array containing the feedback, feedback course, context, course module and the course where is being completed.
145 * @throws moodle_exception
148 protected static function validate_feedback($feedbackid, $courseid = 0) {
151 // Request and permission validation.
152 $feedback = $DB->get_record('feedback', array('id' => $feedbackid), '*', MUST_EXIST
);
153 list($feedbackcourse, $cm) = get_course_and_cm_from_instance($feedback, 'feedback');
155 $context = context_module
::instance($cm->id
);
156 self
::validate_context($context);
158 // Set default completion course.
159 $completioncourse = (object) array('id' => 0);
160 if ($feedbackcourse->id
== SITEID
&& $courseid) {
161 $completioncourse = get_course($courseid);
162 self
::validate_context(context_course
::instance($courseid));
164 $feedbackcompletion = new mod_feedback_completion($feedback, $cm, $courseid);
165 if (!$feedbackcompletion->check_course_is_mapped()) {
166 throw new moodle_exception('cannotaccess', 'mod_feedback');
170 return array($feedback, $feedbackcourse, $cm, $context, $completioncourse);
174 * Utility function for validating access to feedback.
176 * @param stdClass $feedback feedback object
177 * @param stdClass $course course where user completes the feedback (for site feedbacks only)
178 * @param stdClass $cm course module
179 * @param stdClass $context context object
180 * @throws moodle_exception
181 * @return mod_feedback_completion feedback completion instance
184 protected static function validate_feedback_access($feedback, $course, $cm, $context, $checksubmit = false) {
185 $feedbackcompletion = new mod_feedback_completion($feedback, $cm, $course->id
);
187 if (!$feedbackcompletion->can_complete()) {
188 throw new required_capability_exception($context, 'mod/feedback:complete', 'nopermission', '');
191 if (!$feedbackcompletion->is_open()) {
192 throw new moodle_exception('feedback_is_not_open', 'feedback');
195 if ($feedbackcompletion->is_empty()) {
196 throw new moodle_exception('no_items_available_yet', 'feedback');
199 if ($checksubmit && !$feedbackcompletion->can_submit()) {
200 throw new moodle_exception('this_feedback_is_already_submitted', 'feedback');
202 return $feedbackcompletion;
206 * Describes the parameters for get_feedback_access_information.
208 * @return external_external_function_parameters
211 public static function get_feedback_access_information_parameters() {
212 return new external_function_parameters (
214 'feedbackid' => new external_value(PARAM_INT
, 'Feedback instance id.'),
215 'courseid' => new external_value(PARAM_INT
, 'Course where user completes the feedback (for site feedbacks only).',
222 * Return access information for a given feedback.
224 * @param int $feedbackid feedback instance id
225 * @param int $courseid course where user completes the feedback (for site feedbacks only)
226 * @return array of warnings and the access information
228 * @throws moodle_exception
230 public static function get_feedback_access_information($feedbackid, $courseid = 0) {
234 'feedbackid' => $feedbackid,
235 'courseid' => $courseid,
237 $params = self
::validate_parameters(self
::get_feedback_access_information_parameters(), $params);
239 list($feedback, $course, $cm, $context, $completioncourse) = self
::validate_feedback($params['feedbackid'],
240 $params['courseid']);
241 $feedbackcompletion = new mod_feedback_completion($feedback, $cm, $completioncourse->id
);
244 // Capabilities first.
245 $result['canviewanalysis'] = $feedbackcompletion->can_view_analysis();
246 $result['cancomplete'] = $feedbackcompletion->can_complete();
247 $result['cansubmit'] = $feedbackcompletion->can_submit();
248 $result['candeletesubmissions'] = has_capability('mod/feedback:deletesubmissions', $context);
249 $result['canviewreports'] = has_capability('mod/feedback:viewreports', $context);
250 $result['canedititems'] = has_capability('mod/feedback:edititems', $context);
252 // Status information.
253 $result['isempty'] = $feedbackcompletion->is_empty();
254 $result['isopen'] = $feedbackcompletion->is_open();
255 $anycourse = ($course->id
== SITEID
);
256 $result['isalreadysubmitted'] = $feedbackcompletion->is_already_submitted($anycourse);
257 $result['isanonymous'] = $feedbackcompletion->is_anonymous();
259 $result['warnings'] = [];
264 * Describes the get_feedback_access_information return value.
266 * @return external_single_structure
269 public static function get_feedback_access_information_returns() {
270 return new external_single_structure(
272 'canviewanalysis' => new external_value(PARAM_BOOL
, 'Whether the user can view the analysis or not.'),
273 'cancomplete' => new external_value(PARAM_BOOL
, 'Whether the user can complete the feedback or not.'),
274 'cansubmit' => new external_value(PARAM_BOOL
, 'Whether the user can submit the feedback or not.'),
275 'candeletesubmissions' => new external_value(PARAM_BOOL
, 'Whether the user can delete submissions or not.'),
276 'canviewreports' => new external_value(PARAM_BOOL
, 'Whether the user can view the feedback reports or not.'),
277 'canedititems' => new external_value(PARAM_BOOL
, 'Whether the user can edit feedback items or not.'),
278 'isempty' => new external_value(PARAM_BOOL
, 'Whether the feedback has questions or not.'),
279 'isopen' => new external_value(PARAM_BOOL
, 'Whether the feedback has active access time restrictions or not.'),
280 'isalreadysubmitted' => new external_value(PARAM_BOOL
, 'Whether the feedback is already submitted or not.'),
281 'isanonymous' => new external_value(PARAM_BOOL
, 'Whether the feedback is anonymous or not.'),
282 'warnings' => new external_warnings(),
288 * Describes the parameters for view_feedback.
290 * @return external_function_parameters
293 public static function view_feedback_parameters() {
294 return new external_function_parameters (
296 'feedbackid' => new external_value(PARAM_INT
, 'Feedback instance id'),
297 'moduleviewed' => new external_value(PARAM_BOOL
, 'If we need to mark the module as viewed for completion',
298 VALUE_DEFAULT
, false),
299 'courseid' => new external_value(PARAM_INT
, 'Course where user completes the feedback (for site feedbacks only).',
306 * Trigger the course module viewed event and update the module completion status.
308 * @param int $feedbackid feedback instance id
309 * @param bool $moduleviewed If we need to mark the module as viewed for completion
310 * @param int $courseid course where user completes the feedback (for site feedbacks only)
311 * @return array of warnings and status result
313 * @throws moodle_exception
315 public static function view_feedback($feedbackid, $moduleviewed = false, $courseid = 0) {
317 $params = array('feedbackid' => $feedbackid, 'moduleviewed' => $moduleviewed, 'courseid' => $courseid);
318 $params = self
::validate_parameters(self
::view_feedback_parameters(), $params);
321 list($feedback, $course, $cm, $context, $completioncourse) = self
::validate_feedback($params['feedbackid'],
322 $params['courseid']);
323 $feedbackcompletion = new mod_feedback_completion($feedback, $cm, $completioncourse->id
);
325 // Trigger module viewed event.
326 $feedbackcompletion->trigger_module_viewed();
327 if ($params['moduleviewed']) {
328 if (!$feedbackcompletion->is_open()) {
329 throw new moodle_exception('feedback_is_not_open', 'feedback');
331 // Mark activity viewed for completion-tracking.
332 $feedbackcompletion->set_module_viewed();
337 'warnings' => $warnings,
343 * Describes the view_feedback return value.
345 * @return external_single_structure
348 public static function view_feedback_returns() {
349 return new external_single_structure(
351 'status' => new external_value(PARAM_BOOL
, 'status: true if success'),
352 'warnings' => new external_warnings(),
358 * Describes the parameters for get_current_completed_tmp.
360 * @return external_function_parameters
363 public static function get_current_completed_tmp_parameters() {
364 return new external_function_parameters (
366 'feedbackid' => new external_value(PARAM_INT
, 'Feedback instance id'),
367 'courseid' => new external_value(PARAM_INT
, 'Course where user completes the feedback (for site feedbacks only).',
374 * Returns the temporary completion record for the current user.
376 * @param int $feedbackid feedback instance id
377 * @param int $courseid course where user completes the feedback (for site feedbacks only)
378 * @return array of warnings and status result
380 * @throws moodle_exception
382 public static function get_current_completed_tmp($feedbackid, $courseid = 0) {
385 $params = array('feedbackid' => $feedbackid, 'courseid' => $courseid);
386 $params = self
::validate_parameters(self
::get_current_completed_tmp_parameters(), $params);
389 list($feedback, $course, $cm, $context, $completioncourse) = self
::validate_feedback($params['feedbackid'],
390 $params['courseid']);
391 $feedbackcompletion = new mod_feedback_completion($feedback, $cm, $completioncourse->id
);
393 if ($completed = $feedbackcompletion->get_current_completed_tmp()) {
394 $exporter = new feedback_completedtmp_exporter($completed);
396 'feedback' => $exporter->export($PAGE->get_renderer('core')),
397 'warnings' => $warnings,
400 throw new moodle_exception('not_started', 'feedback');
404 * Describes the get_current_completed_tmp return value.
406 * @return external_single_structure
409 public static function get_current_completed_tmp_returns() {
410 return new external_single_structure(
412 'feedback' => feedback_completedtmp_exporter
::get_read_structure(),
413 'warnings' => new external_warnings(),
419 * Describes the parameters for get_items.
421 * @return external_function_parameters
424 public static function get_items_parameters() {
425 return new external_function_parameters (
427 'feedbackid' => new external_value(PARAM_INT
, 'Feedback instance id'),
428 'courseid' => new external_value(PARAM_INT
, 'Course where user completes the feedback (for site feedbacks only).',
435 * Returns the items (questions) in the given feedback.
437 * @param int $feedbackid feedback instance id
438 * @param int $courseid course where user completes the feedback (for site feedbacks only)
439 * @return array of warnings and feedbacks
442 public static function get_items($feedbackid, $courseid = 0) {
445 $params = array('feedbackid' => $feedbackid, 'courseid' => $courseid);
446 $params = self
::validate_parameters(self
::get_items_parameters(), $params);
448 $returneditems = array();
450 list($feedback, $course, $cm, $context, $completioncourse) = self
::validate_feedback($params['feedbackid'],
451 $params['courseid']);
453 $userhasaccess = true;
455 // Check the user has access to the feedback.
456 self
::validate_feedback_access($feedback, $completioncourse, $cm, $context, true);
457 } catch (moodle_exception
$e) {
458 $userhasaccess = false;
460 'item' => $feedback->id
,
461 'warningcode' => clean_param($e->errorcode
, PARAM_ALPHANUM
),
462 'message' => $e->getMessage(),
466 // For consistency with the web behaviour, the items should be returned only when the user can edit or view reports (to
467 // include non-editing teachers too).
469 'mod/feedback:edititems',
470 'mod/feedback:viewreports',
472 if ($userhasaccess ||
has_any_capability($capabilities, $context)) {
473 // Remove previous warnings because, although the user might not have access, they have the proper capability.
475 $feedbackstructure = new mod_feedback_structure($feedback, $cm, $completioncourse->id
);
476 if ($items = $feedbackstructure->get_items()) {
477 foreach ($items as $item) {
478 $itemnumber = empty($item->itemnr
) ?
null : $item->itemnr
;
479 unset($item->itemnr
); // Added by the function, not part of the record.
480 $exporter = new feedback_item_exporter($item, array('context' => $context, 'itemnumber' => $itemnumber));
481 $returneditems[] = $exporter->export($PAGE->get_renderer('core'));
484 } else if ($userhasaccess) {
486 'item' => $feedback->id
,
487 'warningcode' => 'nopermission',
488 'message' => 'nopermission',
493 'items' => $returneditems,
494 'warnings' => $warnings
500 * Describes the get_items return value.
502 * @return external_single_structure
505 public static function get_items_returns() {
506 return new external_single_structure(
508 'items' => new external_multiple_structure(
509 feedback_item_exporter
::get_read_structure()
511 'warnings' => new external_warnings(),
517 * Describes the parameters for launch_feedback.
519 * @return external_function_parameters
522 public static function launch_feedback_parameters() {
523 return new external_function_parameters (
525 'feedbackid' => new external_value(PARAM_INT
, 'Feedback instance id'),
526 'courseid' => new external_value(PARAM_INT
, 'Course where user completes the feedback (for site feedbacks only).',
533 * Starts or continues a feedback submission
535 * @param array $feedbackid feedback instance id
536 * @param int $courseid course where user completes a feedback (for site feedbacks only).
537 * @return array of warnings and launch information
540 public static function launch_feedback($feedbackid, $courseid = 0) {
543 $params = array('feedbackid' => $feedbackid, 'courseid' => $courseid);
544 $params = self
::validate_parameters(self
::launch_feedback_parameters(), $params);
547 list($feedback, $course, $cm, $context, $completioncourse) = self
::validate_feedback($params['feedbackid'],
548 $params['courseid']);
549 // Check we can do a new submission (or continue an existing).
550 $feedbackcompletion = self
::validate_feedback_access($feedback, $completioncourse, $cm, $context, true);
552 $gopage = $feedbackcompletion->get_resume_page();
553 if ($gopage === null) {
554 $gopage = -1; // Last page.
559 'warnings' => $warnings
565 * Describes the launch_feedback return value.
567 * @return external_single_structure
570 public static function launch_feedback_returns() {
571 return new external_single_structure(
573 'gopage' => new external_value(PARAM_INT
, 'The next page to go (-1 if we were already in the last page). 0 for first page.'),
574 'warnings' => new external_warnings(),
580 * Describes the parameters for get_page_items.
582 * @return external_function_parameters
585 public static function get_page_items_parameters() {
586 return new external_function_parameters (
588 'feedbackid' => new external_value(PARAM_INT
, 'Feedback instance id'),
589 'page' => new external_value(PARAM_INT
, 'The page to get starting by 0'),
590 'courseid' => new external_value(PARAM_INT
, 'Course where user completes the feedback (for site feedbacks only).',
597 * Get a single feedback page items.
599 * @param int $feedbackid feedback instance id
600 * @param int $page the page to get starting by 0
601 * @param int $courseid course where user completes the feedback (for site feedbacks only)
602 * @return array of warnings and launch information
605 public static function get_page_items($feedbackid, $page, $courseid = 0) {
608 $params = array('feedbackid' => $feedbackid, 'page' => $page, 'courseid' => $courseid);
609 $params = self
::validate_parameters(self
::get_page_items_parameters(), $params);
611 $returneditems = array();
612 $hasprevpage = false;
613 $hasnextpage = false;
615 list($feedback, $course, $cm, $context, $completioncourse) = self
::validate_feedback($params['feedbackid'],
616 $params['courseid']);
618 $userhasaccess = true;
619 $feedbackcompletion = null;
621 // Check the user has access to the feedback.
622 $feedbackcompletion = self
::validate_feedback_access($feedback, $completioncourse, $cm, $context, true);
623 } catch (moodle_exception
$e) {
624 $userhasaccess = false;
626 'item' => $feedback->id
,
627 'warningcode' => str_replace('_', '', $e->errorcode
),
628 'message' => $e->getMessage(),
632 // For consistency with the web behaviour, the items should be returned only when the user can edit or view reports (to
633 // include non-editing teachers too).
635 'mod/feedback:edititems',
636 'mod/feedback:viewreports',
638 if ($userhasaccess ||
has_any_capability($capabilities, $context)) {
639 // Remove previous warnings because, although the user might not have access, they have the proper capability.
642 if ($feedbackcompletion == null) {
643 $feedbackcompletion = new mod_feedback_completion($feedback, $cm, $completioncourse->id
);
646 $page = $params['page'];
647 $pages = $feedbackcompletion->get_pages();
648 $pageitems = $pages[$page];
649 $hasnextpage = $page < count($pages) - 1; // Until we complete this page we can not trust get_next_page().
650 $hasprevpage = $page && ($feedbackcompletion->get_previous_page($page, false) !== null);
652 foreach ($pageitems as $item) {
653 $itemnumber = empty($item->itemnr
) ?
null : $item->itemnr
;
654 unset($item->itemnr
); // Added by the function, not part of the record.
655 $exporter = new feedback_item_exporter($item, array('context' => $context, 'itemnumber' => $itemnumber));
656 $returneditems[] = $exporter->export($PAGE->get_renderer('core'));
658 } else if ($userhasaccess) {
660 'item' => $feedback->id
,
661 'warningcode' => 'nopermission',
662 'message' => get_string('nopermission', 'mod_feedback'),
667 'items' => $returneditems,
668 'hasprevpage' => $hasprevpage,
669 'hasnextpage' => $hasnextpage,
670 'warnings' => $warnings
676 * Describes the get_page_items return value.
678 * @return external_single_structure
681 public static function get_page_items_returns() {
682 return new external_single_structure(
684 'items' => new external_multiple_structure(
685 feedback_item_exporter
::get_read_structure()
687 'hasprevpage' => new external_value(PARAM_BOOL
, 'Whether is a previous page.'),
688 'hasnextpage' => new external_value(PARAM_BOOL
, 'Whether there are more pages.'),
689 'warnings' => new external_warnings(),
695 * Describes the parameters for process_page.
697 * @return external_function_parameters
700 public static function process_page_parameters() {
701 return new external_function_parameters (
703 'feedbackid' => new external_value(PARAM_INT
, 'Feedback instance id.'),
704 'page' => new external_value(PARAM_INT
, 'The page being processed.'),
705 'responses' => new external_multiple_structure(
706 new external_single_structure(
708 'name' => new external_value(PARAM_NOTAGS
, 'The response name (usually type[index]_id).'),
709 'value' => new external_value(PARAM_RAW
, 'The response value.'),
711 ), 'The data to be processed.', VALUE_DEFAULT
, array()
713 'goprevious' => new external_value(PARAM_BOOL
, 'Whether we want to jump to previous page.', VALUE_DEFAULT
, false),
714 'courseid' => new external_value(PARAM_INT
, 'Course where user completes the feedback (for site feedbacks only).',
721 * Process a jump between pages.
723 * @param array $feedbackid feedback instance id
724 * @param array $page the page being processed
725 * @param array $responses the responses to be processed
726 * @param bool $goprevious whether we want to jump to previous page
727 * @param int $courseid course where user completes the feedback (for site feedbacks only)
728 * @return array of warnings and launch information
731 public static function process_page($feedbackid, $page, $responses = [], $goprevious = false, $courseid = 0) {
732 global $USER, $SESSION;
734 $params = array('feedbackid' => $feedbackid, 'page' => $page, 'responses' => $responses, 'goprevious' => $goprevious,
735 'courseid' => $courseid);
736 $params = self
::validate_parameters(self
::process_page_parameters(), $params);
738 $siteaftersubmit = $completionpagecontents = '';
740 list($feedback, $course, $cm, $context, $completioncourse) = self
::validate_feedback($params['feedbackid'],
741 $params['courseid']);
742 // Check we can do a new submission (or continue an existing).
743 $feedbackcompletion = self
::validate_feedback_access($feedback, $completioncourse, $cm, $context, true);
745 // Create the $_POST object required by the feedback question engine.
747 foreach ($responses as $response) {
748 // First check if we are handling array parameters.
749 if (preg_match('/(.+)\[(.+)\]$/', $response['name'], $matches)) {
750 $_POST[$matches[1]][$matches[2]] = $response['value'];
752 $_POST[$response['name']] = $response['value'];
756 $_POST['id'] = $cm->id
;
757 $_POST['courseid'] = $courseid;
758 $_POST['gopage'] = $params['page'];
759 $_POST['_qf__mod_feedback_complete_form'] = 1;
761 // Determine where to go, backwards or forward.
762 if (!$params['goprevious']) {
763 $_POST['gonextpage'] = 1; // Even if we are saving values we need this set.
764 if ($feedbackcompletion->get_next_page($params['page'], false) === null) {
765 $_POST['savevalues'] = 1; // If there is no next page, it means we are finishing the feedback.
769 // Ignore sesskey (deep in some APIs), the request is already validated.
770 $USER->ignoresesskey
= true;
771 feedback_init_feedback_session();
772 $SESSION->feedback
->is_started
= true;
774 $feedbackcompletion->process_page($params['page'], $params['goprevious']);
775 $completed = $feedbackcompletion->just_completed();
778 if ($feedback->page_after_submit
) {
779 $completionpagecontents = $feedbackcompletion->page_after_submit();
782 if ($feedback->site_after_submit
) {
783 $siteaftersubmit = feedback_encode_target_url($feedback->site_after_submit
);
786 $jumpto = $feedbackcompletion->get_jumpto();
791 'completed' => $completed,
792 'completionpagecontents' => $completionpagecontents,
793 'siteaftersubmit' => $siteaftersubmit,
794 'warnings' => $warnings
800 * Describes the process_page return value.
802 * @return external_single_structure
805 public static function process_page_returns() {
806 return new external_single_structure(
808 'jumpto' => new external_value(PARAM_INT
, 'The page to jump to.'),
809 'completed' => new external_value(PARAM_BOOL
, 'If the user completed the feedback.'),
810 'completionpagecontents' => new external_value(PARAM_RAW
, 'The completion page contents.'),
811 'siteaftersubmit' => new external_value(PARAM_RAW
, 'The link (could be relative) to show after submit.'),
812 'warnings' => new external_warnings(),
818 * Describes the parameters for get_analysis.
820 * @return external_function_parameters
823 public static function get_analysis_parameters() {
824 return new external_function_parameters (
826 'feedbackid' => new external_value(PARAM_INT
, 'Feedback instance id'),
827 'groupid' => new external_value(PARAM_INT
, 'Group id, 0 means that the function will determine the user group',
829 'courseid' => new external_value(PARAM_INT
, 'Course where user completes the feedback (for site feedbacks only).',
836 * Retrieves the feedback analysis.
838 * @param array $feedbackid feedback instance id
839 * @param int $groupid group id, 0 means that the function will determine the user group
840 * @param int $courseid course where user completes the feedback (for site feedbacks only)
841 * @return array of warnings and launch information
844 public static function get_analysis($feedbackid, $groupid = 0, $courseid = 0) {
847 $params = array('feedbackid' => $feedbackid, 'groupid' => $groupid, 'courseid' => $courseid);
848 $params = self
::validate_parameters(self
::get_analysis_parameters(), $params);
849 $warnings = $itemsdata = array();
851 list($feedback, $course, $cm, $context, $completioncourse) = self
::validate_feedback($params['feedbackid'],
852 $params['courseid']);
854 // Check permissions.
855 $feedbackstructure = new mod_feedback_structure($feedback, $cm, $completioncourse->id
);
856 if (!$feedbackstructure->can_view_analysis()) {
857 throw new required_capability_exception($context, 'mod/feedback:viewanalysepage', 'nopermission', '');
860 if (!empty($params['groupid'])) {
861 $groupid = $params['groupid'];
862 // Determine is the group is visible to user.
863 if (!groups_group_visible($groupid, $course, $cm)) {
864 throw new moodle_exception('notingroup');
867 // Check to see if groups are being used here.
868 if ($groupmode = groups_get_activity_groupmode($cm)) {
869 $groupid = groups_get_activity_group($cm);
870 // Determine is the group is visible to user (this is particullary for the group 0 -> all groups).
871 if (!groups_group_visible($groupid, $course, $cm)) {
872 throw new moodle_exception('notingroup');
880 $summary = new mod_feedback\output\
summary($feedbackstructure, $groupid);
881 $summarydata = $summary->export_for_template($PAGE->get_renderer('core'));
883 $checkanonymously = true;
884 if ($groupid > 0 AND $feedback->anonymous
== FEEDBACK_ANONYMOUS_YES
) {
885 $completedcount = $feedbackstructure->count_completed_responses($groupid);
886 if ($completedcount < FEEDBACK_MIN_ANONYMOUS_COUNT_IN_GROUP
) {
887 $checkanonymously = false;
891 if ($checkanonymously) {
892 // Get the items of the feedback.
893 $items = $feedbackstructure->get_items(true);
894 foreach ($items as $item) {
895 $itemobj = feedback_get_item_class($item->typ
);
896 $itemnumber = empty($item->itemnr
) ?
null : $item->itemnr
;
897 unset($item->itemnr
); // Added by the function, not part of the record.
898 $exporter = new feedback_item_exporter($item, array('context' => $context, 'itemnumber' => $itemnumber));
900 $itemsdata[] = array(
901 'item' => $exporter->export($PAGE->get_renderer('core')),
902 'data' => $itemobj->get_analysed_for_external($item, $groupid),
907 'item' => 'feedback',
908 'itemid' => $feedback->id
,
909 'warningcode' => 'insufficientresponsesforthisgroup',
910 'message' => s(get_string('insufficient_responses_for_this_group', 'feedback'))
915 'completedcount' => $summarydata->completedcount
,
916 'itemscount' => $summarydata->itemscount
,
917 'itemsdata' => $itemsdata,
918 'warnings' => $warnings
924 * Describes the get_analysis return value.
926 * @return external_single_structure
929 public static function get_analysis_returns() {
930 return new external_single_structure(
932 'completedcount' => new external_value(PARAM_INT
, 'Number of completed submissions.'),
933 'itemscount' => new external_value(PARAM_INT
, 'Number of items (questions).'),
934 'itemsdata' => new external_multiple_structure(
935 new external_single_structure(
937 'item' => feedback_item_exporter
::get_read_structure(),
938 'data' => new external_multiple_structure(
939 new external_value(PARAM_RAW
, 'The analysis data (can be json encoded)')
944 'warnings' => new external_warnings(),
950 * Describes the parameters for get_unfinished_responses.
952 * @return external_function_parameters
955 public static function get_unfinished_responses_parameters() {
956 return new external_function_parameters (
958 'feedbackid' => new external_value(PARAM_INT
, 'Feedback instance id.'),
959 'courseid' => new external_value(PARAM_INT
, 'Course where user completes the feedback (for site feedbacks only).',
966 * Retrieves responses from the current unfinished attempt.
968 * @param array $feedbackid feedback instance id
969 * @param int $courseid course where user completes the feedback (for site feedbacks only)
970 * @return array of warnings and launch information
973 public static function get_unfinished_responses($feedbackid, $courseid = 0) {
976 $params = array('feedbackid' => $feedbackid, 'courseid' => $courseid);
977 $params = self
::validate_parameters(self
::get_unfinished_responses_parameters(), $params);
978 $warnings = $itemsdata = array();
980 list($feedback, $course, $cm, $context, $completioncourse) = self
::validate_feedback($params['feedbackid'],
981 $params['courseid']);
982 $feedbackcompletion = new mod_feedback_completion($feedback, $cm, $completioncourse->id
);
984 $responses = array();
985 $unfinished = $feedbackcompletion->get_unfinished_responses();
986 foreach ($unfinished as $u) {
987 $exporter = new feedback_valuetmp_exporter($u);
988 $responses[] = $exporter->export($PAGE->get_renderer('core'));
992 'responses' => $responses,
993 'warnings' => $warnings
999 * Describes the get_unfinished_responses return value.
1001 * @return external_single_structure
1004 public static function get_unfinished_responses_returns() {
1005 return new external_single_structure(
1007 'responses' => new external_multiple_structure(
1008 feedback_valuetmp_exporter
::get_read_structure()
1010 'warnings' => new external_warnings(),
1016 * Describes the parameters for get_finished_responses.
1018 * @return external_function_parameters
1021 public static function get_finished_responses_parameters() {
1022 return new external_function_parameters (
1024 'feedbackid' => new external_value(PARAM_INT
, 'Feedback instance id.'),
1025 'courseid' => new external_value(PARAM_INT
, 'Course where user completes the feedback (for site feedbacks only).',
1032 * Retrieves responses from the last finished attempt.
1034 * @param array $feedbackid feedback instance id
1035 * @param int $courseid course where user completes the feedback (for site feedbacks only)
1036 * @return array of warnings and the responses
1039 public static function get_finished_responses($feedbackid, $courseid = 0) {
1042 $params = array('feedbackid' => $feedbackid, 'courseid' => $courseid);
1043 $params = self
::validate_parameters(self
::get_finished_responses_parameters(), $params);
1044 $warnings = $itemsdata = array();
1046 list($feedback, $course, $cm, $context, $completioncourse) = self
::validate_feedback($params['feedbackid'],
1047 $params['courseid']);
1048 $feedbackcompletion = new mod_feedback_completion($feedback, $cm, $completioncourse->id
);
1050 $responses = array();
1051 // Load and get the responses from the last completed feedback.
1052 $feedbackcompletion->find_last_completed();
1053 $unfinished = $feedbackcompletion->get_finished_responses();
1054 foreach ($unfinished as $u) {
1055 $exporter = new feedback_value_exporter($u);
1056 $responses[] = $exporter->export($PAGE->get_renderer('core'));
1060 'responses' => $responses,
1061 'warnings' => $warnings
1067 * Describes the get_finished_responses return value.
1069 * @return external_single_structure
1072 public static function get_finished_responses_returns() {
1073 return new external_single_structure(
1075 'responses' => new external_multiple_structure(
1076 feedback_value_exporter
::get_read_structure()
1078 'warnings' => new external_warnings(),
1084 * Describes the parameters for get_non_respondents.
1086 * @return external_function_parameters
1089 public static function get_non_respondents_parameters() {
1090 return new external_function_parameters (
1092 'feedbackid' => new external_value(PARAM_INT
, 'Feedback instance id'),
1093 'groupid' => new external_value(PARAM_INT
, 'Group id, 0 means that the function will determine the user group.',
1095 'sort' => new external_value(PARAM_ALPHA
, 'Sort param, must be firstname, lastname or lastaccess (default).',
1096 VALUE_DEFAULT
, 'lastaccess'),
1097 'page' => new external_value(PARAM_INT
, 'The page of records to return.', VALUE_DEFAULT
, 0),
1098 'perpage' => new external_value(PARAM_INT
, 'The number of records to return per page.', VALUE_DEFAULT
, 0),
1099 'courseid' => new external_value(PARAM_INT
, 'Course where user completes the feedback (for site feedbacks only).',
1106 * Retrieves a list of students who didn't submit the feedback.
1108 * @param int $feedbackid feedback instance id
1109 * @param int $groupid Group id, 0 means that the function will determine the user group'
1110 * @param str $sort sort param, must be firstname, lastname or lastaccess (default)
1111 * @param int $page the page of records to return
1112 * @param int $perpage the number of records to return per page
1113 * @param int $courseid course where user completes the feedback (for site feedbacks only)
1114 * @return array of warnings and users ids
1117 public static function get_non_respondents($feedbackid, $groupid = 0, $sort = 'lastaccess', $page = 0, $perpage = 0,
1121 require_once($CFG->dirroot
. '/mod/feedback/lib.php');
1123 $params = array('feedbackid' => $feedbackid, 'groupid' => $groupid, 'sort' => $sort, 'page' => $page,
1124 'perpage' => $perpage, 'courseid' => $courseid);
1125 $params = self
::validate_parameters(self
::get_non_respondents_parameters(), $params);
1126 $warnings = $nonrespondents = array();
1128 list($feedback, $course, $cm, $context, $completioncourse) = self
::validate_feedback($params['feedbackid'],
1129 $params['courseid']);
1130 $feedbackcompletion = new mod_feedback_completion($feedback, $cm, $completioncourse->id
);
1131 $completioncourseid = $feedbackcompletion->get_courseid();
1133 if ($feedback->anonymous
!= FEEDBACK_ANONYMOUS_NO ||
$feedback->course
== SITEID
) {
1134 throw new moodle_exception('anonymous', 'feedback');
1137 // Check permissions.
1138 require_capability('mod/feedback:viewreports', $context);
1140 if (!empty($params['groupid'])) {
1141 $groupid = $params['groupid'];
1142 // Determine is the group is visible to user.
1143 if (!groups_group_visible($groupid, $course, $cm)) {
1144 throw new moodle_exception('notingroup');
1147 // Check to see if groups are being used here.
1148 if ($groupmode = groups_get_activity_groupmode($cm)) {
1149 $groupid = groups_get_activity_group($cm);
1150 // Determine is the group is visible to user (this is particullary for the group 0 -> all groups).
1151 if (!groups_group_visible($groupid, $course, $cm)) {
1152 throw new moodle_exception('notingroup');
1159 if ($params['sort'] !== 'firstname' && $params['sort'] !== 'lastname' && $params['sort'] !== 'lastaccess') {
1160 throw new invalid_parameter_exception('Invalid sort param, must be firstname, lastname or lastaccess.');
1163 // Check if we are page filtering.
1164 if ($params['perpage'] == 0) {
1165 $page = $params['page'];
1166 $perpage = FEEDBACK_DEFAULT_PAGE_COUNT
;
1168 $perpage = $params['perpage'];
1169 $page = $perpage * $params['page'];
1171 $users = feedback_get_incomplete_users($cm, $groupid, $params['sort'], $page, $perpage, true);
1172 foreach ($users as $user) {
1173 $nonrespondents[] = [
1174 'courseid' => $completioncourseid,
1175 'userid' => $user->id
,
1176 'fullname' => fullname($user),
1177 'started' => $user->feedbackstarted
1182 'users' => $nonrespondents,
1183 'total' => feedback_count_incomplete_users($cm, $groupid),
1184 'warnings' => $warnings
1190 * Describes the get_non_respondents return value.
1192 * @return external_single_structure
1195 public static function get_non_respondents_returns() {
1196 return new external_single_structure(
1198 'users' => new external_multiple_structure(
1199 new external_single_structure(
1201 'courseid' => new external_value(PARAM_INT
, 'Course id'),
1202 'userid' => new external_value(PARAM_INT
, 'The user id'),
1203 'fullname' => new external_value(PARAM_TEXT
, 'User full name'),
1204 'started' => new external_value(PARAM_BOOL
, 'If the user has started the attempt'),
1208 'total' => new external_value(PARAM_INT
, 'Total number of non respondents'),
1209 'warnings' => new external_warnings(),
1215 * Describes the parameters for get_responses_analysis.
1217 * @return external_function_parameters
1220 public static function get_responses_analysis_parameters() {
1221 return new external_function_parameters (
1223 'feedbackid' => new external_value(PARAM_INT
, 'Feedback instance id'),
1224 'groupid' => new external_value(PARAM_INT
, 'Group id, 0 means that the function will determine the user group',
1226 'page' => new external_value(PARAM_INT
, 'The page of records to return.', VALUE_DEFAULT
, 0),
1227 'perpage' => new external_value(PARAM_INT
, 'The number of records to return per page', VALUE_DEFAULT
, 0),
1228 'courseid' => new external_value(PARAM_INT
, 'Course where user completes the feedback (for site feedbacks only).',
1235 * Return the feedback user responses.
1237 * @param int $feedbackid feedback instance id
1238 * @param int $groupid Group id, 0 means that the function will determine the user group
1239 * @param int $page the page of records to return
1240 * @param int $perpage the number of records to return per page
1241 * @param int $courseid course where user completes the feedback (for site feedbacks only)
1242 * @return array of warnings and users attemps and responses
1243 * @throws moodle_exception
1246 public static function get_responses_analysis($feedbackid, $groupid = 0, $page = 0, $perpage = 0, $courseid = 0) {
1248 $params = array('feedbackid' => $feedbackid, 'groupid' => $groupid, 'page' => $page, 'perpage' => $perpage,
1249 'courseid' => $courseid);
1250 $params = self
::validate_parameters(self
::get_responses_analysis_parameters(), $params);
1251 $warnings = $itemsdata = array();
1253 list($feedback, $course, $cm, $context, $completioncourse) = self
::validate_feedback($params['feedbackid'],
1254 $params['courseid']);
1256 // Check permissions.
1257 require_capability('mod/feedback:viewreports', $context);
1259 if (!empty($params['groupid'])) {
1260 $groupid = $params['groupid'];
1261 // Determine is the group is visible to user.
1262 if (!groups_group_visible($groupid, $course, $cm)) {
1263 throw new moodle_exception('notingroup');
1266 // Check to see if groups are being used here.
1267 if ($groupmode = groups_get_activity_groupmode($cm)) {
1268 $groupid = groups_get_activity_group($cm);
1269 // Determine is the group is visible to user (this is particullary for the group 0 -> all groups).
1270 if (!groups_group_visible($groupid, $course, $cm)) {
1271 throw new moodle_exception('notingroup');
1278 $feedbackstructure = new mod_feedback_structure($feedback, $cm, $completioncourse->id
);
1279 $responsestable = new mod_feedback_responses_table($feedbackstructure, $groupid);
1280 // Ensure responses number is correct prior returning them.
1281 $feedbackstructure->shuffle_anonym_responses();
1282 $anonresponsestable = new mod_feedback_responses_anon_table($feedbackstructure, $groupid);
1285 'attempts' => $responsestable->export_external_structure($params['page'], $params['perpage']),
1286 'totalattempts' => $responsestable->get_total_responses_count(),
1287 'anonattempts' => $anonresponsestable->export_external_structure($params['page'], $params['perpage']),
1288 'totalanonattempts' => $anonresponsestable->get_total_responses_count(),
1289 'warnings' => $warnings
1295 * Describes the get_responses_analysis return value.
1297 * @return external_single_structure
1300 public static function get_responses_analysis_returns() {
1301 $responsestructure = new external_multiple_structure(
1302 new external_single_structure(
1304 'id' => new external_value(PARAM_INT
, 'Response id'),
1305 'name' => new external_value(PARAM_RAW
, 'Response name'),
1306 'printval' => new external_value(PARAM_RAW
, 'Response ready for output'),
1307 'rawval' => new external_value(PARAM_RAW
, 'Response raw value'),
1312 return new external_single_structure(
1314 'attempts' => new external_multiple_structure(
1315 new external_single_structure(
1317 'id' => new external_value(PARAM_INT
, 'Completed id'),
1318 'courseid' => new external_value(PARAM_INT
, 'Course id'),
1319 'userid' => new external_value(PARAM_INT
, 'User who responded'),
1320 'timemodified' => new external_value(PARAM_INT
, 'Time modified for the response'),
1321 'fullname' => new external_value(PARAM_TEXT
, 'User full name'),
1322 'responses' => $responsestructure
1326 'totalattempts' => new external_value(PARAM_INT
, 'Total responses count.'),
1327 'anonattempts' => new external_multiple_structure(
1328 new external_single_structure(
1330 'id' => new external_value(PARAM_INT
, 'Completed id'),
1331 'courseid' => new external_value(PARAM_INT
, 'Course id'),
1332 'number' => new external_value(PARAM_INT
, 'Response number'),
1333 'responses' => $responsestructure
1337 'totalanonattempts' => new external_value(PARAM_INT
, 'Total anonymous responses count.'),
1338 'warnings' => new external_warnings(),
1344 * Describes the parameters for get_last_completed.
1346 * @return external_function_parameters
1349 public static function get_last_completed_parameters() {
1350 return new external_function_parameters (
1352 'feedbackid' => new external_value(PARAM_INT
, 'Feedback instance id'),
1353 'courseid' => new external_value(PARAM_INT
, 'Course where user completes the feedback (for site feedbacks only).',
1360 * Retrieves the last completion record for the current user.
1362 * @param int $feedbackid feedback instance id
1363 * @return array of warnings and the last completed record
1365 * @throws moodle_exception
1367 public static function get_last_completed($feedbackid, $courseid = 0) {
1370 $params = array('feedbackid' => $feedbackid, 'courseid' => $courseid);
1371 $params = self
::validate_parameters(self
::get_last_completed_parameters(), $params);
1372 $warnings = array();
1374 list($feedback, $course, $cm, $context, $completioncourse) = self
::validate_feedback($params['feedbackid'],
1375 $params['courseid']);
1376 $feedbackcompletion = new mod_feedback_completion($feedback, $cm, $completioncourse->id
);
1378 if ($feedbackcompletion->is_anonymous()) {
1379 throw new moodle_exception('anonymous', 'feedback');
1381 if ($completed = $feedbackcompletion->find_last_completed()) {
1382 $exporter = new feedback_completed_exporter($completed);
1384 'completed' => $exporter->export($PAGE->get_renderer('core')),
1385 'warnings' => $warnings,
1388 throw new moodle_exception('not_completed_yet', 'feedback');
1392 * Describes the get_last_completed return value.
1394 * @return external_single_structure
1397 public static function get_last_completed_returns() {
1398 return new external_single_structure(
1400 'completed' => feedback_completed_exporter
::get_read_structure(),
1401 'warnings' => new external_warnings(),