Commit | Line | Data |
---|---|---|
3f0ea6d8 PC |
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 | /** | |
9028d9b5 | 18 | * External grading API |
3f0ea6d8 | 19 | * |
9028d9b5 | 20 | * @package core_grading |
3f0ea6d8 PC |
21 | * @since Moodle 2.5 |
22 | * @copyright 2013 Paul Charsley | |
23 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later | |
24 | */ | |
25 | ||
26 | defined('MOODLE_INTERNAL') || die; | |
27 | ||
28 | require_once("$CFG->libdir/externallib.php"); | |
29 | require_once("$CFG->dirroot/grade/grading/lib.php"); | |
30 | ||
31 | /** | |
9028d9b5 | 32 | * core grading functions |
3f0ea6d8 | 33 | */ |
9028d9b5 | 34 | class core_grading_external extends external_api { |
3f0ea6d8 PC |
35 | |
36 | /** | |
37 | * Describes the parameters for get_definitions | |
38 | * @return external_function_parameters | |
39 | * @since Moodle 2.5 | |
40 | */ | |
41 | public static function get_definitions_parameters () { | |
42 | return new external_function_parameters( | |
43 | array( | |
44 | 'cmids' => new external_multiple_structure( | |
45 | new external_value(PARAM_INT, 'course module id'), '1 or more course module ids'), | |
46 | 'areaname' => new external_value(PARAM_AREA, 'area name'), | |
47 | 'activeonly' => new external_value(PARAM_BOOL, 'Only the active method', VALUE_DEFAULT, 0) | |
48 | ) | |
49 | ); | |
50 | } | |
51 | ||
52 | /** | |
53 | * Returns the definitions for the requested course module ids | |
54 | * @param array of ints $cmids | |
55 | * @param string $areaname | |
56 | * @param boolean $activeonly default is false, if true, only the active method is returned | |
57 | * @return array of areas with definitions for each requested course module id | |
58 | * @since Moodle 2.5 | |
59 | */ | |
60 | public static function get_definitions ($cmids, $areaname, $activeonly = false) { | |
61 | global $DB, $CFG; | |
62 | require_once("$CFG->dirroot/grade/grading/form/lib.php"); | |
63 | $params = self::validate_parameters(self::get_definitions_parameters(), | |
64 | array('cmids' => $cmids, | |
65 | 'areaname' => $areaname, | |
66 | 'activeonly' => $activeonly)); | |
67 | $warnings = array(); | |
68 | $areas = array(); | |
69 | foreach ($params['cmids'] as $cmid) { | |
70 | $context = context_module::instance($cmid); | |
71 | try { | |
72 | self::validate_context($context); | |
73 | } catch (Exception $e) { | |
74 | $warnings[] = array( | |
75 | 'item' => 'module', | |
76 | 'itemid' => $cmid, | |
77 | 'message' => 'No access rights in module context', | |
78 | 'warningcode' => '1' | |
79 | ); | |
80 | continue; | |
81 | } | |
82 | // Check if the user has managegradingforms capability. | |
83 | $isgradingmethodmanager = false; | |
84 | if (has_capability('moodle/grade:managegradingforms', $context)) { | |
85 | $isgradingmethodmanager = true; | |
86 | } | |
87 | $module = get_coursemodule_from_id('', $cmid, 0, false, MUST_EXIST); | |
88 | $componentname = "mod_".$module->modname; | |
89 | ||
90 | // Get the grading manager. | |
91 | $gradingmanager = get_grading_manager($context, $componentname, $params['areaname']); | |
92 | // Get the controller for each grading method. | |
93 | $methods = array(); | |
94 | if ($params['activeonly'] == true) { | |
95 | $methods[] = $gradingmanager->get_active_method(); | |
96 | } else { | |
97 | $methods = array_keys($gradingmanager->get_available_methods(false)); | |
98 | } | |
99 | ||
100 | $area = array(); | |
101 | $area['cmid'] = $cmid; | |
102 | $area['contextid'] = $context->id; | |
103 | $area['component'] = $componentname; | |
104 | $area['activemethod'] = $gradingmanager->get_active_method(); | |
105 | $area['definitions'] = array(); | |
106 | ||
107 | foreach ($methods as $method) { | |
108 | $controller = $gradingmanager->get_controller($method); | |
109 | $def = $controller->get_definition(true); | |
110 | if ($def == false) { | |
111 | continue; | |
112 | } | |
113 | if ($isgradingmethodmanager == false) { | |
114 | $isviewable = true; | |
115 | if ($def->status != gradingform_controller::DEFINITION_STATUS_READY) { | |
116 | $warnings[] = array( | |
27a1d25f DW |
117 | 'item' => 'module', |
118 | 'itemid' => $cmid, | |
119 | 'message' => 'Capability moodle/grade:managegradingforms required to view draft definitions', | |
120 | 'warningcode' => '1' | |
121 | ); | |
3f0ea6d8 PC |
122 | $isviewable = false; |
123 | } | |
124 | if (!empty($def->options)) { | |
125 | $options = json_decode($def->options); | |
27a1d25f DW |
126 | if (isset($options->alwaysshowdefinition) && |
127 | $options->alwaysshowdefinition == 0) { | |
3f0ea6d8 | 128 | $warnings[] = array( |
27a1d25f DW |
129 | 'item' => 'module', |
130 | 'itemid' => $cmid, | |
131 | 'message' => 'Capability moodle/grade:managegradingforms required to preview definition', | |
132 | 'warningcode' => '1' | |
133 | ); | |
3f0ea6d8 PC |
134 | $isviewable = false; |
135 | } | |
136 | } | |
137 | if ($isviewable == false) { | |
138 | continue; | |
139 | } | |
140 | } | |
141 | $definition = array(); | |
142 | $definition['id'] = $def->id; | |
143 | $definition['method'] = $method; | |
144 | $definition['name'] = $def->name; | |
145 | $definition['description'] = $def->description; | |
146 | $definition['descriptionformat'] = $def->descriptionformat; | |
147 | $definition['status'] = $def->status; | |
148 | $definition['copiedfromid'] = $def->copiedfromid; | |
149 | $definition['timecreated'] = $def->timecreated; | |
150 | $definition['usercreated'] = $def->usercreated; | |
151 | $definition['timemodified'] = $def->timemodified; | |
152 | $definition['usermodified'] = $def->usermodified; | |
153 | $definition['timecopied'] = $def->timecopied; | |
154 | // Format the description text field. | |
27a1d25f DW |
155 | $formattedtext = external_format_text($definition['description'], |
156 | $definition['descriptionformat'], | |
157 | $context->id, | |
158 | $componentname, | |
159 | 'description', | |
160 | $def->id); | |
161 | $definition['description'] = $formattedtext[0]; | |
162 | $definition['descriptionformat'] = $formattedtext[1]; | |
163 | ||
3f0ea6d8 PC |
164 | $details = $controller->get_external_definition_details(); |
165 | $items = array(); | |
166 | foreach ($details as $key => $value) { | |
167 | $items[$key] = self::format_text($def->{$key}, $context->id, $componentname, $def->id); | |
168 | } | |
169 | $definition[$method] = $items; | |
170 | $area['definitions'][] = $definition; | |
171 | } | |
172 | $areas[] = $area; | |
173 | } | |
174 | $result = array( | |
175 | 'areas' => $areas, | |
176 | 'warnings' => $warnings | |
177 | ); | |
178 | return $result; | |
179 | } | |
180 | ||
181 | /** | |
182 | * Recursively processes all elements in an array and runs external_format_text()on | |
183 | * all elements which have a text field and associated format field with a key name | |
184 | * that ends with the text 'format'. The modified array is returned. | |
185 | * @param array $items the array to be processed | |
186 | * @param int $contextid | |
187 | * @param string $componentname | |
188 | * @param int $itemid | |
189 | * @see external_format_text in lib/externallib.php | |
190 | * @return array the input array with all fields formatted | |
191 | */ | |
192 | private static function format_text($items, $contextid, $componentname, $itemid) { | |
193 | $formatkeys = array(); | |
194 | foreach ($items as $key => $value) { | |
195 | if (!is_array($value) && substr_compare($key, 'format', -6, 6) === 0) { | |
196 | $formatkeys[] = $key; | |
197 | } | |
198 | } | |
199 | foreach ($formatkeys as $formatkey) { | |
200 | $descriptionkey = substr($formatkey, 0, -6); | |
27a1d25f DW |
201 | $formattedtext = external_format_text($items[$descriptionkey], |
202 | $items[$formatkey], | |
203 | $contextid, | |
204 | $componentname, | |
205 | 'description', | |
206 | $itemid); | |
207 | $items[$descriptionkey] = $formattedtext[0]; | |
208 | $items[$formatkey] = $formattedtext[1]; | |
3f0ea6d8 | 209 | } |
27a1d25f | 210 | foreach ($items as $key => $value) { |
3f0ea6d8 | 211 | if (is_array($value)) { |
27a1d25f | 212 | $items[$key] = self::format_text($value, $contextid, $componentname, $itemid); |
3f0ea6d8 PC |
213 | } |
214 | } | |
215 | return $items; | |
216 | } | |
217 | ||
218 | /** | |
219 | * Creates a grading area | |
220 | * @return external_single_structure | |
221 | * @since Moodle 2.5 | |
222 | */ | |
223 | private static function grading_area() { | |
224 | return new external_single_structure( | |
225 | array ( | |
226 | 'cmid' => new external_value(PARAM_INT, 'course module id'), | |
227 | 'contextid' => new external_value(PARAM_INT, 'context id'), | |
228 | 'component' => new external_value(PARAM_TEXT, 'component name'), | |
229 | 'activemethod' => new external_value(PARAM_TEXT, 'active method', VALUE_OPTIONAL), | |
230 | 'definitions' => new external_multiple_structure(self::definition(), 'definitions') | |
231 | ) | |
232 | ); | |
233 | } | |
234 | ||
235 | /** | |
236 | * creates a grading form definition | |
237 | * @return external_single_structure | |
238 | * @since Moodle 2.5 | |
239 | */ | |
240 | private static function definition() { | |
241 | global $CFG; | |
242 | $definition = array(); | |
243 | $definition['id'] = new external_value(PARAM_INT, 'definition id'); | |
244 | $definition['method'] = new external_value(PARAM_TEXT, 'method'); | |
245 | $definition['name'] = new external_value(PARAM_TEXT, 'name'); | |
246 | $definition['description'] = new external_value(PARAM_RAW, 'description'); | |
247 | $definition['descriptionformat'] = new external_format_value('description'); | |
248 | $definition['status'] = new external_value(PARAM_INT, 'status'); | |
249 | $definition['copiedfromid'] = new external_value(PARAM_INT, 'copied from id', VALUE_OPTIONAL); | |
250 | $definition['timecreated'] = new external_value(PARAM_INT, 'creation time'); | |
251 | $definition['usercreated'] = new external_value(PARAM_INT, 'user who created definition'); | |
252 | $definition['timemodified'] = new external_value(PARAM_INT, 'last modified time'); | |
253 | $definition['usermodified'] = new external_value(PARAM_INT, 'user who modified definition'); | |
254 | $definition['timecopied'] = new external_value(PARAM_INT, 'time copied', VALUE_OPTIONAL); | |
255 | foreach (self::get_grading_methods() as $method) { | |
256 | require_once($CFG->dirroot.'/grade/grading/form/'.$method.'/lib.php'); | |
257 | $details = call_user_func('gradingform_'.$method.'_controller::get_external_definition_details'); | |
258 | if ($details != null) { | |
259 | $items = array(); | |
260 | foreach ($details as $key => $value) { | |
261 | $details[$key]->required = VALUE_OPTIONAL; | |
262 | $items[$key] = $value; | |
263 | } | |
264 | $definition[$method] = new external_single_structure($items, 'items', VALUE_OPTIONAL); | |
265 | } | |
266 | } | |
267 | return new external_single_structure($definition); | |
268 | } | |
269 | ||
270 | /** | |
271 | * Describes the get_definitions return value | |
272 | * @return external_single_structure | |
273 | * @since Moodle 2.5 | |
274 | */ | |
275 | public static function get_definitions_returns() { | |
276 | return new external_single_structure( | |
277 | array( | |
278 | 'areas' => new external_multiple_structure(self::grading_area(), 'list of grading areas'), | |
279 | 'warnings' => new external_warnings() | |
280 | ) | |
281 | ); | |
282 | } | |
283 | ||
284 | /** | |
285 | * @return array of available grading methods | |
286 | * @since Moodle 2.5 | |
287 | */ | |
288 | private static function get_grading_methods() { | |
289 | $methods = array_keys(grading_manager::available_methods(false)); | |
290 | return $methods; | |
291 | } | |
292 | ||
9028d9b5 PC |
293 | /** |
294 | * Describes the parameters for get_gradingform_instances | |
295 | * | |
296 | * @return external_function_parameters | |
297 | * @since Moodle 2.6 | |
298 | */ | |
299 | public static function get_gradingform_instances_parameters () { | |
300 | return new external_function_parameters( | |
301 | array( | |
302 | 'definitionid' => new external_value(PARAM_INT, 'definition id'), | |
303 | 'since' => new external_value(PARAM_INT, 'submitted since', VALUE_DEFAULT, 0) | |
304 | ) | |
305 | ); | |
306 | } | |
307 | ||
308 | /** | |
309 | * Returns the instances and fillings for the requested definition id | |
310 | * | |
311 | * @param int $definitionid | |
312 | * @param int $since only return instances with timemodified >= since | |
313 | * @return array of grading instances with fillings for the definition id | |
314 | * @since Moodle 2.6 | |
315 | */ | |
316 | public static function get_gradingform_instances ($definitionid, $since = 0) { | |
317 | global $DB, $CFG; | |
318 | require_once("$CFG->dirroot/grade/grading/form/lib.php"); | |
319 | $params = self::validate_parameters(self::get_gradingform_instances_parameters(), | |
320 | array('definitionid' => $definitionid, | |
321 | 'since' => $since)); | |
322 | $instances = array(); | |
323 | $warnings = array(); | |
324 | ||
325 | $definition = $DB->get_record('grading_definitions', | |
326 | array('id' => $params['definitionid']), | |
327 | 'areaid,method', MUST_EXIST); | |
328 | $area = $DB->get_record('grading_areas', | |
329 | array('id' => $definition->areaid), | |
330 | 'contextid,component', MUST_EXIST); | |
331 | ||
332 | $context = context::instance_by_id($area->contextid); | |
333 | require_capability('moodle/grade:managegradingforms', $context); | |
334 | ||
335 | $gradingmanager = get_grading_manager($definition->areaid); | |
336 | $controller = $gradingmanager->get_controller($definition->method); | |
337 | $activeinstances = $controller->get_all_active_instances ($params['since']); | |
338 | $details = $controller->get_external_instance_filling_details(); | |
339 | if ($details == null) { | |
340 | $warnings[] = array( | |
341 | 'item' => 'definition', | |
342 | 'itemid' => $params['definitionid'], | |
343 | 'message' => 'Fillings unavailable because get_external_instance_filling_details is not defined', | |
344 | 'warningcode' => '1' | |
345 | ); | |
346 | } | |
347 | $getfilling = null; | |
348 | if (method_exists('gradingform_'.$definition->method.'_instance', 'get_'.$definition->method.'_filling')) { | |
349 | $getfilling = 'get_'.$definition->method.'_filling'; | |
350 | } else { | |
351 | $warnings[] = array( | |
352 | 'item' => 'definition', | |
353 | 'itemid' => $params['definitionid'], | |
354 | 'message' => 'Fillings unavailable because get_'.$definition->method.'_filling is not defined', | |
355 | 'warningcode' => '1' | |
356 | ); | |
357 | } | |
358 | foreach ($activeinstances as $activeinstance) { | |
359 | $instance = array(); | |
360 | $instance['id'] = $activeinstance->get_id(); | |
361 | $instance['raterid'] = $activeinstance->get_data('raterid'); | |
362 | $instance['itemid'] = $activeinstance->get_data('itemid'); | |
363 | $instance['rawgrade'] = $activeinstance->get_data('rawgrade'); | |
364 | $instance['status'] = $activeinstance->get_data('status'); | |
365 | $instance['feedback'] = $activeinstance->get_data('feedback'); | |
366 | $instance['feedbackformat'] = $activeinstance->get_data('feedbackformat'); | |
367 | // Format the feedback text field. | |
368 | $formattedtext = external_format_text($activeinstance->get_data('feedback'), | |
369 | $activeinstance->get_data('feedbackformat'), | |
370 | $context->id, | |
371 | $area->component, | |
372 | 'feedback', | |
373 | $params['definitionid']); | |
374 | $instance['feedback'] = $formattedtext[0]; | |
375 | $instance['feedbackformat'] = $formattedtext[1]; | |
376 | $instance['timemodified'] = $activeinstance->get_data('timemodified'); | |
377 | ||
378 | if ($details != null && $getfilling != null) { | |
379 | $fillingdata = $activeinstance->$getfilling(); | |
380 | $filling = array(); | |
381 | foreach ($details as $key => $value) { | |
382 | $filling[$key] = self::format_text($fillingdata[$key], | |
383 | $context->id, | |
384 | $area->component, | |
385 | $params['definitionid']); | |
386 | } | |
387 | $instance[$definition->method] = $filling; | |
388 | } | |
389 | $instances[] = $instance; | |
390 | } | |
391 | $result = array( | |
392 | 'instances' => $instances, | |
393 | 'warnings' => $warnings | |
394 | ); | |
395 | return $result; | |
396 | } | |
397 | ||
398 | /** | |
399 | * Creates a grading instance | |
400 | * | |
401 | * @return external_single_structure | |
402 | * @since Moodle 2.6 | |
403 | */ | |
404 | private static function grading_instance() { | |
405 | global $CFG; | |
406 | $instance = array(); | |
407 | $instance['id'] = new external_value(PARAM_INT, 'instance id'); | |
408 | $instance['raterid'] = new external_value(PARAM_INT, 'rater id'); | |
409 | $instance['itemid'] = new external_value(PARAM_INT, 'item id'); | |
410 | $instance['rawgrade'] = new external_value(PARAM_TEXT, 'raw grade', VALUE_OPTIONAL); | |
411 | $instance['status'] = new external_value(PARAM_INT, 'status'); | |
412 | $instance['feedback'] = new external_value(PARAM_RAW, 'feedback', VALUE_OPTIONAL); | |
413 | $instance['feedbackformat'] = new external_format_value('feedback', VALUE_OPTIONAL); | |
414 | $instance['timemodified'] = new external_value(PARAM_INT, 'modified time'); | |
415 | foreach (self::get_grading_methods() as $method) { | |
416 | require_once($CFG->dirroot.'/grade/grading/form/'.$method.'/lib.php'); | |
417 | $details = call_user_func('gradingform_'.$method.'_controller::get_external_instance_filling_details'); | |
418 | if ($details != null) { | |
419 | $items = array(); | |
420 | foreach ($details as $key => $value) { | |
421 | $details[$key]->required = VALUE_OPTIONAL; | |
422 | $items[$key] = $value; | |
423 | } | |
424 | $instance[$method] = new external_single_structure($items, 'items', VALUE_OPTIONAL); | |
425 | } | |
426 | } | |
427 | return new external_single_structure($instance); | |
428 | } | |
429 | ||
430 | /** | |
431 | * Describes the get_gradingform_instances return value | |
432 | * | |
433 | * @return external_single_structure | |
434 | * @since Moodle 2.6 | |
435 | */ | |
436 | public static function get_gradingform_instances_returns () { | |
437 | return new external_single_structure( | |
438 | array( | |
439 | 'instances' => new external_multiple_structure(self::grading_instance(), 'list of grading instances'), | |
440 | 'warnings' => new external_warnings() | |
441 | ) | |
442 | ); | |
443 | } | |
444 | ||
445 | } | |
446 | ||
447 | /** | |
448 | * @since Moodle 2.6 | |
449 | * @deprecated See MDL-30085. Please do not use this class any more. | |
450 | * @see core_grading_external | |
451 | */ | |
452 | class core_grade_external extends external_api { | |
453 | ||
454 | public static function get_definitions_parameters () { | |
455 | return core_grading_external::get_definitions_parameters(); | |
456 | } | |
457 | ||
458 | public static function get_definitions ($cmids, $areaname, $activeonly = false) { | |
459 | return core_grading_external::get_definitions($cmids, $areaname, $activeonly = false); | |
460 | } | |
461 | ||
462 | public static function get_definitions_returns() { | |
463 | return core_grading_external::get_definitions_returns(); | |
464 | } | |
465 | ||
3f0ea6d8 | 466 | } |