diff --git a/lib/grade/grade_grade.php b/lib/grade/grade_grade.php index a083ffc6188..7476ac4ce28 100644 --- a/lib/grade/grade_grade.php +++ b/lib/grade/grade_grade.php @@ -718,6 +718,14 @@ class grade_grade extends grade_object { protected static function flatten_dependencies_array(&$dependson, &$dependencydepth) { // Flatten the nested dependencies - this will handle recursion bombs because it removes duplicates. $somethingchanged = true; + // First of all, delete any incorrect (not array or individual null) dependency, they aren't welcome. + // TODO: Maybe we should report about this happening, it shouldn't if all dependencies are correct and consistent. + foreach ($dependson as $itemid => $depends) { + $depends = is_array($depends) ? $depends : []; // Only arrays are accepted. + $dependson[$itemid] = array_filter($depends, function($val) { // Only not-null values are accepted. + return !is_null($val); + }); + } while ($somethingchanged) { $somethingchanged = false; @@ -725,7 +733,7 @@ class grade_grade extends grade_object { // Make a copy so we can tell if it changed. $before = $dependson[$itemid]; foreach ($depends as $subitemid => $subdepends) { - $dependson[$itemid] = array_unique(array_merge($depends, $dependson[$subdepends])); + $dependson[$itemid] = array_unique(array_merge($depends, $dependson[$subdepends] ?? [])); sort($dependson[$itemid], SORT_NUMERIC); } if ($before != $dependson[$itemid]) { diff --git a/lib/grade/tests/grade_grade_test.php b/lib/grade/tests/grade_grade_test.php index c9723d9e38c..488ae73df44 100644 --- a/lib/grade/tests/grade_grade_test.php +++ b/lib/grade/tests/grade_grade_test.php @@ -196,6 +196,11 @@ class core_grade_grade_testcase extends grade_base_testcase { $this->assertTrue($grade->is_hidden()); } + /** + * Test grade_grade::flatten_dependencies_array() + * + * @covers \grade_grade::flatten_dependencies_array() + */ public function test_flatten_dependencies() { // First test a simple normal case. $a = array(1 => array(2, 3), 2 => array(), 3 => array(4), 4 => array()); @@ -231,6 +236,66 @@ class core_grade_grade_testcase extends grade_base_testcase { test_grade_grade_flatten_dependencies_array::test_flatten_dependencies_array($a, $b); $this->assertSame($expecteda, $a); + + // Missing first level dependency. + $a = array(1 => array(2, 3), 3 => array(4), 4 => array()); + $b = array(); + $expecteda = array(1 => array(2, 3, 4), 3 => array(4), 4 => array()); + $expectedb = array(1 => 1); + + test_grade_grade_flatten_dependencies_array::test_flatten_dependencies_array($a, $b); + $this->assertSame($expecteda, $a); + $this->assertSame($expectedb, $b); + + // Missing 2nd level dependency. + $a = array(1 => array(2, 3), 2 => array(), 3 => array(4)); + $b = array(); + $expecteda = array(1 => array(2, 3, 4), 2 => array(), 3 => array(4)); + $expectedb = array(1 => 1); + + test_grade_grade_flatten_dependencies_array::test_flatten_dependencies_array($a, $b); + $this->assertSame($expecteda, $a); + $this->assertSame($expectedb, $b); + + // Null first level dependency. + $a = array(1 => array(2, null), 2 => array(3), 3 => array(4), 4 => array()); + $b = array(); + $expecteda = array(1 => array(2, 3, 4), 2 => array(3, 4), 3 => array(4), 4 => array()); + $expectedb = array(1 => 2, 2 => 1); + + test_grade_grade_flatten_dependencies_array::test_flatten_dependencies_array($a, $b); + $this->assertSame($expecteda, $a); + $this->assertSame($expectedb, $b); + + // Null 2nd level dependency. + $a = array(1 => array(2, 3), 2 => array(), 3 => array(4), 4 => array(null)); + $b = array(); + $expecteda = array(1 => array(2, 3, 4), 2 => array(), 3 => array(4), 4 => array()); + $expectedb = array(1 => 1); + + test_grade_grade_flatten_dependencies_array::test_flatten_dependencies_array($a, $b); + $this->assertSame($expecteda, $a); + $this->assertSame($expectedb, $b); + + // Straight null dependency. + $a = array(1 => array(2, 3), 2 => array(), 3 => array(4), 4 => null); + $b = array(); + $expecteda = array(1 => array(2, 3, 4), 2 => array(), 3 => array(4), 4 => array()); + $expectedb = array(1 => 1); + + test_grade_grade_flatten_dependencies_array::test_flatten_dependencies_array($a, $b); + $this->assertSame($expecteda, $a); + $this->assertSame($expectedb, $b); + + // Also incorrect non-array dependency. + $a = array(1 => array(2, 3), 2 => array(), 3 => array(4), 4 => 23); + $b = array(); + $expecteda = array(1 => array(2, 3, 4), 2 => array(), 3 => array(4), 4 => array()); + $expectedb = array(1 => 1); + + test_grade_grade_flatten_dependencies_array::test_flatten_dependencies_array($a, $b); + $this->assertSame($expecteda, $a); + $this->assertSame($expectedb, $b); } public function test_grade_grade_min_max() {