diff --git a/lib/grade/grade_category.php b/lib/grade/grade_category.php index 10656f95c82..5cd052d7436 100644 --- a/lib/grade/grade_category.php +++ b/lib/grade/grade_category.php @@ -913,7 +913,10 @@ class grade_category extends grade_object { // We're looking for other grade items with the same grade value but a higher grademax $i = 1; while ($originalindex+$i < count($grade_keys)) { + $possibleitemid = $grade_keys[$originalindex+$i]; + $i++; + if ($grade_values[$founditemid] != $grade_values[$possibleitemid]) { // The next grade item has a different grade value. Stop looking. break; @@ -930,8 +933,6 @@ class grade_category extends grade_object { $founditemid = $possibleitemid; // Continue searching to see if there is an even higher grademax } - - $i++; } // Now drop whatever grade item we have found diff --git a/lib/grade/tests/grade_category_test.php b/lib/grade/tests/grade_category_test.php index 727e69867f0..e4281a0460a 100644 --- a/lib/grade/tests/grade_category_test.php +++ b/lib/grade/tests/grade_category_test.php @@ -516,6 +516,21 @@ class grade_category_testcase extends grade_base_testcase { $this->assertEquals(count($grades), 1); $this->assertEquals($grades[$this->grade_items[2]->id], 6); + // MDL-35667 - There was an infinite loop if several items had the same grade and at least one was extra credit + $category = new grade_category(); + $category->droplow = 1; + $category->aggregation = GRADE_AGGREGATE_WEIGHTED_MEAN2; // simple weighted mean + $items[$this->grade_items[1]->id]->aggregationcoef = 1; // Mark grade item 1 as "extra credit" + $grades = array($this->grade_items[0]->id=>1, // 1 out of 110. Should be excluded from aggregation. + $this->grade_items[1]->id=>1, // 1 out of 100. Extra credit. Should be retained. + $this->grade_items[2]->id=>1, // 1 out of 6. Should be retained. + $this->grade_items[4]->id=>1);// 1 out of 100. Should be retained. + $category->apply_limit_rules($grades, $items); + $this->assertEquals(count($grades), 3); + $this->assertEquals($grades[$this->grade_items[1]->id], 1); + $this->assertEquals($grades[$this->grade_items[2]->id], 1); + $this->assertEquals($grades[$this->grade_items[4]->id], 1); + } /**