| 1 | efrain | 1 | <?php
 | 
        
           |  |  | 2 | // This file is part of Moodle - http://moodle.org/
 | 
        
           |  |  | 3 | //
 | 
        
           |  |  | 4 | // Moodle is free software: you can redistribute it and/or modify
 | 
        
           |  |  | 5 | // it under the terms of the GNU General Public License as published by
 | 
        
           |  |  | 6 | // the Free Software Foundation, either version 3 of the License, or
 | 
        
           |  |  | 7 | // (at your option) any later version.
 | 
        
           |  |  | 8 | //
 | 
        
           |  |  | 9 | // Moodle is distributed in the hope that it will be useful,
 | 
        
           |  |  | 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
        
           |  |  | 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
        
           |  |  | 12 | // GNU General Public License for more details.
 | 
        
           |  |  | 13 | //
 | 
        
           |  |  | 14 | // You should have received a copy of the GNU General Public License
 | 
        
           |  |  | 15 | // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
 | 
        
           |  |  | 16 |   | 
        
           |  |  | 17 | namespace core;
 | 
        
           |  |  | 18 |   | 
        
           |  |  | 19 | defined('MOODLE_INTERNAL') || die();
 | 
        
           |  |  | 20 |   | 
        
           |  |  | 21 | require_once(__DIR__.'/fixtures/lib.php');
 | 
        
           |  |  | 22 |   | 
        
           |  |  | 23 | /**
 | 
        
           |  |  | 24 |  * Test grade grades
 | 
        
           |  |  | 25 |  *
 | 
        
           |  |  | 26 |  * @package    core
 | 
        
           |  |  | 27 |  * @category   test
 | 
        
           |  |  | 28 |  * @copyright  nicolas@moodle.com
 | 
        
           |  |  | 29 |  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
 | 
        
           |  |  | 30 |  */
 | 
        
           | 1441 | ariadna | 31 | final class grade_grade_test extends \grade_base_testcase {
 | 
        
           | 1 | efrain | 32 |   | 
        
           | 11 | efrain | 33 |     public function test_grade_grade(): void {
 | 
        
           | 1 | efrain | 34 |         $this->sub_test_grade_grade_construct();
 | 
        
           |  |  | 35 |         $this->sub_test_grade_grade_insert();
 | 
        
           |  |  | 36 |         $this->sub_test_grade_grade_update();
 | 
        
           |  |  | 37 |         $this->sub_test_grade_grade_fetch();
 | 
        
           |  |  | 38 |         $this->sub_test_grade_grade_fetch_all();
 | 
        
           |  |  | 39 |         $this->sub_test_grade_grade_load_grade_item();
 | 
        
           |  |  | 40 |         $this->sub_test_grade_grade_standardise_score();
 | 
        
           |  |  | 41 |         $this->sub_test_grade_grade_is_locked();
 | 
        
           |  |  | 42 |         $this->sub_test_grade_grade_set_hidden();
 | 
        
           |  |  | 43 |         $this->sub_test_grade_grade_is_hidden();
 | 
        
           |  |  | 44 |         $this->sub_test_grade_grade_deleted();
 | 
        
           |  |  | 45 |         $this->sub_test_grade_grade_deleted_event();
 | 
        
           |  |  | 46 |     }
 | 
        
           |  |  | 47 |   | 
        
           |  |  | 48 |     protected function sub_test_grade_grade_construct() {
 | 
        
           |  |  | 49 |         $params = new \stdClass();
 | 
        
           |  |  | 50 |   | 
        
           |  |  | 51 |         $params->itemid = $this->grade_items[0]->id;
 | 
        
           |  |  | 52 |         $params->userid = 1;
 | 
        
           |  |  | 53 |         $params->rawgrade = 88;
 | 
        
           |  |  | 54 |         $params->rawgrademax = 110;
 | 
        
           |  |  | 55 |         $params->rawgrademin = 18;
 | 
        
           |  |  | 56 |   | 
        
           |  |  | 57 |         $grade_grade = new \grade_grade($params, false);
 | 
        
           |  |  | 58 |         $this->assertEquals($params->itemid, $grade_grade->itemid);
 | 
        
           |  |  | 59 |         $this->assertEquals($params->rawgrade, $grade_grade->rawgrade);
 | 
        
           |  |  | 60 |     }
 | 
        
           |  |  | 61 |   | 
        
           |  |  | 62 |     protected function sub_test_grade_grade_insert() {
 | 
        
           |  |  | 63 |         $grade_grade = new \grade_grade();
 | 
        
           |  |  | 64 |         $this->assertTrue(method_exists($grade_grade, 'insert'));
 | 
        
           |  |  | 65 |   | 
        
           |  |  | 66 |         $grade_grade->itemid = $this->grade_items[0]->id;
 | 
        
           |  |  | 67 |         $grade_grade->userid = 10;
 | 
        
           |  |  | 68 |         $grade_grade->rawgrade = 88;
 | 
        
           |  |  | 69 |         $grade_grade->rawgrademax = 110;
 | 
        
           |  |  | 70 |         $grade_grade->rawgrademin = 18;
 | 
        
           |  |  | 71 |   | 
        
           |  |  | 72 |         // Check the grade_item's needsupdate variable first.
 | 
        
           |  |  | 73 |         $grade_grade->load_grade_item();
 | 
        
           |  |  | 74 |         $this->assertEmpty($grade_grade->grade_item->needsupdate);
 | 
        
           |  |  | 75 |   | 
        
           |  |  | 76 |         $grade_grade->insert();
 | 
        
           |  |  | 77 |   | 
        
           |  |  | 78 |         $last_grade_grade = end($this->grade_grades);
 | 
        
           |  |  | 79 |   | 
        
           |  |  | 80 |         $this->assertEquals($grade_grade->id, $last_grade_grade->id + 1);
 | 
        
           |  |  | 81 |   | 
        
           |  |  | 82 |         // Timecreated will only be set if the grade was submitted by an activity module.
 | 
        
           |  |  | 83 |         $this->assertTrue(empty($grade_grade->timecreated));
 | 
        
           |  |  | 84 |         // Timemodified will only be set if the grade was submitted by an activity module.
 | 
        
           |  |  | 85 |         $this->assertTrue(empty($grade_grade->timemodified));
 | 
        
           |  |  | 86 |   | 
        
           |  |  | 87 |         // Keep our collection the same as is in the database.
 | 
        
           |  |  | 88 |         $this->grade_grades[] = $grade_grade;
 | 
        
           |  |  | 89 |     }
 | 
        
           |  |  | 90 |   | 
        
           |  |  | 91 |     protected function sub_test_grade_grade_update() {
 | 
        
           |  |  | 92 |         $grade_grade = new \grade_grade($this->grade_grades[0], false);
 | 
        
           |  |  | 93 |         $this->assertTrue(method_exists($grade_grade, 'update'));
 | 
        
           |  |  | 94 |     }
 | 
        
           |  |  | 95 |   | 
        
           |  |  | 96 |     protected function sub_test_grade_grade_fetch() {
 | 
        
           |  |  | 97 |         $grade_grade = new \grade_grade();
 | 
        
           |  |  | 98 |         $this->assertTrue(method_exists($grade_grade, 'fetch'));
 | 
        
           |  |  | 99 |   | 
        
           |  |  | 100 |         $grades = \grade_grade::fetch(array('id'=>$this->grade_grades[0]->id));
 | 
        
           |  |  | 101 |         $this->assertEquals($this->grade_grades[0]->id, $grades->id);
 | 
        
           |  |  | 102 |         $this->assertEquals($this->grade_grades[0]->rawgrade, $grades->rawgrade);
 | 
        
           |  |  | 103 |     }
 | 
        
           |  |  | 104 |   | 
        
           |  |  | 105 |     protected function sub_test_grade_grade_fetch_all() {
 | 
        
           |  |  | 106 |         $grade_grade = new \grade_grade();
 | 
        
           |  |  | 107 |         $this->assertTrue(method_exists($grade_grade, 'fetch_all'));
 | 
        
           |  |  | 108 |   | 
        
           |  |  | 109 |         $grades = \grade_grade::fetch_all(array());
 | 
        
           |  |  | 110 |         $this->assertEquals(count($this->grade_grades), count($grades));
 | 
        
           |  |  | 111 |     }
 | 
        
           |  |  | 112 |   | 
        
           |  |  | 113 |     protected function sub_test_grade_grade_load_grade_item() {
 | 
        
           |  |  | 114 |         $grade_grade = new \grade_grade($this->grade_grades[0], false);
 | 
        
           |  |  | 115 |         $this->assertTrue(method_exists($grade_grade, 'load_grade_item'));
 | 
        
           |  |  | 116 |         $this->assertNull($grade_grade->grade_item);
 | 
        
           |  |  | 117 |         $this->assertNotEmpty($grade_grade->itemid);
 | 
        
           |  |  | 118 |         $this->assertNotNull($grade_grade->load_grade_item());
 | 
        
           |  |  | 119 |         $this->assertNotNull($grade_grade->grade_item);
 | 
        
           |  |  | 120 |         $this->assertEquals($this->grade_items[0]->id, $grade_grade->grade_item->id);
 | 
        
           |  |  | 121 |     }
 | 
        
           |  |  | 122 |   | 
        
           |  |  | 123 |   | 
        
           |  |  | 124 |     protected function sub_test_grade_grade_standardise_score() {
 | 
        
           |  |  | 125 |         $this->assertEquals(4, round(\grade_grade::standardise_score(6, 0, 7, 0, 5)));
 | 
        
           |  |  | 126 |         $this->assertEquals(40, \grade_grade::standardise_score(50, 30, 80, 0, 100));
 | 
        
           |  |  | 127 |     }
 | 
        
           |  |  | 128 |   | 
        
           |  |  | 129 |     /**
 | 
        
           |  |  | 130 |      * Tests grade_grade::set_locked()
 | 
        
           |  |  | 131 |      *
 | 
        
           |  |  | 132 |      * @covers \grade_grade::set_locked
 | 
        
           |  |  | 133 |      */
 | 
        
           |  |  | 134 |     public function test_grade_grade_set_locked(): void {
 | 
        
           |  |  | 135 |         // Skip this test because set_locked() arguments have been modified, rendering these tests
 | 
        
           |  |  | 136 |         // useless until they are re-written. Note this comes from MDL-32323 (2012!).
 | 
        
           |  |  | 137 |         $this->markTestSkipped('Useless set_locked() tests until they are re-written');
 | 
        
           |  |  | 138 |         $grade_item = new \grade_item($this->grade_items[0]);
 | 
        
           |  |  | 139 |         $grade = new \grade_grade($grade_item->get_final(1));
 | 
        
           |  |  | 140 |         $this->assertTrue(method_exists($grade, 'set_locked'));
 | 
        
           |  |  | 141 |   | 
        
           |  |  | 142 |         $this->assertTrue(empty($grade_item->locked));
 | 
        
           |  |  | 143 |         $this->assertTrue(empty($grade->locked));
 | 
        
           |  |  | 144 |   | 
        
           |  |  | 145 |         $this->assertTrue($grade->set_locked(true));
 | 
        
           |  |  | 146 |         $this->assertFalse(empty($grade->locked));
 | 
        
           |  |  | 147 |         $this->assertTrue($grade->set_locked(false));
 | 
        
           |  |  | 148 |         $this->assertTrue(empty($grade->locked));
 | 
        
           |  |  | 149 |   | 
        
           |  |  | 150 |         $this->assertTrue($grade_item->set_locked(true, true));
 | 
        
           |  |  | 151 |         $grade = new \grade_grade($grade_item->get_final(1));
 | 
        
           |  |  | 152 |   | 
        
           |  |  | 153 |         $this->assertFalse(empty($grade->locked));
 | 
        
           |  |  | 154 |         $this->assertFalse($grade->set_locked(true, false));
 | 
        
           |  |  | 155 |   | 
        
           |  |  | 156 |         $this->assertTrue($grade_item->set_locked(true, false));
 | 
        
           |  |  | 157 |         $grade = new \grade_grade($grade_item->get_final(1));
 | 
        
           |  |  | 158 |   | 
        
           |  |  | 159 |         $this->assertTrue($grade->set_locked(true, false));
 | 
        
           |  |  | 160 |     }
 | 
        
           |  |  | 161 |   | 
        
           |  |  | 162 |     protected function sub_test_grade_grade_is_locked() {
 | 
        
           |  |  | 163 |         $grade = new \grade_grade($this->grade_grades[0], false);
 | 
        
           |  |  | 164 |         $this->assertTrue(method_exists($grade, 'is_locked'));
 | 
        
           |  |  | 165 |   | 
        
           |  |  | 166 |         $this->assertFalse($grade->is_locked());
 | 
        
           |  |  | 167 |         $grade->locked = time();
 | 
        
           |  |  | 168 |         $this->assertTrue($grade->is_locked());
 | 
        
           |  |  | 169 |     }
 | 
        
           |  |  | 170 |   | 
        
           |  |  | 171 |     protected function sub_test_grade_grade_set_hidden() {
 | 
        
           |  |  | 172 |         $grade = new \grade_grade($this->grade_grades[0], false);
 | 
        
           |  |  | 173 |         $grade_item = new \grade_item($this->grade_items[0], false);
 | 
        
           |  |  | 174 |         $this->assertTrue(method_exists($grade, 'set_hidden'));
 | 
        
           |  |  | 175 |   | 
        
           |  |  | 176 |         $this->assertEquals(0, $grade_item->hidden);
 | 
        
           |  |  | 177 |         $this->assertEquals(0, $grade->hidden);
 | 
        
           |  |  | 178 |   | 
        
           |  |  | 179 |         $grade->set_hidden(0);
 | 
        
           |  |  | 180 |         $this->assertEquals(0, $grade->hidden);
 | 
        
           |  |  | 181 |   | 
        
           |  |  | 182 |         $grade->set_hidden(1);
 | 
        
           |  |  | 183 |         $this->assertEquals(1, $grade->hidden);
 | 
        
           |  |  | 184 |   | 
        
           |  |  | 185 |         $grade->set_hidden(0);
 | 
        
           |  |  | 186 |         $this->assertEquals(0, $grade->hidden);
 | 
        
           |  |  | 187 |     }
 | 
        
           |  |  | 188 |   | 
        
           |  |  | 189 |     protected function sub_test_grade_grade_is_hidden() {
 | 
        
           |  |  | 190 |         $grade = new \grade_grade($this->grade_grades[0], false);
 | 
        
           |  |  | 191 |         $this->assertTrue(method_exists($grade, 'is_hidden'));
 | 
        
           |  |  | 192 |   | 
        
           |  |  | 193 |         $this->assertFalse($grade->is_hidden());
 | 
        
           |  |  | 194 |         $grade->hidden = 1;
 | 
        
           |  |  | 195 |         $this->assertTrue($grade->is_hidden());
 | 
        
           |  |  | 196 |   | 
        
           |  |  | 197 |         $grade->hidden = time()-666;
 | 
        
           |  |  | 198 |         $this->assertFalse($grade->is_hidden());
 | 
        
           |  |  | 199 |   | 
        
           |  |  | 200 |         $grade->hidden = time()+666;
 | 
        
           |  |  | 201 |         $this->assertTrue($grade->is_hidden());
 | 
        
           |  |  | 202 |     }
 | 
        
           |  |  | 203 |   | 
        
           |  |  | 204 |     /**
 | 
        
           |  |  | 205 |      * Test \grade_grade::flatten_dependencies_array()
 | 
        
           |  |  | 206 |      *
 | 
        
           |  |  | 207 |      * @covers \grade_grade::flatten_dependencies_array()
 | 
        
           |  |  | 208 |      */
 | 
        
           | 11 | efrain | 209 |     public function test_flatten_dependencies(): void {
 | 
        
           | 1 | efrain | 210 |         // First test a simple normal case.
 | 
        
           |  |  | 211 |         $a = array(1 => array(2, 3), 2 => array(), 3 => array(4), 4 => array());
 | 
        
           |  |  | 212 |         $b = array();
 | 
        
           |  |  | 213 |         $expecteda = array(1 => array(2, 3, 4), 2 => array(), 3 => array(4), 4 => array());
 | 
        
           |  |  | 214 |         $expectedb = array(1 => 1);
 | 
        
           |  |  | 215 |   | 
        
           |  |  | 216 |         \test_grade_grade_flatten_dependencies_array::test_flatten_dependencies_array($a, $b);
 | 
        
           |  |  | 217 |         $this->assertSame($expecteda, $a);
 | 
        
           |  |  | 218 |         $this->assertSame($expectedb, $b);
 | 
        
           |  |  | 219 |   | 
        
           |  |  | 220 |         // Edge case - empty arrays.
 | 
        
           |  |  | 221 |         $a = $b = $expecteda = $expectedb = array();
 | 
        
           |  |  | 222 |   | 
        
           |  |  | 223 |         \test_grade_grade_flatten_dependencies_array::test_flatten_dependencies_array($a, $b);
 | 
        
           |  |  | 224 |         $this->assertSame($expecteda, $a);
 | 
        
           |  |  | 225 |         $this->assertSame($expectedb, $b);
 | 
        
           |  |  | 226 |   | 
        
           |  |  | 227 |         // Circular dependency.
 | 
        
           |  |  | 228 |         $a = array(1 => array(2), 2 => array(3), 3 => array(1));
 | 
        
           |  |  | 229 |         $b = array();
 | 
        
           |  |  | 230 |         $expecteda = array(1 => array(1, 2, 3), 2 => array(1, 2, 3), 3 => array(1, 2, 3));
 | 
        
           |  |  | 231 |   | 
        
           |  |  | 232 |         \test_grade_grade_flatten_dependencies_array::test_flatten_dependencies_array($a, $b);
 | 
        
           |  |  | 233 |         $this->assertSame($expecteda, $a);
 | 
        
           |  |  | 234 |         // Note - we don't test the depth when we got circular dependencies - the main thing we wanted to test was that there was
 | 
        
           |  |  | 235 |         // no ka-boom. The result would be hard to understand and doesn't matter.
 | 
        
           |  |  | 236 |   | 
        
           |  |  | 237 |         // Circular dependency 2.
 | 
        
           |  |  | 238 |         $a = array(1 => array(2), 2 => array(3), 3 => array(4), 4 => array(2, 1));
 | 
        
           |  |  | 239 |         $b = array();
 | 
        
           |  |  | 240 |         $expecteda = array(1 => array(1, 2, 3, 4), 2 => array(1, 2, 3, 4), 3 => array(1, 2, 3, 4), 4 => array(1, 2, 3, 4));
 | 
        
           |  |  | 241 |   | 
        
           |  |  | 242 |         \test_grade_grade_flatten_dependencies_array::test_flatten_dependencies_array($a, $b);
 | 
        
           |  |  | 243 |         $this->assertSame($expecteda, $a);
 | 
        
           |  |  | 244 |   | 
        
           |  |  | 245 |         // Missing first level dependency.
 | 
        
           |  |  | 246 |         $a = array(1 => array(2, 3), 3 => array(4), 4 => array());
 | 
        
           |  |  | 247 |         $b = array();
 | 
        
           |  |  | 248 |         $expecteda = array(1 => array(2, 3, 4), 3 => array(4), 4 => array());
 | 
        
           |  |  | 249 |         $expectedb = array(1 => 1);
 | 
        
           |  |  | 250 |   | 
        
           |  |  | 251 |         \test_grade_grade_flatten_dependencies_array::test_flatten_dependencies_array($a, $b);
 | 
        
           |  |  | 252 |         $this->assertSame($expecteda, $a);
 | 
        
           |  |  | 253 |         $this->assertSame($expectedb, $b);
 | 
        
           |  |  | 254 |   | 
        
           |  |  | 255 |         // Missing 2nd level dependency.
 | 
        
           |  |  | 256 |         $a = array(1 => array(2, 3), 2 => array(), 3 => array(4));
 | 
        
           |  |  | 257 |         $b = array();
 | 
        
           |  |  | 258 |         $expecteda = array(1 => array(2, 3, 4), 2 => array(), 3 => array(4));
 | 
        
           |  |  | 259 |         $expectedb = array(1 => 1);
 | 
        
           |  |  | 260 |   | 
        
           |  |  | 261 |         \test_grade_grade_flatten_dependencies_array::test_flatten_dependencies_array($a, $b);
 | 
        
           |  |  | 262 |         $this->assertSame($expecteda, $a);
 | 
        
           |  |  | 263 |         $this->assertSame($expectedb, $b);
 | 
        
           |  |  | 264 |   | 
        
           |  |  | 265 |         // Null first level dependency.
 | 
        
           |  |  | 266 |         $a = array(1 => array(2, null), 2 => array(3), 3 => array(4), 4 => array());
 | 
        
           |  |  | 267 |         $b = array();
 | 
        
           |  |  | 268 |         $expecteda = array(1 => array(2, 3, 4), 2 => array(3, 4), 3 => array(4), 4 => array());
 | 
        
           |  |  | 269 |         $expectedb = array(1 => 2, 2 => 1);
 | 
        
           |  |  | 270 |   | 
        
           |  |  | 271 |         \test_grade_grade_flatten_dependencies_array::test_flatten_dependencies_array($a, $b);
 | 
        
           |  |  | 272 |         $this->assertSame($expecteda, $a);
 | 
        
           |  |  | 273 |         $this->assertSame($expectedb, $b);
 | 
        
           |  |  | 274 |   | 
        
           |  |  | 275 |         // Null 2nd level dependency.
 | 
        
           |  |  | 276 |         $a = array(1 => array(2, 3), 2 => array(), 3 => array(4), 4 => array(null));
 | 
        
           |  |  | 277 |         $b = array();
 | 
        
           |  |  | 278 |         $expecteda = array(1 => array(2, 3, 4), 2 => array(), 3 => array(4), 4 => array());
 | 
        
           |  |  | 279 |         $expectedb = array(1 => 1);
 | 
        
           |  |  | 280 |   | 
        
           |  |  | 281 |         \test_grade_grade_flatten_dependencies_array::test_flatten_dependencies_array($a, $b);
 | 
        
           |  |  | 282 |         $this->assertSame($expecteda, $a);
 | 
        
           |  |  | 283 |         $this->assertSame($expectedb, $b);
 | 
        
           |  |  | 284 |   | 
        
           |  |  | 285 |         // Straight null dependency.
 | 
        
           |  |  | 286 |         $a = array(1 => array(2, 3), 2 => array(), 3 => array(4), 4 => null);
 | 
        
           |  |  | 287 |         $b = array();
 | 
        
           |  |  | 288 |         $expecteda = array(1 => array(2, 3, 4), 2 => array(), 3 => array(4), 4 => array());
 | 
        
           |  |  | 289 |         $expectedb = array(1 => 1);
 | 
        
           |  |  | 290 |   | 
        
           |  |  | 291 |         \test_grade_grade_flatten_dependencies_array::test_flatten_dependencies_array($a, $b);
 | 
        
           |  |  | 292 |         $this->assertSame($expecteda, $a);
 | 
        
           |  |  | 293 |         $this->assertSame($expectedb, $b);
 | 
        
           |  |  | 294 |   | 
        
           |  |  | 295 |         // Also incorrect non-array dependency.
 | 
        
           |  |  | 296 |         $a = array(1 => array(2, 3), 2 => array(), 3 => array(4), 4 => 23);
 | 
        
           |  |  | 297 |         $b = array();
 | 
        
           |  |  | 298 |         $expecteda = array(1 => array(2, 3, 4), 2 => array(), 3 => array(4), 4 => array());
 | 
        
           |  |  | 299 |         $expectedb = array(1 => 1);
 | 
        
           |  |  | 300 |   | 
        
           |  |  | 301 |         \test_grade_grade_flatten_dependencies_array::test_flatten_dependencies_array($a, $b);
 | 
        
           |  |  | 302 |         $this->assertSame($expecteda, $a);
 | 
        
           |  |  | 303 |         $this->assertSame($expectedb, $b);
 | 
        
           |  |  | 304 |     }
 | 
        
           |  |  | 305 |   | 
        
           | 11 | efrain | 306 |     public function test_grade_grade_min_max(): void {
 | 
        
           | 1 | efrain | 307 |         global $CFG;
 | 
        
           |  |  | 308 |         $initialminmaxtouse = $CFG->grade_minmaxtouse;
 | 
        
           |  |  | 309 |   | 
        
           |  |  | 310 |         $this->setAdminUser();
 | 
        
           |  |  | 311 |         $course = $this->getDataGenerator()->create_course();
 | 
        
           |  |  | 312 |         $user = $this->getDataGenerator()->create_user();
 | 
        
           |  |  | 313 |         $assignrecord = $this->getDataGenerator()->create_module('assign', array('course' => $course, 'grade' => 100));
 | 
        
           |  |  | 314 |         $cm = get_coursemodule_from_instance('assign', $assignrecord->id);
 | 
        
           |  |  | 315 |         $assigncontext = \context_module::instance($cm->id);
 | 
        
           |  |  | 316 |         $assign = new \assign($assigncontext, $cm, $course);
 | 
        
           |  |  | 317 |   | 
        
           |  |  | 318 |         // Fetch the assignment item.
 | 
        
           |  |  | 319 |         $giparams = array('itemtype' => 'mod', 'itemmodule' => 'assign', 'iteminstance' => $assignrecord->id,
 | 
        
           |  |  | 320 |                 'courseid' => $course->id, 'itemnumber' => 0);
 | 
        
           |  |  | 321 |         $gi = \grade_item::fetch($giparams);
 | 
        
           |  |  | 322 |         $this->assertEquals(0, $gi->grademin);
 | 
        
           |  |  | 323 |         $this->assertEquals(100, $gi->grademax);
 | 
        
           |  |  | 324 |   | 
        
           |  |  | 325 |         // Give a grade to the student.
 | 
        
           |  |  | 326 |         $usergrade = $assign->get_user_grade($user->id, true);
 | 
        
           |  |  | 327 |         $usergrade->grade = 10;
 | 
        
           |  |  | 328 |         $assign->update_grade($usergrade);
 | 
        
           |  |  | 329 |   | 
        
           |  |  | 330 |         // Check the grade stored in gradebook.
 | 
        
           |  |  | 331 |         $gg = \grade_grade::fetch(array('userid' => $user->id, 'itemid' => $gi->id));
 | 
        
           |  |  | 332 |         $this->assertEquals(10, $gg->rawgrade);
 | 
        
           |  |  | 333 |         $this->assertEquals(0, $gg->get_grade_min());
 | 
        
           |  |  | 334 |         $this->assertEquals(100, $gg->get_grade_max());
 | 
        
           |  |  | 335 |   | 
        
           |  |  | 336 |         // Change the min/max grade of the item.
 | 
        
           |  |  | 337 |         $gi->grademax = 50;
 | 
        
           |  |  | 338 |         $gi->grademin = 2;
 | 
        
           |  |  | 339 |         $gi->update();
 | 
        
           |  |  | 340 |   | 
        
           |  |  | 341 |         // Fetch the updated item.
 | 
        
           |  |  | 342 |         $gi = \grade_item::fetch($giparams);
 | 
        
           |  |  | 343 |   | 
        
           |  |  | 344 |         // Now check the grade grade min/max with system setting.
 | 
        
           |  |  | 345 |         $CFG->grade_minmaxtouse = GRADE_MIN_MAX_FROM_GRADE_ITEM;
 | 
        
           |  |  | 346 |         grade_set_setting($course->id, 'minmaxtouse', null); // Ensure no course setting.
 | 
        
           |  |  | 347 |   | 
        
           |  |  | 348 |         $gg = \grade_grade::fetch(array('userid' => $user->id, 'itemid' => $gi->id));
 | 
        
           |  |  | 349 |         $this->assertEquals(2, $gg->get_grade_min());
 | 
        
           |  |  | 350 |         $this->assertEquals(50, $gg->get_grade_max());
 | 
        
           |  |  | 351 |   | 
        
           |  |  | 352 |         // Now with other system setting.
 | 
        
           |  |  | 353 |         $CFG->grade_minmaxtouse = GRADE_MIN_MAX_FROM_GRADE_GRADE;
 | 
        
           |  |  | 354 |         grade_set_setting($course->id, 'minmaxtouse', null); // Ensure no course setting, and reset static cache.
 | 
        
           |  |  | 355 |         $gg = \grade_grade::fetch(array('userid' => $user->id, 'itemid' => $gi->id));
 | 
        
           |  |  | 356 |         $this->assertEquals(0, $gg->get_grade_min());
 | 
        
           |  |  | 357 |         $this->assertEquals(100, $gg->get_grade_max());
 | 
        
           |  |  | 358 |   | 
        
           |  |  | 359 |         // Now with overriden setting in course.
 | 
        
           |  |  | 360 |         $CFG->grade_minmaxtouse = GRADE_MIN_MAX_FROM_GRADE_ITEM;
 | 
        
           |  |  | 361 |         grade_set_setting($course->id, 'minmaxtouse', GRADE_MIN_MAX_FROM_GRADE_GRADE);
 | 
        
           |  |  | 362 |         $gg = \grade_grade::fetch(array('userid' => $user->id, 'itemid' => $gi->id));
 | 
        
           |  |  | 363 |         $this->assertEquals(0, $gg->get_grade_min());
 | 
        
           |  |  | 364 |         $this->assertEquals(100, $gg->get_grade_max());
 | 
        
           |  |  | 365 |   | 
        
           |  |  | 366 |         $CFG->grade_minmaxtouse = GRADE_MIN_MAX_FROM_GRADE_GRADE;
 | 
        
           |  |  | 367 |         grade_set_setting($course->id, 'minmaxtouse', GRADE_MIN_MAX_FROM_GRADE_ITEM);
 | 
        
           |  |  | 368 |         $gg = \grade_grade::fetch(array('userid' => $user->id, 'itemid' => $gi->id));
 | 
        
           |  |  | 369 |         $this->assertEquals(2, $gg->get_grade_min());
 | 
        
           |  |  | 370 |         $this->assertEquals(50, $gg->get_grade_max());
 | 
        
           |  |  | 371 |   | 
        
           |  |  | 372 |         $CFG->grade_minmaxtouse = $initialminmaxtouse;
 | 
        
           |  |  | 373 |     }
 | 
        
           |  |  | 374 |   | 
        
           | 11 | efrain | 375 |     public function test_grade_grade_min_max_with_course_item(): void {
 | 
        
           | 1 | efrain | 376 |         global $CFG, $DB;
 | 
        
           |  |  | 377 |         $initialminmaxtouse = $CFG->grade_minmaxtouse;
 | 
        
           |  |  | 378 |   | 
        
           |  |  | 379 |         $this->setAdminUser();
 | 
        
           |  |  | 380 |         $course = $this->getDataGenerator()->create_course();
 | 
        
           |  |  | 381 |         $user = $this->getDataGenerator()->create_user();
 | 
        
           |  |  | 382 |         $gi = \grade_item::fetch_course_item($course->id);
 | 
        
           |  |  | 383 |   | 
        
           |  |  | 384 |         // Fetch the category item.
 | 
        
           |  |  | 385 |         $this->assertEquals(0, $gi->grademin);
 | 
        
           |  |  | 386 |         $this->assertEquals(100, $gi->grademax);
 | 
        
           |  |  | 387 |   | 
        
           |  |  | 388 |         // Give a grade to the student.
 | 
        
           |  |  | 389 |         $gi->update_final_grade($user->id, 10);
 | 
        
           |  |  | 390 |   | 
        
           |  |  | 391 |         // Check the grade min/max stored in gradebook.
 | 
        
           |  |  | 392 |         $gg = \grade_grade::fetch(array('userid' => $user->id, 'itemid' => $gi->id));
 | 
        
           |  |  | 393 |         $this->assertEquals(0, $gg->get_grade_min());
 | 
        
           |  |  | 394 |         $this->assertEquals(100, $gg->get_grade_max());
 | 
        
           |  |  | 395 |   | 
        
           |  |  | 396 |         // Change the min/max grade of the item.
 | 
        
           |  |  | 397 |         $gi->grademin = 2;
 | 
        
           |  |  | 398 |         $gi->grademax = 50;
 | 
        
           |  |  | 399 |         $gi->update();
 | 
        
           |  |  | 400 |   | 
        
           |  |  | 401 |         // Fetch the updated item.
 | 
        
           |  |  | 402 |         $gi = \grade_item::fetch_course_item($course->id);
 | 
        
           |  |  | 403 |   | 
        
           |  |  | 404 |         // Now check the grade grade min/max with system setting.
 | 
        
           |  |  | 405 |         $CFG->grade_minmaxtouse = GRADE_MIN_MAX_FROM_GRADE_ITEM;
 | 
        
           |  |  | 406 |         grade_set_setting($course->id, 'minmaxtouse', null); // Ensure no course setting.
 | 
        
           |  |  | 407 |   | 
        
           |  |  | 408 |         $gg = \grade_grade::fetch(array('userid' => $user->id, 'itemid' => $gi->id));
 | 
        
           |  |  | 409 |         $this->assertEquals(0, $gg->get_grade_min());
 | 
        
           |  |  | 410 |         $this->assertEquals(100, $gg->get_grade_max());
 | 
        
           |  |  | 411 |   | 
        
           |  |  | 412 |         // Now with other system setting.
 | 
        
           |  |  | 413 |         $CFG->grade_minmaxtouse = GRADE_MIN_MAX_FROM_GRADE_GRADE;
 | 
        
           |  |  | 414 |         grade_set_setting($course->id, 'minmaxtouse', null); // Ensure no course setting, and reset static cache.
 | 
        
           |  |  | 415 |         $gg = \grade_grade::fetch(array('userid' => $user->id, 'itemid' => $gi->id));
 | 
        
           |  |  | 416 |         $this->assertEquals(0, $gg->get_grade_min());
 | 
        
           |  |  | 417 |         $this->assertEquals(100, $gg->get_grade_max());
 | 
        
           |  |  | 418 |   | 
        
           |  |  | 419 |         // Now with overriden setting in course.
 | 
        
           |  |  | 420 |         $CFG->grade_minmaxtouse = GRADE_MIN_MAX_FROM_GRADE_ITEM;
 | 
        
           |  |  | 421 |         grade_set_setting($course->id, 'minmaxtouse', GRADE_MIN_MAX_FROM_GRADE_GRADE);
 | 
        
           |  |  | 422 |         $gg = \grade_grade::fetch(array('userid' => $user->id, 'itemid' => $gi->id));
 | 
        
           |  |  | 423 |         $this->assertEquals(0, $gg->get_grade_min());
 | 
        
           |  |  | 424 |         $this->assertEquals(100, $gg->get_grade_max());
 | 
        
           |  |  | 425 |   | 
        
           |  |  | 426 |         $CFG->grade_minmaxtouse = GRADE_MIN_MAX_FROM_GRADE_GRADE;
 | 
        
           |  |  | 427 |         grade_set_setting($course->id, 'minmaxtouse', GRADE_MIN_MAX_FROM_GRADE_ITEM);
 | 
        
           |  |  | 428 |         $gg = \grade_grade::fetch(array('userid' => $user->id, 'itemid' => $gi->id));
 | 
        
           |  |  | 429 |         $this->assertEquals(0, $gg->get_grade_min());
 | 
        
           |  |  | 430 |         $this->assertEquals(100, $gg->get_grade_max());
 | 
        
           |  |  | 431 |   | 
        
           |  |  | 432 |         $CFG->grade_minmaxtouse = $initialminmaxtouse;
 | 
        
           |  |  | 433 |     }
 | 
        
           |  |  | 434 |   | 
        
           | 11 | efrain | 435 |     public function test_grade_grade_min_max_with_category_item(): void {
 | 
        
           | 1 | efrain | 436 |         global $CFG, $DB;
 | 
        
           |  |  | 437 |         $initialminmaxtouse = $CFG->grade_minmaxtouse;
 | 
        
           |  |  | 438 |   | 
        
           |  |  | 439 |         $this->setAdminUser();
 | 
        
           |  |  | 440 |         $course = $this->getDataGenerator()->create_course();
 | 
        
           |  |  | 441 |         $user = $this->getDataGenerator()->create_user();
 | 
        
           |  |  | 442 |         $coursegi = \grade_item::fetch_course_item($course->id);
 | 
        
           |  |  | 443 |   | 
        
           |  |  | 444 |         // Create a category item.
 | 
        
           |  |  | 445 |         $gc = new \grade_category(array('courseid' => $course->id, 'fullname' => 'test'), false);
 | 
        
           |  |  | 446 |         $gc->insert();
 | 
        
           |  |  | 447 |         $gi = $gc->get_grade_item();
 | 
        
           |  |  | 448 |         $gi->grademax = 100;
 | 
        
           |  |  | 449 |         $gi->grademin = 0;
 | 
        
           |  |  | 450 |         $gi->update();
 | 
        
           |  |  | 451 |   | 
        
           |  |  | 452 |         // Fetch the category item.
 | 
        
           |  |  | 453 |         $giparams = array('itemtype' => 'category', 'iteminstance' => $gc->id);
 | 
        
           |  |  | 454 |         $gi = \grade_item::fetch($giparams);
 | 
        
           |  |  | 455 |         $this->assertEquals(0, $gi->grademin);
 | 
        
           |  |  | 456 |         $this->assertEquals(100, $gi->grademax);
 | 
        
           |  |  | 457 |   | 
        
           |  |  | 458 |         // Give a grade to the student.
 | 
        
           |  |  | 459 |         $gi->update_final_grade($user->id, 10);
 | 
        
           |  |  | 460 |   | 
        
           |  |  | 461 |         // Check the grade min/max stored in gradebook.
 | 
        
           |  |  | 462 |         $gg = \grade_grade::fetch(array('userid' => $user->id, 'itemid' => $gi->id));
 | 
        
           |  |  | 463 |         $this->assertEquals(0, $gg->get_grade_min());
 | 
        
           |  |  | 464 |         $this->assertEquals(100, $gg->get_grade_max());
 | 
        
           |  |  | 465 |   | 
        
           |  |  | 466 |         // Change the min/max grade of the item.
 | 
        
           |  |  | 467 |         $gi->grademin = 2;
 | 
        
           |  |  | 468 |         $gi->grademax = 50;
 | 
        
           |  |  | 469 |         $gi->update();
 | 
        
           |  |  | 470 |   | 
        
           |  |  | 471 |         // Fetch the updated item.
 | 
        
           |  |  | 472 |         $gi = \grade_item::fetch($giparams);
 | 
        
           |  |  | 473 |   | 
        
           |  |  | 474 |         // Now check the grade grade min/max with system setting.
 | 
        
           |  |  | 475 |         $CFG->grade_minmaxtouse = GRADE_MIN_MAX_FROM_GRADE_ITEM;
 | 
        
           |  |  | 476 |         grade_set_setting($course->id, 'minmaxtouse', null); // Ensure no course setting.
 | 
        
           |  |  | 477 |   | 
        
           |  |  | 478 |         $gg = \grade_grade::fetch(array('userid' => $user->id, 'itemid' => $gi->id));
 | 
        
           |  |  | 479 |         $this->assertEquals(0, $gg->get_grade_min());
 | 
        
           |  |  | 480 |         $this->assertEquals(100, $gg->get_grade_max());
 | 
        
           |  |  | 481 |   | 
        
           |  |  | 482 |         // Now with other system setting.
 | 
        
           |  |  | 483 |         $CFG->grade_minmaxtouse = GRADE_MIN_MAX_FROM_GRADE_GRADE;
 | 
        
           |  |  | 484 |         grade_set_setting($course->id, 'minmaxtouse', null); // Ensure no course setting, and reset static cache.
 | 
        
           |  |  | 485 |         $gg = \grade_grade::fetch(array('userid' => $user->id, 'itemid' => $gi->id));
 | 
        
           |  |  | 486 |         $this->assertEquals(0, $gg->get_grade_min());
 | 
        
           |  |  | 487 |         $this->assertEquals(100, $gg->get_grade_max());
 | 
        
           |  |  | 488 |   | 
        
           |  |  | 489 |         // Now with overriden setting in course.
 | 
        
           |  |  | 490 |         $CFG->grade_minmaxtouse = GRADE_MIN_MAX_FROM_GRADE_ITEM;
 | 
        
           |  |  | 491 |         grade_set_setting($course->id, 'minmaxtouse', GRADE_MIN_MAX_FROM_GRADE_GRADE);
 | 
        
           |  |  | 492 |         $gg = \grade_grade::fetch(array('userid' => $user->id, 'itemid' => $gi->id));
 | 
        
           |  |  | 493 |         $this->assertEquals(0, $gg->get_grade_min());
 | 
        
           |  |  | 494 |         $this->assertEquals(100, $gg->get_grade_max());
 | 
        
           |  |  | 495 |   | 
        
           |  |  | 496 |         $CFG->grade_minmaxtouse = GRADE_MIN_MAX_FROM_GRADE_GRADE;
 | 
        
           |  |  | 497 |         grade_set_setting($course->id, 'minmaxtouse', GRADE_MIN_MAX_FROM_GRADE_ITEM);
 | 
        
           |  |  | 498 |         $gg = \grade_grade::fetch(array('userid' => $user->id, 'itemid' => $gi->id));
 | 
        
           |  |  | 499 |         $this->assertEquals(0, $gg->get_grade_min());
 | 
        
           |  |  | 500 |         $this->assertEquals(100, $gg->get_grade_max());
 | 
        
           |  |  | 501 |   | 
        
           |  |  | 502 |         $CFG->grade_minmaxtouse = $initialminmaxtouse;
 | 
        
           |  |  | 503 |     }
 | 
        
           |  |  | 504 |   | 
        
           |  |  | 505 |     /**
 | 
        
           |  |  | 506 |      * Tests when a grade_grade has been deleted.
 | 
        
           |  |  | 507 |      */
 | 
        
           |  |  | 508 |     public function sub_test_grade_grade_deleted() {
 | 
        
           |  |  | 509 |         $dg = $this->getDataGenerator();
 | 
        
           |  |  | 510 |   | 
        
           |  |  | 511 |         // Create the data we need for the tests.
 | 
        
           |  |  | 512 |         $fs = new \file_storage();
 | 
        
           |  |  | 513 |         $u1 = $dg->create_user();
 | 
        
           |  |  | 514 |         $c1 = $dg->create_course();
 | 
        
           |  |  | 515 |         $a1 = $dg->create_module('assign', ['course' => $c1->id]);
 | 
        
           |  |  | 516 |         $a1context = \context_module::instance($a1->cmid);
 | 
        
           |  |  | 517 |   | 
        
           |  |  | 518 |         $gi = new \grade_item($dg->create_grade_item(
 | 
        
           |  |  | 519 |             [
 | 
        
           |  |  | 520 |                 'courseid' => $c1->id,
 | 
        
           |  |  | 521 |                 'itemtype' => 'mod',
 | 
        
           |  |  | 522 |                 'itemmodule' => 'assign',
 | 
        
           |  |  | 523 |                 'iteminstance' => $a1->id
 | 
        
           |  |  | 524 |             ]
 | 
        
           |  |  | 525 |         ), false);
 | 
        
           |  |  | 526 |   | 
        
           |  |  | 527 |         // Add feedback files to copy as our update.
 | 
        
           |  |  | 528 |         $this->add_feedback_file_to_copy();
 | 
        
           |  |  | 529 |   | 
        
           |  |  | 530 |         $grades['feedback'] = 'Nice feedback!';
 | 
        
           |  |  | 531 |         $grades['feedbackformat'] = FORMAT_MOODLE;
 | 
        
           |  |  | 532 |         $grades['feedbackfiles'] = [
 | 
        
           |  |  | 533 |             'contextid' => 1,
 | 
        
           |  |  | 534 |             'component' => 'test',
 | 
        
           |  |  | 535 |             'filearea' => 'testarea',
 | 
        
           |  |  | 536 |             'itemid' => 1
 | 
        
           |  |  | 537 |         ];
 | 
        
           |  |  | 538 |   | 
        
           |  |  | 539 |         $grades['userid'] = $u1->id;
 | 
        
           |  |  | 540 |         grade_update('mod/assign', $gi->courseid, $gi->itemtype, $gi->itemmodule, $gi->iteminstance,
 | 
        
           |  |  | 541 |             $gi->itemnumber, $grades);
 | 
        
           |  |  | 542 |   | 
        
           |  |  | 543 |         // Feedback file area.
 | 
        
           |  |  | 544 |         $files = $fs->get_area_files($a1context->id, GRADE_FILE_COMPONENT, GRADE_FEEDBACK_FILEAREA);
 | 
        
           |  |  | 545 |         $this->assertEquals(2, count($files));
 | 
        
           |  |  | 546 |   | 
        
           |  |  | 547 |         // History file area.
 | 
        
           |  |  | 548 |         $files = $fs->get_area_files($a1context->id, GRADE_FILE_COMPONENT, GRADE_HISTORY_FEEDBACK_FILEAREA);
 | 
        
           |  |  | 549 |         $this->assertEquals(2, count($files));
 | 
        
           |  |  | 550 |   | 
        
           |  |  | 551 |         $gg = \grade_grade::fetch(array('userid' => $u1->id, 'itemid' => $gi->id));
 | 
        
           |  |  | 552 |   | 
        
           |  |  | 553 |         $gg->delete();
 | 
        
           |  |  | 554 |   | 
        
           |  |  | 555 |         // Feedback file area.
 | 
        
           |  |  | 556 |         $files = $fs->get_area_files($a1context->id, GRADE_FILE_COMPONENT, GRADE_FEEDBACK_FILEAREA);
 | 
        
           |  |  | 557 |         $this->assertEquals(0, count($files));
 | 
        
           |  |  | 558 |   | 
        
           |  |  | 559 |         // History file area.
 | 
        
           |  |  | 560 |         $files = $fs->get_area_files($a1context->id, GRADE_FILE_COMPONENT, GRADE_HISTORY_FEEDBACK_FILEAREA);
 | 
        
           |  |  | 561 |         $this->assertEquals(2, count($files));
 | 
        
           |  |  | 562 |     }
 | 
        
           |  |  | 563 |   | 
        
           |  |  | 564 |     /**
 | 
        
           |  |  | 565 |      * Creates a feedback file to copy to the gradebook area.
 | 
        
           |  |  | 566 |      */
 | 
        
           |  |  | 567 |     private function add_feedback_file_to_copy() {
 | 
        
           |  |  | 568 |         $dummy = array(
 | 
        
           |  |  | 569 |             'contextid' => 1,
 | 
        
           |  |  | 570 |             'component' => 'test',
 | 
        
           |  |  | 571 |             'filearea' => 'testarea',
 | 
        
           |  |  | 572 |             'itemid' => 1,
 | 
        
           |  |  | 573 |             'filepath' => '/',
 | 
        
           |  |  | 574 |             'filename' => 'feedback1.txt'
 | 
        
           |  |  | 575 |         );
 | 
        
           |  |  | 576 |   | 
        
           |  |  | 577 |         $fs = get_file_storage();
 | 
        
           |  |  | 578 |         $fs->create_file_from_string($dummy, '');
 | 
        
           |  |  | 579 |     }
 | 
        
           |  |  | 580 |   | 
        
           |  |  | 581 |     /**
 | 
        
           |  |  | 582 |      * Tests grade_deleted event.
 | 
        
           |  |  | 583 |      */
 | 
        
           |  |  | 584 |     public function sub_test_grade_grade_deleted_event() {
 | 
        
           |  |  | 585 |         global $DB;
 | 
        
           |  |  | 586 |         $dg = $this->getDataGenerator();
 | 
        
           |  |  | 587 |   | 
        
           |  |  | 588 |         // Create the data we need for the tests.
 | 
        
           |  |  | 589 |         $u1 = $dg->create_user();
 | 
        
           |  |  | 590 |         $u2 = $dg->create_user();
 | 
        
           |  |  | 591 |         $c1 = $dg->create_course();
 | 
        
           |  |  | 592 |         $a1 = $dg->create_module('assign', ['course' => $c1->id]);
 | 
        
           |  |  | 593 |   | 
        
           |  |  | 594 |         $gi = new \grade_item($dg->create_grade_item(
 | 
        
           |  |  | 595 |             [
 | 
        
           |  |  | 596 |                 'courseid' => $c1->id,
 | 
        
           |  |  | 597 |                 'itemtype' => 'mod',
 | 
        
           |  |  | 598 |                 'itemmodule' => 'assign',
 | 
        
           |  |  | 599 |                 'iteminstance' => $a1->id
 | 
        
           |  |  | 600 |             ]
 | 
        
           |  |  | 601 |         ), false);
 | 
        
           |  |  | 602 |   | 
        
           |  |  | 603 |         grade_update('mod/assign', $gi->courseid, $gi->itemtype, $gi->itemmodule, $gi->iteminstance,
 | 
        
           |  |  | 604 |             $gi->itemnumber, ['userid' => $u1->id]);
 | 
        
           |  |  | 605 |         grade_update('mod/assign', $gi->courseid, $gi->itemtype, $gi->itemmodule, $gi->iteminstance,
 | 
        
           |  |  | 606 |             $gi->itemnumber, ['userid' => $u2->id]);
 | 
        
           |  |  | 607 |   | 
        
           |  |  | 608 |         $gg = \grade_grade::fetch(array('userid' => $u1->id, 'itemid' => $gi->id));
 | 
        
           |  |  | 609 |         $this->assertEquals($u1->id, $gg->userid);
 | 
        
           |  |  | 610 |         $gg->load_grade_item();
 | 
        
           |  |  | 611 |         $this->assertEquals($gi->id, $gg->grade_item->id);
 | 
        
           |  |  | 612 |   | 
        
           |  |  | 613 |         // Delete user with valid grade item.
 | 
        
           |  |  | 614 |         $sink = $this->redirectEvents();
 | 
        
           |  |  | 615 |         grade_user_delete($u1->id);
 | 
        
           |  |  | 616 |         $events = $sink->get_events();
 | 
        
           |  |  | 617 |         $event = reset($events);
 | 
        
           |  |  | 618 |         $sink->close();
 | 
        
           |  |  | 619 |         $this->assertInstanceOf('core\event\grade_deleted', $event);
 | 
        
           |  |  | 620 |   | 
        
           |  |  | 621 |         $gg = \grade_grade::fetch(array('userid' => $u2->id, 'itemid' => $gi->id));
 | 
        
           |  |  | 622 |         $this->assertEquals($u2->id, $gg->userid);
 | 
        
           |  |  | 623 |         $gg->load_grade_item();
 | 
        
           |  |  | 624 |         $this->assertEquals($gi->id, $gg->grade_item->id);
 | 
        
           |  |  | 625 |   | 
        
           |  |  | 626 |         // Delete grade item, mock up orphaned grade_grades.
 | 
        
           |  |  | 627 |         $DB->delete_records('grade_items', ['id' => $gi->id]);
 | 
        
           |  |  | 628 |         $gg = \grade_grade::fetch(array('userid' => $u2->id, 'itemid' => $gi->id));
 | 
        
           |  |  | 629 |         $this->assertEquals($u2->id, $gg->userid);
 | 
        
           |  |  | 630 |   | 
        
           |  |  | 631 |         // No event is triggered and there is a debugging message.
 | 
        
           |  |  | 632 |         $sink = $this->redirectEvents();
 | 
        
           |  |  | 633 |         grade_user_delete($u2->id);
 | 
        
           |  |  | 634 |         $this->assertDebuggingCalled("Missing grade item id $gi->id");
 | 
        
           |  |  | 635 |         $events = $sink->get_events();
 | 
        
           |  |  | 636 |         $sink->close();
 | 
        
           |  |  | 637 |         $this->assertEmpty($events);
 | 
        
           |  |  | 638 |   | 
        
           |  |  | 639 |         // The grade should be deleted.
 | 
        
           |  |  | 640 |         $gg = \grade_grade::fetch(array('userid' => $u2->id, 'itemid' => $gi->id));
 | 
        
           |  |  | 641 |         $this->assertEmpty($gg);
 | 
        
           |  |  | 642 |     }
 | 
        
           |  |  | 643 |   | 
        
           |  |  | 644 |     /**
 | 
        
           |  |  | 645 |      * Tests get_hiding_affected by locked category and overridden grades.
 | 
        
           |  |  | 646 |      */
 | 
        
           | 11 | efrain | 647 |     public function test_category_get_hiding_affected(): void {
 | 
        
           | 1 | efrain | 648 |         $generator = $this->getDataGenerator();
 | 
        
           |  |  | 649 |   | 
        
           |  |  | 650 |         // Create the data we need for the tests.
 | 
        
           |  |  | 651 |         $course1 = $generator->create_course();
 | 
        
           |  |  | 652 |         $user1 = $generator->create_and_enrol($course1, 'student');
 | 
        
           |  |  | 653 |         $assignment2 = $generator->create_module('assign', ['course' => $course1->id]);
 | 
        
           |  |  | 654 |   | 
        
           |  |  | 655 |         // Create a category item.
 | 
        
           |  |  | 656 |         $gradecategory = new \grade_category(array('courseid' => $course1->id, 'fullname' => 'test'), false);
 | 
        
           |  |  | 657 |         $gradecategoryid = $gradecategory->insert();
 | 
        
           |  |  | 658 |   | 
        
           |  |  | 659 |         // Create one hidden grade item.
 | 
        
           |  |  | 660 |         $gradeitem1a = new \grade_item($generator->create_grade_item(
 | 
        
           |  |  | 661 |             [
 | 
        
           |  |  | 662 |                 'courseid' => $course1->id,
 | 
        
           |  |  | 663 |                 'itemtype' => 'mod',
 | 
        
           |  |  | 664 |                 'itemmodule' => 'assign',
 | 
        
           |  |  | 665 |                 'iteminstance' => $assignment2->id,
 | 
        
           |  |  | 666 |                 'categoryid' => $gradecategoryid,
 | 
        
           |  |  | 667 |                 'hidden' => 1,
 | 
        
           |  |  | 668 |             ]
 | 
        
           |  |  | 669 |         ), false);
 | 
        
           |  |  | 670 |         grade_update('mod/assign', $gradeitem1a->courseid, $gradeitem1a->itemtype, $gradeitem1a->itemmodule, $gradeitem1a->iteminstance,
 | 
        
           |  |  | 671 |         $gradeitem1a->itemnumber, ['userid' => $user1->id]);
 | 
        
           |  |  | 672 |   | 
        
           |  |  | 673 |         // Get category grade item.
 | 
        
           |  |  | 674 |         $gradeitem = $gradecategory->get_grade_item();
 | 
        
           |  |  | 675 |         // Reset needsupdate to allow set_locked.
 | 
        
           |  |  | 676 |         $gradeitem->needsupdate = 0;
 | 
        
           |  |  | 677 |         $gradeitem->update();
 | 
        
           |  |  | 678 |         // Lock category grade item.
 | 
        
           |  |  | 679 |         $gradeitem->set_locked(1);
 | 
        
           |  |  | 680 |   | 
        
           |  |  | 681 |         $hidingaffectedlocked = $this->call_get_hiding_affected($course1, $user1);
 | 
        
           |  |  | 682 |         // Since locked category now should be recalculated.
 | 
        
           |  |  | 683 |         // The number of unknown items is 2, this includes category item and course item.
 | 
        
           |  |  | 684 |         $this->assertEquals(2, count($hidingaffectedlocked['unknown']));
 | 
        
           |  |  | 685 |   | 
        
           |  |  | 686 |         // Unlock category.
 | 
        
           |  |  | 687 |         $gradeitem->set_locked(0);
 | 
        
           |  |  | 688 |         $hidingaffectedunlocked = $this->call_get_hiding_affected($course1, $user1);
 | 
        
           |  |  | 689 |         // When category unlocked, hidden item should exist in altered items.
 | 
        
           |  |  | 690 |         $this->assertTrue(in_array($gradeitem1a->id, array_keys($hidingaffectedunlocked['altered'])));
 | 
        
           |  |  | 691 |   | 
        
           |  |  | 692 |         // This creates all the grade_grades we need.
 | 
        
           |  |  | 693 |         grade_regrade_final_grades($course1->id);
 | 
        
           |  |  | 694 |   | 
        
           |  |  | 695 |         // Set grade override.
 | 
        
           |  |  | 696 |         $gradegrade = \grade_grade::fetch([
 | 
        
           |  |  | 697 |             'userid' => $user1->id,
 | 
        
           |  |  | 698 |             'itemid' => $gradeitem->id,
 | 
        
           |  |  | 699 |         ]);
 | 
        
           |  |  | 700 |         // Set override grade grade, and check that grade submission has been overridden.
 | 
        
           |  |  | 701 |         $gradegrade->set_overridden(true);
 | 
        
           |  |  | 702 |         $this->assertEquals(true, $gradegrade->is_overridden());
 | 
        
           |  |  | 703 |         $hidingaffectedoverridden = $this->call_get_hiding_affected($course1, $user1);
 | 
        
           |  |  | 704 |         // No need to recalculate overridden grades.
 | 
        
           |  |  | 705 |         $this->assertTrue(in_array($gradegrade->itemid, array_keys($hidingaffectedoverridden['alteredaggregationstatus'])));
 | 
        
           |  |  | 706 |         $this->assertEquals('used', $hidingaffectedoverridden['alteredaggregationstatus'][$gradegrade->itemid]);
 | 
        
           |  |  | 707 |     }
 | 
        
           |  |  | 708 |   | 
        
           |  |  | 709 |     /**
 | 
        
           |  |  | 710 |      * Call get_hiding_affected().
 | 
        
           |  |  | 711 |      * @param \stdClass $course The course object
 | 
        
           |  |  | 712 |      * @param \stdClass $user The student object
 | 
        
           |  |  | 713 |      * @return array
 | 
        
           |  |  | 714 |      */
 | 
        
           |  |  | 715 |     private function call_get_hiding_affected($course, $user) {
 | 
        
           |  |  | 716 |         global $DB;
 | 
        
           |  |  | 717 |   | 
        
           |  |  | 718 |         $items = \grade_item::fetch_all(array('courseid' => $course->id));
 | 
        
           |  |  | 719 |         $grades = array();
 | 
        
           |  |  | 720 |         $sql = "SELECT g.*
 | 
        
           |  |  | 721 |                   FROM {grade_grades} g
 | 
        
           |  |  | 722 |                   JOIN {grade_items} gi ON gi.id = g.itemid
 | 
        
           |  |  | 723 |                  WHERE g.userid = :userid AND gi.courseid = :courseid";
 | 
        
           |  |  | 724 |         if ($gradesrecords = $DB->get_records_sql($sql, ['userid' => $user->id, 'courseid' => $course->id])) {
 | 
        
           |  |  | 725 |             foreach ($gradesrecords as $grade) {
 | 
        
           |  |  | 726 |                 $grades[$grade->itemid] = new \grade_grade($grade, false);
 | 
        
           |  |  | 727 |             }
 | 
        
           |  |  | 728 |             unset($gradesrecords);
 | 
        
           |  |  | 729 |         }
 | 
        
           |  |  | 730 |         foreach ($items as $itemid => $gradeitem) {
 | 
        
           |  |  | 731 |             if (!isset($grades[$itemid])) {
 | 
        
           |  |  | 732 |                 $gradegrade = new \grade_grade();
 | 
        
           |  |  | 733 |                 $gradegrade->userid = $user->id;
 | 
        
           |  |  | 734 |                 $gradegrade->itemid = $gradeitem->id;
 | 
        
           |  |  | 735 |                 $grades[$itemid] = $gradegrade;
 | 
        
           |  |  | 736 |             }
 | 
        
           |  |  | 737 |         }
 | 
        
           |  |  | 738 |   | 
        
           |  |  | 739 |         return \grade_grade::get_hiding_affected($grades, $items);
 | 
        
           |  |  | 740 |     }
 | 
        
           |  |  | 741 | }
 |