See Release Notes
Long Term Support Release
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 /** 18 * Data provider tests. 19 * 20 * @package core_grades 21 * @category test 22 * @copyright 2018 Frédéric Massart 23 * @author Frédéric Massart <fred@branchup.tech> 24 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 25 */ 26 namespace core_grades\privacy; 27 28 defined('MOODLE_INTERNAL') || die(); 29 global $CFG; 30 31 use core_privacy\tests\provider_testcase; 32 use core_privacy\local\request\approved_contextlist; 33 use core_privacy\local\request\transform; 34 use core_privacy\local\request\writer; 35 use core_grades\privacy\provider; 36 37 require_once($CFG->libdir . '/gradelib.php'); 38 39 /** 40 * Data provider testcase class. 41 * 42 * @package core_grades 43 * @category test 44 * @copyright 2018 Frédéric Massart 45 * @author Frédéric Massart <fred@branchup.tech> 46 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 47 */ 48 class provider_test extends provider_testcase { 49 50 public function setUp(): void { 51 global $PAGE; 52 $this->resetAfterTest(); 53 $PAGE->get_renderer('core'); 54 } 55 56 public function test_get_contexts_for_userid_gradebook_edits() { 57 $dg = $this->getDataGenerator(); 58 59 $c1 = $dg->create_course(); 60 $c2 = $dg->create_course(); 61 62 $u1 = $dg->create_user(); 63 $u2 = $dg->create_user(); 64 $u3 = $dg->create_user(); 65 $u4 = $dg->create_user(); 66 $u5 = $dg->create_user(); 67 $u6 = $dg->create_user(); 68 $u7 = $dg->create_user(); 69 $u8 = $dg->create_user(); 70 $u9 = $dg->create_user(); 71 $u10 = $dg->create_user(); 72 $u11 = $dg->create_user(); 73 74 $sysctx = \context_system::instance(); 75 $c1ctx = \context_course::instance($c1->id); 76 $c2ctx = \context_course::instance($c2->id); 77 78 // Create some stuff. 79 $gi1a = new \grade_item($dg->create_grade_item(['courseid' => $c1->id]), false); 80 $gi1b = new \grade_item($dg->create_grade_item(['courseid' => $c1->id]), false); 81 $gi2a = new \grade_item($dg->create_grade_item(['courseid' => $c2->id]), false); 82 $gc1a = new \grade_category($dg->create_grade_category(['courseid' => $c1->id]), false); 83 $gc1b = new \grade_category($dg->create_grade_category(['courseid' => $c1->id]), false); 84 $gc2a = new \grade_category($dg->create_grade_category(['courseid' => $c2->id]), false); 85 $go2 = new \grade_outcome($dg->create_grade_outcome(['courseid' => $c2->id, 'shortname' => 'go2', 86 'fullname' => 'go2']), false); 87 88 // Nothing as of now. 89 foreach ([$u1, $u2, $u3, $u4, $u5, $u6, $u7, $u8, $u9, $u10, $u11] as $u) { 90 $contexts = array_flip(provider::get_contexts_for_userid($u->id)->get_contextids()); 91 $this->assertEmpty($contexts); 92 } 93 94 $go0 = new \grade_outcome(['shortname' => 'go0', 'fullname' => 'go0', 'usermodified' => $u1->id]); 95 $go0->insert(); 96 $go1 = new \grade_outcome(['shortname' => 'go1', 'fullname' => 'go1', 'courseid' => $c1->id, 'usermodified' => $u11->id]); 97 $go1->insert(); 98 99 // Create scales. 100 $s1 = new \grade_scale(['name' => 's1', 'scale' => 'a,b', 'userid' => $u7->id, 'courseid' => 0, 'description' => '']); 101 $s1->insert(); 102 $s2 = new \grade_scale(['name' => 's2', 'scale' => 'a,b', 'userid' => $u8->id, 'courseid' => $c1->id, 'description' => '']); 103 $s2->insert(); 104 105 // User 2 creates history. 106 $this->setUser($u2); 107 $go0->shortname .= ' edited'; 108 $go0->update(); 109 $gc1a->fullname .= ' edited'; 110 $gc1a->update(); 111 112 // User 3 creates history. 113 $this->setUser($u3); 114 $go1->shortname .= ' edited'; 115 $go1->update(); 116 $gc2a->fullname .= ' a'; 117 $gc2a->update(); 118 119 // User 4 updates an outcome in course (creates history). 120 $this->setUser($u4); 121 $go2->shortname .= ' edited'; 122 $go2->update(); 123 124 // User 5 updates an item. 125 $this->setUser($u5); 126 $gi1a->itemname .= ' edited'; 127 $gi1a->update(); 128 129 // User 6 creates history. 130 $this->setUser($u6); 131 $gi2a->delete(); 132 133 // User 9 creates history. 134 $this->setUser($u9); 135 $s1->name .= ' edited'; 136 $s1->update(); 137 138 // Assert contexts. 139 $contexts = array_flip(provider::get_contexts_for_userid($u1->id)->get_contextids()); 140 $this->assertCount(1, $contexts); 141 $this->assertArrayHasKey($sysctx->id, $contexts); 142 $contexts = array_flip(provider::get_contexts_for_userid($u11->id)->get_contextids()); 143 $this->assertCount(1, $contexts); 144 $this->assertArrayHasKey($c1ctx->id, $contexts); 145 $contexts = array_flip(provider::get_contexts_for_userid($u2->id)->get_contextids()); 146 $this->assertCount(2, $contexts); 147 $this->assertArrayHasKey($sysctx->id, $contexts); 148 $this->assertArrayHasKey($c1ctx->id, $contexts); 149 $contexts = array_flip(provider::get_contexts_for_userid($u3->id)->get_contextids()); 150 $this->assertCount(2, $contexts); 151 $this->assertArrayHasKey($c1ctx->id, $contexts); 152 $this->assertArrayHasKey($c2ctx->id, $contexts); 153 $contexts = array_flip(provider::get_contexts_for_userid($u4->id)->get_contextids()); 154 $this->assertCount(1, $contexts); 155 $this->assertArrayHasKey($c2ctx->id, $contexts); 156 $contexts = array_flip(provider::get_contexts_for_userid($u5->id)->get_contextids()); 157 $this->assertCount(1, $contexts); 158 $this->assertArrayHasKey($c1ctx->id, $contexts); 159 $contexts = array_flip(provider::get_contexts_for_userid($u6->id)->get_contextids()); 160 $this->assertCount(1, $contexts); 161 $this->assertArrayHasKey($c2ctx->id, $contexts); 162 $contexts = array_flip(provider::get_contexts_for_userid($u7->id)->get_contextids()); 163 $this->assertCount(1, $contexts); 164 $this->assertArrayHasKey($sysctx->id, $contexts); 165 $contexts = array_flip(provider::get_contexts_for_userid($u8->id)->get_contextids()); 166 $this->assertCount(1, $contexts); 167 $this->assertArrayHasKey($c1ctx->id, $contexts); 168 $contexts = array_flip(provider::get_contexts_for_userid($u9->id)->get_contextids()); 169 $this->assertCount(1, $contexts); 170 $this->assertArrayHasKey($sysctx->id, $contexts); 171 172 // User 10 creates history. 173 $this->setUser($u10); 174 $s2->delete(); 175 176 $contexts = array_flip(provider::get_contexts_for_userid($u10->id)->get_contextids()); 177 $this->assertCount(1, $contexts); 178 $this->assertArrayHasKey($c1ctx->id, $contexts); 179 } 180 181 public function test_get_contexts_for_userid_grades_and_history() { 182 $dg = $this->getDataGenerator(); 183 184 $c1 = $dg->create_course(); 185 $c2 = $dg->create_course(); 186 187 $u1 = $dg->create_user(); 188 $u2 = $dg->create_user(); 189 $u3 = $dg->create_user(); 190 $u4 = $dg->create_user(); 191 $u5 = $dg->create_user(); 192 $u6 = $dg->create_user(); 193 194 $sysctx = \context_system::instance(); 195 $c1ctx = \context_course::instance($c1->id); 196 $c2ctx = \context_course::instance($c2->id); 197 198 // Create some stuff. 199 $gi1a = new \grade_item($dg->create_grade_item(['courseid' => $c1->id]), false); 200 $gi1b = new \grade_item($dg->create_grade_item(['courseid' => $c1->id]), false); 201 $gi2a = new \grade_item($dg->create_grade_item(['courseid' => $c2->id]), false); 202 $gi2b = new \grade_item($dg->create_grade_item(['courseid' => $c2->id]), false); 203 204 // Nothing as of now. 205 foreach ([$u1, $u2, $u3, $u4, $u5, $u6] as $u) { 206 $contexts = array_flip(provider::get_contexts_for_userid($u->id)->get_contextids()); 207 $this->assertEmpty($contexts); 208 } 209 210 // User 1 is graded in course 1. 211 $gi1a->update_final_grade($u1->id, 1, 'test'); 212 213 // User 2 is graded in course 2. 214 $gi2a->update_final_grade($u2->id, 10, 'test'); 215 216 // User 3 is set as modifier. 217 $gi1a->update_final_grade($u1->id, 1, 'test', '', FORMAT_MOODLE, $u3->id); 218 219 // User 4 is set as modifier, and creates history.. 220 $this->setUser($u4); 221 $gi1a->update_final_grade($u2->id, 1, 'test'); 222 223 // User 5 creates history, user 6 is the known modifier, and we delete the item. 224 $this->setUser($u5); 225 $gi2b->update_final_grade($u2->id, 1, 'test', '', FORMAT_PLAIN, $u6->id); 226 $gi2b->delete(); 227 228 // Assert contexts. 229 $contexts = array_flip(provider::get_contexts_for_userid($u1->id)->get_contextids()); 230 $this->assertCount(1, $contexts); 231 $this->assertArrayHasKey($c1ctx->id, $contexts); 232 $contexts = array_flip(provider::get_contexts_for_userid($u2->id)->get_contextids()); 233 $this->assertCount(3, $contexts); 234 $this->assertArrayHasKey($c1ctx->id, $contexts); 235 $this->assertArrayHasKey($c2ctx->id, $contexts); 236 $this->assertArrayHasKey(\context_user::instance($u2->id)->id, $contexts); 237 $contexts = array_flip(provider::get_contexts_for_userid($u3->id)->get_contextids()); 238 $this->assertCount(1, $contexts); 239 $this->assertArrayHasKey($c1ctx->id, $contexts); 240 $contexts = array_flip(provider::get_contexts_for_userid($u4->id)->get_contextids()); 241 $this->assertCount(1, $contexts); 242 $this->assertArrayHasKey($c1ctx->id, $contexts); 243 $contexts = array_flip(provider::get_contexts_for_userid($u5->id)->get_contextids()); 244 $this->assertCount(2, $contexts); 245 $this->assertArrayHasKey($c2ctx->id, $contexts); 246 $this->assertArrayHasKey(\context_user::instance($u2->id)->id, $contexts); 247 $contexts = array_flip(provider::get_contexts_for_userid($u6->id)->get_contextids()); 248 $this->assertCount(1, $contexts); 249 $this->assertArrayHasKey(\context_user::instance($u2->id)->id, $contexts); 250 } 251 252 /** 253 * Test that the appropriate user IDs are returned for a given context. 254 */ 255 public function test_get_users_in_context_gradebook_edits() { 256 $dg = $this->getDataGenerator(); 257 258 $c1 = $dg->create_course(); 259 $c2 = $dg->create_course(); 260 261 $u1 = $dg->create_user(); 262 $u2 = $dg->create_user(); 263 $u3 = $dg->create_user(); 264 $u4 = $dg->create_user(); 265 $u5 = $dg->create_user(); 266 $u6 = $dg->create_user(); 267 $u7 = $dg->create_user(); 268 $u8 = $dg->create_user(); 269 $u9 = $dg->create_user(); 270 $u10 = $dg->create_user(); 271 $u11 = $dg->create_user(); 272 273 $sysctx = \context_system::instance(); 274 $c1ctx = \context_course::instance($c1->id); 275 $c2ctx = \context_course::instance($c2->id); 276 277 // Create some stuff. 278 $gi1a = new \grade_item($dg->create_grade_item(['courseid' => $c1->id]), false); 279 $gi1b = new \grade_item($dg->create_grade_item(['courseid' => $c1->id]), false); 280 $gi2a = new \grade_item($dg->create_grade_item(['courseid' => $c2->id]), false); 281 $gc1a = new \grade_category($dg->create_grade_category(['courseid' => $c1->id]), false); 282 $gc1b = new \grade_category($dg->create_grade_category(['courseid' => $c1->id]), false); 283 $gc2a = new \grade_category($dg->create_grade_category(['courseid' => $c2->id]), false); 284 $go2 = new \grade_outcome($dg->create_grade_outcome(['courseid' => $c2->id, 'shortname' => 'go2', 285 'fullname' => 'go2']), false); 286 287 $go0 = new \grade_outcome(['shortname' => 'go0', 'fullname' => 'go0', 'usermodified' => $u1->id]); 288 $go0->insert(); 289 $go1 = new \grade_outcome(['shortname' => 'go1', 'fullname' => 'go1', 'courseid' => $c1->id, 'usermodified' => $u11->id]); 290 $go1->insert(); 291 292 // Create scales. 293 $s1 = new \grade_scale(['name' => 's1', 'scale' => 'a,b', 'userid' => $u7->id, 'courseid' => 0, 'description' => '']); 294 $s1->insert(); 295 $s2 = new \grade_scale(['name' => 's2', 'scale' => 'a,b', 'userid' => $u8->id, 'courseid' => $c1->id, 'description' => '']); 296 $s2->insert(); 297 298 // User 2 creates history. 299 $this->setUser($u2); 300 $go0->shortname .= ' edited'; 301 $go0->update(); 302 $gc1a->fullname .= ' edited'; 303 $gc1a->update(); 304 305 // User 3 creates history. 306 $this->setUser($u3); 307 $go1->shortname .= ' edited'; 308 $go1->update(); 309 $gc2a->fullname .= ' a'; 310 $gc2a->update(); 311 312 // User 4 updates an outcome in course (creates history). 313 $this->setUser($u4); 314 $go2->shortname .= ' edited'; 315 $go2->update(); 316 317 // User 5 updates an item. 318 $this->setUser($u5); 319 $gi1a->itemname .= ' edited'; 320 $gi1a->update(); 321 322 // User 6 creates history. 323 $this->setUser($u6); 324 $gi2a->delete(); 325 326 // User 9 creates history. 327 $this->setUser($u9); 328 $s1->name .= ' edited'; 329 $s1->update(); 330 331 $userlist = new \core_privacy\local\request\userlist($sysctx, 'core_grades'); 332 provider::get_users_in_context($userlist); 333 $systemcontextuserids = [$u1->id, $u2->id, $u7->id, $u9->id]; 334 $this->assertEquals($systemcontextuserids, $userlist->get_userids()); 335 336 $userlist = new \core_privacy\local\request\userlist($c1ctx, 'core_grades'); 337 provider::get_users_in_context($userlist); 338 $course1userids = [$u11->id, $u3->id, $u8->id, $u5->id, $u2->id]; 339 $this->assertEquals($course1userids, $userlist->get_userids()); 340 341 $userlist = new \core_privacy\local\request\userlist($c2ctx, 'core_grades'); 342 provider::get_users_in_context($userlist); 343 $course2userids = [$u4->id, $u6->id, $u3->id]; 344 $this->assertEquals($course2userids, $userlist->get_userids()); 345 } 346 347 /** 348 * Test that the appropriate user IDs are returned for a given context. 349 */ 350 public function test_get_users_in_context_grades_and_history() { 351 $dg = $this->getDataGenerator(); 352 353 $c1 = $dg->create_course(); 354 $c2 = $dg->create_course(); 355 356 $u1 = $dg->create_user(); 357 $u2 = $dg->create_user(); 358 $u3 = $dg->create_user(); 359 $u4 = $dg->create_user(); 360 $u5 = $dg->create_user(); 361 $u6 = $dg->create_user(); 362 363 $c1ctx = \context_course::instance($c1->id); 364 $c2ctx = \context_course::instance($c2->id); 365 $u2ctx = \context_user::instance($u2->id); 366 367 // Create some stuff. 368 $gi1a = new \grade_item($dg->create_grade_item(['courseid' => $c1->id]), false); 369 $gi1b = new \grade_item($dg->create_grade_item(['courseid' => $c1->id]), false); 370 $gi2a = new \grade_item($dg->create_grade_item(['courseid' => $c2->id]), false); 371 $gi2b = new \grade_item($dg->create_grade_item(['courseid' => $c2->id]), false); 372 373 // User 1 is graded in course 1. 374 $gi1a->update_final_grade($u1->id, 1, 'test'); 375 376 // User 2 is graded in course 2. 377 $gi2a->update_final_grade($u2->id, 10, 'test'); 378 379 // User 3 is set as modifier. 380 $gi1a->update_final_grade($u1->id, 1, 'test', '', FORMAT_MOODLE, $u3->id); 381 382 // User 4 is set as modifier, and creates history.. 383 $this->setUser($u4); 384 $gi1a->update_final_grade($u2->id, 1, 'test'); 385 386 // User 5 creates history, user 6 is the known modifier, and we delete the item. 387 $this->setUser($u5); 388 $gi2b->update_final_grade($u2->id, 1, 'test', '', FORMAT_PLAIN, $u6->id); 389 $gi2b->delete(); 390 391 $userlist = new \core_privacy\local\request\userlist($c1ctx, 'core_grades'); 392 provider::get_users_in_context($userlist); 393 $course1userids = [$u1->id, $u2->id, $u3->id, $u4->id]; 394 $this->assertEqualsCanonicalizing($course1userids, $userlist->get_userids()); 395 396 $userlist = new \core_privacy\local\request\userlist($c2ctx, 'core_grades'); 397 provider::get_users_in_context($userlist); 398 $course2userids = [$u5->id, $u2->id]; 399 $this->assertEqualsCanonicalizing($course2userids, $userlist->get_userids()); 400 401 $userlist = new \core_privacy\local\request\userlist($u2ctx, 'core_grades'); 402 provider::get_users_in_context($userlist); 403 $this->assertEquals([$u2->id], $userlist->get_userids()); 404 } 405 406 public function test_delete_data_for_all_users_in_context() { 407 global $DB; 408 409 $fs = new \file_storage(); 410 411 $dg = $this->getDataGenerator(); 412 413 $c1 = $dg->create_course(); 414 $c2 = $dg->create_course(); 415 $u1 = $dg->create_user(); 416 $u2 = $dg->create_user(); 417 $u1ctx = \context_user::instance($u1->id); 418 $c1ctx = \context_course::instance($c1->id); 419 $c2ctx = \context_course::instance($c2->id); 420 421 $a1 = $dg->create_module('assign', ['course' => $c1->id]); 422 $a2 = $dg->create_module('assign', ['course' => $c1->id]); 423 $a3 = $dg->create_module('assign', ['course' => $c2->id]); 424 $a4 = $dg->create_module('assign', ['course' => $c2->id]); 425 426 $a1context = \context_module::instance($a1->cmid); 427 $a2context = \context_module::instance($a2->cmid); 428 $a3context = \context_module::instance($a3->cmid); 429 $a4context = \context_module::instance($a4->cmid); 430 431 // Create some stuff. 432 $gi1a = new \grade_item($dg->create_grade_item( 433 [ 434 'courseid' => $c1->id, 435 'itemtype' => 'mod', 436 'itemmodule' => 'assign', 437 'iteminstance' => $a1->id 438 ] 439 ), false); 440 $gi1b = new \grade_item($dg->create_grade_item( 441 [ 442 'courseid' => $c1->id, 443 'itemtype' => 'mod', 444 'itemmodule' => 'assign', 445 'iteminstance' => $a2->id 446 ] 447 ), false); 448 $gi2a = new \grade_item($dg->create_grade_item( 449 [ 450 'courseid' => $c2->id, 451 'itemtype' => 'mod', 452 'itemmodule' => 'assign', 453 'iteminstance' => $a3->id 454 ] 455 ), false); 456 $gi2b = new \grade_item($dg->create_grade_item( 457 [ 458 'courseid' => $c2->id, 459 'itemtype' => 'mod', 460 'itemmodule' => 'assign', 461 'iteminstance' => $a4->id 462 ] 463 ), false); 464 465 $this->add_feedback_file_to_copy(); 466 467 $grades['feedback'] = 'Nice feedback!'; 468 $grades['feedbackformat'] = FORMAT_MOODLE; 469 $grades['feedbackfiles'] = [ 470 'contextid' => 1, 471 'component' => 'test', 472 'filearea' => 'testarea', 473 'itemid' => 1 474 ]; 475 476 $grades['userid'] = $u1->id; 477 grade_update('mod/assign', $gi1a->courseid, $gi1a->itemtype, $gi1a->itemmodule, $gi1a->iteminstance, 478 $gi1a->itemnumber, $grades); 479 480 $grades['userid'] = $u2->id; 481 grade_update('mod/assign', $gi1a->courseid, $gi1a->itemtype, $gi1a->itemmodule, $gi1a->iteminstance, 482 $gi1a->itemnumber, $grades); 483 484 $grades['userid'] = $u1->id; 485 grade_update('mod/assign', $gi1b->courseid, $gi1b->itemtype, $gi1b->itemmodule, $gi1b->iteminstance, 486 $gi1b->itemnumber, $grades); 487 488 $grades['userid'] = $u1->id; 489 grade_update('mod/assign', $gi2a->courseid, $gi2a->itemtype, $gi2a->itemmodule, $gi2a->iteminstance, 490 $gi2a->itemnumber, $grades); 491 492 $grades['userid'] = $u2->id; 493 grade_update('mod/assign', $gi2a->courseid, $gi2a->itemtype, $gi2a->itemmodule, $gi2a->iteminstance, 494 $gi2a->itemnumber, $grades); 495 496 $grades['userid'] = $u1->id; 497 grade_update('mod/assign', $gi2b->courseid, $gi2b->itemtype, $gi2b->itemmodule, $gi2b->iteminstance, 498 $gi2b->itemnumber, $grades); 499 500 $grades['userid'] = $u2->id; 501 grade_update('mod/assign', $gi2b->courseid, $gi2b->itemtype, $gi2b->itemmodule, $gi2b->iteminstance, 502 $gi2b->itemnumber, $grades); 503 $gi2b->delete(); 504 505 // Feedback file area. 506 $files = $fs->get_area_files($a1context->id, GRADE_FILE_COMPONENT, GRADE_FEEDBACK_FILEAREA); 507 $this->assertEquals(4, count($files)); 508 509 $files = $fs->get_area_files($a2context->id, GRADE_FILE_COMPONENT, GRADE_FEEDBACK_FILEAREA); 510 $this->assertEquals(2, count($files)); 511 512 $files = $fs->get_area_files($a3context->id, GRADE_FILE_COMPONENT, GRADE_FEEDBACK_FILEAREA); 513 $this->assertEquals(4, count($files)); 514 515 // Grade item 2 was deleted, so the associated files were as well. 516 $files = $fs->get_area_files($a4context->id, GRADE_FILE_COMPONENT, GRADE_FEEDBACK_FILEAREA); 517 $this->assertEquals(0, count($files)); 518 519 // History file area. 520 $files = $fs->get_area_files($a1context->id, GRADE_FILE_COMPONENT, GRADE_HISTORY_FEEDBACK_FILEAREA); 521 $this->assertEquals(4, count($files)); 522 523 $files = $fs->get_area_files($a2context->id, GRADE_FILE_COMPONENT, GRADE_HISTORY_FEEDBACK_FILEAREA); 524 $this->assertEquals(2, count($files)); 525 526 $files = $fs->get_area_files($a3context->id, GRADE_FILE_COMPONENT, GRADE_HISTORY_FEEDBACK_FILEAREA); 527 $this->assertEquals(4, count($files)); 528 529 // Grade item 2 was deleted, so the associated files were as well. 530 $files = $fs->get_area_files($a4context->id, GRADE_FILE_COMPONENT, GRADE_HISTORY_FEEDBACK_FILEAREA); 531 $this->assertEquals(0, count($files)); 532 533 $this->assertTrue($DB->record_exists('grade_grades', ['userid' => $u1->id, 'itemid' => $gi1a->id])); 534 $this->assertTrue($DB->record_exists('grade_grades', ['userid' => $u2->id, 'itemid' => $gi1a->id])); 535 $this->assertTrue($DB->record_exists('grade_grades', ['userid' => $u1->id, 'itemid' => $gi1b->id])); 536 $this->assertTrue($DB->record_exists('grade_grades', ['userid' => $u1->id, 'itemid' => $gi2a->id])); 537 $this->assertTrue($DB->record_exists('grade_grades', ['userid' => $u2->id, 'itemid' => $gi2a->id])); 538 $this->assertTrue($DB->record_exists('grade_grades_history', ['userid' => $u1->id, 'itemid' => $gi2b->id])); 539 $this->assertTrue($DB->record_exists('grade_grades_history', ['userid' => $u2->id, 'itemid' => $gi2b->id])); 540 541 provider::delete_data_for_all_users_in_context($c1ctx); 542 $this->assertFalse($DB->record_exists('grade_grades', ['userid' => $u1->id, 'itemid' => $gi1a->id])); 543 $this->assertFalse($DB->record_exists('grade_grades', ['userid' => $u2->id, 'itemid' => $gi1a->id])); 544 $this->assertFalse($DB->record_exists('grade_grades', ['userid' => $u1->id, 'itemid' => $gi1b->id])); 545 $this->assertTrue($DB->record_exists('grade_grades', ['userid' => $u1->id, 'itemid' => $gi2a->id])); 546 $this->assertTrue($DB->record_exists('grade_grades', ['userid' => $u2->id, 'itemid' => $gi2a->id])); 547 $this->assertTrue($DB->record_exists('grade_grades_history', ['userid' => $u1->id, 'itemid' => $gi2b->id])); 548 $this->assertTrue($DB->record_exists('grade_grades_history', ['userid' => $u2->id, 'itemid' => $gi2b->id])); 549 550 // Feedback file area. 551 $files = $fs->get_area_files($a1context->id, GRADE_FILE_COMPONENT, GRADE_FEEDBACK_FILEAREA); 552 $this->assertEquals(0, count($files)); 553 554 $files = $fs->get_area_files($a2context->id, GRADE_FILE_COMPONENT, GRADE_FEEDBACK_FILEAREA); 555 $this->assertEquals(0, count($files)); 556 557 $files = $fs->get_area_files($a3context->id, GRADE_FILE_COMPONENT, GRADE_FEEDBACK_FILEAREA); 558 $this->assertEquals(4, count($files)); 559 560 // Grade item 2 was deleted, so the associated files were as well. 561 $files = $fs->get_area_files($a4context->id, GRADE_FILE_COMPONENT, GRADE_FEEDBACK_FILEAREA); 562 $this->assertEquals(0, count($files)); 563 564 // History file area. 565 $files = $fs->get_area_files($a1context->id, GRADE_FILE_COMPONENT, GRADE_HISTORY_FEEDBACK_FILEAREA); 566 $this->assertEquals(0, count($files)); 567 568 $files = $fs->get_area_files($a2context->id, GRADE_FILE_COMPONENT, GRADE_HISTORY_FEEDBACK_FILEAREA); 569 $this->assertEquals(0, count($files)); 570 571 $files = $fs->get_area_files($a3context->id, GRADE_FILE_COMPONENT, GRADE_HISTORY_FEEDBACK_FILEAREA); 572 $this->assertEquals(4, count($files)); 573 574 // Grade item 2 was deleted, so the associated files were as well. 575 $files = $fs->get_area_files($a4context->id, GRADE_FILE_COMPONENT, GRADE_HISTORY_FEEDBACK_FILEAREA); 576 $this->assertEquals(0, count($files)); 577 578 provider::delete_data_for_all_users_in_context($u1ctx); 579 $this->assertTrue($DB->record_exists('grade_grades', ['userid' => $u1->id, 'itemid' => $gi2a->id])); 580 $this->assertTrue($DB->record_exists('grade_grades', ['userid' => $u2->id, 'itemid' => $gi2a->id])); 581 $this->assertFalse($DB->record_exists('grade_grades_history', ['userid' => $u1->id, 'itemid' => $gi2b->id])); 582 $this->assertTrue($DB->record_exists('grade_grades_history', ['userid' => $u2->id, 'itemid' => $gi2b->id])); 583 584 // Feedback file area. 585 $files = $fs->get_area_files($a1context->id, GRADE_FILE_COMPONENT, GRADE_FEEDBACK_FILEAREA); 586 $this->assertEquals(0, count($files)); 587 588 $files = $fs->get_area_files($a2context->id, GRADE_FILE_COMPONENT, GRADE_FEEDBACK_FILEAREA); 589 $this->assertEquals(0, count($files)); 590 591 // The user context is only reported when there are orphan historical grades, so we only delete those files. 592 $files = $fs->get_area_files($a3context->id, GRADE_FILE_COMPONENT, GRADE_FEEDBACK_FILEAREA); 593 $this->assertEquals(4, count($files)); 594 595 // Grade item 2 was deleted, so the associated files were as well. 596 $files = $fs->get_area_files($a4context->id, GRADE_FILE_COMPONENT, GRADE_FEEDBACK_FILEAREA); 597 $this->assertEquals(0, count($files)); 598 599 // History file area. 600 $files = $fs->get_area_files($a1context->id, GRADE_FILE_COMPONENT, GRADE_HISTORY_FEEDBACK_FILEAREA); 601 $this->assertEquals(0, count($files)); 602 603 $files = $fs->get_area_files($a2context->id, GRADE_FILE_COMPONENT, GRADE_HISTORY_FEEDBACK_FILEAREA); 604 $this->assertEquals(0, count($files)); 605 606 // User 2 still has historical files. 607 $files = $fs->get_area_files($a3context->id, GRADE_FILE_COMPONENT, GRADE_HISTORY_FEEDBACK_FILEAREA); 608 $this->assertEquals(2, count($files)); 609 610 // Grade item 2 was deleted, so the associated files were as well. 611 $files = $fs->get_area_files($a4context->id, GRADE_FILE_COMPONENT, GRADE_HISTORY_FEEDBACK_FILEAREA); 612 $this->assertEquals(0, count($files)); 613 614 provider::delete_data_for_all_users_in_context($c2ctx); 615 $this->assertFalse($DB->record_exists('grade_grades', ['userid' => $u1->id, 'itemid' => $gi2a->id])); 616 $this->assertFalse($DB->record_exists('grade_grades', ['userid' => $u2->id, 'itemid' => $gi2a->id])); 617 $this->assertTrue($DB->record_exists('grade_grades_history', ['userid' => $u2->id, 'itemid' => $gi2b->id])); 618 619 // Feedback file area. 620 $files = $fs->get_area_files($a1context->id, GRADE_FILE_COMPONENT, GRADE_FEEDBACK_FILEAREA); 621 $this->assertEquals(0, count($files)); 622 623 $files = $fs->get_area_files($a2context->id, GRADE_FILE_COMPONENT, GRADE_FEEDBACK_FILEAREA); 624 $this->assertEquals(0, count($files)); 625 626 $files = $fs->get_area_files($a3context->id, GRADE_FILE_COMPONENT, GRADE_FEEDBACK_FILEAREA); 627 $this->assertEquals(0, count($files)); 628 629 $files = $fs->get_area_files($a4context->id, GRADE_FILE_COMPONENT, GRADE_FEEDBACK_FILEAREA); 630 $this->assertEquals(0, count($files)); 631 632 // History file area. 633 $files = $fs->get_area_files($a1context->id, GRADE_FILE_COMPONENT, GRADE_HISTORY_FEEDBACK_FILEAREA); 634 $this->assertEquals(0, count($files)); 635 636 $files = $fs->get_area_files($a2context->id, GRADE_FILE_COMPONENT, GRADE_HISTORY_FEEDBACK_FILEAREA); 637 $this->assertEquals(0, count($files)); 638 639 $files = $fs->get_area_files($a3context->id, GRADE_FILE_COMPONENT, GRADE_HISTORY_FEEDBACK_FILEAREA); 640 $this->assertEquals(0, count($files)); 641 642 $files = $fs->get_area_files($a4context->id, GRADE_FILE_COMPONENT, GRADE_HISTORY_FEEDBACK_FILEAREA); 643 $this->assertEquals(0, count($files)); 644 } 645 646 public function test_delete_data_for_user() { 647 global $DB; 648 649 $fs = new \file_storage(); 650 651 $dg = $this->getDataGenerator(); 652 653 $c1 = $dg->create_course(); 654 $c2 = $dg->create_course(); 655 $u1 = $dg->create_user(); 656 $u2 = $dg->create_user(); 657 $u1ctx = \context_user::instance($u1->id); 658 $u2ctx = \context_user::instance($u2->id); 659 $c1ctx = \context_course::instance($c1->id); 660 $c2ctx = \context_course::instance($c2->id); 661 662 $a1 = $dg->create_module('assign', ['course' => $c1->id]); 663 $a2 = $dg->create_module('assign', ['course' => $c1->id]); 664 $a3 = $dg->create_module('assign', ['course' => $c2->id]); 665 $a4 = $dg->create_module('assign', ['course' => $c2->id]); 666 667 $a1context = \context_module::instance($a1->cmid); 668 $a2context = \context_module::instance($a2->cmid); 669 $a3context = \context_module::instance($a3->cmid); 670 $a4context = \context_module::instance($a4->cmid); 671 672 // Create some stuff. 673 $gi1a = new \grade_item($dg->create_grade_item( 674 [ 675 'courseid' => $c1->id, 676 'itemtype' => 'mod', 677 'itemmodule' => 'assign', 678 'iteminstance' => $a1->id 679 ] 680 ), false); 681 $gi1b = new \grade_item($dg->create_grade_item( 682 [ 683 'courseid' => $c1->id, 684 'itemtype' => 'mod', 685 'itemmodule' => 'assign', 686 'iteminstance' => $a2->id 687 ] 688 ), false); 689 $gi2a = new \grade_item($dg->create_grade_item( 690 [ 691 'courseid' => $c2->id, 692 'itemtype' => 'mod', 693 'itemmodule' => 'assign', 694 'iteminstance' => $a3->id 695 ] 696 ), false); 697 $gi2b = new \grade_item($dg->create_grade_item( 698 [ 699 'courseid' => $c2->id, 700 'itemtype' => 'mod', 701 'itemmodule' => 'assign', 702 'iteminstance' => $a4->id 703 ] 704 ), false); 705 706 $this->add_feedback_file_to_copy(); 707 708 $grades['feedback'] = 'Nice feedback!'; 709 $grades['feedbackfiles'] = [ 710 'contextid' => 1, 711 'component' => 'test', 712 'filearea' => 'testarea', 713 'itemid' => 1 714 ]; 715 716 $grades['userid'] = $u1->id; 717 grade_update('mod/assign', $gi1a->courseid, $gi1a->itemtype, $gi1a->itemmodule, $gi1a->iteminstance, 718 $gi1a->itemnumber, $grades); 719 720 $grades['userid'] = $u2->id; 721 grade_update('mod/assign', $gi1a->courseid, $gi1a->itemtype, $gi1a->itemmodule, $gi1a->iteminstance, 722 $gi1a->itemnumber, $grades); 723 724 $grades['userid'] = $u1->id; 725 grade_update('mod/assign', $gi1b->courseid, $gi1b->itemtype, $gi1b->itemmodule, $gi1b->iteminstance, 726 $gi1b->itemnumber, $grades); 727 728 $grades['userid'] = $u1->id; 729 grade_update('mod/assign', $gi2a->courseid, $gi2a->itemtype, $gi2a->itemmodule, $gi2a->iteminstance, 730 $gi2a->itemnumber, $grades); 731 732 $grades['userid'] = $u2->id; 733 grade_update('mod/assign', $gi2a->courseid, $gi2a->itemtype, $gi2a->itemmodule, $gi2a->iteminstance, 734 $gi2a->itemnumber, $grades); 735 736 $grades['userid'] = $u1->id; 737 grade_update('mod/assign', $gi2b->courseid, $gi2b->itemtype, $gi2b->itemmodule, $gi2b->iteminstance, 738 $gi2b->itemnumber, $grades); 739 740 $grades['userid'] = $u2->id; 741 grade_update('mod/assign', $gi2b->courseid, $gi2b->itemtype, $gi2b->itemmodule, $gi2b->iteminstance, 742 $gi2b->itemnumber, $grades); 743 744 $gi2b->delete(); 745 746 $this->assertTrue($DB->record_exists('grade_grades', ['userid' => $u1->id, 'itemid' => $gi1a->id])); 747 $this->assertTrue($DB->record_exists('grade_grades', ['userid' => $u2->id, 'itemid' => $gi1a->id])); 748 $this->assertTrue($DB->record_exists('grade_grades', ['userid' => $u1->id, 'itemid' => $gi1b->id])); 749 $this->assertTrue($DB->record_exists('grade_grades', ['userid' => $u1->id, 'itemid' => $gi2a->id])); 750 $this->assertTrue($DB->record_exists('grade_grades', ['userid' => $u2->id, 'itemid' => $gi2a->id])); 751 $this->assertTrue($DB->record_exists('grade_grades_history', ['userid' => $u1->id, 'itemid' => $gi2b->id])); 752 $this->assertTrue($DB->record_exists('grade_grades_history', ['userid' => $u2->id, 'itemid' => $gi2b->id])); 753 754 // Feedback file area. 755 $files = $fs->get_area_files($a1context->id, GRADE_FILE_COMPONENT, GRADE_FEEDBACK_FILEAREA); 756 $this->assertEquals(4, count($files)); 757 758 $files = $fs->get_area_files($a2context->id, GRADE_FILE_COMPONENT, GRADE_FEEDBACK_FILEAREA); 759 $this->assertEquals(2, count($files)); 760 761 $files = $fs->get_area_files($a3context->id, GRADE_FILE_COMPONENT, GRADE_FEEDBACK_FILEAREA); 762 $this->assertEquals(4, count($files)); 763 764 // Grade item 2 was deleted, so the associated files were as well. 765 $files = $fs->get_area_files($a4context->id, GRADE_FILE_COMPONENT, GRADE_FEEDBACK_FILEAREA); 766 $this->assertEquals(0, count($files)); 767 768 // History file area. 769 $files = $fs->get_area_files($a1context->id, GRADE_FILE_COMPONENT, GRADE_HISTORY_FEEDBACK_FILEAREA); 770 $this->assertEquals(4, count($files)); 771 772 $files = $fs->get_area_files($a2context->id, GRADE_FILE_COMPONENT, GRADE_HISTORY_FEEDBACK_FILEAREA); 773 $this->assertEquals(2, count($files)); 774 775 $files = $fs->get_area_files($a3context->id, GRADE_FILE_COMPONENT, GRADE_HISTORY_FEEDBACK_FILEAREA); 776 $this->assertEquals(4, count($files)); 777 778 // Grade item 2 was deleted, so the associated files were as well. 779 $files = $fs->get_area_files($a4context->id, GRADE_FILE_COMPONENT, GRADE_HISTORY_FEEDBACK_FILEAREA); 780 $this->assertEquals(0, count($files)); 781 782 provider::delete_data_for_user(new approved_contextlist($u1, 'core_grades', [$c1ctx->id])); 783 $this->assertFalse($DB->record_exists('grade_grades', ['userid' => $u1->id, 'itemid' => $gi1a->id])); 784 $this->assertTrue($DB->record_exists('grade_grades', ['userid' => $u2->id, 'itemid' => $gi1a->id])); 785 $this->assertFalse($DB->record_exists('grade_grades', ['userid' => $u1->id, 'itemid' => $gi1b->id])); 786 $this->assertTrue($DB->record_exists('grade_grades', ['userid' => $u1->id, 'itemid' => $gi2a->id])); 787 $this->assertTrue($DB->record_exists('grade_grades', ['userid' => $u2->id, 'itemid' => $gi2a->id])); 788 $this->assertTrue($DB->record_exists('grade_grades_history', ['userid' => $u1->id, 'itemid' => $gi2b->id])); 789 $this->assertTrue($DB->record_exists('grade_grades_history', ['userid' => $u2->id, 'itemid' => $gi2b->id])); 790 791 // Feedback file area. 792 $files = $fs->get_area_files($a1context->id, GRADE_FILE_COMPONENT, GRADE_FEEDBACK_FILEAREA); 793 $this->assertEquals(2, count($files)); 794 795 $files = $fs->get_area_files($a2context->id, GRADE_FILE_COMPONENT, GRADE_FEEDBACK_FILEAREA); 796 $this->assertEquals(0, count($files)); 797 798 $files = $fs->get_area_files($a3context->id, GRADE_FILE_COMPONENT, GRADE_FEEDBACK_FILEAREA); 799 $this->assertEquals(4, count($files)); 800 801 // Grade item 2 was deleted, so the associated files were as well. 802 $files = $fs->get_area_files($a4context->id, GRADE_FILE_COMPONENT, GRADE_FEEDBACK_FILEAREA); 803 $this->assertEquals(0, count($files)); 804 805 // History file area. 806 $files = $fs->get_area_files($a1context->id, GRADE_FILE_COMPONENT, GRADE_HISTORY_FEEDBACK_FILEAREA); 807 $this->assertEquals(2, count($files)); 808 809 $files = $fs->get_area_files($a2context->id, GRADE_FILE_COMPONENT, GRADE_HISTORY_FEEDBACK_FILEAREA); 810 $this->assertEquals(0, count($files)); 811 812 $files = $fs->get_area_files($a3context->id, GRADE_FILE_COMPONENT, GRADE_HISTORY_FEEDBACK_FILEAREA); 813 $this->assertEquals(4, count($files)); 814 815 // Grade item 2 was deleted, so the associated files were as well. 816 $files = $fs->get_area_files($a4context->id, GRADE_FILE_COMPONENT, GRADE_HISTORY_FEEDBACK_FILEAREA); 817 $this->assertEquals(0, count($files)); 818 819 provider::delete_data_for_user(new approved_contextlist($u1, 'core_grades', [$u1ctx->id])); 820 $this->assertFalse($DB->record_exists('grade_grades', ['userid' => $u1->id, 'itemid' => $gi1a->id])); 821 $this->assertTrue($DB->record_exists('grade_grades', ['userid' => $u2->id, 'itemid' => $gi1a->id])); 822 $this->assertFalse($DB->record_exists('grade_grades', ['userid' => $u1->id, 'itemid' => $gi1b->id])); 823 $this->assertTrue($DB->record_exists('grade_grades', ['userid' => $u1->id, 'itemid' => $gi2a->id])); 824 $this->assertTrue($DB->record_exists('grade_grades', ['userid' => $u2->id, 'itemid' => $gi2a->id])); 825 $this->assertFalse($DB->record_exists('grade_grades_history', ['userid' => $u1->id, 'itemid' => $gi2b->id])); 826 $this->assertTrue($DB->record_exists('grade_grades_history', ['userid' => $u2->id, 'itemid' => $gi2b->id])); 827 828 // Feedback file area. 829 $files = $fs->get_area_files($a1context->id, GRADE_FILE_COMPONENT, GRADE_FEEDBACK_FILEAREA); 830 $this->assertEquals(2, count($files)); 831 832 $files = $fs->get_area_files($a2context->id, GRADE_FILE_COMPONENT, GRADE_FEEDBACK_FILEAREA); 833 $this->assertEquals(0, count($files)); 834 835 $files = $fs->get_area_files($a3context->id, GRADE_FILE_COMPONENT, GRADE_FEEDBACK_FILEAREA); 836 $this->assertEquals(4, count($files)); 837 838 // Grade item 2 was deleted, so the associated files were as well. 839 $files = $fs->get_area_files($a4context->id, GRADE_FILE_COMPONENT, GRADE_FEEDBACK_FILEAREA); 840 $this->assertEquals(0, count($files)); 841 842 // History file area. 843 $files = $fs->get_area_files($a1context->id, GRADE_FILE_COMPONENT, GRADE_HISTORY_FEEDBACK_FILEAREA); 844 $this->assertEquals(2, count($files)); 845 846 $files = $fs->get_area_files($a2context->id, GRADE_FILE_COMPONENT, GRADE_HISTORY_FEEDBACK_FILEAREA); 847 $this->assertEquals(0, count($files)); 848 849 $files = $fs->get_area_files($a3context->id, GRADE_FILE_COMPONENT, GRADE_HISTORY_FEEDBACK_FILEAREA); 850 $this->assertEquals(2, count($files)); 851 852 // Grade item 2 was deleted, so the associated files were as well. 853 $files = $fs->get_area_files($a4context->id, GRADE_FILE_COMPONENT, GRADE_HISTORY_FEEDBACK_FILEAREA); 854 $this->assertEquals(0, count($files)); 855 856 provider::delete_data_for_user(new approved_contextlist($u1, 'core_grades', [$u2ctx->id, $c2ctx->id])); 857 $this->assertFalse($DB->record_exists('grade_grades', ['userid' => $u1->id, 'itemid' => $gi1a->id])); 858 $this->assertTrue($DB->record_exists('grade_grades', ['userid' => $u2->id, 'itemid' => $gi1a->id])); 859 $this->assertFalse($DB->record_exists('grade_grades', ['userid' => $u1->id, 'itemid' => $gi1b->id])); 860 $this->assertFalse($DB->record_exists('grade_grades', ['userid' => $u1->id, 'itemid' => $gi2a->id])); 861 $this->assertTrue($DB->record_exists('grade_grades', ['userid' => $u2->id, 'itemid' => $gi2a->id])); 862 $this->assertFalse($DB->record_exists('grade_grades_history', ['userid' => $u1->id, 'itemid' => $gi2b->id])); 863 $this->assertTrue($DB->record_exists('grade_grades_history', ['userid' => $u2->id, 'itemid' => $gi2b->id])); 864 865 // Feedback file area. 866 $files = $fs->get_area_files($a1context->id, GRADE_FILE_COMPONENT, GRADE_FEEDBACK_FILEAREA); 867 $this->assertEquals(2, count($files)); 868 869 $files = $fs->get_area_files($a2context->id, GRADE_FILE_COMPONENT, GRADE_FEEDBACK_FILEAREA); 870 $this->assertEquals(0, count($files)); 871 872 $files = $fs->get_area_files($a3context->id, GRADE_FILE_COMPONENT, GRADE_FEEDBACK_FILEAREA); 873 $this->assertEquals(2, count($files)); 874 875 // Grade item 2 was deleted, so the associated files were as well. 876 $files = $fs->get_area_files($a4context->id, GRADE_FILE_COMPONENT, GRADE_FEEDBACK_FILEAREA); 877 $this->assertEquals(0, count($files)); 878 879 // History file area. 880 $files = $fs->get_area_files($a1context->id, GRADE_FILE_COMPONENT, GRADE_HISTORY_FEEDBACK_FILEAREA); 881 $this->assertEquals(2, count($files)); 882 883 $files = $fs->get_area_files($a2context->id, GRADE_FILE_COMPONENT, GRADE_HISTORY_FEEDBACK_FILEAREA); 884 $this->assertEquals(0, count($files)); 885 886 $files = $fs->get_area_files($a3context->id, GRADE_FILE_COMPONENT, GRADE_HISTORY_FEEDBACK_FILEAREA); 887 $this->assertEquals(2, count($files)); 888 889 // Grade item 2 was deleted, so the associated files were as well. 890 $files = $fs->get_area_files($a4context->id, GRADE_FILE_COMPONENT, GRADE_HISTORY_FEEDBACK_FILEAREA); 891 $this->assertEquals(0, count($files)); 892 } 893 894 /** 895 * Test deleting multiple users for a context works. 896 */ 897 public function test_delete_data_for_users() { 898 global $DB; 899 $dg = $this->getDataGenerator(); 900 901 $c1 = $dg->create_course(); 902 $c2 = $dg->create_course(); 903 $u1 = $dg->create_user(); 904 $u2 = $dg->create_user(); 905 $u3 = $dg->create_user(); 906 $u4 = $dg->create_user(); 907 $u1ctx = \context_user::instance($u1->id); 908 $u2ctx = \context_user::instance($u2->id); 909 $c1ctx = \context_course::instance($c1->id); 910 $c2ctx = \context_course::instance($c2->id); 911 912 // Create some stuff. 913 $gi1a = new \grade_item($dg->create_grade_item(['courseid' => $c1->id]), false); 914 $gi1b = new \grade_item($dg->create_grade_item(['courseid' => $c1->id]), false); 915 $gi2a = new \grade_item($dg->create_grade_item(['courseid' => $c2->id]), false); 916 $gi2b = new \grade_item($dg->create_grade_item(['courseid' => $c2->id]), false); 917 918 $gi1a->update_final_grade($u1->id, 1, 'test'); 919 $gi1a->update_final_grade($u2->id, 1, 'test'); 920 $gi1a->update_final_grade($u3->id, 1, 'test'); 921 $gi1b->update_final_grade($u1->id, 1, 'test'); 922 $gi1b->update_final_grade($u4->id, 1, 'test'); 923 $gi2a->update_final_grade($u1->id, 1, 'test'); 924 $gi2a->update_final_grade($u2->id, 1, 'test'); 925 $gi2a->update_final_grade($u4->id, 1, 'test'); 926 $gi2b->update_final_grade($u1->id, 1, 'test'); 927 $gi2b->update_final_grade($u2->id, 1, 'test'); 928 $gi2b->update_final_grade($u3->id, 1, 'test'); 929 $gi2b->delete(); 930 931 $this->assertTrue($DB->record_exists('grade_grades', ['userid' => $u1->id, 'itemid' => $gi1a->id])); 932 $this->assertTrue($DB->record_exists('grade_grades', ['userid' => $u2->id, 'itemid' => $gi1a->id])); 933 $this->assertTrue($DB->record_exists('grade_grades', ['userid' => $u3->id, 'itemid' => $gi1a->id])); 934 $this->assertTrue($DB->record_exists('grade_grades', ['userid' => $u1->id, 'itemid' => $gi1b->id])); 935 $this->assertTrue($DB->record_exists('grade_grades', ['userid' => $u4->id, 'itemid' => $gi1b->id])); 936 $this->assertTrue($DB->record_exists('grade_grades', ['userid' => $u1->id, 'itemid' => $gi2a->id])); 937 $this->assertTrue($DB->record_exists('grade_grades', ['userid' => $u2->id, 'itemid' => $gi2a->id])); 938 $this->assertTrue($DB->record_exists('grade_grades', ['userid' => $u4->id, 'itemid' => $gi2a->id])); 939 $this->assertFalse($DB->record_exists('grade_grades', ['userid' => $u1->id, 'itemid' => $gi2b->id])); 940 $this->assertFalse($DB->record_exists('grade_grades', ['userid' => $u2->id, 'itemid' => $gi2b->id])); 941 $this->assertFalse($DB->record_exists('grade_grades', ['userid' => $u3->id, 'itemid' => $gi2b->id])); 942 943 $userlist = new \core_privacy\local\request\approved_userlist($c1ctx, 'core_grades', [$u1->id, $u2->id]); 944 provider::delete_data_for_users($userlist); 945 946 $this->assertFalse($DB->record_exists('grade_grades', ['userid' => $u1->id, 'itemid' => $gi1a->id])); 947 $this->assertFalse($DB->record_exists('grade_grades', ['userid' => $u2->id, 'itemid' => $gi1a->id])); 948 $this->assertTrue($DB->record_exists('grade_grades', ['userid' => $u3->id, 'itemid' => $gi1a->id])); 949 $this->assertFalse($DB->record_exists('grade_grades', ['userid' => $u1->id, 'itemid' => $gi1b->id])); 950 $this->assertTrue($DB->record_exists('grade_grades', ['userid' => $u4->id, 'itemid' => $gi1b->id])); 951 $this->assertTrue($DB->record_exists('grade_grades', ['userid' => $u1->id, 'itemid' => $gi2a->id])); 952 $this->assertTrue($DB->record_exists('grade_grades', ['userid' => $u2->id, 'itemid' => $gi2a->id])); 953 $this->assertTrue($DB->record_exists('grade_grades', ['userid' => $u4->id, 'itemid' => $gi2a->id])); 954 955 $userlist = new \core_privacy\local\request\approved_userlist($c2ctx, 'core_grades', [$u2->id, $u4->id]); 956 provider::delete_data_for_users($userlist); 957 958 $this->assertFalse($DB->record_exists('grade_grades', ['userid' => $u1->id, 'itemid' => $gi1a->id])); 959 $this->assertFalse($DB->record_exists('grade_grades', ['userid' => $u2->id, 'itemid' => $gi1a->id])); 960 $this->assertTrue($DB->record_exists('grade_grades', ['userid' => $u3->id, 'itemid' => $gi1a->id])); 961 $this->assertFalse($DB->record_exists('grade_grades', ['userid' => $u1->id, 'itemid' => $gi1b->id])); 962 $this->assertTrue($DB->record_exists('grade_grades', ['userid' => $u4->id, 'itemid' => $gi1b->id])); 963 $this->assertTrue($DB->record_exists('grade_grades', ['userid' => $u1->id, 'itemid' => $gi2a->id])); 964 $this->assertFalse($DB->record_exists('grade_grades', ['userid' => $u2->id, 'itemid' => $gi2a->id])); 965 $this->assertFalse($DB->record_exists('grade_grades', ['userid' => $u4->id, 'itemid' => $gi2a->id])); 966 } 967 968 public function test_export_data_for_user_about_grades_and_history() { 969 $dg = $this->getDataGenerator(); 970 971 $c1 = $dg->create_course(); 972 $c2 = $dg->create_course(); 973 974 // Users being graded. 975 $ug1 = $dg->create_user(); 976 $ug2 = $dg->create_user(); 977 $ug3 = $dg->create_user(); 978 // Users performing actions. 979 $ua1 = $dg->create_user(); 980 $ua2 = $dg->create_user(); 981 $ua3 = $dg->create_user(); 982 983 $ug1ctx = \context_user::instance($ug1->id); 984 $ug2ctx = \context_user::instance($ug2->id); 985 $c1ctx = \context_course::instance($c1->id); 986 $c2ctx = \context_course::instance($c2->id); 987 988 $rootpath = [get_string('grades', 'core_grades')]; 989 $relatedtomepath = array_merge($rootpath, [get_string('privacy:path:relatedtome', 'core_grades')]); 990 991 // Create the course minimal stuff. 992 \grade_category::fetch_course_category($c1->id); 993 $ci1 = \grade_item::fetch_course_item($c1->id); 994 \grade_category::fetch_course_category($c2->id); 995 $ci2 = \grade_item::fetch_course_item($c2->id); 996 997 $this->add_feedback_file_to_copy(); 998 999 $grades['feedbackfiles'] = [ 1000 'contextid' => 1, 1001 'component' => 'test', 1002 'filearea' => 'testarea', 1003 'itemid' => 1 1004 ]; 1005 1006 $a1 = $dg->create_module('assign', ['course' => $c1->id]); 1007 1008 // Create data that will sit in the user context because we will delete the grate item. 1009 $gi1 = new \grade_item($dg->create_grade_item( 1010 [ 1011 'courseid' => $c1->id, 1012 'itemtype' => 'mod', 1013 'itemmodule' => 'assign', 1014 'iteminstance' => $a1->id, 1015 'aggregationcoef2' => 1 1016 ] 1017 ), false); 1018 1019 $grades['feedback'] = 'Well done!'; 1020 $grades['feedbackformat'] = FORMAT_PLAIN; 1021 $grades['userid'] = $ug1->id; 1022 $grades['usermodified'] = $ua2->id; 1023 $grades['rawgrade'] = 100; 1024 grade_update('mod/assign', $gi1->courseid, $gi1->itemtype, $gi1->itemmodule, $gi1->iteminstance, 1025 $gi1->itemnumber, $grades); 1026 1027 $grades['feedback'] = 'Hi'; 1028 $grades['userid'] = $ug1->id; 1029 $grades['usermodified'] = $ua2->id; 1030 $grades['rawgrade'] = 1; 1031 grade_update('mod/assign', $gi1->courseid, $gi1->itemtype, $gi1->itemmodule, $gi1->iteminstance, 1032 $gi1->itemnumber, $grades); 1033 1034 $grades['feedback'] = 'Hello'; 1035 $grades['userid'] = $ug3->id; 1036 $grades['usermodified'] = $ua2->id; 1037 $grades['rawgrade'] = 12; 1038 grade_update('mod/assign', $gi1->courseid, $gi1->itemtype, $gi1->itemmodule, $gi1->iteminstance, 1039 $gi1->itemnumber, $grades); 1040 1041 // Create another set for another user. 1042 $a2 = $dg->create_module('assign', ['course' => $c2->id]); 1043 $a3 = $dg->create_module('assign', ['course' => $c2->id]); 1044 $gi2a = new \grade_item($dg->create_grade_item( 1045 [ 1046 'courseid' => $c2->id, 1047 'itemtype' => 'mod', 1048 'itemmodule' => 'assign', 1049 'iteminstance' => $a2->id 1050 ] 1051 ), false); 1052 $gi2b = new \grade_item($dg->create_grade_item( 1053 [ 1054 'courseid' => $c2->id, 1055 'itemtype' => 'mod', 1056 'itemmodule' => 'assign', 1057 'iteminstance' => $a3->id 1058 ] 1059 ), false); 1060 1061 $grades['feedback'] = ''; 1062 $grades['userid'] = $ug1->id; 1063 $grades['usermodified'] = $ua2->id; 1064 $grades['rawgrade'] = 15; 1065 grade_update('mod/assign', $gi2a->courseid, $gi2a->itemtype, $gi2a->itemmodule, $gi2a->iteminstance, 1066 $gi2a->itemnumber, $grades); 1067 1068 $grades['feedback'] = 'Well played!'; 1069 $grades['userid'] = $ug1->id; 1070 $grades['usermodified'] = $ua2->id; 1071 $grades['rawgrade'] = 30; 1072 grade_update('mod/assign', $gi2b->courseid, $gi2b->itemtype, $gi2b->itemmodule, $gi2b->iteminstance, 1073 $gi2b->itemnumber, $grades); 1074 1075 // Export action user 1 everywhere. 1076 provider::export_user_data(new approved_contextlist($ua1, 'core_grades', [$ug1ctx->id, $ug2ctx->id, 1077 $c1ctx->id, $c2ctx->id])); 1078 $this->assert_context_has_no_data($ug1ctx); 1079 $this->assert_context_has_no_data($ug2ctx); 1080 $this->assert_context_has_no_data($c1ctx); 1081 $this->assert_context_has_no_data($c2ctx); 1082 1083 // Export action user 2 in course 1. 1084 writer::reset(); 1085 provider::export_user_data(new approved_contextlist($ua2, 'core_grades', [$c1ctx->id])); 1086 $this->assert_context_has_no_data($ug1ctx); 1087 $this->assert_context_has_no_data($ug2ctx); 1088 $this->assert_context_has_no_data($c2ctx); 1089 $data = writer::with_context($c1ctx)->get_data($rootpath); 1090 $this->assertEmpty($data); 1091 1092 // Here we are testing the export of grades that we've changed. 1093 $data = writer::with_context($c1ctx)->get_related_data($relatedtomepath, 'grades'); 1094 $this->assertCount(2, $data->grades); 1095 $this->assertEquals($gi1->get_name(), $data->grades[0]['item']); 1096 $this->assertEquals(1, $data->grades[0]['grade']); 1097 $this->assertEquals('Hi', $data->grades[0]['feedback']); 1098 $this->assertEquals(transform::yesno(true), $data->grades[0]['created_or_modified_by_you']); 1099 $this->assertEquals($gi1->get_name(), $data->grades[1]['item']); 1100 $this->assertEquals(12, $data->grades[1]['grade']); 1101 $this->assertEquals('Hello', $data->grades[1]['feedback']); 1102 $this->assertEquals(transform::yesno(true), $data->grades[1]['created_or_modified_by_you']); 1103 1104 $pathtofiles = [ 1105 get_string('grades', 'core_grades'), 1106 get_string('feedbackfiles', 'core_grades') 1107 ]; 1108 $file = writer::with_context($gi1->get_context())->get_files($pathtofiles)['feedback1.txt']; 1109 1110 $this->assertInstanceOf('stored_file', $file); 1111 $this->assertEquals('feedback1.txt', $file->get_filename()); 1112 1113 $relatedtomepath = array_merge($rootpath, [get_string('privacy:path:relatedtome', 'core_grades')]); 1114 1115 // Here we are testing the export of history of grades that we've changed. 1116 $data = writer::with_context($c1ctx)->get_related_data($relatedtomepath, 'grades_history'); 1117 $this->assertCount(3, $data->modified_records); 1118 $grade = $data->modified_records[0]; 1119 $this->assertEquals($ug1->id, $grade['userid']); 1120 $this->assertEquals($gi1->get_name(), $grade['item']); 1121 $this->assertEquals(100, $grade['grade']); 1122 $this->assertEquals('Well done!', $grade['feedback']); 1123 $this->assertEquals(transform::yesno(false), $grade['logged_in_user_was_you']); 1124 $this->assertEquals(transform::yesno(true), $grade['author_of_change_was_you']); 1125 $grade = $data->modified_records[1]; 1126 $this->assertEquals($ug1->id, $grade['userid']); 1127 $this->assertEquals($gi1->get_name(), $grade['item']); 1128 $this->assertEquals(1, $grade['grade']); 1129 $this->assertEquals('Hi', $grade['feedback']); 1130 $this->assertEquals(transform::yesno(false), $grade['logged_in_user_was_you']); 1131 $this->assertEquals(transform::yesno(true), $grade['author_of_change_was_you']); 1132 $grade = $data->modified_records[2]; 1133 $this->assertEquals($ug3->id, $grade['userid']); 1134 $this->assertEquals($gi1->get_name(), $grade['item']); 1135 $this->assertEquals(12, $grade['grade']); 1136 $this->assertEquals('Hello', $grade['feedback']); 1137 $this->assertEquals(transform::yesno(false), $grade['logged_in_user_was_you']); 1138 $this->assertEquals(transform::yesno(true), $grade['author_of_change_was_you']); 1139 1140 $pathtofiles = [ 1141 get_string('grades', 'core_grades'), 1142 get_string('feedbackhistoryfiles', 'core_grades') 1143 ]; 1144 $file = writer::with_context($gi1->get_context())->get_files($pathtofiles)['feedback1.txt']; 1145 1146 $this->assertInstanceOf('stored_file', $file); 1147 $this->assertEquals('feedback1.txt', $file->get_filename()); 1148 1149 // Create a history record with logged user. 1150 $this->setUser($ua3); 1151 $gi1->update_final_grade($ug3->id, 50, 'test', '...', FORMAT_PLAIN, $ua2->id); 1152 writer::reset(); 1153 provider::export_user_data(new approved_contextlist($ua3, 'core_grades', [$c1ctx->id])); 1154 $data = writer::with_context($c1ctx)->get_related_data($relatedtomepath, 'grades_history'); 1155 $this->assertCount(1, $data->modified_records); 1156 $grade = $data->modified_records[0]; 1157 $this->assertEquals($ug3->id, $grade['userid']); 1158 $this->assertEquals($gi1->get_name(), $grade['item']); 1159 $this->assertEquals(50, $grade['grade']); 1160 $this->assertEquals('...', $grade['feedback']); 1161 $this->assertEquals(transform::yesno(true), $grade['logged_in_user_was_you']); 1162 $this->assertEquals(transform::yesno(false), $grade['author_of_change_was_you']); 1163 1164 // Test that we export our own grades. 1165 writer::reset(); 1166 provider::export_user_data(new approved_contextlist($ug1, 'core_grades', [$c1ctx->id])); 1167 $data = writer::with_context($c1ctx)->get_data($rootpath); 1168 $this->assert_context_has_no_data($c2ctx); 1169 $this->assertCount(3, $data->grades); 1170 $grade = $data->grades[0]; 1171 $this->assertEquals($ci1->get_name(), $grade['item']); 1172 $this->assertEquals(1, $grade['grade']); 1173 $grade = $data->grades[2]; 1174 $this->assertEquals($gi1->get_name(), $grade['item']); 1175 $this->assertEquals(1, $grade['grade']); 1176 $this->assertEquals('Hi', $grade['feedback']); 1177 1178 // Test that we export our own grades in two courses. 1179 writer::reset(); 1180 provider::export_user_data(new approved_contextlist($ug1, 'core_grades', [$ug1ctx->id, $c1ctx->id, $c2ctx->id])); 1181 $this->assert_context_has_no_data($ug1ctx); 1182 $data = writer::with_context($c1ctx)->get_data($rootpath); 1183 $this->assertCount(3, $data->grades); 1184 $grade = $data->grades[0]; 1185 $this->assertEquals($ci1->get_name(), $grade['item']); 1186 $this->assertEquals(1, $grade['grade']); 1187 $grade = $data->grades[2]; 1188 $this->assertEquals($gi1->get_name(), $grade['item']); 1189 $this->assertEquals(1, $grade['grade']); 1190 $this->assertEquals('Hi', $grade['feedback']); 1191 1192 $data = writer::with_context($c2ctx)->get_data($rootpath); 1193 $this->assertCount(5, $data->grades); 1194 $grade = $data->grades[0]; 1195 $this->assertEquals($ci2->get_name(), $grade['item']); 1196 $grade = $data->grades[3]; 1197 $this->assertEquals($gi2a->get_name(), $grade['item']); 1198 $this->assertEquals(15, $grade['grade']); 1199 $this->assertEquals('', $grade['feedback']); 1200 $grade = $data->grades[4]; 1201 $this->assertEquals($gi2b->get_name(), $grade['item']); 1202 $this->assertEquals(30, $grade['grade']); 1203 $this->assertEquals('Well played!', $grade['feedback']); 1204 1205 // Delete a grade item. 1206 $this->setUser($ua3); 1207 $gi1->delete(); 1208 1209 // Now, we should find history of grades in our own context. 1210 writer::reset(); 1211 provider::export_user_data(new approved_contextlist($ug1, 'core_grades', [$ug1ctx->id, $c1ctx->id, $c2ctx->id])); 1212 $data = writer::with_context($c1ctx)->get_data($rootpath); 1213 $this->assertCount(2, $data->grades); 1214 $this->assertEquals($ci1->get_name(), $data->grades[0]['item']); 1215 $data = writer::with_context($c2ctx)->get_data($rootpath); 1216 $this->assertCount(5, $data->grades); 1217 $data = writer::with_context($ug1ctx)->get_related_data($rootpath, 'history'); 1218 $this->assertCount(3, $data->grades); 1219 $grade = $data->grades[0]; 1220 $this->assertEquals(get_string('privacy:request:unknowndeletedgradeitem', 'core_grades'), $grade['name']); 1221 $this->assertEquals(100, $grade['grade']); 1222 $this->assertEquals('Well done!', $grade['feedback']); 1223 $this->assertEquals(transform::yesno(true), $grade['graded_user_was_you']); 1224 $this->assertEquals(transform::yesno(false), $grade['logged_in_user_was_you']); 1225 $this->assertEquals(transform::yesno(false), $grade['author_of_change_was_you']); 1226 $this->assertEquals(get_string('privacy:request:historyactioninsert', 'core_grades'), $grade['action']); 1227 $grade = $data->grades[1]; 1228 $this->assertEquals(get_string('privacy:request:unknowndeletedgradeitem', 'core_grades'), $grade['name']); 1229 $this->assertEquals(1, $grade['grade']); 1230 $this->assertEquals('Hi', $grade['feedback']); 1231 $this->assertEquals(transform::yesno(true), $grade['graded_user_was_you']); 1232 $this->assertEquals(transform::yesno(false), $grade['logged_in_user_was_you']); 1233 $this->assertEquals(transform::yesno(false), $grade['author_of_change_was_you']); 1234 $this->assertEquals(get_string('privacy:request:historyactionupdate', 'core_grades'), $grade['action']); 1235 $grade = $data->grades[2]; 1236 $this->assertEquals(get_string('privacy:request:unknowndeletedgradeitem', 'core_grades'), $grade['name']); 1237 $this->assertEquals(1, $grade['grade']); 1238 $this->assertEquals('Hi', $grade['feedback']); 1239 $this->assertEquals(transform::yesno(true), $grade['graded_user_was_you']); 1240 $this->assertEquals(transform::yesno(false), $grade['logged_in_user_was_you']); 1241 $this->assertEquals(transform::yesno(false), $grade['author_of_change_was_you']); 1242 $this->assertEquals(get_string('privacy:request:historyactiondelete', 'core_grades'), $grade['action']); 1243 1244 // The action user 3 should have a record of the deletion in the user's context. 1245 writer::reset(); 1246 provider::export_user_data(new approved_contextlist($ua3, 'core_grades', [$ug1ctx->id])); 1247 $data = writer::with_context($ug1ctx)->get_related_data($rootpath, 'history'); 1248 $this->assertCount(1, $data->grades); 1249 $grade = $data->grades[0]; 1250 $this->assertEquals(get_string('privacy:request:unknowndeletedgradeitem', 'core_grades'), $grade['name']); 1251 $this->assertEquals(1, $grade['grade']); 1252 $this->assertEquals('Hi', $grade['feedback']); 1253 $this->assertEquals(transform::yesno(true), $grade['logged_in_user_was_you']); 1254 $this->assertEquals(transform::yesno(false), $grade['author_of_change_was_you']); 1255 $this->assertEquals(get_string('privacy:request:historyactiondelete', 'core_grades'), $grade['action']); 1256 1257 // The action user 2 should have a record of their edits in the user's context. 1258 writer::reset(); 1259 provider::export_user_data(new approved_contextlist($ua2, 'core_grades', [$ug1ctx->id])); 1260 $data = writer::with_context($ug1ctx)->get_related_data($rootpath, 'history'); 1261 $this->assertCount(3, $data->grades); 1262 $grade = $data->grades[0]; 1263 $this->assertEquals(get_string('privacy:request:unknowndeletedgradeitem', 'core_grades'), $grade['name']); 1264 $this->assertEquals(100, $grade['grade']); 1265 $this->assertEquals('Well done!', $grade['feedback']); 1266 $this->assertEquals(transform::yesno(false), $grade['logged_in_user_was_you']); 1267 $this->assertEquals(transform::yesno(true), $grade['author_of_change_was_you']); 1268 $this->assertEquals(get_string('privacy:request:historyactioninsert', 'core_grades'), $grade['action']); 1269 $grade = $data->grades[1]; 1270 $this->assertEquals(get_string('privacy:request:unknowndeletedgradeitem', 'core_grades'), $grade['name']); 1271 $this->assertEquals(1, $grade['grade']); 1272 $this->assertEquals('Hi', $grade['feedback']); 1273 $this->assertEquals(transform::yesno(false), $grade['logged_in_user_was_you']); 1274 $this->assertEquals(transform::yesno(true), $grade['author_of_change_was_you']); 1275 $this->assertEquals(get_string('privacy:request:historyactionupdate', 'core_grades'), $grade['action']); 1276 $grade = $data->grades[2]; 1277 $this->assertEquals(get_string('privacy:request:unknowndeletedgradeitem', 'core_grades'), $grade['name']); 1278 $this->assertEquals(1, $grade['grade']); 1279 $this->assertEquals('Hi', $grade['feedback']); 1280 $this->assertEquals(transform::yesno(false), $grade['logged_in_user_was_you']); 1281 $this->assertEquals(transform::yesno(true), $grade['author_of_change_was_you']); 1282 $this->assertEquals(get_string('privacy:request:historyactiondelete', 'core_grades'), $grade['action']); 1283 } 1284 1285 public function test_export_data_for_user_with_scale() { 1286 global $DB; 1287 $dg = $this->getDataGenerator(); 1288 $c1 = $dg->create_course(); 1289 $scale = $dg->create_scale(['scale' => 'Awesome,OK,Reasonable,Bad']); 1290 $u1 = $dg->create_user(); 1291 $u2 = $dg->create_user(); 1292 1293 $u1ctx = \context_user::instance($u1->id); 1294 $c1ctx = \context_course::instance($c1->id); 1295 1296 $rootpath = [get_string('grades', 'core_grades')]; 1297 1298 // Create another set for another user. 1299 $gi1 = new \grade_item($dg->create_grade_item(['courseid' => $c1->id, 'scaleid' => $scale->id]), false); 1300 $gi1->update_final_grade($u1->id, 1, 'test', '', FORMAT_PLAIN, $u2->id); 1301 $gi2 = new \grade_item($dg->create_grade_item(['courseid' => $c1->id, 'scaleid' => $scale->id]), false); 1302 $gi2->update_final_grade($u1->id, 3, 'test', '', FORMAT_PLAIN, $u2->id); 1303 1304 // Export user's data. 1305 writer::reset(); 1306 provider::export_user_data(new approved_contextlist($u1, 'core_grades', [$c1ctx->id])); 1307 $data = writer::with_context($c1ctx)->get_data($rootpath); 1308 $this->assertCount(3, $data->grades); 1309 $this->assertEquals(\grade_item::fetch_course_item($c1->id)->get_name(), $data->grades[0]['item']); 1310 $this->assertEquals($gi1->get_name(), $data->grades[1]['item']); 1311 $this->assertEquals(1, $data->grades[1]['grade']); 1312 $this->assertEquals('Awesome', $data->grades[1]['grade_formatted']); 1313 $this->assertEquals($gi2->get_name(), $data->grades[2]['item']); 1314 $this->assertEquals(3, $data->grades[2]['grade']); 1315 $this->assertEquals('Reasonable', $data->grades[2]['grade_formatted']); 1316 } 1317 1318 public function test_export_data_for_user_about_gradebook_edits() { 1319 global $DB; 1320 $dg = $this->getDataGenerator(); 1321 $c1 = $dg->create_course(); 1322 $c2 = $dg->create_course(); 1323 $u1 = $dg->create_user(); 1324 $u2 = $dg->create_user(); 1325 $u3 = $dg->create_user(); 1326 $u4 = $dg->create_user(); 1327 $u5 = $dg->create_user(); 1328 $u6 = $dg->create_user(); 1329 $u7 = $dg->create_user(); 1330 $u8 = $dg->create_user(); 1331 $u9 = $dg->create_user(); 1332 $u10 = $dg->create_user(); 1333 1334 $sysctx = \context_system::instance(); 1335 $u1ctx = \context_user::instance($u1->id); 1336 $u2ctx = \context_user::instance($u2->id); 1337 $u3ctx = \context_user::instance($u3->id); 1338 $u4ctx = \context_user::instance($u4->id); 1339 $u5ctx = \context_user::instance($u5->id); 1340 $u6ctx = \context_user::instance($u6->id); 1341 $c1ctx = \context_course::instance($c1->id); 1342 $c2ctx = \context_course::instance($c2->id); 1343 1344 $rootpath = [get_string('grades', 'core_grades')]; 1345 $relatedtomepath = array_merge($rootpath, [get_string('privacy:path:relatedtome', 'core_grades')]); 1346 $allcontexts = [$sysctx->id, $c1ctx->id, $c2ctx->id, $u1ctx->id, $u2ctx->id, $u3ctx->id, $u4ctx->id, 1347 $u5ctx->id, $u6ctx->id]; 1348 $updateactionstr = get_string('privacy:request:historyactionupdate', 'core_grades'); 1349 1350 // Create some stuff. 1351 $gi1a = new \grade_item($dg->create_grade_item(['courseid' => $c1->id]), false); 1352 $gi1b = new \grade_item($dg->create_grade_item(['courseid' => $c1->id]), false); 1353 $gi2a = new \grade_item($dg->create_grade_item(['courseid' => $c2->id]), false); 1354 $gc1a = new \grade_category($dg->create_grade_category(['courseid' => $c1->id]), false); 1355 $gc1b = new \grade_category($dg->create_grade_category(['courseid' => $c1->id]), false); 1356 $gc2a = new \grade_category($dg->create_grade_category(['courseid' => $c2->id]), false); 1357 $go2 = new \grade_outcome($dg->create_grade_outcome(['courseid' => $c2->id, 'shortname' => 'go2', 1358 'fullname' => 'go2']), false); 1359 1360 $go0 = new \grade_outcome(['shortname' => 'go0', 'fullname' => 'go0', 'usermodified' => $u1->id]); 1361 $go0->insert(); 1362 $go1 = new \grade_outcome(['shortname' => 'go1', 'fullname' => 'go1', 'courseid' => $c1->id, 'usermodified' => $u1->id]); 1363 $go1->insert(); 1364 1365 // Create scales. 1366 $s1 = new \grade_scale(['name' => 's1', 'scale' => 'a,b', 'userid' => $u7->id, 'courseid' => 0, 'description' => '']); 1367 $s1->insert(); 1368 $s2 = new \grade_scale(['name' => 's2', 'scale' => 'a,b', 'userid' => $u8->id, 'courseid' => $c1->id, 'description' => '']); 1369 $s2->insert(); 1370 $s3 = new \grade_scale(['name' => 's3', 'scale' => 'a,b', 'userid' => $u8->id, 'courseid' => $c2->id, 'description' => '']); 1371 $s3->insert(); 1372 1373 // User 2 creates history. 1374 $this->setUser($u2); 1375 $go0->shortname .= ' edited'; 1376 $go0->update(); 1377 $gc1a->fullname .= ' edited'; 1378 $gc1a->update(); 1379 1380 // User 3 creates history. 1381 $this->setUser($u3); 1382 $go1->shortname .= ' edited'; 1383 $go1->update(); 1384 $gc2a->fullname .= ' a'; 1385 $gc2a->update(); 1386 1387 // User 4 updates an outcome in course (creates history). 1388 $this->setUser($u4); 1389 $go2->shortname .= ' edited'; 1390 $go2->update(); 1391 1392 // User 5 updates an item. 1393 $this->setUser($u5); 1394 $gi1a->itemname .= ' edited'; 1395 $gi1a->update(); 1396 1397 // User 6 creates history. 1398 $this->setUser($u6); 1399 $gi2a->delete(); 1400 1401 // User 9 creates history. 1402 $this->setUser($u9); 1403 $s1->name .= ' edited'; 1404 $s1->update(); 1405 1406 // User 10 creates history. 1407 $this->setUser($u10); 1408 $s3->delete(); 1409 1410 $this->setAdminUser(); 1411 1412 // Export data for u1. 1413 writer::reset(); 1414 provider::export_user_data(new approved_contextlist($u1, 'core_grades', $allcontexts)); 1415 $data = writer::with_context($sysctx)->get_related_data($relatedtomepath, 'outcomes'); 1416 $this->assertCount(1, $data->outcomes); 1417 $this->assertEquals($go0->shortname, $data->outcomes[0]['shortname']); 1418 $this->assertEquals($go0->fullname, $data->outcomes[0]['fullname']); 1419 $this->assertEquals(transform::yesno(true), $data->outcomes[0]['created_or_modified_by_you']); 1420 $data = writer::with_context($c1ctx)->get_related_data($relatedtomepath, 'outcomes'); 1421 $this->assertCount(1, $data->outcomes); 1422 $this->assertEquals($go1->shortname, $data->outcomes[0]['shortname']); 1423 $this->assertEquals($go1->fullname, $data->outcomes[0]['fullname']); 1424 $this->assertEquals(transform::yesno(true), $data->outcomes[0]['created_or_modified_by_you']); 1425 $data = writer::with_context($sysctx)->get_related_data($relatedtomepath, 'outcomes_history'); 1426 $this->assertEmpty($data); 1427 $data = writer::with_context($c1ctx)->get_related_data($relatedtomepath, 'outcomes_history'); 1428 $this->assertEmpty($data); 1429 1430 // Export data for u2. 1431 writer::reset(); 1432 provider::export_user_data(new approved_contextlist($u2, 'core_grades', $allcontexts)); 1433 $data = writer::with_context($sysctx)->get_related_data($relatedtomepath, 'outcomes'); 1434 $this->assertEmpty($data); 1435 $data = writer::with_context($c1ctx)->get_related_data($relatedtomepath, 'outcomes'); 1436 $this->assertEmpty($data); 1437 $data = writer::with_context($sysctx)->get_related_data($relatedtomepath, 'outcomes_history'); 1438 $this->assertCount(1, $data->modified_records); 1439 $this->assertEquals($go0->shortname, $data->modified_records[0]['shortname']); 1440 $this->assertEquals($go0->fullname, $data->modified_records[0]['fullname']); 1441 $this->assertEquals(transform::yesno(true), $data->modified_records[0]['logged_in_user_was_you']); 1442 $this->assertEquals($updateactionstr, $data->modified_records[0]['action']); 1443 1444 $data = writer::with_context($c1ctx)->get_related_data($relatedtomepath, 'categories_history'); 1445 $this->assertCount(1, $data->modified_records); 1446 $this->assertEquals($gc1a->fullname, $data->modified_records[0]['name']); 1447 $this->assertEquals(transform::yesno(true), $data->modified_records[0]['logged_in_user_was_you']); 1448 $this->assertEquals($updateactionstr, $data->modified_records[0]['action']); 1449 1450 // Export data for u3. 1451 writer::reset(); 1452 provider::export_user_data(new approved_contextlist($u3, 'core_grades', $allcontexts)); 1453 $data = writer::with_context($c1ctx)->get_related_data($relatedtomepath, 'outcomes_history'); 1454 $this->assertCount(1, $data->modified_records); 1455 $this->assertEquals($go1->shortname, $data->modified_records[0]['shortname']); 1456 $this->assertEquals($go1->fullname, $data->modified_records[0]['fullname']); 1457 $this->assertEquals(transform::yesno(true), $data->modified_records[0]['logged_in_user_was_you']); 1458 $this->assertEquals($updateactionstr, $data->modified_records[0]['action']); 1459 1460 $data = writer::with_context($c2ctx)->get_related_data($relatedtomepath, 'categories_history'); 1461 $this->assertCount(1, $data->modified_records); 1462 $this->assertEquals($gc2a->fullname, $data->modified_records[0]['name']); 1463 $this->assertEquals(transform::yesno(true), $data->modified_records[0]['logged_in_user_was_you']); 1464 $this->assertEquals($updateactionstr, $data->modified_records[0]['action']); 1465 1466 // Export data for u4. 1467 writer::reset(); 1468 provider::export_user_data(new approved_contextlist($u4, 'core_grades', $allcontexts)); 1469 $data = writer::with_context($c2ctx)->get_related_data($relatedtomepath, 'outcomes_history'); 1470 $this->assertCount(1, $data->modified_records); 1471 $this->assertEquals($go2->shortname, $data->modified_records[0]['shortname']); 1472 $this->assertEquals($go2->fullname, $data->modified_records[0]['fullname']); 1473 $this->assertEquals(transform::yesno(true), $data->modified_records[0]['logged_in_user_was_you']); 1474 $this->assertEquals($updateactionstr, $data->modified_records[0]['action']); 1475 1476 // Export data for u5. 1477 writer::reset(); 1478 provider::export_user_data(new approved_contextlist($u5, 'core_grades', $allcontexts)); 1479 $data = writer::with_context($c1ctx)->get_related_data($relatedtomepath, 'items_history'); 1480 $this->assertCount(1, $data->modified_records); 1481 $this->assertEquals($gi1a->itemname, $data->modified_records[0]['name']); 1482 $this->assertEquals(transform::yesno(true), $data->modified_records[0]['logged_in_user_was_you']); 1483 $this->assertEquals($updateactionstr, $data->modified_records[0]['action']); 1484 1485 // Export data for u6. 1486 writer::reset(); 1487 provider::export_user_data(new approved_contextlist($u6, 'core_grades', $allcontexts)); 1488 $data = writer::with_context($c1ctx)->get_related_data($relatedtomepath, 'items_history'); 1489 $this->assertEmpty($data); 1490 $data = writer::with_context($c2ctx)->get_related_data($relatedtomepath, 'items_history'); 1491 $this->assertCount(1, $data->modified_records); 1492 $this->assertEquals($gi2a->itemname, $data->modified_records[0]['name']); 1493 $this->assertEquals(transform::yesno(true), $data->modified_records[0]['logged_in_user_was_you']); 1494 $this->assertEquals(get_string('privacy:request:historyactiondelete', 'core_grades'), 1495 $data->modified_records[0]['action']); 1496 1497 // Export data for u7. 1498 writer::reset(); 1499 provider::export_user_data(new approved_contextlist($u7, 'core_grades', $allcontexts)); 1500 $data = writer::with_context($c1ctx)->get_related_data($relatedtomepath, 'scales'); 1501 $this->assertEmpty($data); 1502 $data = writer::with_context($sysctx)->get_related_data($relatedtomepath, 'scales'); 1503 $this->assertCount(1, $data->scales); 1504 $this->assertEquals($s1->name, $data->scales[0]['name']); 1505 $this->assertEquals(transform::yesno(true), $data->scales[0]['created_or_modified_by_you']); 1506 1507 // Export data for u8. 1508 writer::reset(); 1509 provider::export_user_data(new approved_contextlist($u8, 'core_grades', $allcontexts)); 1510 $data = writer::with_context($sysctx)->get_related_data($relatedtomepath, 'scales'); 1511 $this->assertEmpty($data); 1512 $data = writer::with_context($c1ctx)->get_related_data($relatedtomepath, 'scales'); 1513 $this->assertCount(1, $data->scales); 1514 $this->assertEquals($s2->name, $data->scales[0]['name']); 1515 $this->assertEquals(transform::yesno(true), $data->scales[0]['created_or_modified_by_you']); 1516 $data = writer::with_context($c2ctx)->get_related_data($relatedtomepath, 'scales_history'); 1517 $this->assertCount(2, $data->modified_records); 1518 $this->assertEquals($s3->name, $data->modified_records[0]['name']); 1519 $this->assertEquals(transform::yesno(true), $data->modified_records[0]['author_of_change_was_you']); 1520 $this->assertEquals(transform::yesno(false), $data->modified_records[0]['author_of_action_was_you']); 1521 $this->assertEquals(get_string('privacy:request:historyactioninsert', 'core_grades'), 1522 $data->modified_records[0]['action']); 1523 $this->assertEquals($s3->name, $data->modified_records[1]['name']); 1524 $this->assertEquals(transform::yesno(true), $data->modified_records[1]['author_of_change_was_you']); 1525 $this->assertEquals(transform::yesno(false), $data->modified_records[1]['author_of_action_was_you']); 1526 $this->assertEquals(get_string('privacy:request:historyactiondelete', 'core_grades'), 1527 $data->modified_records[1]['action']); 1528 1529 // Export data for u9. 1530 writer::reset(); 1531 provider::export_user_data(new approved_contextlist($u9, 'core_grades', $allcontexts)); 1532 $data = writer::with_context($c1ctx)->get_related_data($relatedtomepath, 'scales'); 1533 $this->assertEmpty($data); 1534 $data = writer::with_context($sysctx)->get_related_data($relatedtomepath, 'scales'); 1535 $this->assertEmpty($data); 1536 $data = writer::with_context($sysctx)->get_related_data($relatedtomepath, 'scales_history'); 1537 $this->assertCount(1, $data->modified_records); 1538 $this->assertEquals($s1->name, $data->modified_records[0]['name']); 1539 $this->assertEquals(transform::yesno(false), $data->modified_records[0]['author_of_change_was_you']); 1540 $this->assertEquals(transform::yesno(true), $data->modified_records[0]['author_of_action_was_you']); 1541 $this->assertEquals(get_string('privacy:request:historyactionupdate', 'core_grades'), 1542 $data->modified_records[0]['action']); 1543 1544 // Export data for u10. 1545 writer::reset(); 1546 provider::export_user_data(new approved_contextlist($u10, 'core_grades', $allcontexts)); 1547 $data = writer::with_context($c1ctx)->get_related_data($relatedtomepath, 'scales'); 1548 $this->assertEmpty($data); 1549 $data = writer::with_context($c2ctx)->get_related_data($relatedtomepath, 'scales'); 1550 $this->assertEmpty($data); 1551 $data = writer::with_context($sysctx)->get_related_data($relatedtomepath, 'scales'); 1552 $this->assertEmpty($data); 1553 $data = writer::with_context($c1ctx)->get_related_data($relatedtomepath, 'scales_history'); 1554 $this->assertEmpty($data); 1555 $data = writer::with_context($sysctx)->get_related_data($relatedtomepath, 'scales_history'); 1556 $this->assertEmpty($data); 1557 $data = writer::with_context($c2ctx)->get_related_data($relatedtomepath, 'scales_history'); 1558 $this->assertCount(1, $data->modified_records); 1559 $this->assertEquals($s3->name, $data->modified_records[0]['name']); 1560 $this->assertEquals(transform::yesno(false), $data->modified_records[0]['author_of_change_was_you']); 1561 $this->assertEquals(transform::yesno(true), $data->modified_records[0]['author_of_action_was_you']); 1562 $this->assertEquals(get_string('privacy:request:historyactiondelete', 'core_grades'), 1563 $data->modified_records[0]['action']); 1564 } 1565 1566 /** 1567 * Assert there is no grade data in the context. 1568 * 1569 * @param context $context The context. 1570 * @return void 1571 */ 1572 protected function assert_context_has_no_data(\context $context) { 1573 $rootpath = [get_string('grades', 'core_grades')]; 1574 $relatedtomepath = array_merge($rootpath, [get_string('privacy:path:relatedtome', 'core_grades')]); 1575 1576 $data = writer::with_context($context)->get_data($rootpath); 1577 $this->assertEmpty($data); 1578 1579 $data = writer::with_context($context)->get_related_data($rootpath, 'history'); 1580 $this->assertEmpty($data); 1581 1582 $files = ['categories_history', 'items_history', 'outcomes', 'outcomes_history', 'grades', 'grades_history', 'history']; 1583 foreach ($files as $file) { 1584 $data = writer::with_context($context)->get_related_data($relatedtomepath, $file); 1585 $this->assertEmpty($data); 1586 } 1587 } 1588 1589 /** 1590 * Creates a feedback file to copy to the gradebook area. 1591 */ 1592 private function add_feedback_file_to_copy() { 1593 $dummy = array( 1594 'contextid' => 1, 1595 'component' => 'test', 1596 'filearea' => 'testarea', 1597 'itemid' => 1, 1598 'filepath' => '/', 1599 'filename' => 'feedback1.txt' 1600 ); 1601 1602 $fs = get_file_storage(); 1603 $fs->create_file_from_string($dummy, ''); 1604 } 1605 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body