MDL-66809 core_grades: Implement scale-based marking
[moodle.git] / grade / classes / component_gradeitem.php
index c2d41bb..eae68a6 100644 (file)
@@ -99,6 +99,15 @@ abstract class component_gradeitem {
      */
     abstract protected function get_table_name(): string;
 
+    /**
+     * Get the itemid for the current gradeitem.
+     *
+     * @return int
+     */
+    public function get_grade_itemid(): int {
+        return component_gradeitems::get_itemnumber_from_itemname($this->component, $this->itemname);
+    }
+
     /**
      * Whether grading is enabled for this item.
      *
@@ -138,6 +147,8 @@ abstract class component_gradeitem {
      * @return stdClass
      */
     protected function get_scale(): ?stdClass {
+        global $DB;
+
         $gradetype = $this->get_gradeitem_value();
         if ($gradetype > 0) {
             return null;
@@ -156,7 +167,7 @@ abstract class component_gradeitem {
      *
      * @return bool
      */
-    protected function is_using_scale(): bool {
+    public function is_using_scale(): bool {
         $gradetype = $this->get_gradeitem_value();
 
         return $gradetype < 0;
@@ -289,11 +300,11 @@ abstract class component_gradeitem {
     }
 
     /**
-     * Get the advanced grading menu items.
+     * Get the list of available grade items.
      *
      * @return array
      */
-    protected function get_advanced_grading_grade_menu(): array {
+    public function get_grade_menu(): array {
         return make_grades_menu($this->get_gradeitem_value());
     }
 
@@ -302,31 +313,37 @@ abstract class component_gradeitem {
      *
      * @param float $grade The value being checked
      * @throws moodle_exception
-     * @throws rating_exception
      * @return bool
      */
     public function check_grade_validity(?float $grade): bool {
-        if ($this->is_using_scale()) {
-            // Fetch all options for this scale.
-            $scaleoptions = make_menu_from_list($this->get_scale());
-            if (!array_key_exists($grade, $scaleoptions)) {
-                // The selected option did not exist.
-                throw new rating_exception('ratinginvalid', 'rating');
-            }
-        } else if ($grade) {
-            $maxgrade = $this->get_gradeitem_value();
-            if ($grade > $maxgrade) {
-                // The grade is greater than the maximum possible value.
-                throw new moodle_exception('error:notinrange', 'core_grading', '', (object) [
-                    'maxgrade' => $maxgrade,
-                    'grade' => $grade,
-                ]);
-            } else if ($grade < 0) {
-                // Negative grades are not supported.
-                throw new moodle_exception('error:notinrange', 'core_grading', '', (object) [
-                    'maxgrade' => $maxgrade,
-                    'grade' => $grade,
-                ]);
+        $grade = grade_floatval(unformat_float($grade));
+        if ($grade) {
+            if ($this->is_using_scale()) {
+                // Fetch all options for this scale.
+                $scaleoptions = make_menu_from_list($this->get_scale()->scale);
+
+                if ($grade != -1 && !array_key_exists((int) $grade, $scaleoptions)) {
+                    // The selected option did not exist.
+                    throw new moodle_exception('error:notinrange', 'core_grading', '', (object) [
+                        'maxgrade' => count($scaleoptions),
+                        'grade' => $grade,
+                    ]);
+                }
+            } else if ($grade) {
+                $maxgrade = $this->get_gradeitem_value();
+                if ($grade > $maxgrade) {
+                    // The grade is greater than the maximum possible value.
+                    throw new moodle_exception('error:notinrange', 'core_grading', '', (object) [
+                        'maxgrade' => $maxgrade,
+                        'grade' => $grade,
+                    ]);
+                } else if ($grade < 0) {
+                    // Negative grades are not supported.
+                    throw new moodle_exception('error:notinrange', 'core_grading', '', (object) [
+                        'maxgrade' => $maxgrade,
+                        'grade' => $grade,
+                    ]);
+                }
             }
         }
 
@@ -438,7 +455,7 @@ abstract class component_gradeitem {
 
         // Set the allowed grade range.
         $gradinginstance->get_controller()->set_grade_range(
-            $this->get_advanced_grading_grade_menu(),
+            $this->get_grade_menu(),
             $this->allow_decimals()
         );