Merge branch 'MDL-76985-MOODLE_400_STABLE' of https://github.com/sh-csg/moodle into...
[moodle.git] / lib / tests / grading_external_test.php
blob2d1ef1f364ddb79a17197a32dce8b3ad8db2e82b
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.
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/>.
17 namespace core;
19 use core_grading_external;
21 defined('MOODLE_INTERNAL') || die();
23 global $CFG;
25 require_once($CFG->dirroot . '/webservice/tests/helpers.php');
27 /**
28 * Unit tests for the grading API defined in core_grading_external class.
30 * @package core
31 * @category test
32 * @copyright 2013 Paul Charsley
33 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
35 class grading_external_test extends \externallib_advanced_testcase {
37 /**
38 * Test get_definitions
40 public function test_get_definitions() {
41 global $DB, $CFG, $USER;
43 $this->resetAfterTest(true);
44 // Create a course and assignment.
45 $coursedata['idnumber'] = 'idnumbercourse';
46 $coursedata['fullname'] = 'Lightwork Course';
47 $coursedata['summary'] = 'Lightwork Course description';
48 $coursedata['summaryformat'] = FORMAT_MOODLE;
49 $course = self::getDataGenerator()->create_course($coursedata);
51 $assigndata['course'] = $course->id;
52 $assigndata['name'] = 'lightwork assignment';
54 $cm = self::getDataGenerator()->create_module('assign', $assigndata);
56 // Create manual enrolment record.
57 $manualenroldata['enrol'] = 'manual';
58 $manualenroldata['status'] = 0;
59 $manualenroldata['courseid'] = $course->id;
60 $enrolid = $DB->insert_record('enrol', $manualenroldata);
62 // Create a teacher and give them capabilities.
63 $coursecontext = \context_course::instance($course->id);
64 $roleid = $this->assignUserCapability('moodle/course:viewparticipants', $coursecontext->id, 3);
65 $modulecontext = \context_module::instance($cm->cmid);
66 $this->assignUserCapability('mod/assign:grade', $modulecontext->id, $roleid);
68 // Create the teacher's enrolment record.
69 $userenrolmentdata['status'] = 0;
70 $userenrolmentdata['enrolid'] = $enrolid;
71 $userenrolmentdata['userid'] = $USER->id;
72 $DB->insert_record('user_enrolments', $userenrolmentdata);
74 // Create a grading area.
75 $gradingarea = array(
76 'contextid' => $modulecontext->id,
77 'component' => 'mod_assign',
78 'areaname' => 'submissions',
79 'activemethod' => 'rubric'
81 $areaid = $DB->insert_record('grading_areas', $gradingarea);
83 // Create a rubric grading definition.
84 $rubricdefinition = array (
85 'areaid' => $areaid,
86 'method' => 'rubric',
87 'name' => 'test',
88 'status' => 20,
89 'copiedfromid' => 1,
90 'timecreated' => 1,
91 'usercreated' => $USER->id,
92 'timemodified' => 1,
93 'usermodified' => $USER->id,
94 'timecopied' => 0
96 $definitionid = $DB->insert_record('grading_definitions', $rubricdefinition);
98 // Create a criterion with levels.
99 $rubriccriteria1 = array (
100 'definitionid' => $definitionid,
101 'sortorder' => 1,
102 'description' => 'Demonstrate an understanding of disease control',
103 'descriptionformat' => 0
105 $criterionid1 = $DB->insert_record('gradingform_rubric_criteria', $rubriccriteria1);
106 $rubriclevel1 = array (
107 'criterionid' => $criterionid1,
108 'score' => 5,
109 'definition' => 'pass',
110 'definitionformat' => 0
112 $DB->insert_record('gradingform_rubric_levels', $rubriclevel1);
113 $rubriclevel2 = array (
114 'criterionid' => $criterionid1,
115 'score' => 10,
116 'definition' => 'excellent',
117 'definitionformat' => 0
119 $DB->insert_record('gradingform_rubric_levels', $rubriclevel2);
121 // Create a second criterion with levels.
122 $rubriccriteria2 = array (
123 'definitionid' => $definitionid,
124 'sortorder' => 2,
125 'description' => 'Demonstrate an understanding of brucellosis',
126 'descriptionformat' => 0
128 $criterionid2 = $DB->insert_record('gradingform_rubric_criteria', $rubriccriteria2);
129 $rubriclevel1 = array (
130 'criterionid' => $criterionid2,
131 'score' => 5,
132 'definition' => 'pass',
133 'definitionformat' => 0
135 $DB->insert_record('gradingform_rubric_levels', $rubriclevel1);
136 $rubriclevel2 = array (
137 'criterionid' => $criterionid2,
138 'score' => 10,
139 'definition' => 'excellent',
140 'definitionformat' => 0
142 $DB->insert_record('gradingform_rubric_levels', $rubriclevel2);
144 // Call the external function.
145 $cmids = array ($cm->cmid);
146 $areaname = 'submissions';
147 $result = core_grading_external::get_definitions($cmids, $areaname);
148 $result = \external_api::clean_returnvalue(core_grading_external::get_definitions_returns(), $result);
150 $this->assertEquals(1, count($result['areas']));
151 $this->assertEquals(1, count($result['areas'][0]['definitions']));
152 $definition = $result['areas'][0]['definitions'][0];
154 $this->assertEquals($rubricdefinition['method'], $definition['method']);
155 $this->assertEquals($USER->id, $definition['usercreated']);
157 require_once("$CFG->dirroot/grade/grading/lib.php");
158 require_once($CFG->dirroot.'/grade/grading/form/'.$rubricdefinition['method'].'/lib.php');
160 $gradingmanager = get_grading_manager($areaid);
162 $this->assertEquals(1, count($definition[$rubricdefinition['method']]));
164 $rubricdetails = $definition[$rubricdefinition['method']];
165 $details = call_user_func('gradingform_'.$rubricdefinition['method'].'_controller::get_external_definition_details');
167 $this->assertEquals(2, count($rubricdetails[key($details)]));
169 $found = false;
170 foreach ($rubricdetails[key($details)] as $criterion) {
171 if ($criterion['id'] == $criterionid1) {
172 $this->assertEquals($rubriccriteria1['description'], $criterion['description']);
173 $this->assertEquals(2, count($criterion['levels']));
174 $found = true;
175 break;
178 $this->assertTrue($found);
182 * Test get_gradingform_instances
184 public function test_get_gradingform_instances() {
185 global $DB, $USER;
187 $this->resetAfterTest(true);
188 // Create a course and assignment.
189 $coursedata['idnumber'] = 'idnumbercourse';
190 $coursedata['fullname'] = 'Lightwork Course';
191 $coursedata['summary'] = 'Lightwork Course description';
192 $coursedata['summaryformat'] = FORMAT_MOODLE;
193 $course = self::getDataGenerator()->create_course($coursedata);
195 $assigndata['course'] = $course->id;
196 $assigndata['name'] = 'lightwork assignment';
198 $assign = self::getDataGenerator()->create_module('assign', $assigndata);
200 // Create manual enrolment record.
201 $manualenroldata['enrol'] = 'manual';
202 $manualenroldata['status'] = 0;
203 $manualenroldata['courseid'] = $course->id;
204 $enrolid = $DB->insert_record('enrol', $manualenroldata);
206 // Create a teacher and give them capabilities.
207 $coursecontext = \context_course::instance($course->id);
208 $roleid = $this->assignUserCapability('moodle/course:viewparticipants', $coursecontext->id, 3);
209 $modulecontext = \context_module::instance($assign->cmid);
210 $this->assignUserCapability('mod/assign:grade', $modulecontext->id, $roleid);
212 // Create the teacher's enrolment record.
213 $userenrolmentdata['status'] = 0;
214 $userenrolmentdata['enrolid'] = $enrolid;
215 $userenrolmentdata['userid'] = $USER->id;
216 $DB->insert_record('user_enrolments', $userenrolmentdata);
218 // Create a student with an assignment grade.
219 $student = self::getDataGenerator()->create_user();
220 $assigngrade = new \stdClass();
221 $assigngrade->assignment = $assign->id;
222 $assigngrade->userid = $student->id;
223 $assigngrade->timecreated = time();
224 $assigngrade->timemodified = $assigngrade->timecreated;
225 $assigngrade->grader = $USER->id;
226 $assigngrade->grade = 50;
227 $assigngrade->attemptnumber = 0;
228 $gid = $DB->insert_record('assign_grades', $assigngrade);
230 // Create a grading area.
231 $gradingarea = array(
232 'contextid' => $modulecontext->id,
233 'component' => 'mod_assign',
234 'areaname' => 'submissions',
235 'activemethod' => 'rubric'
237 $areaid = $DB->insert_record('grading_areas', $gradingarea);
239 // Create a rubric grading definition.
240 $rubricdefinition = array (
241 'areaid' => $areaid,
242 'method' => 'rubric',
243 'name' => 'test',
244 'status' => 20,
245 'copiedfromid' => 1,
246 'timecreated' => 1,
247 'usercreated' => $USER->id,
248 'timemodified' => 1,
249 'usermodified' => $USER->id,
250 'timecopied' => 0
252 $definitionid = $DB->insert_record('grading_definitions', $rubricdefinition);
254 // Create a criterion with a level.
255 $rubriccriteria = array (
256 'definitionid' => $definitionid,
257 'sortorder' => 1,
258 'description' => 'Demonstrate an understanding of disease control',
259 'descriptionformat' => 0
261 $criterionid = $DB->insert_record('gradingform_rubric_criteria', $rubriccriteria);
262 $rubriclevel = array (
263 'criterionid' => $criterionid,
264 'score' => 50,
265 'definition' => 'pass',
266 'definitionformat' => 0
268 $levelid = $DB->insert_record('gradingform_rubric_levels', $rubriclevel);
270 // Create a grading instance.
271 $instance = array (
272 'definitionid' => $definitionid,
273 'raterid' => $USER->id,
274 'itemid' => $gid,
275 'status' => 1,
276 'feedbackformat' => 0,
277 'timemodified' => 1
279 $instanceid = $DB->insert_record('grading_instances', $instance);
281 // Create a filling.
282 $filling = array (
283 'instanceid' => $instanceid,
284 'criterionid' => $criterionid,
285 'levelid' => $levelid,
286 'remark' => 'excellent work',
287 'remarkformat' => 0
289 $DB->insert_record('gradingform_rubric_fillings', $filling);
291 // Call the external function.
292 $result = core_grading_external::get_gradingform_instances($definitionid, 0);
293 $result = \external_api::clean_returnvalue(core_grading_external::get_gradingform_instances_returns(), $result);
295 $this->assertEquals(1, count($result['instances']));
296 $this->assertEquals($USER->id, $result['instances'][0]['raterid']);
297 $this->assertEquals($gid, $result['instances'][0]['itemid']);
298 $this->assertEquals(1, $result['instances'][0]['status']);
299 $this->assertEquals(1, $result['instances'][0]['timemodified']);
300 $this->assertEquals(1, count($result['instances'][0]['rubric']));
301 $this->assertEquals(1, count($result['instances'][0]['rubric']['criteria']));
302 $criteria = $result['instances'][0]['rubric']['criteria'];
303 $this->assertEquals($criterionid, $criteria[0]['criterionid']);
304 $this->assertEquals($levelid, $criteria[0]['levelid']);
305 $this->assertEquals('excellent work', $criteria[0]['remark']);
310 * Test save_definitions for rubric grading method
312 public function test_save_definitions_rubric() {
313 global $DB, $CFG, $USER;
315 $this->resetAfterTest(true);
316 // Create a course and assignment.
317 $course = self::getDataGenerator()->create_course();
318 $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
319 $params['course'] = $course->id;
320 $instance = $generator->create_instance($params);
321 $cm = get_coursemodule_from_instance('assign', $instance->id);
322 $context = \context_module::instance($cm->id);
323 $coursecontext = \context_course::instance($course->id);
325 // Create the teacher.
326 $teacher = self::getDataGenerator()->create_user();
327 $USER->id = $teacher->id;
328 $teacherrole = $DB->get_record('role', array('shortname' => 'editingteacher'));
329 $this->assignUserCapability('moodle/grade:managegradingforms', $context->id, $teacherrole->id);
330 $this->getDataGenerator()->enrol_user($teacher->id,
331 $course->id,
332 $teacherrole->id);
334 // The grading area to insert.
335 $gradingarea = array(
336 'cmid' => $cm->id,
337 'contextid' => $context->id,
338 'component' => 'mod_assign',
339 'areaname' => 'submissions',
340 'activemethod' => 'rubric'
343 // The rubric definition to insert.
344 $rubricdefinition = array(
345 'method' => 'rubric',
346 'name' => 'test',
347 'description' => '',
348 'status' => 20,
349 'copiedfromid' => 1,
350 'timecreated' => 1,
351 'usercreated' => $teacher->id,
352 'timemodified' => 1,
353 'usermodified' => $teacher->id,
354 'timecopied' => 0
357 // The criterion to insert.
358 $rubriccriteria1 = array (
359 'sortorder' => 1,
360 'description' => 'Demonstrate an understanding of disease control',
361 'descriptionformat' => 0
364 // 3 levels for the criterion.
365 $rubriclevel1 = array (
366 'score' => 50,
367 'definition' => 'pass',
368 'definitionformat' => 0
370 $rubriclevel2 = array (
371 'score' => 100,
372 'definition' => 'excellent',
373 'definitionformat' => 0
375 $rubriclevel3 = array (
376 'score' => 0,
377 'definition' => 'fail',
378 'definitionformat' => 0
381 $rubriccriteria1['levels'] = array($rubriclevel1, $rubriclevel2, $rubriclevel3);
382 $rubricdefinition['rubric'] = array('rubric_criteria' => array($rubriccriteria1));
383 $gradingarea['definitions'] = array($rubricdefinition);
385 $results = core_grading_external::save_definitions(array($gradingarea));
387 $area = $DB->get_record('grading_areas',
388 array('contextid' => $context->id, 'component' => 'mod_assign', 'areaname' => 'submissions'),
389 '*', MUST_EXIST);
390 $this->assertEquals($area->activemethod, 'rubric');
392 $definition = $DB->get_record('grading_definitions', array('areaid' => $area->id, 'method' => 'rubric'), '*', MUST_EXIST);
393 $this->assertEquals($rubricdefinition['name'], $definition->name);
395 $criterion1 = $DB->get_record('gradingform_rubric_criteria', array('definitionid' => $definition->id), '*', MUST_EXIST);
396 $levels = $DB->get_records('gradingform_rubric_levels', array('criterionid' => $criterion1->id));
397 $validlevelcount = 0;
398 $expectedvalue = true;
399 foreach ($levels as $level) {
400 if ($level->score == 0) {
401 $this->assertEquals('fail', $level->definition);
402 $validlevelcount++;
403 } else if ($level->score == 50) {
404 $this->assertEquals('pass', $level->definition);
405 $validlevelcount++;
406 } else if ($level->score == 100) {
407 $this->assertEquals('excellent', $level->definition);
408 $excellentlevelid = $level->id;
409 $validlevelcount++;
410 } else {
411 $expectedvalue = false;
414 $this->assertEquals(3, $validlevelcount);
415 $this->assertTrue($expectedvalue, 'A level with an unexpected score was found');
417 // Test add a new level and modify an existing.
418 // Test add a new criteria and modify an existing.
419 // Test modify a definition.
421 // The rubric definition to update.
422 $rubricdefinition = array(
423 'id' => $definition->id,
424 'method' => 'rubric',
425 'name' => 'test changed',
426 'description' => '',
427 'status' => 20,
428 'copiedfromid' => 1,
429 'timecreated' => 1,
430 'usercreated' => $teacher->id,
431 'timemodified' => 1,
432 'usermodified' => $teacher->id,
433 'timecopied' => 0
436 // A criterion to update.
437 $rubriccriteria1 = array (
438 'id' => $criterion1->id,
439 'sortorder' => 1,
440 'description' => 'Demonstrate an understanding of rabies control',
441 'descriptionformat' => 0
444 // A new criterion to add.
445 $rubriccriteria2 = array (
446 'sortorder' => 2,
447 'description' => 'Demonstrate an understanding of anthrax control',
448 'descriptionformat' => 0
451 // A level to update.
452 $rubriclevel2 = array (
453 'id' => $excellentlevelid,
454 'score' => 75,
455 'definition' => 'excellent',
456 'definitionformat' => 0
459 // A level to insert.
460 $rubriclevel4 = array (
461 'score' => 100,
462 'definition' => 'superb',
463 'definitionformat' => 0
466 $rubriccriteria1['levels'] = array($rubriclevel1, $rubriclevel2, $rubriclevel3, $rubriclevel4);
467 $rubricdefinition['rubric'] = array('rubric_criteria' => array($rubriccriteria1, $rubriccriteria2));
468 $gradingarea['definitions'] = array($rubricdefinition);
470 $results = core_grading_external::save_definitions(array($gradingarea));
472 // Test definition name change.
473 $definition = $DB->get_record('grading_definitions', array('id' => $definition->id), '*', MUST_EXIST);
474 $this->assertEquals('test changed', $definition->name);
476 // Test criteria description change.
477 $modifiedcriteria = $DB->get_record('gradingform_rubric_criteria', array('id' => $criterion1->id), '*', MUST_EXIST);
478 $this->assertEquals('Demonstrate an understanding of rabies control', $modifiedcriteria->description);
480 // Test new criteria added.
481 $newcriteria = $DB->get_record('gradingform_rubric_criteria',
482 array('definitionid' => $definition->id, 'sortorder' => 2), '*', MUST_EXIST);
483 $this->assertEquals('Demonstrate an understanding of anthrax control', $newcriteria->description);
485 // Test excellent level score change from 100 to 75.
486 $modifiedlevel = $DB->get_record('gradingform_rubric_levels', array('id' => $excellentlevelid), '*', MUST_EXIST);
487 $this->assertEquals(75, $modifiedlevel->score);
489 // Test new superb level added.
490 $newlevel = $DB->get_record('gradingform_rubric_levels',
491 array('criterionid' => $criterion1->id, 'score' => 100), '*', MUST_EXIST);
492 $this->assertEquals('superb', $newlevel->definition);
494 // Test remove a level
495 // Test remove a criterion
496 // The rubric definition with the removed criterion and levels.
497 $rubricdefinition = array(
498 'id' => $definition->id,
499 'method' => 'rubric',
500 'name' => 'test changed',
501 'description' => '',
502 'status' => 20,
503 'copiedfromid' => 1,
504 'timecreated' => 1,
505 'usercreated' => $teacher->id,
506 'timemodified' => 1,
507 'usermodified' => $teacher->id,
508 'timecopied' => 0
511 $rubriccriteria1 = array (
512 'id' => $criterion1->id,
513 'sortorder' => 1,
514 'description' => 'Demonstrate an understanding of rabies control',
515 'descriptionformat' => 0
518 $rubriclevel1 = array (
519 'score' => 0,
520 'definition' => 'fail',
521 'definitionformat' => 0
523 $rubriclevel2 = array (
524 'score' => 100,
525 'definition' => 'pass',
526 'definitionformat' => 0
529 $rubriccriteria1['levels'] = array($rubriclevel1, $rubriclevel2);
530 $rubricdefinition['rubric'] = array('rubric_criteria' => array($rubriccriteria1));
531 $gradingarea['definitions'] = array($rubricdefinition);
533 $results = core_grading_external::save_definitions(array($gradingarea));
535 // Only 1 criterion should now exist.
536 $this->assertEquals(1, $DB->count_records('gradingform_rubric_criteria', array('definitionid' => $definition->id)));
537 $criterion1 = $DB->get_record('gradingform_rubric_criteria', array('definitionid' => $definition->id), '*', MUST_EXIST);
538 $this->assertEquals('Demonstrate an understanding of rabies control', $criterion1->description);
539 // This criterion should only have 2 levels.
540 $this->assertEquals(2, $DB->count_records('gradingform_rubric_levels', array('criterionid' => $criterion1->id)));
542 $gradingarea['activemethod'] = 'invalid';
543 $this->expectException('moodle_exception');
544 $results = core_grading_external::save_definitions(array($gradingarea));
549 * Tests save_definitions for the marking guide grading method
551 public function test_save_definitions_marking_guide() {
552 global $DB, $CFG, $USER;
554 $this->resetAfterTest(true);
555 // Create a course and assignment.
556 $course = self::getDataGenerator()->create_course();
557 $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
558 $params['course'] = $course->id;
559 $instance = $generator->create_instance($params);
560 $cm = get_coursemodule_from_instance('assign', $instance->id);
561 $context = \context_module::instance($cm->id);
562 $coursecontext = \context_course::instance($course->id);
564 // Create the teacher.
565 $teacher = self::getDataGenerator()->create_user();
566 $USER->id = $teacher->id;
567 $teacherrole = $DB->get_record('role', array('shortname' => 'editingteacher'));
568 $this->assignUserCapability('moodle/grade:managegradingforms', $context->id, $teacherrole->id);
569 $this->getDataGenerator()->enrol_user($teacher->id,
570 $course->id,
571 $teacherrole->id);
573 // Test insert a grading area with guide definition, criteria and comments.
574 $gradingarea = array(
575 'cmid' => $cm->id,
576 'contextid' => $context->id,
577 'component' => 'mod_assign',
578 'areaname' => 'submissions',
579 'activemethod' => 'guide'
582 $guidedefinition = array(
583 'method' => 'guide',
584 'name' => 'test',
585 'description' => '',
586 'status' => 20,
587 'copiedfromid' => 1,
588 'timecreated' => 1,
589 'usercreated' => $teacher->id,
590 'timemodified' => 1,
591 'usermodified' => $teacher->id,
592 'timecopied' => 0
595 $guidecomment = array(
596 'sortorder' => 1,
597 'description' => 'Students need to show that they understand the control of zoonoses',
598 'descriptionformat' => 0
600 $guidecriteria1 = array (
601 'sortorder' => 1,
602 'shortname' => 'Rabies Control',
603 'description' => 'Understand rabies control techniques',
604 'descriptionformat' => 0,
605 'descriptionmarkers' => 'Student must demonstrate that they understand rabies control',
606 'descriptionmarkersformat' => 0,
607 'maxscore' => 50
609 $guidecriteria2 = array (
610 'sortorder' => 2,
611 'shortname' => 'Anthrax Control',
612 'description' => 'Understand anthrax control',
613 'descriptionformat' => 0,
614 'descriptionmarkers' => 'Student must demonstrate that they understand anthrax control',
615 'descriptionmarkersformat' => 0,
616 'maxscore' => 50
619 $guidedefinition['guide'] = array('guide_criteria' => array($guidecriteria1, $guidecriteria2),
620 'guide_comments' => array($guidecomment));
621 $gradingarea['definitions'] = array($guidedefinition);
623 $results = core_grading_external::save_definitions(array($gradingarea));
624 $area = $DB->get_record('grading_areas',
625 array('contextid' => $context->id, 'component' => 'mod_assign', 'areaname' => 'submissions'),
626 '*', MUST_EXIST);
627 $this->assertEquals($area->activemethod, 'guide');
629 $definition = $DB->get_record('grading_definitions', array('areaid' => $area->id, 'method' => 'guide'), '*', MUST_EXIST);
630 $this->assertEquals($guidedefinition['name'], $definition->name);
631 $this->assertEquals(2, $DB->count_records('gradingform_guide_criteria', array('definitionid' => $definition->id)));
632 $this->assertEquals(1, $DB->count_records('gradingform_guide_comments', array('definitionid' => $definition->id)));
634 // Test removal of a criteria.
635 $guidedefinition['guide'] = array('guide_criteria' => array($guidecriteria1),
636 'guide_comments' => array($guidecomment));
637 $gradingarea['definitions'] = array($guidedefinition);
638 $results = core_grading_external::save_definitions(array($gradingarea));
639 $this->assertEquals(1, $DB->count_records('gradingform_guide_criteria', array('definitionid' => $definition->id)));
641 // Test an invalid method in the definition.
642 $guidedefinition['method'] = 'invalid';
643 $gradingarea['definitions'] = array($guidedefinition);
644 $this->expectException('invalid_parameter_exception');
645 $results = core_grading_external::save_definitions(array($gradingarea));