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