Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 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
 * Web services relating to fetching of a marking guide for the grading panel.
19
 *
20
 * @package    gradingform_guide
21
 * @copyright  2019 Andrew Nicols <andrew@nicols.co.uk>
22
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
23
 */
24
 
25
declare(strict_types = 1);
26
 
27
namespace gradingform_guide\grades\grader\gradingpanel\external;
28
 
29
global $CFG;
30
 
31
use coding_exception;
32
use context;
33
use core_user;
34
use core_grades\component_gradeitem as gradeitem;
35
use core_grades\component_gradeitems;
36
use core_external\external_api;
37
use core_external\external_function_parameters;
38
use core_external\external_multiple_structure;
39
use core_external\external_single_structure;
40
use core_external\external_value;
41
use core_external\external_warnings;
42
use moodle_exception;
43
use stdClass;
44
require_once($CFG->dirroot.'/grade/grading/form/guide/lib.php');
45
 
46
/**
47
 * Web services relating to fetching of a marking guide for the grading panel.
48
 *
49
 * @package    gradingform_guide
50
 * @copyright  2019 Andrew Nicols <andrew@nicols.co.uk>
51
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
52
 */
53
class fetch extends external_api {
54
 
55
    /**
56
     * Describes the parameters for fetching the grading panel for a simple grade.
57
     *
58
     * @return external_function_parameters
59
     * @since Moodle 3.8
60
     */
61
    public static function execute_parameters(): external_function_parameters {
62
        return new external_function_parameters ([
63
            'component' => new external_value(
64
                PARAM_ALPHANUMEXT,
65
                'The name of the component',
66
                VALUE_REQUIRED
67
            ),
68
            'contextid' => new external_value(
69
                PARAM_INT,
70
                'The ID of the context being graded',
71
                VALUE_REQUIRED
72
            ),
73
            'itemname' => new external_value(
74
                PARAM_ALPHANUM,
75
                'The grade item itemname being graded',
76
                VALUE_REQUIRED
77
            ),
78
            'gradeduserid' => new external_value(
79
                PARAM_INT,
80
                'The ID of the user show',
81
                VALUE_REQUIRED
82
            ),
83
        ]);
84
    }
85
 
86
    /**
87
     * Fetch the data required to build a grading panel for a simple grade.
88
     *
89
     * @param string $component
90
     * @param int $contextid
91
     * @param string $itemname
92
     * @param int $gradeduserid
93
     * @return array
94
     * @throws \dml_exception
95
     * @throws \invalid_parameter_exception
96
     * @throws \restricted_context_exception
97
     * @throws coding_exception
98
     * @throws moodle_exception
99
     * @since Moodle 3.8
100
     */
101
    public static function execute(string $component, int $contextid, string $itemname, int $gradeduserid): array {
102
        global $CFG, $USER;
103
        require_once("{$CFG->libdir}/gradelib.php");
104
        [
105
            'component' => $component,
106
            'contextid' => $contextid,
107
            'itemname' => $itemname,
108
            'gradeduserid' => $gradeduserid,
109
        ] = self::validate_parameters(self::execute_parameters(), [
110
            'component' => $component,
111
            'contextid' => $contextid,
112
            'itemname' => $itemname,
113
            'gradeduserid' => $gradeduserid,
114
        ]);
115
 
116
        // Validate the context.
117
        $context = context::instance_by_id($contextid);
118
        self::validate_context($context);
119
 
120
        // Validate that the supplied itemname is a gradable item.
121
        if (!component_gradeitems::is_valid_itemname($component, $itemname)) {
122
            throw new coding_exception("The '{$itemname}' item is not valid for the '{$component}' component");
123
        }
124
 
125
        // Fetch the gradeitem instance.
126
        $gradeitem = gradeitem::instance($component, $context, $itemname);
127
 
128
        if (MARKING_GUIDE !== $gradeitem->get_advanced_grading_method()) {
129
            throw new moodle_exception(
130
                "The {$itemname} item in {$component}/{$contextid} is not configured for advanced grading with a marking guide"
131
            );
132
        }
133
 
134
        // Fetch the actual data.
135
        $gradeduser = core_user::get_user($gradeduserid, '*', MUST_EXIST);
136
 
137
        // One can access its own grades. Others just if they're graders.
138
        if ($gradeduserid != $USER->id) {
139
            $gradeitem->require_user_can_grade($gradeduser, $USER);
140
        }
141
 
142
        return self::get_fetch_data($gradeitem, $gradeduser);
143
    }
144
 
145
    /**
146
     * Get the data to be fetched.
147
     *
148
     * @param gradeitem $gradeitem
149
     * @param stdClass $gradeduser
150
     * @return array
151
     */
152
    public static function get_fetch_data(gradeitem $gradeitem, stdClass $gradeduser): array {
153
        global $USER;
154
 
155
        $hasgrade = $gradeitem->user_has_grade($gradeduser);
156
        $grade = $gradeitem->get_formatted_grade_for_user($gradeduser, $USER);
157
        $instance = $gradeitem->get_advanced_grading_instance($USER, $grade);
158
        if (!$instance) {
159
            throw new moodle_exception('error:gradingunavailable', 'grading');
160
        }
161
        $controller = $instance->get_controller();
162
        $definition = $controller->get_definition();
163
        $fillings = $instance->get_guide_filling();
164
        $context = $controller->get_context();
165
        $definitionid = (int) $definition->id;
166
 
167
        // Set up some items we need to return on other interfaces.
168
        $gradegrade = \grade_grade::fetch(['itemid' => $gradeitem->get_grade_item()->id, 'userid' => $gradeduser->id]);
169
        $gradername = $gradegrade ? fullname(\core_user::get_user($gradegrade->usermodified)) : null;
170
        $maxgrade = max(array_keys($controller->get_grade_range()));
171
 
172
        $criterion = [];
173
        if ($definition->guide_criteria) {
174
            $criterion = array_map(function($criterion) use ($definitionid, $fillings, $context) {
175
                $result = [
176
                    'id' => $criterion['id'],
177
                    'name' => $criterion['shortname'],
178
                    'maxscore' => $criterion['maxscore'],
179
                    'description' => self::get_formatted_text(
180
                        $context,
181
                        $definitionid,
182
                        'description',
183
                        $criterion['description'],
184
                        (int) $criterion['descriptionformat']
185
                    ),
186
                    'descriptionmarkers' => self::get_formatted_text(
187
                        $context,
188
                        $definitionid,
189
                        'descriptionmarkers',
190
                        $criterion['descriptionmarkers'],
191
                        (int) $criterion['descriptionmarkersformat']
192
                    ),
193
                    'score' => null,
194
                    'remark' => null,
195
                ];
196
 
197
                if (array_key_exists($criterion['id'], $fillings['criteria'])) {
198
                    $filling = $fillings['criteria'][$criterion['id']];
199
 
200
                    $result['score'] = $filling['score'];
201
                    $result['remark'] = self::get_formatted_text(
202
                        $context,
203
                        $definitionid,
204
                        'remark',
205
                        $filling['remark'],
206
                        (int) $filling['remarkformat']
207
                    );
208
                }
209
 
210
                return $result;
211
            }, $definition->guide_criteria);
212
        }
213
 
214
        $comments = [];
215
        if ($definition->guide_comments) {
216
            $comments = array_map(function($comment) use ($definitionid, $context) {
217
                return [
218
                    'id' => $comment['id'],
219
                    'sortorder' => $comment['sortorder'],
220
                    'description' => self::get_formatted_text(
221
                        $context,
222
                        $definitionid,
223
                        'description',
224
                        $comment['description'],
225
                        (int) $comment['descriptionformat']
226
                    ),
227
                ];
228
            }, $definition->guide_comments);
229
        }
230
 
231
        return [
232
            'templatename' => 'gradingform_guide/grades/grader/gradingpanel',
233
            'hasgrade' => $hasgrade,
234
            'grade' => [
235
                'instanceid' => $instance->get_id(),
236
                'criterion' => $criterion,
237
                'hascomments' => !empty($comments),
238
                'comments' => $comments,
239
                'usergrade' => $grade->usergrade,
240
                'maxgrade' => $maxgrade,
241
                'gradedby' => $gradername,
242
                'timecreated' => $grade->timecreated,
243
                'timemodified' => $grade->timemodified,
244
            ],
245
            'warnings' => [],
246
        ];
247
    }
248
 
249
    /**
250
     * Describes the data returned from the external function.
251
     *
252
     * @return external_single_structure
253
     * @since Moodle 3.8
254
     */
255
    public static function execute_returns(): external_single_structure {
256
        return new external_single_structure([
257
            'templatename' => new external_value(PARAM_SAFEPATH, 'The template to use when rendering this data'),
258
            'hasgrade' => new external_value(PARAM_BOOL, 'Does the user have a grade?'),
259
            'grade' => new external_single_structure([
260
                'instanceid' => new external_value(PARAM_INT, 'The id of the current grading instance'),
261
                'criterion' => new external_multiple_structure(
262
                    new external_single_structure([
263
                        'id' => new external_value(PARAM_INT, 'The id of the criterion'),
264
                        'name' => new external_value(PARAM_RAW, 'The name of the criterion'),
265
                        'maxscore' => new external_value(PARAM_FLOAT, 'The maximum score for this criterion'),
266
                        'description' => new external_value(PARAM_RAW, 'The description of the criterion'),
267
                        'descriptionmarkers' => new external_value(PARAM_RAW, 'The description of the criterion for markers'),
268
                        'score' => new external_value(PARAM_FLOAT, 'The current score for user being assessed', VALUE_OPTIONAL),
269
                        'remark' => new external_value(PARAM_RAW, 'Any remarks for this criterion for the user being assessed', VALUE_OPTIONAL),
270
                    ]),
271
                    'The criterion by which this item will be graded'
272
                ),
273
                'hascomments' => new external_value(PARAM_BOOL, 'Whether there are any frequently-used comments'),
274
                'comments' => new external_multiple_structure(
275
                    new external_single_structure([
276
                        'id' => new external_value(PARAM_INT, 'Comment id'),
277
                        'sortorder' => new external_value(PARAM_INT, 'The sortorder of this comment'),
278
                        'description' => new external_value(PARAM_RAW, 'The comment value'),
279
                    ]),
280
                    'Frequently used comments'
281
                ),
282
                'usergrade' => new external_value(PARAM_RAW, 'Current user grade'),
283
                'maxgrade' => new external_value(PARAM_RAW, 'Max possible grade'),
284
                'gradedby' => new external_value(PARAM_RAW, 'The assumed grader of this grading instance'),
285
                'timecreated' => new external_value(PARAM_INT, 'The time that the grade was created'),
286
                'timemodified' => new external_value(PARAM_INT, 'The time that the grade was last updated'),
287
            ]),
288
            'warnings' => new external_warnings(),
289
        ]);
290
    }
291
 
292
    /**
293
     * Get a formatted version of the remark/description/etc.
294
     *
295
     * @param context $context
296
     * @param int $definitionid
297
     * @param string $filearea The file area of the field
298
     * @param string $text The text to be formatted
299
     * @param int $format The input format of the string
300
     * @return string
301
     */
302
    protected static function get_formatted_text(context $context, int $definitionid, string $filearea, string $text, int $format): string {
303
        $formatoptions = [
304
            'noclean' => false,
305
            'trusted' => false,
306
            'filter' => true,
307
        ];
308
 
309
        [$newtext] = \core_external\util::format_text(
310
            $text,
311
            $format,
312
            $context,
313
            'grading',
314
            $filearea,
315
            $definitionid,
316
            $formatoptions
317
        );
318
 
319
        return $newtext;
320
    }
321
}