diff --git a/.upgradenotes/MDL-85837-2025070911024739.yml b/.upgradenotes/MDL-85837-2025070911024739.yml new file mode 100644 index 00000000000..d69d36c458d --- /dev/null +++ b/.upgradenotes/MDL-85837-2025070911024739.yml @@ -0,0 +1,7 @@ +issueNumber: MDL-85837 +notes: + core_grades: + - message: >- + New 'is_gradable()' function has been created to return whether the item + has any gradeitem that is GRADE_TYPE_VALUE or GRADE_TYPE_SCALE. + type: improved diff --git a/lib/gradelib.php b/lib/gradelib.php index 4c0aece41ed..8d286b27c3e 100644 --- a/lib/gradelib.php +++ b/lib/gradelib.php @@ -305,6 +305,35 @@ function grade_update($source, $courseid, $itemtype, $itemmodule, $iteminstance, } } +/** + * Returns whether the item is gradable or not. It's considered gradable when there is at least one gradeitem + * set as GRADE_TYPE_VALUE or GRADE_TYPE_SCALE. + * + * @category grade + * @param int $courseid ID of course + * @param string $itemtype Type of grade item. For example, 'mod' or 'block' + * @param string $itemmodule More specific then $itemtype. For example, 'forum' or 'quiz'. May be NULL for some item types + * @param int $iteminstance Instance ID of graded item. For example the forum ID. + * @return bool returns true if the there is any grade item set as GRADE_TYPE_VALUE, GRADE_TYPE_SCALE. + * @category grade + */ +function is_gradable(int $courseid, string $itemtype, string $itemmodule, int $iteminstance): bool { + $items = grade_item::fetch_all([ + 'itemtype' => $itemtype, + 'itemmodule' => $itemmodule, + 'iteminstance' => $iteminstance, + 'courseid' => $courseid, + ]); + if ($items) { + foreach ($items as $item) { + if ($item->gradetype == GRADE_TYPE_VALUE || $item->gradetype == GRADE_TYPE_SCALE) { + return true; + } + } + } + return false; +} + /** * Updates a user's outcomes. Manual outcomes can not be updated. * diff --git a/lib/tests/gradelib_test.php b/lib/tests/gradelib_test.php index deb301ae048..3d20c10f5e2 100644 --- a/lib/tests/gradelib_test.php +++ b/lib/tests/gradelib_test.php @@ -58,6 +58,71 @@ final class gradelib_test extends \advanced_testcase { $this->assertTrue(grade_update_mod_grades($modinstance)); } + + /** + * Tests is_gradable() function return. + * + * @covers \is_gradable() + * @dataProvider graditems_provider + * @param array $gradetypes Grade item types to create. + * @param bool $expected The expected result for is_gradable() function. + * @return void + */ + public function test_is_gradable(array $gradetypes, bool $expected): void { + $this->resetAfterTest(); + + $generator = $this->getDataGenerator(); + $course = $generator->create_course(); + $assignment = $generator->create_module('assign', ['course' => $course->id, 'gradetype' => GRADE_TYPE_NONE]); + // Create grade items. + foreach ($gradetypes as $gradetype) { + $generator->create_grade_item( + [ + 'courseid' => $course->id, + 'itemtype' => 'mod', + 'itemmodule' => 'assign', + 'iteminstance' => $assignment->id, + 'gradetype' => $gradetype, + ] + ); + } + $this->assertEquals($expected, is_gradable($course->id, 'mod', 'assign', $assignment->id)); + } + + /** + * Data provider for testing test_is_gradable function. + * + * @return array + */ + public static function graditems_provider(): array { + return [ + 'No grade items' => [ + 'gradetypes' => [], + 'expected' => false, + ], + 'No grading item' => [ + 'gradetypes' => [GRADE_TYPE_NONE], + 'expected' => false, + ], + 'Grading by feedback' => [ + 'gradetypes' => [GRADE_TYPE_TEXT], + 'expected' => false, + ], + 'Grading by points' => [ + 'gradetypes' => [GRADE_TYPE_VALUE], + 'expected' => true, + ], + 'Grading by scale' => [ + 'gradetypes' => [GRADE_TYPE_SCALE], + 'expected' => true, + ], + 'Mix of grading' => [ + 'gradetypes' => [GRADE_TYPE_TEXT, GRADE_TYPE_NONE, GRADE_TYPE_VALUE, GRADE_TYPE_SCALE], + 'expected' => true, + ], + ]; + } + /** * Tests the function remove_grade_letters(). */