From 2e1c282ef6c1dd943481e3d22f4458eae4f9c9fb Mon Sep 17 00:00:00 2001 From: Mark Nelson Date: Thu, 17 Jun 2021 17:25:21 +0800 Subject: [PATCH 1/6] MDL-71439 core_grades: remove returning null when not possible The method explicitly declares 'stdClass' as the return type. --- grade/classes/component_gradeitem.php | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/grade/classes/component_gradeitem.php b/grade/classes/component_gradeitem.php index 1245b022dc0..7b6dec8099c 100644 --- a/grade/classes/component_gradeitem.php +++ b/grade/classes/component_gradeitem.php @@ -377,9 +377,7 @@ abstract class component_gradeitem { public function get_grade(int $gradeid): stdClass { global $DB; - $grade = $DB->get_record($this->get_table_name(), ['id' => $gradeid]); - - return $grade ?: null; + return $DB->get_record($this->get_table_name(), ['id' => $gradeid]); } /** From 581bc8d6b48aebc8a57acceea9e4e68aa02323a5 Mon Sep 17 00:00:00 2001 From: Mark Nelson Date: Thu, 17 Jun 2021 17:30:11 +0800 Subject: [PATCH 2/6] MDL-71439 core_grades: fixed undefined class issues --- grade/classes/component_gradeitem.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/grade/classes/component_gradeitem.php b/grade/classes/component_gradeitem.php index 7b6dec8099c..4c5ca423171 100644 --- a/grade/classes/component_gradeitem.php +++ b/grade/classes/component_gradeitem.php @@ -86,7 +86,7 @@ abstract class component_gradeitem { $classname = "{$component}\\grades\\{$itemname}_gradeitem"; if (!class_exists($classname)) { - throw new coding_exception("Unknown gradeitem {$itemname} for component {$classname}"); + throw new \coding_exception("Unknown gradeitem {$itemname} for component {$classname}"); } return $classname::load_from_context($context); @@ -145,7 +145,7 @@ abstract class component_gradeitem { * * @param stdClass $gradeduser The user being graded * @param stdClass $grader The user who is grading - * @throws required_capability_exception + * @throws \required_capability_exception */ abstract public function require_user_can_grade(stdClass $gradeduser, stdClass $grader): void; From 85eda546b38f822497a281b60a65e9c387ffb918 Mon Sep 17 00:00:00 2001 From: Mark Nelson Date: Thu, 17 Jun 2021 16:34:13 +0800 Subject: [PATCH 3/6] MDL-71439 core_grades: add new method 'get_formatted_grade_for_user' --- grade/classes/component_gradeitem.php | 42 ++++ grade/tests/component_gradeitem_test.php | 254 +++++++++++++++++++++++ 2 files changed, 296 insertions(+) create mode 100644 grade/tests/component_gradeitem_test.php diff --git a/grade/classes/component_gradeitem.php b/grade/classes/component_gradeitem.php index 4c5ca423171..060e5b89776 100644 --- a/grade/classes/component_gradeitem.php +++ b/grade/classes/component_gradeitem.php @@ -389,6 +389,48 @@ abstract class component_gradeitem { */ abstract public function get_grade_for_user(stdClass $gradeduser, stdClass $grader): ?stdClass; + /** + * Returns the grade that should be displayed to the user. + * + * The grade does not necessarily return a float value, this method takes grade settings into considering so + * the correct value be shown, eg. a float vs a letter. + * + * @param stdClass $gradeduser + * @param stdClass $grader + * @return stdClass|null + */ + public function get_formatted_grade_for_user(stdClass $gradeduser, stdClass $grader): ?stdClass { + global $DB; + + if ($grade = $this->get_grade_for_user($gradeduser, $grader)) { + $gradeitem = $this->get_grade_item(); + if (!$this->is_using_scale()) { + $grade->usergrade = grade_format_gradevalue($grade->grade, $gradeitem); + $grade->maxgrade = format_float($gradeitem->grademax, $gradeitem->get_decimals()); + // If displaying the raw grade, also display the total value. + if ($gradeitem->get_displaytype() == GRADE_DISPLAY_TYPE_REAL) { + $grade->usergrade .= ' / ' . $grade->maxgrade; + } + } else { + $grade->usergrade = '-'; + if ($scale = $DB->get_record('scale', ['id' => $gradeitem->scaleid])) { + $options = make_menu_from_list($scale->scale); + + $gradeint = (int) $grade->grade; + if (isset($options[$gradeint])) { + $grade->usergrade = $options[$gradeint]; + } + } + + $grade->maxgrade = format_float($gradeitem->grademax, $gradeitem->get_decimals()); + } + + return $grade; + } + + return null; + } + /** * Get the grade status for the specified user. * If the user has a grade as defined by the implementor return true else return false. diff --git a/grade/tests/component_gradeitem_test.php b/grade/tests/component_gradeitem_test.php new file mode 100644 index 00000000000..83e9855f954 --- /dev/null +++ b/grade/tests/component_gradeitem_test.php @@ -0,0 +1,254 @@ +. + +/** + * Unit tests for the class component_gradeitem. + * + * @package core_grades + * @category test + * @copyright 2021 Mark Nelson + * @license http://www.gnu.org/copyleft/gpl.html GNU Public License + */ + +namespace core_grades; + +use advanced_testcase; +use mod_forum\local\container; +use mod_forum\local\entities\forum as forum_entity; + +defined('MOODLE_INTERNAL') || die(); + +/** + * Unit tests for the class component_gradeitem. + * + * @package core_grades + * @category test + * @copyright 2021 Mark Nelson + * @license http://www.gnu.org/copyleft/gpl.html GNU Public License + */ +class component_gradeitem_test extends advanced_testcase { + + /** + * Test get_formatted_grade_for_user with points. + */ + public function test_get_formatted_grade_for_user_with_points() { + $grade = $this->initialise_test_and_get_grade_item(5, 4); + + $this->assertEquals(4, $grade->grade); + $this->assertEquals('4.00 / 5.00', $grade->usergrade); + $this->assertEquals(5, $grade->maxgrade); + } + + /** + * Test get_formatted_grade_for_user with letters. + */ + public function test_get_formatted_grade_for_user_with_letters() { + $grade = $this->initialise_test_and_get_grade_item(5, 4, GRADE_DISPLAY_TYPE_LETTER); + + $this->assertEquals(4, $grade->grade); + $this->assertEquals('B-', $grade->usergrade); + $this->assertEquals(5, $grade->maxgrade); + } + + /** + * Test get_formatted_grade_for_user with percentage. + */ + public function test_get_formatted_grade_for_user_with_percentage() { + $grade = $this->initialise_test_and_get_grade_item(5, 4, GRADE_DISPLAY_TYPE_PERCENTAGE); + + $this->assertEquals(4, $grade->grade); + $this->assertEquals('80.00 %', $grade->usergrade); + $this->assertEquals(5, $grade->maxgrade); + } + + /** + * Test get_formatted_grade_for_user with points and letter. + */ + public function test_get_formatted_grade_for_user_with_points_letter() { + $grade = $this->initialise_test_and_get_grade_item(5, 4, GRADE_DISPLAY_TYPE_REAL_LETTER); + + $this->assertEquals(4, $grade->grade); + $this->assertEquals('4.00 (B-)', $grade->usergrade); + $this->assertEquals(5, $grade->maxgrade); + } + + /** + * Test get_formatted_grade_for_user with scales. + */ + public function test_get_formatted_grade_for_user_with_scales() { + $grade = $this->initialise_test_and_get_grade_item(-2, 2); + + $this->assertEquals(2, $grade->grade); + $this->assertEquals('Competent', $grade->usergrade); + $this->assertEquals(2, $grade->maxgrade); + } + + /** + * Test get_formatted_grade_for_user with rubric. + */ + public function test_get_formatted_grade_for_user_with_rubric() { + $this->resetAfterTest(); + + $generator = \testing_util::get_data_generator(); + $rubricgenerator = $generator->get_plugin_generator('gradingform_rubric'); + + $forum = $this->get_forum_instance(); + $course = $forum->get_course_record(); + $teacher = $this->getDataGenerator()->create_and_enrol($course, 'teacher'); + $student = $this->getDataGenerator()->create_and_enrol($course); + + $this->setUser($teacher); + + $controller = $rubricgenerator->get_test_rubric($forum->get_context(), 'forum', 'forum'); + + // In the situation of mod_forum this would be the id from forum_grades. + $itemid = 1; + $instance = $controller->create_instance($student->id, $itemid); + + $spellingscore = 1; + $spellingremark = 'Too many mistakes. Please try again.'; + $picturescore = 2; + $pictureremark = 'Great number of pictures. Well done.'; + + $submissiondata = $rubricgenerator->get_test_form_data( + $controller, + (int) $student->id, + $spellingscore, + $spellingremark, + $picturescore, + $pictureremark + ); + + $gradeitem = component_gradeitem::instance('mod_forum', $forum->get_context(), 'forum'); + $gradeitem->store_grade_from_formdata($student, $teacher, (object) [ + 'instanceid' => $instance->get_id(), + 'advancedgrading' => $submissiondata, + ]); + + $this->setUser($student); + + $result = $gradeitem->get_formatted_grade_for_user($student, $teacher); + + $this->assertEquals(75, $result->grade); + $this->assertEquals('75.00 / 100.00', $result->usergrade); + $this->assertEquals(100, $result->maxgrade); + } + + /** + * Test get_formatted_grade_for_user with a marking guide. + */ + public function test_get_formatted_grade_for_user_with_marking_guide() { + $this->resetAfterTest(); + + $generator = \testing_util::get_data_generator(); + $guidegenerator = $generator->get_plugin_generator('gradingform_guide'); + + $forum = $this->get_forum_instance(); + $course = $forum->get_course_record(); + $teacher = $this->getDataGenerator()->create_and_enrol($course, 'teacher'); + $student = $this->getDataGenerator()->create_and_enrol($course); + + $this->setUser($teacher); + + $controller = $guidegenerator->get_test_guide($forum->get_context(), 'forum', 'forum'); + + // In the situation of mod_forum this would be the id from forum_grades. + $itemid = 1; + $instance = $controller->create_instance($student->id, $itemid); + + $spellingscore = 10; + $spellingremark = 'Propper good speling'; + $picturescore = 0; + $pictureremark = 'ASCII art is not a picture'; + + $submissiondata = $guidegenerator->get_test_form_data($controller, + $itemid, + $spellingscore, + $spellingremark, + $picturescore, + $pictureremark + ); + + $gradeitem = component_gradeitem::instance('mod_forum', $forum->get_context(), 'forum'); + $gradeitem->store_grade_from_formdata($student, $teacher, (object) [ + 'instanceid' => $instance->get_id(), + 'advancedgrading' => $submissiondata, + ]); + + $this->setUser($student); + + $result = $gradeitem->get_formatted_grade_for_user($student, $teacher); + + $this->assertEquals(25, $result->grade); + $this->assertEquals('25.00 / 100.00', $result->usergrade); + $this->assertEquals(100, $result->maxgrade); + } + + /** + * Initialise test and returns the grade item. + * + * @param int $gradeforum The grade_forum value for the forum. + * @param int $gradegiven The grade given by the teacher. + * @param int|null $displaytype The display type of the grade. + * @return \stdClass|null + */ + protected function initialise_test_and_get_grade_item(int $gradeforum, int $gradegiven, int $displaytype = null): \stdClass { + $this->resetAfterTest(); + + $forum = $this->get_forum_instance([ + // Negative numbers mean a scale, positive numbers represent the maximum mark. + 'grade_forum' => $gradeforum, + ]); + $course = $forum->get_course_record(); + $teacher = $this->getDataGenerator()->create_and_enrol($course, 'teacher'); + $student = $this->getDataGenerator()->create_and_enrol($course); + + $this->setUser($teacher); + + // Get the grade item. + $gradeitem = component_gradeitem::instance('mod_forum', $forum->get_context(), 'forum'); + + // Grade the student. + $gradeitem->store_grade_from_formdata($student, $teacher, (object) ['grade' => $gradegiven]); + + // Change the 'Grade display type' if specified. + if ($displaytype) { + grade_set_setting($course->id, 'displaytype', $displaytype); + } + + return $gradeitem->get_formatted_grade_for_user($student, $teacher); + } + + /** + * Get a forum instance. + * + * @param array $config + * @return forum_entity + */ + protected function get_forum_instance(array $config = []): forum_entity { + $this->resetAfterTest(); + + $datagenerator = $this->getDataGenerator(); + $course = $datagenerator->create_course(); + $forum = $datagenerator->create_module('forum', array_merge(['course' => $course->id, + 'grade_forum' => 100], $config)); + + $vaultfactory = container::get_vault_factory(); + $vault = $vaultfactory->get_forum_vault(); + + return $vault->get_from_id((int) $forum->id); + } +} From 4eecb896a20760f7ca81bc420e313c7d603fff9d Mon Sep 17 00:00:00 2001 From: Mark Nelson Date: Fri, 25 Jun 2021 15:29:09 +0800 Subject: [PATCH 4/6] MDL-71439 core_grades: return result of new method in web services --- .../grades/grader/gradingpanel/point/external/fetch.php | 7 +++---- .../grades/grader/gradingpanel/point/external/store.php | 5 ++--- .../grades/grader/gradingpanel/scale/external/fetch.php | 4 ++-- .../grades/grader/gradingpanel/external/fetch.php | 4 ++-- ...des_grader_gradingpanel_guide_external_fetch_test.php | 4 ++-- ...des_grader_gradingpanel_guide_external_store_test.php | 2 +- .../grades/grader/gradingpanel/external/fetch.php | 4 ++-- ...es_grader_gradingpanel_rubric_external_fetch_test.php | 4 ++-- ...es_grader_gradingpanel_rubric_external_store_test.php | 2 +- ...des_grader_gradingpanel_point_external_fetch_test.php | 4 ++-- ...des_grader_gradingpanel_point_external_store_test.php | 9 ++++----- ...des_grader_gradingpanel_scale_external_fetch_test.php | 4 ++-- ...des_grader_gradingpanel_scale_external_store_test.php | 6 +++--- 13 files changed, 28 insertions(+), 31 deletions(-) diff --git a/grade/classes/grades/grader/gradingpanel/point/external/fetch.php b/grade/classes/grades/grader/gradingpanel/point/external/fetch.php index 108724ed7ed..09fbb4ea22e 100644 --- a/grade/classes/grades/grader/gradingpanel/point/external/fetch.php +++ b/grade/classes/grades/grader/gradingpanel/point/external/fetch.php @@ -136,14 +136,13 @@ class fetch extends external_api { } $hasgrade = $gradeitem->user_has_grade($gradeduser); - $grade = $gradeitem->get_grade_for_user($gradeduser, $USER); + $grade = $gradeitem->get_formatted_grade_for_user($gradeduser, $USER); // Set up some items we need to return on other interfaces. $gradegrade = \grade_grade::fetch(['itemid' => $gradeitem->get_grade_item()->id, 'userid' => $gradeduser->id]); $gradername = $gradegrade ? fullname(\core_user::get_user($gradegrade->usermodified)) : null; - $maxgrade = (int) $gradeitem->get_grade_item()->grademax; - return self::get_fetch_data($grade, $hasgrade, $maxgrade, $gradername); + return self::get_fetch_data($grade, $hasgrade, (int) $grade->maxgrade, $gradername); } /** @@ -161,7 +160,7 @@ class fetch extends external_api { 'hasgrade' => $hasgrade, 'grade' => [ 'grade' => $grade->grade, - 'usergrade' => $grade->grade, + 'usergrade' => $grade->usergrade, 'maxgrade' => $maxgrade, 'gradedby' => $gradername, 'timecreated' => $grade->timecreated, diff --git a/grade/classes/grades/grader/gradingpanel/point/external/store.php b/grade/classes/grades/grader/gradingpanel/point/external/store.php index 54880279388..92a723630b0 100644 --- a/grade/classes/grades/grader/gradingpanel/point/external/store.php +++ b/grade/classes/grades/grader/gradingpanel/point/external/store.php @@ -170,13 +170,12 @@ class store extends external_api { } // Fetch the updated grade back out. - $grade = $gradeitem->get_grade_for_user($gradeduser, $USER); + $grade = $gradeitem->get_formatted_grade_for_user($gradeduser, $USER); $gradegrade = \grade_grade::fetch(['itemid' => $gradeitem->get_grade_item()->id, 'userid' => $gradeduser->id]); $gradername = $gradegrade ? fullname(\core_user::get_user($gradegrade->usermodified)) : null; - $maxgrade = (int) $gradeitem->get_grade_item()->grademax; - return fetch::get_fetch_data($grade, $hasgrade, $maxgrade, $gradername); + return fetch::get_fetch_data($grade, $hasgrade, (int) $grade->maxgrade, $gradername); } /** diff --git a/grade/classes/grades/grader/gradingpanel/scale/external/fetch.php b/grade/classes/grades/grader/gradingpanel/scale/external/fetch.php index 3501e31a629..87f4c0465b6 100644 --- a/grade/classes/grades/grader/gradingpanel/scale/external/fetch.php +++ b/grade/classes/grades/grader/gradingpanel/scale/external/fetch.php @@ -155,7 +155,7 @@ class fetch extends external_api { global $USER; $hasgrade = $gradeitem->user_has_grade($gradeduser); - $grade = $gradeitem->get_grade_for_user($gradeduser, $USER); + $grade = $gradeitem->get_formatted_grade_for_user($gradeduser, $USER); $currentgrade = (int) unformat_float($grade->grade); $menu = $gradeitem->get_grade_menu(); @@ -172,7 +172,7 @@ class fetch extends external_api { 'hasgrade' => $hasgrade, 'grade' => [ 'options' => $values, - 'usergrade' => $grade->grade, + 'usergrade' => $grade->usergrade, 'maxgrade' => $maxgrade, 'gradedby' => $gradername, 'timecreated' => $grade->timecreated, diff --git a/grade/grading/form/guide/classes/grades/grader/gradingpanel/external/fetch.php b/grade/grading/form/guide/classes/grades/grader/gradingpanel/external/fetch.php index 79d678359b2..c07cb5c0c60 100644 --- a/grade/grading/form/guide/classes/grades/grader/gradingpanel/external/fetch.php +++ b/grade/grading/form/guide/classes/grades/grader/gradingpanel/external/fetch.php @@ -154,7 +154,7 @@ class fetch extends external_api { global $USER; $hasgrade = $gradeitem->user_has_grade($gradeduser); - $grade = $gradeitem->get_grade_for_user($gradeduser, $USER); + $grade = $gradeitem->get_formatted_grade_for_user($gradeduser, $USER); $instance = $gradeitem->get_advanced_grading_instance($USER, $grade); if (!$instance) { throw new moodle_exception('error:gradingunavailable', 'grading'); @@ -237,7 +237,7 @@ class fetch extends external_api { 'criterion' => $criterion, 'hascomments' => !empty($comments), 'comments' => $comments, - 'usergrade' => $grade->grade, + 'usergrade' => $grade->usergrade, 'maxgrade' => $maxgrade, 'gradedby' => $gradername, 'timecreated' => $grade->timecreated, diff --git a/grade/grading/form/guide/tests/grades_grader_gradingpanel_guide_external_fetch_test.php b/grade/grading/form/guide/tests/grades_grader_gradingpanel_guide_external_fetch_test.php index 77c05972866..95132f8027d 100644 --- a/grade/grading/form/guide/tests/grades_grader_gradingpanel_guide_external_fetch_test.php +++ b/grade/grading/form/guide/tests/grades_grader_gradingpanel_guide_external_fetch_test.php @@ -136,7 +136,7 @@ class fetch_test extends advanced_testcase { $this->assertIsInt($result['grade']['timemodified']); $this->assertArrayHasKey('usergrade', $result['grade']); - $this->assertEquals(0, $result['grade']['usergrade']); + $this->assertEquals('- / 100.00', $result['grade']['usergrade']); $this->assertArrayHasKey('maxgrade', $result['grade']); $this->assertIsInt($result['grade']['maxgrade']); @@ -275,7 +275,7 @@ class fetch_test extends advanced_testcase { $this->assertIsInt($result['grade']['timemodified']); $this->assertArrayHasKey('usergrade', $result['grade']); - $this->assertEquals(25, $result['grade']['usergrade']); + $this->assertEquals('25.00 / 100.00', $result['grade']['usergrade']); $this->assertArrayHasKey('maxgrade', $result['grade']); $this->assertIsInt($result['grade']['maxgrade']); diff --git a/grade/grading/form/guide/tests/grades_grader_gradingpanel_guide_external_store_test.php b/grade/grading/form/guide/tests/grades_grader_gradingpanel_guide_external_store_test.php index 89296feaa34..5e428d3513a 100644 --- a/grade/grading/form/guide/tests/grades_grader_gradingpanel_guide_external_store_test.php +++ b/grade/grading/form/guide/tests/grades_grader_gradingpanel_guide_external_store_test.php @@ -168,7 +168,7 @@ class store_test extends advanced_testcase { $this->assertIsInt($result['grade']['timemodified']); $this->assertArrayHasKey('usergrade', $result['grade']); - $this->assertEquals(0.5, $result['grade']['usergrade']); + $this->assertEquals('0.50 / 2.00', $result['grade']['usergrade']); $this->assertArrayHasKey('maxgrade', $result['grade']); $this->assertIsInt($result['grade']['maxgrade']); diff --git a/grade/grading/form/rubric/classes/grades/grader/gradingpanel/external/fetch.php b/grade/grading/form/rubric/classes/grades/grader/gradingpanel/external/fetch.php index 49fa81d21a9..e5081d75864 100644 --- a/grade/grading/form/rubric/classes/grades/grader/gradingpanel/external/fetch.php +++ b/grade/grading/form/rubric/classes/grades/grader/gradingpanel/external/fetch.php @@ -147,7 +147,7 @@ class fetch extends external_api { global $USER; // Set up all the controllers etc that we'll be needing. $hasgrade = $gradeitem->user_has_grade($gradeduser); - $grade = $gradeitem->get_grade_for_user($gradeduser, $USER); + $grade = $gradeitem->get_formatted_grade_for_user($gradeduser, $USER); $instance = $gradeitem->get_advanced_grading_instance($USER, $grade); if (!$instance) { throw new moodle_exception('error:gradingunavailable', 'grading'); @@ -252,7 +252,7 @@ class fetch extends external_api { 'rubricmode' => 'evaluate editable', 'teacherdescription' => $teacherdescription, 'canedit' => false, - 'usergrade' => $grade->grade, + 'usergrade' => $grade->usergrade, 'maxgrade' => $maxgrade, 'gradedby' => $gradername, 'timecreated' => $grade->timecreated, diff --git a/grade/grading/form/rubric/tests/grades_grader_gradingpanel_rubric_external_fetch_test.php b/grade/grading/form/rubric/tests/grades_grader_gradingpanel_rubric_external_fetch_test.php index c62bf381aa5..2db09d99a98 100644 --- a/grade/grading/form/rubric/tests/grades_grader_gradingpanel_rubric_external_fetch_test.php +++ b/grade/grading/form/rubric/tests/grades_grader_gradingpanel_rubric_external_fetch_test.php @@ -137,7 +137,7 @@ class fetch_test extends advanced_testcase { $this->assertIsInt($result['grade']['timemodified']); $this->assertArrayHasKey('usergrade', $result['grade']); - $this->assertEquals(0, $result['grade']['usergrade']); + $this->assertEquals('- / 100.00', $result['grade']['usergrade']); $this->assertArrayHasKey('maxgrade', $result['grade']); $this->assertIsInt($result['grade']['maxgrade']); @@ -282,7 +282,7 @@ class fetch_test extends advanced_testcase { $this->assertIsInt($result['grade']['timemodified']); $this->assertArrayHasKey('usergrade', $result['grade']); - $this->assertEquals(50, $result['grade']['usergrade']); + $this->assertEquals('50.00 / 100.00', $result['grade']['usergrade']); $this->assertArrayHasKey('maxgrade', $result['grade']); $this->assertIsInt($result['grade']['maxgrade']); diff --git a/grade/grading/form/rubric/tests/grades_grader_gradingpanel_rubric_external_store_test.php b/grade/grading/form/rubric/tests/grades_grader_gradingpanel_rubric_external_store_test.php index e7b8aafab14..4d666cfda3b 100644 --- a/grade/grading/form/rubric/tests/grades_grader_gradingpanel_rubric_external_store_test.php +++ b/grade/grading/form/rubric/tests/grades_grader_gradingpanel_rubric_external_store_test.php @@ -167,7 +167,7 @@ class store_test extends advanced_testcase { $this->assertIsInt($result['grade']['timemodified']); $this->assertArrayHasKey('usergrade', $result['grade']); - $this->assertEquals(1, $result['grade']['usergrade']); + $this->assertEquals('1.00 / 2.00', $result['grade']['usergrade']); $this->assertArrayHasKey('maxgrade', $result['grade']); $this->assertIsInt($result['grade']['maxgrade']); diff --git a/grade/tests/grades_grader_gradingpanel_point_external_fetch_test.php b/grade/tests/grades_grader_gradingpanel_point_external_fetch_test.php index 208693bd486..9dc2cb221ff 100644 --- a/grade/tests/grades_grader_gradingpanel_point_external_fetch_test.php +++ b/grade/tests/grades_grader_gradingpanel_point_external_fetch_test.php @@ -138,7 +138,7 @@ class fetch_test extends advanced_testcase { $this->assertIsInt($result['grade']['timemodified']); $this->assertArrayHasKey('usergrade', $result['grade']); - $this->assertEquals(0, $result['grade']['usergrade']); + $this->assertEquals('- / 5.00', $result['grade']['usergrade']); $this->assertArrayHasKey('maxgrade', $result['grade']); $this->assertIsInt($result['grade']['maxgrade']); @@ -239,7 +239,7 @@ class fetch_test extends advanced_testcase { $this->assertIsInt($result['grade']['timemodified']); $this->assertArrayHasKey('usergrade', $result['grade']); - $this->assertEquals(4, $result['grade']['usergrade']); + $this->assertEquals('4.00 / 5.00', $result['grade']['usergrade']); $this->assertArrayHasKey('maxgrade', $result['grade']); $this->assertIsInt($result['grade']['maxgrade']); diff --git a/grade/tests/grades_grader_gradingpanel_point_external_store_test.php b/grade/tests/grades_grader_gradingpanel_point_external_store_test.php index 05494286f56..57649ab14dd 100644 --- a/grade/tests/grades_grader_gradingpanel_point_external_store_test.php +++ b/grade/tests/grades_grader_gradingpanel_point_external_store_test.php @@ -174,7 +174,7 @@ class store_test extends advanced_testcase { $this->assertIsInt($result['grade']['timemodified']); $this->assertArrayHasKey('usergrade', $result['grade']); - $this->assertEquals(null, $result['grade']['usergrade']); + $this->assertEquals('- / 5.00', $result['grade']['usergrade']); $this->assertArrayHasKey('maxgrade', $result['grade']); $this->assertIsInt($result['grade']['maxgrade']); @@ -217,7 +217,6 @@ class store_test extends advanced_testcase { $formdata = [ 'grade' => 4, ]; - $formattedvalue = grade_floatval(unformat_float(4)); $gradeitem = component_gradeitem::instance('mod_forum', $forum->get_context(), 'forum'); @@ -240,14 +239,14 @@ class store_test extends advanced_testcase { $this->assertIsArray($result['grade']); $this->assertArrayHasKey('grade', $result['grade']); - $this->assertEquals($formattedvalue, $result['grade']['grade']); + $this->assertEquals(grade_floatval(unformat_float(4)), $result['grade']['grade']); $this->assertIsInt($result['grade']['timecreated']); $this->assertArrayHasKey('timemodified', $result['grade']); $this->assertIsInt($result['grade']['timemodified']); $this->assertArrayHasKey('usergrade', $result['grade']); - $this->assertEquals($formattedvalue, $result['grade']['usergrade']); + $this->assertEquals('4.00 / 5.00', $result['grade']['usergrade']); $this->assertArrayHasKey('maxgrade', $result['grade']); $this->assertIsInt($result['grade']['maxgrade']); @@ -269,7 +268,7 @@ class store_test extends advanced_testcase { 'itemid' => $storedgradeitem->id, ]); - $this->assertEquals($formattedvalue, $storedgrade->rawgrade); + $this->assertEquals(grade_floatval(unformat_float(4)), $storedgrade->rawgrade); } /** diff --git a/grade/tests/grades_grader_gradingpanel_scale_external_fetch_test.php b/grade/tests/grades_grader_gradingpanel_scale_external_fetch_test.php index 9a8ec1d0543..863f328109a 100644 --- a/grade/tests/grades_grader_gradingpanel_scale_external_fetch_test.php +++ b/grade/tests/grades_grader_gradingpanel_scale_external_fetch_test.php @@ -142,7 +142,7 @@ class fetch_test extends advanced_testcase { $this->assertIsInt($result['grade']['timemodified']); $this->assertArrayHasKey('usergrade', $result['grade']); - $this->assertEquals(0, $result['grade']['usergrade']); + $this->assertEquals('-', $result['grade']['usergrade']); $this->assertArrayHasKey('maxgrade', $result['grade']); $this->assertIsInt($result['grade']['maxgrade']); @@ -286,7 +286,7 @@ class fetch_test extends advanced_testcase { $this->assertIsInt($result['grade']['timemodified']); $this->assertArrayHasKey('usergrade', $result['grade']); - $this->assertEquals(2, $result['grade']['usergrade']); + $this->assertEquals('B', $result['grade']['usergrade']); $this->assertArrayHasKey('maxgrade', $result['grade']); $this->assertIsInt($result['grade']['maxgrade']); diff --git a/grade/tests/grades_grader_gradingpanel_scale_external_store_test.php b/grade/tests/grades_grader_gradingpanel_scale_external_store_test.php index b389b07e951..d127ab85ebb 100644 --- a/grade/tests/grades_grader_gradingpanel_scale_external_store_test.php +++ b/grade/tests/grades_grader_gradingpanel_scale_external_store_test.php @@ -160,7 +160,7 @@ class store_test extends advanced_testcase { $this->assertIsInt($result['grade']['timemodified']); $this->assertArrayHasKey('usergrade', $result['grade']); - $this->assertEquals(0, $result['grade']['usergrade']); + $this->assertEquals('-', $result['grade']['usergrade']); $this->assertArrayHasKey('maxgrade', $result['grade']); $this->assertIsInt($result['grade']['maxgrade']); @@ -244,7 +244,7 @@ class store_test extends advanced_testcase { $this->assertIsInt($result['grade']['timemodified']); $this->assertArrayHasKey('usergrade', $result['grade']); - $this->assertEquals(-1, $result['grade']['usergrade']); + $this->assertEquals('-', $result['grade']['usergrade']); $this->assertArrayHasKey('maxgrade', $result['grade']); $this->assertIsInt($result['grade']['maxgrade']); @@ -331,7 +331,7 @@ class store_test extends advanced_testcase { $this->assertIsInt($result['grade']['timemodified']); $this->assertArrayHasKey('usergrade', $result['grade']); - $this->assertEquals(2, $result['grade']['usergrade']); + $this->assertEquals('B', $result['grade']['usergrade']); $this->assertArrayHasKey('maxgrade', $result['grade']); $this->assertIsInt($result['grade']['maxgrade']); From 2621d36782be01124e3dea0f40e6086e58dcc27b Mon Sep 17 00:00:00 2001 From: Mark Nelson Date: Fri, 25 Jun 2021 18:23:16 +0800 Subject: [PATCH 5/6] MDL-71439 mod_forum: display user grade from web service --- mod/forum/templates/local/grades/view_grade.mustache | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mod/forum/templates/local/grades/view_grade.mustache b/mod/forum/templates/local/grades/view_grade.mustache index 6b88e58b106..b5db349afe4 100644 --- a/mod/forum/templates/local/grades/view_grade.mustache +++ b/mod/forum/templates/local/grades/view_grade.mustache @@ -41,7 +41,7 @@ {{#grade}}
{{#str}}gradenoun{{/str}}:
-

{{usergrade}} / {{maxgrade}}

+

{{usergrade}}

{{#str}}gradedby, forum{{/str}}:
From 7bf0b6ab5188027d3946c07437615f9b56635d6a Mon Sep 17 00:00:00 2001 From: Mark Nelson Date: Mon, 28 Jun 2021 16:17:38 +0800 Subject: [PATCH 6/6] MDL-71439 core_grades: return a blank mustache template for letters --- .../gradingpanel/point/external/fetch.php | 25 +++++++++++++---- .../gradingpanel/point/external/store.php | 2 +- .../grader/gradingpanel/point_blank.mustache | 28 +++++++++++++++++++ 3 files changed, 49 insertions(+), 6 deletions(-) create mode 100644 grade/templates/grades/grader/gradingpanel/point_blank.mustache diff --git a/grade/classes/grades/grader/gradingpanel/point/external/fetch.php b/grade/classes/grades/grader/gradingpanel/point/external/fetch.php index 09fbb4ea22e..e9cc279bae7 100644 --- a/grade/classes/grades/grader/gradingpanel/point/external/fetch.php +++ b/grade/classes/grades/grader/gradingpanel/point/external/fetch.php @@ -137,12 +137,13 @@ class fetch extends external_api { $hasgrade = $gradeitem->user_has_grade($gradeduser); $grade = $gradeitem->get_formatted_grade_for_user($gradeduser, $USER); + $isgrading = $gradeitem->user_can_grade($gradeduser, $USER); // Set up some items we need to return on other interfaces. $gradegrade = \grade_grade::fetch(['itemid' => $gradeitem->get_grade_item()->id, 'userid' => $gradeduser->id]); $gradername = $gradegrade ? fullname(\core_user::get_user($gradegrade->usermodified)) : null; - return self::get_fetch_data($grade, $hasgrade, (int) $grade->maxgrade, $gradername); + return self::get_fetch_data($grade, $hasgrade, $gradeitem, $gradername, $isgrading); } /** @@ -150,18 +151,32 @@ class fetch extends external_api { * * @param stdClass $grade * @param bool $hasgrade - * @param int $maxgrade + * @param gradeitem $gradeitem * @param string|null $gradername + * @param bool $isgrading * @return array */ - public static function get_fetch_data(stdClass $grade, bool $hasgrade, int $maxgrade, ?string $gradername): array { + public static function get_fetch_data(stdClass $grade, + bool $hasgrade, + gradeitem $gradeitem, + ?string $gradername, + bool $isgrading = false + ): array { + $templatename = 'core_grades/grades/grader/gradingpanel/point'; + + // We do not want to display anything if we are showing the grade as a letter. For example the 'Grade' might + // read 'B-'. We do not want to show the user the actual point they were given. See MDL-71439. + if (($gradeitem->get_grade_item()->get_displaytype() == GRADE_DISPLAY_TYPE_LETTER) && !$isgrading) { + $templatename = 'core_grades/grades/grader/gradingpanel/point_blank'; + } + return [ - 'templatename' => 'core_grades/grades/grader/gradingpanel/point', + 'templatename' => $templatename, 'hasgrade' => $hasgrade, 'grade' => [ 'grade' => $grade->grade, 'usergrade' => $grade->usergrade, - 'maxgrade' => $maxgrade, + 'maxgrade' => (int) $grade->maxgrade, 'gradedby' => $gradername, 'timecreated' => $grade->timecreated, 'timemodified' => $grade->timemodified, diff --git a/grade/classes/grades/grader/gradingpanel/point/external/store.php b/grade/classes/grades/grader/gradingpanel/point/external/store.php index 92a723630b0..e419832a7dd 100644 --- a/grade/classes/grades/grader/gradingpanel/point/external/store.php +++ b/grade/classes/grades/grader/gradingpanel/point/external/store.php @@ -175,7 +175,7 @@ class store extends external_api { $gradegrade = \grade_grade::fetch(['itemid' => $gradeitem->get_grade_item()->id, 'userid' => $gradeduser->id]); $gradername = $gradegrade ? fullname(\core_user::get_user($gradegrade->usermodified)) : null; - return fetch::get_fetch_data($grade, $hasgrade, (int) $grade->maxgrade, $gradername); + return fetch::get_fetch_data($grade, $hasgrade, $gradeitem, $gradername); } /** diff --git a/grade/templates/grades/grader/gradingpanel/point_blank.mustache b/grade/templates/grades/grader/gradingpanel/point_blank.mustache new file mode 100644 index 00000000000..6c41562a4e9 --- /dev/null +++ b/grade/templates/grades/grader/gradingpanel/point_blank.mustache @@ -0,0 +1,28 @@ +{{! + This file is part of Moodle - http://moodle.org/ + + Moodle is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Moodle is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Moodle. If not, see . +}} +{{! + @template core_grades/grades/grader/gradingpanel/point_black + + Point-based grading template for use in the grading panel. + + Context variables required for this template: + + Example context (json): + { + + } +}} \ No newline at end of file