Differences Between: [Versions 310 and 403] [Versions 311 and 403] [Versions 39 and 403] [Versions 400 and 403] [Versions 401 and 403]
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 namespace mod_h5pactivity\external; 18 19 use mod_h5pactivity\local\manager; 20 use mod_h5pactivity\local\report\results as report_results; 21 use core_external\external_api; 22 use core_external\external_function_parameters; 23 use core_external\external_multiple_structure; 24 use core_external\external_single_structure; 25 use core_external\external_value; 26 use core_external\external_warnings; 27 use context_module; 28 use stdClass; 29 30 /** 31 * This is the external method for getting the information needed to present a results report. 32 * 33 * @package mod_h5pactivity 34 * @since Moodle 3.9 35 * @copyright 2020 Ferran Recio <ferran@moodle.com> 36 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 37 */ 38 class get_results extends external_api { 39 40 /** 41 * Webservice parameters. 42 * 43 * @return external_function_parameters 44 */ 45 public static function execute_parameters(): external_function_parameters { 46 return new external_function_parameters( 47 [ 48 'h5pactivityid' => new external_value(PARAM_INT, 'h5p activity instance id'), 49 'attemptids' => new external_multiple_structure( 50 new external_value(PARAM_INT, 'The attempt id'), 51 'Attempt ids', VALUE_DEFAULT, [] 52 ), 53 ] 54 ); 55 } 56 57 /** 58 * Return user attempts results information in a h5p activity. 59 * 60 * In case an empty array of attempt ids is passed, the method will load all 61 * activity attempts from the current user. 62 * 63 * @throws moodle_exception if the user cannot see the report 64 * @param int $h5pactivityid The h5p activity id 65 * @param int[] $attemptids The attempt ids 66 * @return stdClass report data 67 */ 68 public static function execute(int $h5pactivityid, array $attemptids = []): stdClass { 69 global $USER; 70 71 $params = external_api::validate_parameters(self::execute_parameters(), [ 72 'h5pactivityid' => $h5pactivityid, 73 'attemptids' => $attemptids, 74 ]); 75 $h5pactivityid = $params['h5pactivityid']; 76 $attemptids = $params['attemptids']; 77 78 $warnings = []; 79 80 // Request and permission validation. 81 list ($course, $cm) = get_course_and_cm_from_instance($h5pactivityid, 'h5pactivity'); 82 83 $context = context_module::instance($cm->id); 84 self::validate_context($context); 85 86 $manager = manager::create_from_coursemodule($cm); 87 88 if (empty($attemptids)) { 89 $attemptids = []; 90 foreach ($manager->get_user_attempts($USER->id) as $attempt) { 91 $attemptids[] = $attempt->get_id(); 92 } 93 } 94 95 $attempts = []; 96 foreach ($attemptids as $attemptid) { 97 $report = $manager->get_report(null, $attemptid); 98 99 if ($report && $report instanceof report_results) { 100 $attempts[] = self::export_attempt($report); 101 } else { 102 $warnings[] = [ 103 'item' => 'h5pactivity_attempts', 104 'itemid' => $attemptid, 105 'warningcode' => '1', 106 'message' => "Cannot access attempt", 107 ]; 108 } 109 } 110 111 $result = (object)[ 112 'activityid' => $h5pactivityid, 113 'attempts' => $attempts, 114 'warnings' => $warnings, 115 ]; 116 117 return $result; 118 } 119 120 /** 121 * Return a data object from an attempt. 122 * 123 * @param report_results $report the attempt data 124 * @return stdClass a WS compatible version of the attempt 125 */ 126 private static function export_attempt(report_results $report): stdClass { 127 128 $data = $report->export_data_for_external(); 129 130 $attemptdata = $data->attempt; 131 132 $attempt = (object)[ 133 'id' => $attemptdata->id, 134 'h5pactivityid' => $attemptdata->h5pactivityid, 135 'userid' => $attemptdata->userid, 136 'timecreated' => $attemptdata->timecreated, 137 'timemodified' => $attemptdata->timemodified, 138 'attempt' => $attemptdata->attempt, 139 'rawscore' => $attemptdata->rawscore, 140 'maxscore' => $attemptdata->maxscore, 141 'duration' => (empty($attemptdata->durationvalue)) ? 0 : $attemptdata->durationvalue, 142 'scaled' => (empty($attemptdata->scaled)) ? 0 : $attemptdata->scaled, 143 'results' => [], 144 ]; 145 if (isset($attemptdata->completion) && $attemptdata->completion !== null) { 146 $attempt->completion = $attemptdata->completion; 147 } 148 if (isset($attemptdata->success) && $attemptdata->success !== null) { 149 $attempt->success = $attemptdata->success; 150 } 151 foreach ($data->results as $result) { 152 $attempt->results[] = self::export_result($result); 153 } 154 return $attempt; 155 } 156 157 /** 158 * Return a data object from a result. 159 * 160 * @param stdClass $data the result data 161 * @return stdClass a WS compatible version of the result 162 */ 163 private static function export_result(stdClass $data): stdClass { 164 $result = (object)[ 165 'id' => $data->id, 166 'attemptid' => $data->attemptid, 167 'subcontent' => $data->subcontent, 168 'timecreated' => $data->timecreated, 169 'interactiontype' => $data->interactiontype, 170 'description' => $data->description, 171 'rawscore' => $data->rawscore, 172 'maxscore' => $data->maxscore, 173 'duration' => $data->duration, 174 'optionslabel' => $data->optionslabel ?? get_string('choice', 'mod_h5pactivity'), 175 'correctlabel' => $data->correctlabel ?? get_string('correct_answer', 'mod_h5pactivity'), 176 'answerlabel' => $data->answerlabel ?? get_string('attempt_answer', 'mod_h5pactivity'), 177 'track' => $data->track ?? false, 178 ]; 179 if (isset($data->completion) && $data->completion !== null) { 180 $result->completion = $data->completion; 181 } 182 if (isset($data->success) && $data->success !== null) { 183 $result->success = $data->success; 184 } 185 if (isset($data->options)) { 186 $result->options = $data->options; 187 } 188 if (isset($data->content)) { 189 $result->content = $data->content; 190 } 191 return $result; 192 } 193 194 /** 195 * Describes the get_h5pactivity_access_information return value. 196 * 197 * @return external_single_structure 198 */ 199 public static function execute_returns(): external_single_structure { 200 return new external_single_structure([ 201 'activityid' => new external_value(PARAM_INT, 'Activity course module ID'), 202 'attempts' => new external_multiple_structure( 203 self::get_attempt_returns(), 'The complete attempts list' 204 ), 205 'warnings' => new external_warnings(), 206 ], 'Activity attempts results data'); 207 } 208 209 /** 210 * Return the external structure of an attempt 211 * @return external_single_structure 212 */ 213 private static function get_attempt_returns(): external_single_structure { 214 215 $result = new external_single_structure([ 216 'id' => new external_value(PARAM_INT, 'ID of the context'), 217 'h5pactivityid' => new external_value(PARAM_INT, 'ID of the H5P activity'), 218 'userid' => new external_value(PARAM_INT, 'ID of the user'), 219 'timecreated' => new external_value(PARAM_INT, 'Attempt creation'), 220 'timemodified' => new external_value(PARAM_INT, 'Attempt modified'), 221 'attempt' => new external_value(PARAM_INT, 'Attempt number'), 222 'rawscore' => new external_value(PARAM_INT, 'Attempt score value'), 223 'maxscore' => new external_value(PARAM_INT, 'Attempt max score'), 224 'duration' => new external_value(PARAM_INT, 'Attempt duration in seconds'), 225 'completion' => new external_value(PARAM_INT, 'Attempt completion', VALUE_OPTIONAL), 226 'success' => new external_value(PARAM_INT, 'Attempt success', VALUE_OPTIONAL), 227 'scaled' => new external_value(PARAM_FLOAT, 'Attempt scaled'), 228 'results' => new external_multiple_structure( 229 self::get_result_returns(), 230 'The results of the attempt', VALUE_OPTIONAL 231 ), 232 ], 'The attempt general information'); 233 return $result; 234 } 235 236 /** 237 * Return the external structure of a result 238 * @return external_single_structure 239 */ 240 private static function get_result_returns(): external_single_structure { 241 242 $result = new external_single_structure([ 243 'id' => new external_value(PARAM_INT, 'ID of the context'), 244 'attemptid' => new external_value(PARAM_INT, 'ID of the H5P attempt'), 245 'subcontent' => new external_value(PARAM_NOTAGS, 'Subcontent identifier'), 246 'timecreated' => new external_value(PARAM_INT, 'Result creation'), 247 'interactiontype' => new external_value(PARAM_NOTAGS, 'Interaction type'), 248 'description' => new external_value(PARAM_RAW, 'Result description'), 249 'content' => new external_value(PARAM_RAW, 'Result extra content', VALUE_OPTIONAL), 250 'rawscore' => new external_value(PARAM_INT, 'Result score value'), 251 'maxscore' => new external_value(PARAM_INT, 'Result max score'), 252 'duration' => new external_value(PARAM_INT, 'Result duration in seconds', VALUE_OPTIONAL, 0), 253 'completion' => new external_value(PARAM_INT, 'Result completion', VALUE_OPTIONAL), 254 'success' => new external_value(PARAM_INT, 'Result success', VALUE_OPTIONAL), 255 'optionslabel' => new external_value(PARAM_NOTAGS, 'Label used for result options', VALUE_OPTIONAL), 256 'correctlabel' => new external_value(PARAM_NOTAGS, 'Label used for correct answers', VALUE_OPTIONAL), 257 'answerlabel' => new external_value(PARAM_NOTAGS, 'Label used for user answers', VALUE_OPTIONAL), 258 'track' => new external_value(PARAM_BOOL, 'If the result has valid track information', VALUE_OPTIONAL), 259 'options' => new external_multiple_structure( 260 new external_single_structure([ 261 'description' => new external_value(PARAM_RAW, 'Option description', VALUE_OPTIONAL), 262 'id' => new external_value(PARAM_TEXT, 'Option string identifier', VALUE_OPTIONAL), 263 'correctanswer' => self::get_answer_returns('The option correct answer', VALUE_OPTIONAL), 264 'useranswer' => self::get_answer_returns('The option user answer', VALUE_OPTIONAL), 265 ]), 266 'The statement options', VALUE_OPTIONAL 267 ), 268 ], 'A single result statement tracking information'); 269 return $result; 270 } 271 272 /** 273 * Return the external structure of an answer or correctanswer 274 * 275 * @param string $description the return description 276 * @param int $required the return required value 277 * @return external_single_structure 278 */ 279 private static function get_answer_returns(string $description, int $required = VALUE_REQUIRED): external_single_structure { 280 281 $result = new external_single_structure([ 282 'answer' => new external_value(PARAM_NOTAGS, 'Option text value', VALUE_OPTIONAL), 283 'correct' => new external_value(PARAM_BOOL, 'If has to be displayed as correct', VALUE_OPTIONAL), 284 'incorrect' => new external_value(PARAM_BOOL, 'If has to be displayed as incorrect', VALUE_OPTIONAL), 285 'text' => new external_value(PARAM_BOOL, 'If has to be displayed as simple text', VALUE_OPTIONAL), 286 'checked' => new external_value(PARAM_BOOL, 'If has to be displayed as a checked option', VALUE_OPTIONAL), 287 'unchecked' => new external_value(PARAM_BOOL, 'If has to be displayed as a unchecked option', VALUE_OPTIONAL), 288 'pass' => new external_value(PARAM_BOOL, 'If has to be displayed as passed', VALUE_OPTIONAL), 289 'fail' => new external_value(PARAM_BOOL, 'If has to be displayed as failed', VALUE_OPTIONAL), 290 ], $description, $required); 291 return $result; 292 } 293 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body