Differences Between: [Versions 400 and 402] [Versions 400 and 403]
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 * Base class for unit tests for mod_assign. 19 * 20 * @package mod_assign 21 * @copyright 2018 Adrian Greeve <adrian@moodle.com> 22 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 */ 24 25 namespace mod_assign\privacy; 26 27 defined('MOODLE_INTERNAL') || die(); 28 29 global $CFG; 30 require_once($CFG->dirroot . '/mod/assign/locallib.php'); 31 32 use core_privacy\tests\provider_testcase; 33 use core_privacy\local\request\writer; 34 use core_privacy\local\request\approved_contextlist; 35 use mod_assign\privacy\provider; 36 37 /** 38 * Unit tests for mod/assign/classes/privacy/ 39 * 40 * @copyright 2018 Adrian Greeve <adrian@moodle.com> 41 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 42 */ 43 class provider_test extends provider_testcase { 44 45 /** 46 * Convenience method for creating a submission. 47 * 48 * @param assign $assign The assign object 49 * @param stdClass $user The user object 50 * @param string $submissiontext Submission text 51 * @param integer $attemptnumber The attempt number 52 * @return object A submission object. 53 */ 54 protected function create_submission($assign, $user, $submissiontext, $attemptnumber = 0) { 55 $submission = $assign->get_user_submission($user->id, true, $attemptnumber); 56 $submission->onlinetext_editor = ['text' => $submissiontext, 57 'format' => FORMAT_MOODLE]; 58 59 $this->setUser($user); 60 $notices = []; 61 $assign->save_submission($submission, $notices); 62 return $submission; 63 } 64 65 /** 66 * Convenience function to create an instance of an assignment. 67 * 68 * @param array $params Array of parameters to pass to the generator 69 * @return assign The assign class. 70 */ 71 protected function create_instance($params = array()) { 72 $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign'); 73 $instance = $generator->create_instance($params); 74 $cm = get_coursemodule_from_instance('assign', $instance->id); 75 $context = \context_module::instance($cm->id); 76 return new \assign($context, $cm, $params['course']); 77 } 78 79 /** 80 * Test that getting the contexts for a user works. 81 */ 82 public function test_get_contexts_for_userid() { 83 global $DB; 84 $this->resetAfterTest(); 85 86 $course1 = $this->getDataGenerator()->create_course(); 87 $course2 = $this->getDataGenerator()->create_course(); 88 $course3 = $this->getDataGenerator()->create_course(); 89 90 $user1 = $this->getDataGenerator()->create_user(); 91 $this->getDataGenerator()->enrol_user($user1->id, $course1->id, 'student'); 92 $this->getDataGenerator()->enrol_user($user1->id, $course3->id, 'student'); 93 // Need a second user to create content in other assignments. 94 $user2 = $this->getDataGenerator()->create_user(); 95 $this->getDataGenerator()->enrol_user($user2->id, $course2->id, 'student'); 96 97 // Create multiple assignments. 98 // Assignment with a text submission. 99 $assign1 = $this->create_instance(['course' => $course1]); 100 // Assignment two in a different course that the user is not enrolled in. 101 $assign2 = $this->create_instance(['course' => $course2]); 102 // Assignment three has an entry in the override table. 103 $assign3 = $this->create_instance(['course' => $course3, 'cutoffdate' => time()]); 104 // Assignment four - blind marking. 105 $assign4 = $this->create_instance(['course' => $course1, 'blindmarking' => 1]); 106 // Assignment five - user flags. 107 $assign5 = $this->create_instance(['course' => $course3]); 108 109 // Override has to be manually inserted into the DB. 110 $overridedata = new \stdClass(); 111 $overridedata->assignid = $assign3->get_instance()->id; 112 $overridedata->userid = $user1->id; 113 $overridedata->duedate = time(); 114 $DB->insert_record('assign_overrides', $overridedata); 115 // Assign unique id for blind marking in assignment four for user 1. 116 \assign::get_uniqueid_for_user_static($assign4->get_instance()->id, $user1->id); 117 // Create an entry in the user flags table. 118 $assign5->get_user_flags($user1->id, true); 119 120 // The user will be in these contexts. 121 $usercontextids = [ 122 $assign1->get_context()->id, 123 $assign3->get_context()->id, 124 $assign4->get_context()->id, 125 $assign5->get_context()->id, 126 ]; 127 128 $submission = new \stdClass(); 129 $submission->assignment = $assign1->get_instance()->id; 130 $submission->userid = $user1->id; 131 $submission->timecreated = time(); 132 $submission->onlinetext_editor = ['text' => 'Submission text', 133 'format' => FORMAT_MOODLE]; 134 135 $this->setUser($user1); 136 $notices = []; 137 $assign1->save_submission($submission, $notices); 138 139 // Create a submission for the second assignment. 140 $submission->assignment = $assign2->get_instance()->id; 141 $submission->userid = $user2->id; 142 $this->setUser($user2); 143 $assign2->save_submission($submission, $notices); 144 145 $contextlist = provider::get_contexts_for_userid($user1->id); 146 $this->assertEquals(count($usercontextids), count($contextlist->get_contextids())); 147 // There should be no difference between the contexts. 148 $this->assertEmpty(array_diff($usercontextids, $contextlist->get_contextids())); 149 } 150 151 /** 152 * Test returning a list of user IDs related to a context (assign). 153 */ 154 public function test_get_users_in_context() { 155 global $DB; 156 157 $this->resetAfterTest(); 158 159 $course = $this->getDataGenerator()->create_course(); 160 161 // Only made a comment on a submission. 162 $user1 = $this->getDataGenerator()->create_user(); 163 // User 2 only has information about an activity override. 164 $user2 = $this->getDataGenerator()->create_user(); 165 // User 3 made a submission. 166 $user3 = $this->getDataGenerator()->create_user(); 167 // User 4 makes a submission and it is marked by the teacher. 168 $user4 = $this->getDataGenerator()->create_user(); 169 // Grading and providing feedback as a teacher. 170 $user5 = $this->getDataGenerator()->create_user(); 171 // This user has no entries and should not show up. 172 $user6 = $this->getDataGenerator()->create_user(); 173 174 $this->getDataGenerator()->enrol_user($user1->id, $course->id, 'student'); 175 $this->getDataGenerator()->enrol_user($user2->id, $course->id, 'student'); 176 $this->getDataGenerator()->enrol_user($user3->id, $course->id, 'student'); 177 $this->getDataGenerator()->enrol_user($user4->id, $course->id, 'student'); 178 $this->getDataGenerator()->enrol_user($user5->id, $course->id, 'editingteacher'); 179 $this->getDataGenerator()->enrol_user($user6->id, $course->id, 'student'); 180 181 $assign1 = $this->create_instance(['course' => $course, 182 'assignsubmission_onlinetext_enabled' => true, 183 'assignfeedback_comments_enabled' => true]); 184 $assign2 = $this->create_instance(['course' => $course]); 185 186 $context = $assign1->get_context(); 187 188 // Jam an entry in the comments table for user 1. 189 $comment = (object) [ 190 'contextid' => $context->id, 191 'component' => 'assignsubmission_comments', 192 'commentarea' => 'submission_comments', 193 'itemid' => 5, 194 'content' => 'A comment by user 1', 195 'format' => 0, 196 'userid' => $user1->id, 197 'timecreated' => time() 198 ]; 199 $DB->insert_record('comments', $comment); 200 201 $this->setUser($user5); // Set the user to the teacher. 202 203 $overridedata = new \stdClass(); 204 $overridedata->assignid = $assign1->get_instance()->id; 205 $overridedata->userid = $user2->id; 206 $overridedata->duedate = time(); 207 $overridedata->allowsubmissionsfromdate = time(); 208 $overridedata->cutoffdate = time(); 209 $DB->insert_record('assign_overrides', $overridedata); 210 211 $submissiontext = 'My first submission'; 212 $submission = $this->create_submission($assign1, $user3, $submissiontext); 213 214 $submissiontext = 'My first submission'; 215 $submission = $this->create_submission($assign1, $user4, $submissiontext); 216 217 $this->setUser($user5); 218 219 $grade = '72.00'; 220 $teachercommenttext = 'This is better. Thanks.'; 221 $data = new \stdClass(); 222 $data->attemptnumber = 1; 223 $data->grade = $grade; 224 $data->assignfeedbackcomments_editor = ['text' => $teachercommenttext, 'format' => FORMAT_MOODLE]; 225 226 // Give the submission a grade. 227 $assign1->save_grade($user4->id, $data); 228 229 $userlist = new \core_privacy\local\request\userlist($context, 'assign'); 230 provider::get_users_in_context($userlist); 231 $userids = $userlist->get_userids(); 232 $this->assertTrue(in_array($user1->id, $userids)); 233 $this->assertTrue(in_array($user2->id, $userids)); 234 $this->assertTrue(in_array($user3->id, $userids)); 235 $this->assertTrue(in_array($user4->id, $userids)); 236 $this->assertTrue(in_array($user5->id, $userids)); 237 $this->assertFalse(in_array($user6->id, $userids)); 238 } 239 240 /** 241 * Test that a student with multiple submissions and grades is returned with the correct data. 242 */ 243 public function test_export_user_data_student() { 244 global $DB; 245 $this->resetAfterTest(); 246 $course = $this->getDataGenerator()->create_course(); 247 $coursecontext = \context_course::instance($course->id); 248 249 $user = $this->getDataGenerator()->create_user(); 250 $teacher = $this->getDataGenerator()->create_user(); 251 $this->getDataGenerator()->enrol_user($user->id, $course->id, 'student'); 252 $this->getDataGenerator()->enrol_user($teacher->id, $course->id, 'editingteacher'); 253 $assign = $this->create_instance([ 254 'course' => $course, 255 'name' => 'Assign 1', 256 'attemptreopenmethod' => ASSIGN_ATTEMPT_REOPEN_METHOD_MANUAL, 257 'maxattempts' => 3, 258 'assignsubmission_onlinetext_enabled' => true, 259 'assignfeedback_comments_enabled' => true 260 ]); 261 262 $context = $assign->get_context(); 263 // Create some submissions (multiple attempts) for a student. 264 $submissiontext = 'My first submission'; 265 $submission = $this->create_submission($assign, $user, $submissiontext); 266 267 $this->setUser($teacher); 268 269 $overridedata = new \stdClass(); 270 $overridedata->assignid = $assign->get_instance()->id; 271 $overridedata->userid = $user->id; 272 $overridedata->duedate = time(); 273 $overridedata->allowsubmissionsfromdate = time(); 274 $overridedata->cutoffdate = time(); 275 $DB->insert_record('assign_overrides', $overridedata); 276 277 $grade1 = '67.00'; 278 $teachercommenttext = 'Please try again.'; 279 $data = new \stdClass(); 280 $data->attemptnumber = 0; 281 $data->grade = $grade1; 282 $data->assignfeedbackcomments_editor = ['text' => $teachercommenttext, 'format' => FORMAT_MOODLE]; 283 284 // Give the submission a grade. 285 $assign->save_grade($user->id, $data); 286 287 $submissiontext2 = 'My second submission'; 288 $submission = $this->create_submission($assign, $user, $submissiontext2, 1); 289 290 $this->setUser($teacher); 291 292 $grade2 = '72.00'; 293 $teachercommenttext2 = 'This is better. Thanks.'; 294 $data = new \stdClass(); 295 $data->attemptnumber = 1; 296 $data->grade = $grade2; 297 $data->assignfeedbackcomments_editor = ['text' => $teachercommenttext2, 'format' => FORMAT_MOODLE]; 298 299 // Give the submission a grade. 300 $assign->save_grade($user->id, $data); 301 302 $writer = writer::with_context($context); 303 $this->assertFalse($writer->has_any_data()); 304 305 // The student should have some text submitted. 306 // Add the course context as well to make sure there is no error. 307 $approvedlist = new approved_contextlist($user, 'mod_assign', [$context->id, $coursecontext->id]); 308 provider::export_user_data($approvedlist); 309 310 // Check that we have general details about the assignment. 311 $this->assertEquals('Assign 1', $writer->get_data()->name); 312 // Check Submissions. 313 $this->assertEquals($submissiontext, $writer->get_data(['attempt 1', 'Submission Text'])->text); 314 $this->assertEquals($submissiontext2, $writer->get_data(['attempt 2', 'Submission Text'])->text); 315 $this->assertEquals(1, $writer->get_data(['attempt 1', 'submission'])->attemptnumber); 316 $this->assertEquals(2, $writer->get_data(['attempt 2', 'submission'])->attemptnumber); 317 // Check grades. 318 $this->assertEquals((float)$grade1, $writer->get_data(['attempt 1', 'grade'])->grade); 319 $this->assertEquals((float)$grade2, $writer->get_data(['attempt 2', 'grade'])->grade); 320 // Check feedback. 321 $this->assertStringContainsString($teachercommenttext, $writer->get_data(['attempt 1', 'Feedback comments'])->commenttext); 322 $this->assertStringContainsString($teachercommenttext2, $writer->get_data(['attempt 2', 'Feedback comments'])->commenttext); 323 324 // Check override data was exported correctly. 325 $overrideexport = $writer->get_data(['Overrides']); 326 $this->assertEquals(\core_privacy\local\request\transform::datetime($overridedata->duedate), 327 $overrideexport->duedate); 328 $this->assertEquals(\core_privacy\local\request\transform::datetime($overridedata->cutoffdate), 329 $overrideexport->cutoffdate); 330 $this->assertEquals(\core_privacy\local\request\transform::datetime($overridedata->allowsubmissionsfromdate), 331 $overrideexport->allowsubmissionsfromdate); 332 } 333 334 /** 335 * Tests the data returned for a teacher. 336 */ 337 public function test_export_user_data_teacher() { 338 $this->resetAfterTest(); 339 $course = $this->getDataGenerator()->create_course(); 340 $coursecontext = \context_course::instance($course->id); 341 342 $user1 = $this->getDataGenerator()->create_user(); 343 $user2 = $this->getDataGenerator()->create_user(); 344 $teacher = $this->getDataGenerator()->create_user(); 345 $this->getDataGenerator()->enrol_user($user1->id, $course->id, 'student'); 346 $this->getDataGenerator()->enrol_user($user2->id, $course->id, 'student'); 347 $this->getDataGenerator()->enrol_user($teacher->id, $course->id, 'editingteacher'); 348 $assign = $this->create_instance([ 349 'course' => $course, 350 'name' => 'Assign 1', 351 'attemptreopenmethod' => ASSIGN_ATTEMPT_REOPEN_METHOD_MANUAL, 352 'maxattempts' => 3, 353 'assignsubmission_onlinetext_enabled' => true, 354 'assignfeedback_comments_enabled' => true 355 ]); 356 357 $context = $assign->get_context(); 358 359 // Create and grade some submissions from the students. 360 $submissiontext = 'My first submission'; 361 $submission = $this->create_submission($assign, $user1, $submissiontext); 362 363 $this->setUser($teacher); 364 365 $grade1 = '54.00'; 366 $teachercommenttext = 'Comment on user 1 attempt 1.'; 367 $data = new \stdClass(); 368 $data->attemptnumber = 0; 369 $data->grade = $grade1; 370 $data->assignfeedbackcomments_editor = ['text' => $teachercommenttext, 'format' => FORMAT_MOODLE]; 371 372 // Give the submission a grade. 373 $assign->save_grade($user1->id, $data); 374 375 // Create and grade some submissions from the students. 376 $submissiontext2 = 'My first submission for user 2'; 377 $submission = $this->create_submission($assign, $user2, $submissiontext2); 378 379 $this->setUser($teacher); 380 381 $grade2 = '56.00'; 382 $teachercommenttext2 = 'Comment on user 2 first attempt.'; 383 $data = new \stdClass(); 384 $data->attemptnumber = 0; 385 $data->grade = $grade2; 386 $data->assignfeedbackcomments_editor = ['text' => $teachercommenttext2, 'format' => FORMAT_MOODLE]; 387 388 // Give the submission a grade. 389 $assign->save_grade($user2->id, $data); 390 391 // Create and grade some submissions from the students. 392 $submissiontext3 = 'My second submission for user 2'; 393 $submission = $this->create_submission($assign, $user2, $submissiontext3, 1); 394 395 $this->setUser($teacher); 396 397 $grade3 = '83.00'; 398 $teachercommenttext3 = 'Comment on user 2 another attempt.'; 399 $data = new \stdClass(); 400 $data->attemptnumber = 1; 401 $data->grade = $grade3; 402 $data->assignfeedbackcomments_editor = ['text' => $teachercommenttext3, 'format' => FORMAT_MOODLE]; 403 404 // Give the submission a grade. 405 $assign->save_grade($user2->id, $data); 406 407 // Set up some flags. 408 $duedate = time(); 409 $flagdata = $assign->get_user_flags($teacher->id, true); 410 $flagdata->mailed = 1; 411 $flagdata->extensionduedate = $duedate; 412 $assign->update_user_flags($flagdata); 413 414 $writer = writer::with_context($context); 415 $this->assertFalse($writer->has_any_data()); 416 417 // The student should have some text submitted. 418 $approvedlist = new approved_contextlist($teacher, 'mod_assign', [$context->id, $coursecontext->id]); 419 provider::export_user_data($approvedlist); 420 421 // Check flag metadata. 422 $metadata = $writer->get_all_metadata(); 423 $this->assertEquals(\core_privacy\local\request\transform::yesno(1), $metadata['mailed']->value); 424 $this->assertEquals(\core_privacy\local\request\transform::datetime($duedate), $metadata['extensionduedate']->value); 425 426 // Check for student grades given. 427 $student1grade = $writer->get_data(['studentsubmissions', $user1->id, 'attempt 1', 'grade']); 428 $this->assertEquals((float)$grade1, $student1grade->grade); 429 $student2grade1 = $writer->get_data(['studentsubmissions', $user2->id, 'attempt 1', 'grade']); 430 $this->assertEquals((float)$grade2, $student2grade1->grade); 431 $student2grade2 = $writer->get_data(['studentsubmissions', $user2->id, 'attempt 2', 'grade']); 432 $this->assertEquals((float)$grade3, $student2grade2->grade); 433 // Check for feedback given to students. 434 $this->assertStringContainsString($teachercommenttext, $writer->get_data(['studentsubmissions', $user1->id, 'attempt 1', 435 'Feedback comments'])->commenttext); 436 $this->assertStringContainsString($teachercommenttext2, $writer->get_data(['studentsubmissions', $user2->id, 'attempt 1', 437 'Feedback comments'])->commenttext); 438 $this->assertStringContainsString($teachercommenttext3, $writer->get_data(['studentsubmissions', $user2->id, 'attempt 2', 439 'Feedback comments'])->commenttext); 440 } 441 442 /** 443 * A test for deleting all user data for a given context. 444 */ 445 public function test_delete_data_for_all_users_in_context() { 446 global $DB; 447 $this->resetAfterTest(); 448 $course = $this->getDataGenerator()->create_course(); 449 450 $user1 = $this->getDataGenerator()->create_user(); 451 $user2 = $this->getDataGenerator()->create_user(); 452 $teacher = $this->getDataGenerator()->create_user(); 453 $this->getDataGenerator()->enrol_user($user1->id, $course->id, 'student'); 454 $this->getDataGenerator()->enrol_user($user2->id, $course->id, 'student'); 455 $this->getDataGenerator()->enrol_user($teacher->id, $course->id, 'editingteacher'); 456 $assign = $this->create_instance([ 457 'course' => $course, 458 'name' => 'Assign 1', 459 'attemptreopenmethod' => ASSIGN_ATTEMPT_REOPEN_METHOD_MANUAL, 460 'maxattempts' => 3, 461 'assignsubmission_onlinetext_enabled' => true, 462 'assignfeedback_comments_enabled' => true 463 ]); 464 465 $context = $assign->get_context(); 466 467 // Create and grade some submissions from the students. 468 $submissiontext = 'My first submission'; 469 $submission = $this->create_submission($assign, $user1, $submissiontext); 470 471 $this->setUser($teacher); 472 473 // Overrides for both students. 474 $overridedata = new \stdClass(); 475 $overridedata->assignid = $assign->get_instance()->id; 476 $overridedata->userid = $user1->id; 477 $overridedata->duedate = time(); 478 $DB->insert_record('assign_overrides', $overridedata); 479 $overridedata->userid = $user2->id; 480 $DB->insert_record('assign_overrides', $overridedata); 481 assign_update_events($assign); 482 483 $grade1 = '54.00'; 484 $teachercommenttext = 'Comment on user 1 attempt 1.'; 485 $data = new \stdClass(); 486 $data->attemptnumber = 0; 487 $data->grade = $grade1; 488 $data->assignfeedbackcomments_editor = ['text' => $teachercommenttext, 'format' => FORMAT_MOODLE]; 489 490 // Give the submission a grade. 491 $assign->save_grade($user1->id, $data); 492 493 // Create and grade some submissions from the students. 494 $submissiontext2 = 'My first submission for user 2'; 495 $submission = $this->create_submission($assign, $user2, $submissiontext2); 496 497 $this->setUser($teacher); 498 499 $grade2 = '56.00'; 500 $teachercommenttext2 = 'Comment on user 2 first attempt.'; 501 $data = new \stdClass(); 502 $data->attemptnumber = 0; 503 $data->grade = $grade2; 504 $data->assignfeedbackcomments_editor = ['text' => $teachercommenttext2, 'format' => FORMAT_MOODLE]; 505 506 // Give the submission a grade. 507 $assign->save_grade($user2->id, $data); 508 509 // Create and grade some submissions from the students. 510 $submissiontext3 = 'My second submission for user 2'; 511 $submission = $this->create_submission($assign, $user2, $submissiontext3, 1); 512 513 $this->setUser($teacher); 514 515 $grade3 = '83.00'; 516 $teachercommenttext3 = 'Comment on user 2 another attempt.'; 517 $data = new \stdClass(); 518 $data->attemptnumber = 1; 519 $data->grade = $grade3; 520 $data->assignfeedbackcomments_editor = ['text' => $teachercommenttext3, 'format' => FORMAT_MOODLE]; 521 522 // Give the submission a grade. 523 $assign->save_grade($user2->id, $data); 524 525 // Delete all user data for this assignment. 526 provider::delete_data_for_all_users_in_context($context); 527 528 // Check all relevant tables. 529 $records = $DB->get_records('assign_submission'); 530 $this->assertEmpty($records); 531 $records = $DB->get_records('assign_grades'); 532 $this->assertEmpty($records); 533 $records = $DB->get_records('assignsubmission_onlinetext'); 534 $this->assertEmpty($records); 535 $records = $DB->get_records('assignfeedback_comments'); 536 $this->assertEmpty($records); 537 538 // Check that overrides and the calendar events are deleted. 539 $records = $DB->get_records('event'); 540 $this->assertEmpty($records); 541 $records = $DB->get_records('assign_overrides'); 542 $this->assertEmpty($records); 543 } 544 545 /** 546 * A test for deleting all user data for one user. 547 */ 548 public function test_delete_data_for_user() { 549 global $DB; 550 $this->resetAfterTest(); 551 $course = $this->getDataGenerator()->create_course(); 552 553 $coursecontext = \context_course::instance($course->id); 554 555 $user1 = $this->getDataGenerator()->create_user(); 556 $user2 = $this->getDataGenerator()->create_user(); 557 $teacher = $this->getDataGenerator()->create_user(); 558 $this->getDataGenerator()->enrol_user($user1->id, $course->id, 'student'); 559 $this->getDataGenerator()->enrol_user($user2->id, $course->id, 'student'); 560 $this->getDataGenerator()->enrol_user($teacher->id, $course->id, 'editingteacher'); 561 $assign = $this->create_instance([ 562 'course' => $course, 563 'name' => 'Assign 1', 564 'attemptreopenmethod' => ASSIGN_ATTEMPT_REOPEN_METHOD_MANUAL, 565 'maxattempts' => 3, 566 'assignsubmission_onlinetext_enabled' => true, 567 'assignfeedback_comments_enabled' => true 568 ]); 569 570 $context = $assign->get_context(); 571 572 // Create and grade some submissions from the students. 573 $submissiontext = 'My first submission'; 574 $submission1 = $this->create_submission($assign, $user1, $submissiontext); 575 576 $this->setUser($teacher); 577 578 // Overrides for both students. 579 $overridedata = new \stdClass(); 580 $overridedata->assignid = $assign->get_instance()->id; 581 $overridedata->userid = $user1->id; 582 $overridedata->duedate = time(); 583 $DB->insert_record('assign_overrides', $overridedata); 584 $overridedata->userid = $user2->id; 585 $DB->insert_record('assign_overrides', $overridedata); 586 assign_update_events($assign); 587 588 $grade1 = '54.00'; 589 $teachercommenttext = 'Comment on user 1 attempt 1.'; 590 $data = new \stdClass(); 591 $data->attemptnumber = 0; 592 $data->grade = $grade1; 593 $data->assignfeedbackcomments_editor = ['text' => $teachercommenttext, 'format' => FORMAT_MOODLE]; 594 595 // Give the submission a grade. 596 $assign->save_grade($user1->id, $data); 597 598 // Create and grade some submissions from the students. 599 $submissiontext2 = 'My first submission for user 2'; 600 $submission2 = $this->create_submission($assign, $user2, $submissiontext2); 601 602 $this->setUser($teacher); 603 604 $grade2 = '56.00'; 605 $teachercommenttext2 = 'Comment on user 2 first attempt.'; 606 $data = new \stdClass(); 607 $data->attemptnumber = 0; 608 $data->grade = $grade2; 609 $data->assignfeedbackcomments_editor = ['text' => $teachercommenttext2, 'format' => FORMAT_MOODLE]; 610 611 // Give the submission a grade. 612 $assign->save_grade($user2->id, $data); 613 614 // Create and grade some submissions from the students. 615 $submissiontext3 = 'My second submission for user 2'; 616 $submission3 = $this->create_submission($assign, $user2, $submissiontext3, 1); 617 618 $this->setUser($teacher); 619 620 $grade3 = '83.00'; 621 $teachercommenttext3 = 'Comment on user 2 another attempt.'; 622 $data = new \stdClass(); 623 $data->attemptnumber = 1; 624 $data->grade = $grade3; 625 $data->assignfeedbackcomments_editor = ['text' => $teachercommenttext3, 'format' => FORMAT_MOODLE]; 626 627 // Give the submission a grade. 628 $assign->save_grade($user2->id, $data); 629 630 // Delete user 2's data. 631 $approvedlist = new approved_contextlist($user2, 'mod_assign', [$context->id, $coursecontext->id]); 632 provider::delete_data_for_user($approvedlist); 633 634 // Check all relevant tables. 635 $records = $DB->get_records('assign_submission'); 636 foreach ($records as $record) { 637 $this->assertEquals($user1->id, $record->userid); 638 $this->assertNotEquals($user2->id, $record->userid); 639 } 640 $records = $DB->get_records('assign_grades'); 641 foreach ($records as $record) { 642 $this->assertEquals($user1->id, $record->userid); 643 $this->assertNotEquals($user2->id, $record->userid); 644 } 645 $records = $DB->get_records('assignsubmission_onlinetext'); 646 $this->assertCount(1, $records); 647 $record = array_shift($records); 648 // The only submission is for user 1. 649 $this->assertEquals($submission1->id, $record->submission); 650 $records = $DB->get_records('assignfeedback_comments'); 651 $this->assertCount(1, $records); 652 $record = array_shift($records); 653 // The only record is the feedback comment for user 1. 654 $this->assertEquals($teachercommenttext, $record->commenttext); 655 656 // Check calendar events as well as assign overrides. 657 $records = $DB->get_records('event'); 658 $this->assertCount(1, $records); 659 $record = array_shift($records); 660 // The remaining event should be for user 1. 661 $this->assertEquals($user1->id, $record->userid); 662 // Now for assign_overrides 663 $records = $DB->get_records('assign_overrides'); 664 $this->assertCount(1, $records); 665 $record = array_shift($records); 666 // The remaining event should be for user 1. 667 $this->assertEquals($user1->id, $record->userid); 668 } 669 670 /** 671 * A test for deleting all user data for a bunch of users. 672 */ 673 public function test_delete_data_for_users() { 674 global $DB; 675 676 $this->resetAfterTest(); 677 678 $course = $this->getDataGenerator()->create_course(); 679 680 // Only made a comment on a submission. 681 $user1 = $this->getDataGenerator()->create_user(); 682 // User 2 only has information about an activity override. 683 $user2 = $this->getDataGenerator()->create_user(); 684 // User 3 made a submission. 685 $user3 = $this->getDataGenerator()->create_user(); 686 // User 4 makes a submission and it is marked by the teacher. 687 $user4 = $this->getDataGenerator()->create_user(); 688 // Grading and providing feedback as a teacher. 689 $user5 = $this->getDataGenerator()->create_user(); 690 // This user has entries in assignment 2 and should not have their data deleted. 691 $user6 = $this->getDataGenerator()->create_user(); 692 693 $this->getDataGenerator()->enrol_user($user1->id, $course->id, 'student'); 694 $this->getDataGenerator()->enrol_user($user2->id, $course->id, 'student'); 695 $this->getDataGenerator()->enrol_user($user3->id, $course->id, 'student'); 696 $this->getDataGenerator()->enrol_user($user4->id, $course->id, 'student'); 697 $this->getDataGenerator()->enrol_user($user5->id, $course->id, 'editingteacher'); 698 $this->getDataGenerator()->enrol_user($user6->id, $course->id, 'student'); 699 700 $assign1 = $this->create_instance(['course' => $course, 701 'assignsubmission_onlinetext_enabled' => true, 702 'assignfeedback_comments_enabled' => true]); 703 $assign2 = $this->create_instance(['course' => $course, 704 'assignsubmission_onlinetext_enabled' => true, 705 'assignfeedback_comments_enabled' => true]); 706 707 $context = $assign1->get_context(); 708 709 // Jam an entry in the comments table for user 1. 710 $comment = (object) [ 711 'contextid' => $context->id, 712 'component' => 'assignsubmission_comments', 713 'commentarea' => 'submission_comments', 714 'itemid' => 5, 715 'content' => 'A comment by user 1', 716 'format' => 0, 717 'userid' => $user1->id, 718 'timecreated' => time() 719 ]; 720 $DB->insert_record('comments', $comment); 721 722 $this->setUser($user5); // Set the user to the teacher. 723 724 $overridedata = new \stdClass(); 725 $overridedata->assignid = $assign1->get_instance()->id; 726 $overridedata->userid = $user2->id; 727 $overridedata->duedate = time(); 728 $overridedata->allowsubmissionsfromdate = time(); 729 $overridedata->cutoffdate = time(); 730 $DB->insert_record('assign_overrides', $overridedata); 731 732 $submissiontext = 'My first submission'; 733 $submission = $this->create_submission($assign1, $user3, $submissiontext); 734 735 $submissiontext = 'My first submission'; 736 $submission = $this->create_submission($assign1, $user4, $submissiontext); 737 738 $submissiontext = 'My first submission'; 739 $submission = $this->create_submission($assign2, $user6, $submissiontext); 740 741 $this->setUser($user5); 742 743 $grade = '72.00'; 744 $teachercommenttext = 'This is better. Thanks.'; 745 $data = new \stdClass(); 746 $data->attemptnumber = 1; 747 $data->grade = $grade; 748 $data->assignfeedbackcomments_editor = ['text' => $teachercommenttext, 'format' => FORMAT_MOODLE]; 749 750 // Give the submission a grade. 751 $assign1->save_grade($user4->id, $data); 752 753 $this->setUser($user5); 754 755 $grade = '81.00'; 756 $teachercommenttext = 'This is nice.'; 757 $data = new \stdClass(); 758 $data->attemptnumber = 1; 759 $data->grade = $grade; 760 $data->assignfeedbackcomments_editor = ['text' => $teachercommenttext, 'format' => FORMAT_MOODLE]; 761 762 // Give the submission a grade. 763 $assign2->save_grade($user6->id, $data); 764 765 // Check data is in place. 766 $data = $DB->get_records('assign_submission'); 767 // We should have one entry for user 3 and two entries each for user 4 and 6. 768 $this->assertCount(5, $data); 769 $usercounts = [ 770 $user3->id => 0, 771 $user4->id => 0, 772 $user6->id => 0 773 ]; 774 foreach ($data as $datum) { 775 $usercounts[$datum->userid]++; 776 } 777 $this->assertEquals(1, $usercounts[$user3->id]); 778 $this->assertEquals(2, $usercounts[$user4->id]); 779 $this->assertEquals(2, $usercounts[$user6->id]); 780 781 $data = $DB->get_records('assign_grades'); 782 // Two entries in assign_grades, one for each grade given. 783 $this->assertCount(2, $data); 784 785 $data = $DB->get_records('assign_overrides'); 786 $this->assertCount(1, $data); 787 788 $data = $DB->get_records('comments'); 789 $this->assertCount(1, $data); 790 791 $userlist = new \core_privacy\local\request\approved_userlist($context, 'assign', [$user1->id, $user2->id]); 792 provider::delete_data_for_users($userlist); 793 794 $data = $DB->get_records('assign_overrides'); 795 $this->assertEmpty($data); 796 797 $data = $DB->get_records('comments'); 798 $this->assertEmpty($data); 799 800 $data = $DB->get_records('assign_submission'); 801 // No change here. 802 $this->assertCount(5, $data); 803 804 $userlist = new \core_privacy\local\request\approved_userlist($context, 'assign', [$user3->id, $user5->id]); 805 provider::delete_data_for_users($userlist); 806 807 $data = $DB->get_records('assign_submission'); 808 // Only the record for user 3 has been deleted. 809 $this->assertCount(4, $data); 810 811 $data = $DB->get_records('assign_grades'); 812 // Grades should be unchanged. 813 $this->assertCount(2, $data); 814 } 815 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body