PageRenderTime 747ms CodeModel.GetById 100ms app.highlight 414ms RepoModel.GetById 97ms app.codeStats 1ms

/grade/externallib.php

https://bitbucket.org/moodle/moodle
PHP | 468 lines | 333 code | 29 blank | 106 comment | 31 complexity | 3538f037866182cfdd30ce32c3e076d1 MD5 | raw file
  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 * External grading API
 19 *
 20 * @package    core_grading
 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
 26defined('MOODLE_INTERNAL') || die;
 27
 28require_once("$CFG->libdir/externallib.php");
 29require_once("$CFG->dirroot/grade/grading/lib.php");
 30
 31/**
 32 * core grading functions
 33 */
 34class core_grading_external extends external_api {
 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(
117                            'item' => 'module',
118                            'itemid' => $cmid,
119                            'message' => 'Capability moodle/grade:managegradingforms required to view draft definitions',
120                            'warningcode' => '1'
121                        );
122                        $isviewable = false;
123                    }
124                    if (!empty($def->options)) {
125                        $options = json_decode($def->options);
126                        if (isset($options->alwaysshowdefinition) &&
127                                $options->alwaysshowdefinition == 0) {
128                            $warnings[] = array(
129                                'item' => 'module',
130                                'itemid' => $cmid,
131                                'message' => 'Capability moodle/grade:managegradingforms required to preview definition',
132                                'warningcode' => '1'
133                            );
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.
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
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);
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];
209        }
210        foreach ($items as $key => $value) {
211            if (is_array($value)) {
212                $items[$key] = self::format_text($value, $contextid, $componentname, $itemid);
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
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 * core grading functions. Renamed to core_grading_external
449 *
450 * @since Moodle 2.5
451 * @deprecated since 2.6 See MDL-30085. Please do not use this class any more.
452 * @see core_grading_external
453 */
454class core_grade_external extends external_api {
455
456    public static function get_definitions_parameters() {
457        return core_grading_external::get_definitions_parameters();
458    }
459
460    public static function get_definitions($cmids, $areaname, $activeonly = false) {
461        return core_grading_external::get_definitions($cmids, $areaname, $activeonly = false);
462    }
463
464    public static function get_definitions_returns() {
465        return core_grading_external::get_definitions_returns();
466    }
467
468}