Commit | Line | Data |
---|---|---|
b87f31db 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 | * Choice module external API | |
19 | * | |
20 | * @package mod_choice | |
21 | * @category external | |
22 | * @copyright 2015 Costantino Cito <ccito@cvaconsulting.com> | |
23 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later | |
24 | * @since Moodle 3.0 | |
25 | */ | |
26 | ||
27 | defined('MOODLE_INTERNAL') || die; | |
28 | require_once($CFG->libdir . '/externallib.php'); | |
29 | require_once($CFG->dirroot . '/mod/choice/lib.php'); | |
30 | ||
31 | /** | |
32 | * Choice module external functions | |
33 | * | |
34 | * @package mod_choice | |
35 | * @category external | |
36 | * @copyright 2015 Costantino Cito <ccito@cvaconsulting.com> | |
37 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later | |
38 | * @since Moodle 3.0 | |
39 | */ | |
40 | class mod_choice_external extends external_api { | |
41 | ||
42 | /** | |
43 | * Describes the parameters for get_choices_by_courses. | |
44 | * | |
45 | * @return external_external_function_parameters | |
46 | * @since Moodle 3.0 | |
47 | */ | |
48 | public static function get_choice_results_parameters() { | |
49 | return new external_function_parameters (array('choiceid' => new external_value(PARAM_INT, 'choice instance id'))); | |
50 | } | |
51 | /** | |
52 | * Returns user's results for a specific choice | |
53 | * and a list of those users that did not answered yet. | |
54 | * | |
55 | * @param int $choiceid the choice instance id | |
56 | * @return array of responses details | |
57 | * @since Moodle 3.0 | |
58 | */ | |
59 | public static function get_choice_results($choiceid) { | |
60 | global $USER; | |
61 | ||
62 | $params = self::validate_parameters(self::get_choice_results_parameters(), array('choiceid' => $choiceid)); | |
63 | ||
64 | if (!$choice = choice_get_choice($params['choiceid'])) { | |
65 | throw new moodle_exception("invalidcoursemodule", "error"); | |
66 | } | |
67 | list($course, $cm) = get_course_and_cm_from_instance($choice, 'choice'); | |
68 | ||
69 | $context = context_module::instance($cm->id); | |
70 | self::validate_context($context); | |
71 | ||
72 | $groupmode = groups_get_activity_groupmode($cm); | |
73 | // Check if we have to include responses from inactive users. | |
74 | $onlyactive = $choice->includeinactive ? false : true; | |
75 | $users = choice_get_response_data($choice, $cm, $groupmode, $onlyactive); | |
76 | // Show those who haven't answered the question. | |
77 | if (!empty($choice->showunanswered)) { | |
78 | $choice->option[0] = get_string('notanswered', 'choice'); | |
79 | $choice->maxanswers[0] = 0; | |
80 | } | |
81 | $results = prepare_choice_show_results($choice, $course, $cm, $users); | |
82 | ||
83 | $options = array(); | |
84 | $fullnamecap = has_capability('moodle/site:viewfullnames', $context); | |
85 | foreach ($results->options as $optionid => $option) { | |
86 | ||
87 | $userresponses = array(); | |
88 | $numberofuser = 0; | |
89 | $percentageamount = 0; | |
90 | if (property_exists($option, 'user') and | |
91 | (has_capability('mod/choice:readresponses', $context) or choice_can_view_results($choice))) { | |
92 | $numberofuser = count($option->user); | |
93 | $percentageamount = ((float)$numberofuser / (float)$results->numberofuser) * 100.0; | |
94 | if ($choice->publish) { | |
95 | foreach ($option->user as $userresponse) { | |
96 | $response = array(); | |
97 | $response['userid'] = $userresponse->id; | |
98 | $response['fullname'] = fullname($userresponse, $fullnamecap); | |
99 | $usercontext = context_user::instance($userresponse->id, IGNORE_MISSING); | |
100 | if ($usercontext) { | |
101 | $profileimageurl = moodle_url::make_webservice_pluginfile_url($usercontext->id, 'user', 'icon', null, | |
102 | '/', 'f1')->out(false); | |
103 | } else { | |
104 | $profileimageurl = ''; | |
105 | } | |
106 | $response['profileimageurl'] = $profileimageurl; | |
107 | // Add optional properties. | |
108 | foreach (array('answerid', 'timemodified') as $field) { | |
109 | if (property_exists($userresponse, 'answerid')) { | |
110 | $response[$field] = $userresponse->$field; | |
111 | } | |
112 | } | |
113 | $userresponses[] = $response; | |
114 | } | |
115 | } | |
116 | } | |
117 | ||
118 | $options[] = array('id' => $optionid, | |
119 | 'text' => format_string($option->text, true, array('context' => $context)), | |
120 | 'maxanswer' => $option->maxanswer, | |
121 | 'userresponses' => $userresponses, | |
122 | 'numberofuser' => $numberofuser, | |
123 | 'percentageamount' => $percentageamount | |
124 | ); | |
125 | } | |
126 | ||
127 | $warnings = array(); | |
128 | return array( | |
129 | 'options' => $options, | |
130 | 'warnings' => $warnings | |
131 | ); | |
132 | } | |
133 | ||
134 | /** | |
135 | * Describes the get_choice_results return value. | |
136 | * | |
137 | * @return external_single_structure | |
138 | * @since Moodle 3.0 | |
139 | */ | |
140 | public static function get_choice_results_returns() { | |
141 | return new external_single_structure( | |
142 | array( | |
143 | 'options' => new external_multiple_structure( | |
144 | new external_single_structure( | |
145 | array( | |
146 | 'id' => new external_value(PARAM_INT, 'choice instance id'), | |
147 | 'text' => new external_value(PARAM_RAW, 'text of the choice'), | |
148 | 'maxanswer' => new external_value(PARAM_INT, 'maximum number of answers'), | |
149 | 'userresponses' => new external_multiple_structure( | |
150 | new external_single_structure( | |
151 | array( | |
152 | 'userid' => new external_value(PARAM_INT, 'user id'), | |
153 | 'fullname' => new external_value(PARAM_NOTAGS, 'user full name'), | |
154 | 'profileimageurl' => new external_value(PARAM_URL, 'profile user image url'), | |
155 | 'answerid' => new external_value(PARAM_INT, 'answer id', VALUE_OPTIONAL), | |
156 | 'timemodified' => new external_value(PARAM_INT, 'time of modification', VALUE_OPTIONAL), | |
157 | ), 'User responses' | |
158 | ) | |
159 | ), | |
160 | 'numberofuser' => new external_value(PARAM_INT, 'number of users answers'), | |
161 | 'percentageamount' => new external_value(PARAM_FLOAT, 'percentage of users answers') | |
162 | ), 'Options' | |
163 | ) | |
164 | ), | |
165 | 'warnings' => new external_warnings(), | |
166 | ) | |
167 | ); | |
168 | } | |
169 | ||
565528ce JL |
170 | /** |
171 | * Describes the parameters for mod_choice_get_choice_options. | |
172 | * | |
173 | * @return external_external_function_parameters | |
174 | * @since Moodle 3.0 | |
175 | */ | |
176 | public static function get_choice_options_parameters() { | |
177 | return new external_function_parameters (array('choiceid' => new external_value(PARAM_INT, 'choice instance id'))); | |
178 | } | |
179 | ||
180 | /** | |
181 | * Returns options for a specific choice | |
182 | * | |
183 | * @param int $choiceid the choice instance id | |
184 | * @return array of options details | |
185 | * @since Moodle 3.0 | |
186 | */ | |
187 | public static function get_choice_options($choiceid) { | |
188 | global $USER; | |
189 | $warnings = array(); | |
190 | $params = self::validate_parameters(self::get_choice_options_parameters(), array('choiceid' => $choiceid)); | |
191 | ||
192 | if (!$choice = choice_get_choice($params['choiceid'])) { | |
193 | throw new moodle_exception("invalidcoursemodule", "error"); | |
194 | } | |
195 | list($course, $cm) = get_course_and_cm_from_instance($choice, 'choice'); | |
196 | ||
197 | $context = context_module::instance($cm->id); | |
198 | self::validate_context($context); | |
199 | ||
200 | require_capability('mod/choice:choose', $context); | |
201 | ||
202 | $groupmode = groups_get_activity_groupmode($cm); | |
203 | $onlyactive = $choice->includeinactive ? false : true; | |
204 | $allresponses = choice_get_response_data($choice, $cm, $groupmode, $onlyactive); | |
205 | ||
206 | $timenow = time(); | |
207 | $choiceopen = true; | |
208 | $showpreview = false; | |
209 | ||
210 | if ($choice->timeclose !== 0) { | |
211 | if ($choice->timeopen > $timenow) { | |
212 | $choiceopen = false; | |
213 | $warnings[1] = get_string("notopenyet", "choice", userdate($choice->timeopen)); | |
214 | if ($choice->showpreview) { | |
215 | $warnings[2] = get_string('previewonly', 'choice', userdate($choice->timeopen)); | |
216 | $showpreview = true; | |
217 | } | |
218 | } | |
219 | if ($timenow > $choice->timeclose) { | |
220 | $choiceopen = false; | |
221 | $warnings[3] = get_string("expired", "choice", userdate($choice->timeclose)); | |
222 | } | |
223 | } | |
224 | $optionsarray = array(); | |
225 | ||
226 | if ($choiceopen or $showpreview) { | |
227 | ||
228 | $options = choice_prepare_options($choice, $USER, $cm, $allresponses); | |
229 | ||
230 | foreach ($options['options'] as $option) { | |
231 | $optionarr = array(); | |
232 | $optionarr['id'] = $option->attributes->value; | |
233 | $optionarr['text'] = format_string($option->text, true, array('context' => $context)); | |
234 | $optionarr['maxanswers'] = $option->maxanswers; | |
235 | $optionarr['displaylayout'] = $option->displaylayout; | |
236 | $optionarr['countanswers'] = $option->countanswers; | |
237 | foreach (array('checked', 'disabled') as $field) { | |
238 | if (property_exists($option->attributes, $field) and $option->attributes->$field == 1) { | |
239 | $optionarr[$field] = 1; | |
240 | } else { | |
241 | $optionarr[$field] = 0; | |
242 | } | |
243 | } | |
244 | // When showpreview is active, we show options as disabled. | |
245 | if ($showpreview or ($optionarr['checked'] == 1 and !$choice->allowupdate)) { | |
246 | $optionarr['disabled'] = 1; | |
247 | } | |
248 | $optionsarray[] = $optionarr; | |
249 | } | |
250 | } | |
251 | foreach ($warnings as $key => $message) { | |
252 | $warnings[$key] = array( | |
253 | 'item' => 'choice', | |
254 | 'itemid' => $cm->id, | |
255 | 'warningcode' => $key, | |
256 | 'message' => $message | |
257 | ); | |
258 | } | |
259 | return array( | |
260 | 'options' => $optionsarray, | |
261 | 'warnings' => $warnings | |
262 | ); | |
263 | } | |
264 | ||
265 | /** | |
266 | * Describes the get_choice_results return value. | |
267 | * | |
268 | * @return external_multiple_structure | |
269 | * @since Moodle 3.0 | |
270 | */ | |
271 | public static function get_choice_options_returns() { | |
272 | return new external_single_structure( | |
273 | array( | |
274 | 'options' => new external_multiple_structure( | |
275 | new external_single_structure( | |
276 | array( | |
277 | 'id' => new external_value(PARAM_INT, 'option id'), | |
278 | 'text' => new external_value(PARAM_RAW, 'text of the choice'), | |
279 | 'maxanswers' => new external_value(PARAM_INT, 'maximum number of answers'), | |
280 | 'displaylayout' => new external_value(PARAM_BOOL, 'true for orizontal, otherwise vertical'), | |
281 | 'countanswers' => new external_value(PARAM_INT, 'number of answers'), | |
282 | 'checked' => new external_value(PARAM_BOOL, 'we already answered'), | |
283 | 'disabled' => new external_value(PARAM_BOOL, 'option disabled'), | |
284 | ) | |
285 | ), 'Options' | |
286 | ), | |
287 | 'warnings' => new external_warnings(), | |
288 | ) | |
289 | ); | |
290 | } | |
291 | ||
10064594 JL |
292 | /** |
293 | * Describes the parameters for submit_choice_response. | |
294 | * | |
295 | * @return external_external_function_parameters | |
296 | * @since Moodle 3.0 | |
297 | */ | |
298 | public static function submit_choice_response_parameters() { | |
299 | return new external_function_parameters ( | |
300 | array( | |
301 | 'choiceid' => new external_value(PARAM_INT, 'choice instance id'), | |
302 | 'responses' => new external_multiple_structure( | |
303 | new external_value(PARAM_INT, 'answer id'), | |
304 | 'Array of response ids' | |
305 | ), | |
306 | ) | |
307 | ); | |
308 | } | |
309 | ||
310 | /** | |
311 | * Submit choice responses | |
312 | * | |
313 | * @param int $choiceid the choice instance id | |
314 | * @param array $responses the response ids | |
315 | * @return array ansers informatinon and warnings | |
316 | * @since Moodle 3.0 | |
317 | */ | |
318 | public static function submit_choice_response($choiceid, $responses) { | |
319 | global $USER; | |
320 | ||
321 | $warnings = array(); | |
322 | $params = self::validate_parameters(self::submit_choice_response_parameters(), | |
323 | array( | |
324 | 'choiceid' => $choiceid, | |
325 | 'responses' => $responses | |
326 | )); | |
327 | ||
328 | if (!$choice = choice_get_choice($params['choiceid'])) { | |
329 | throw new moodle_exception("invalidcoursemodule", "error"); | |
330 | } | |
331 | list($course, $cm) = get_course_and_cm_from_instance($choice, 'choice'); | |
332 | ||
333 | $context = context_module::instance($cm->id); | |
334 | self::validate_context($context); | |
335 | ||
336 | require_capability('mod/choice:choose', $context); | |
337 | ||
338 | $timenow = time(); | |
339 | if ($choice->timeclose != 0) { | |
340 | if ($choice->timeopen > $timenow) { | |
341 | throw new moodle_exception("notopenyet", "choice", '', userdate($choice->timeopen)); | |
342 | } else if ($timenow > $choice->timeclose) { | |
343 | throw new moodle_exception("expired", "choice", '', userdate($choice->timeclose)); | |
344 | } | |
345 | } | |
346 | if (!choice_get_my_response($choice) or $choice->allowupdate) { | |
347 | // When a single response is given, we convert the array to a simple variable | |
348 | // in order to avoid choice_user_submit_response to check with allowmultiple even | |
349 | // for a single response. | |
350 | if (count($params['responses']) == 1) { | |
351 | $params['responses'] = reset($params['responses']); | |
352 | } | |
353 | choice_user_submit_response($params['responses'], $choice, $USER->id, $course, $cm); | |
354 | } else { | |
355 | throw new moodle_exception('missingrequiredcapability', 'webservice', '', 'allowupdate'); | |
356 | } | |
357 | $answers = choice_get_my_response($choice); | |
358 | ||
359 | return array( | |
360 | 'answers' => $answers, | |
361 | 'warnings' => $warnings | |
362 | ); | |
363 | } | |
364 | ||
365 | /** | |
366 | * Describes the submit_choice_response return value. | |
367 | * | |
368 | * @return external_multiple_structure | |
369 | * @since Moodle 3.0 | |
370 | */ | |
371 | public static function submit_choice_response_returns() { | |
372 | return new external_single_structure( | |
373 | array( | |
374 | 'answers' => new external_multiple_structure( | |
375 | new external_single_structure( | |
376 | array( | |
377 | 'id' => new external_value(PARAM_INT, 'answer id'), | |
378 | 'choiceid' => new external_value(PARAM_INT, 'choiceid'), | |
379 | 'userid' => new external_value(PARAM_INT, 'user id'), | |
380 | 'optionid' => new external_value(PARAM_INT, 'optionid'), | |
381 | 'timemodified' => new external_value(PARAM_INT, 'time of last modification') | |
382 | ), 'Answers' | |
383 | ) | |
384 | ), | |
385 | 'warnings' => new external_warnings(), | |
386 | ) | |
387 | ); | |
388 | } | |
389 | ||
b87f31db | 390 | } |