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 * Privacy test for the event monitor 19 * 20 * @package mod_assignment 21 * @category test 22 * @copyright 2018 Zig Tan <zig@moodle.com> 23 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 24 */ 25 namespace mod_assignment\privacy; 26 27 defined('MOODLE_INTERNAL') || die(); 28 29 require_once (__DIR__ . '/../../lib.php'); 30 31 use mod_assignment\privacy\provider; 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_privacy\tests\provider_testcase; 36 37 /** 38 * Privacy test for the event monitor 39 * 40 * @package mod_assignment 41 * @category test 42 * @copyright 2018 Zig Tan <zig@moodle.com> 43 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 44 */ 45 class provider_test extends provider_testcase { 46 47 /** 48 * @var int array Array of test student ids associated for Course 1. 49 */ 50 private $course1students = []; 51 52 /** 53 * @var int array Array of test student ids associated for Course 2. 54 */ 55 private $course2students = []; 56 57 /** 58 * @var int array Array of test assignments associated for Course 1. 59 */ 60 private $course1assignments = []; 61 62 /** 63 * @var int array Array of test assignments associated for Course 2. 64 */ 65 private $course2assignments = []; 66 67 /** 68 * Test for provider::get_contexts_for_userid(). 69 * 70 * @throws coding_exception 71 */ 72 public function test_get_contexts_for_userid() { 73 global $DB; 74 75 $this->resetAfterTest(true); 76 $this->create_courses_and_assignments(); 77 78 // Get Teacher 1 to test get_contexts_for_userid(). 79 $teacher1 = $DB->get_record('user', ['username' => 'teacher1']); 80 $contextids = provider::get_contexts_for_userid($teacher1->id); 81 // Verify there should be 4 contexts, as Teacher 1 has submitted tests and marked Assignments in Course 1 and 2. 82 $this->assertEquals(4, count($contextids->get_contextids())); 83 84 // Get Teacher 2 to test get_contexts_for_userid(). 85 $teacher2 = $DB->get_record('user', ['username' => 'teacher2']); 86 $contextids = provider::get_contexts_for_userid($teacher2->id); 87 // Verify there should be 0 contexts, as teacher 2 has not marked any Assignments. 88 $this->assertEquals(0, count($contextids->get_contextids())); 89 90 // Get Student 1 to test get_contexts_for_userid(). 91 $student1 = $DB->get_record('user', ['username' => 'student1']); 92 $contextids = provider::get_contexts_for_userid($student1->id); 93 // Verify there should be 2 contexts, as student 1 added submissions for both Assignments in Course 1. 94 $this->assertEquals(2, count($contextids->get_contextids())); 95 96 // Get Student 2 to test get_contexts_for_userid(). 97 $student2 = $DB->get_record('user', ['username' => 'student2']); 98 $contextids = provider::get_contexts_for_userid($student2->id); 99 // Verify there should be 2 context, as student 2 added submissions for both Assignments in Course 2. 100 $this->assertEquals(2, count($contextids->get_contextids())); 101 } 102 103 /** 104 * Test that the correct userids are returned for a specific context. 105 */ 106 public function test_get_users_in_context() { 107 108 $this->resetAfterTest(true); 109 110 $student1 = $this->getDataGenerator()->create_user(['username' => 'student1']); 111 $student2 = $this->getDataGenerator()->create_user(['username' => 'student2']); 112 // Student 3 should not turn up in the results of this test. 113 $student3 = $this->getDataGenerator()->create_user(['username' => 'student3']); 114 $teacher1 = $this->getDataGenerator()->create_user(['username' => 'teacher1']); 115 116 $course = $this->getDataGenerator()->create_course(); 117 $course1assignment1 = $this->getDataGenerator()->create_module('assignment', 118 [ 119 'course' => $course->id, 120 'name' => 'Course 1 - Assignment 1 (onlinetext)', 121 'assignmenttype' => 'onlinetext', 122 ] 123 ); 124 // Create a second assignment in the same course. 125 $course1assignment2 = $this->getDataGenerator()->create_module('assignment', 126 [ 127 'course' => $course->id, 128 'name' => 'Course 1 - Assignment 1 (onlinetext)', 129 'assignmenttype' => 'onlinetext', 130 ] 131 ); 132 133 $this->add_assignment_submission( 134 $course1assignment1, 135 $student1, 136 "Course 1 - Ass 1: Student1 Test Submission" 137 ); 138 139 $this->add_assignment_submission( 140 $course1assignment1, 141 $student2, 142 "Course 1 - Ass 1: Student2 Test Submission" 143 ); 144 // Add a submission for the second assignment. 145 $this->add_assignment_submission( 146 $course1assignment2, 147 $student3, 148 "Course 1 - Ass 2: Student3 Test Submission" 149 ); 150 151 $submissions = $this->get_course_assignment_submissions($course->id); 152 foreach ($submissions as $submission) { 153 $this->mark_assignment_submission($submission->assignment, $submission->id, $teacher1, 50); 154 } 155 156 $c1ass1ctx = \context_module::instance($course1assignment1->cmid); 157 $userlist = new \core_privacy\local\request\userlist($c1ass1ctx, 'mod_assignment'); 158 159 provider::get_users_in_context($userlist); 160 $userids = $userlist->get_userids(); 161 162 // This is both students and the teacher who marked both assignments. 163 $this->assertCount(3, $userids); 164 // Make sure that student 3 is not in the returned userids. 165 $this->assertFalse(in_array($student3->id, $userids)); 166 // Try with the course context. 167 $coursecontext = \context_course::instance($course->id); 168 $userlist = new \core_privacy\local\request\userlist($coursecontext, 'mod_assignment'); 169 provider::get_users_in_context($userlist); 170 $this->assertEmpty($userlist->get_userids()); 171 } 172 173 /** 174 * Test for provider::export_user_data(). 175 * 176 * @throws coding_exception 177 */ 178 public function test_export_user_data_teacher() { 179 global $DB; 180 181 $this->resetAfterTest(true); 182 $this->create_courses_and_assignments(); 183 184 // Test Teacher 1 export_data_for_user() - marking assignment submissions for both Course 1 and 2. 185 $teacher1 = $DB->get_record('user', ['username' => 'teacher1']); 186 187 $contextlist = provider::get_contexts_for_userid($teacher1->id); 188 $approvedcontextlist = new approved_contextlist($teacher1, 'mod_assignment', $contextlist->get_contextids()); 189 190 // Verify Teacher 1 has four contexts. 191 $this->assertCount(4, $contextlist->get_contextids()); 192 193 // Retrieve Assignment Submissions data for Teacher 1. 194 provider::export_user_data($approvedcontextlist); 195 196 $contexts = $contextlist->get_contexts(); 197 198 // Context 1 - Course 1's Assignment 1 -- (onlinetext). 199 $context = \context_module::instance($this->course1assignments['ass1']->cmid); 200 $this->assertContains($context, $contexts); 201 202 $writer = writer::with_context($context); 203 $subcontexts = [ 204 get_string('privacy:markedsubmissionspath', 'mod_assignment'), 205 transform::user($teacher1->id) 206 ]; 207 // Verify the test assignment submission from Teacher 1 exists. 208 $submission = $writer->get_data($subcontexts); 209 $this->assertEquals('<p>Course 1 - Ass 1: Teacher Test Submission</p>', $submission->data1); 210 211 foreach ($this->course1students as $student) { 212 $subcontexts = [ 213 get_string('privacy:markedsubmissionspath', 'mod_assignment'), 214 transform::user($student->id) 215 ]; 216 // Verify the student assignment submissions exists. 217 $submission = $writer->get_data($subcontexts); 218 $this->assertEquals("<p>Course 1 - Ass 1: " . $student->id . "</p>", $submission->data1); 219 } 220 221 // Context 2 - Course 1's Assignment 2 -- (single file upload). 222 $context = \context_module::instance($this->course1assignments['ass2']->cmid); 223 $this->assertContains($context, $contexts); 224 225 $writer = writer::with_context($context); 226 foreach ($this->course1students as $student) { 227 $subcontexts = [ 228 get_string('privacy:markedsubmissionspath', 'mod_assignment'), 229 transform::user($student->id) 230 ]; 231 // Verify the student assignment submissions exists. 232 $submission = $writer->get_data($subcontexts); 233 $this->assertEquals("<p>Course 1 - Ass 2: " . $student->id . "</p>", $submission->data1); 234 235 // Verify the student assignment submission file upload exists. 236 $submissionfiles = $writer->get_files($subcontexts); 237 $this->assertTrue(array_key_exists('Student' . $student->id . '-Course1-Ass2-(File 1 of 1)', $submissionfiles)); 238 } 239 240 // Context 3 - Course 2's Assignment 1 -- (offline). 241 $context = \context_module::instance($this->course2assignments['ass1']->cmid); 242 $this->assertContains($context, $contexts); 243 244 $writer = writer::with_context($context); 245 foreach ($this->course2students as $student) { 246 $subcontexts = [ 247 get_string('privacy:markedsubmissionspath', 'mod_assignment'), 248 transform::user($student->id) 249 ]; 250 // Verify the student assignment submissions exists. 251 $submission = $writer->get_data($subcontexts); 252 $this->assertEquals("<p>Course 2 - Ass 1: " . $student->id . "</p>", $submission->data1); 253 } 254 255 // Context 4 - Course 2's Assignment 2 -- (multiple file upload). 256 $context = \context_module::instance($this->course2assignments['ass2']->cmid); 257 $this->assertContains($context, $contexts); 258 259 $writer = writer::with_context($context); 260 foreach ($this->course2students as $student) { 261 $subcontexts = [ 262 get_string('privacy:markedsubmissionspath', 'mod_assignment'), 263 transform::user($student->id) 264 ]; 265 // Verify the student assignment submissions exists. 266 $submission = $writer->get_data($subcontexts); 267 $this->assertEquals("<p>Course 2 - Ass 2: " . $student->id . "</p>", $submission->data1); 268 269 // Verify the student assignment submission file upload exists. 270 $submissionfiles = $writer->get_files($subcontexts); 271 $this->assertTrue(array_key_exists('Student' . $student->id . '-Course2-Ass2-(File 1 of 2)', $submissionfiles)); 272 $this->assertTrue(array_key_exists('Student' . $student->id . '-Course2-Ass2-(File 2 of 2)', $submissionfiles)); 273 } 274 } 275 276 /** 277 * Test for provider::export_user_data(). 278 * 279 * @throws dml_exception 280 */ 281 public function test_export_user_data_student() { 282 global $DB; 283 284 $this->resetAfterTest(true); 285 $this->create_courses_and_assignments(); 286 287 // Test Student 1 export_data_for_user() - added assignment submissions for both assignments in Course 1. 288 $student1 = $DB->get_record('user', ['username' => 'student1']); 289 290 $contextlist = provider::get_contexts_for_userid($student1->id); 291 $approvedcontextlist = new approved_contextlist($student1, 'mod_assignment', $contextlist->get_contextids()); 292 293 // Retrieve Assignment Submissions data for Student 1. 294 provider::export_user_data($approvedcontextlist); 295 $contexts = $contextlist->get_contexts(); 296 297 // Context 1 - Course 1's Assignment 1 -- (onlinetext). 298 $context = \context_module::instance($this->course1assignments['ass1']->cmid); 299 $this->assertContains($context, $contexts); 300 301 $writer = writer::with_context($context); 302 $subcontexts = [ 303 get_string('privacy:submissionpath', 'mod_assignment') 304 ]; 305 306 // Verify the student assignment submissions exists. 307 $submission = $writer->get_data($subcontexts); 308 $this->assertEquals("<p>Course 1 - Ass 1: " . $student1->id . "</p>", $submission->data1); 309 310 // Context 2 - Course 1's Assignment 2 -- (single file upload). 311 $context = \context_module::instance($this->course1assignments['ass2']->cmid); 312 $this->assertContains($context, $contexts); 313 314 $writer = writer::with_context($context); 315 $subcontexts = [ 316 get_string('privacy:submissionpath', 'mod_assignment') 317 ]; 318 319 // Verify the student assignment submission exists. 320 $submission = $writer->get_data($subcontexts); 321 $this->assertEquals("<p>Course 1 - Ass 2: " . $student1->id . "</p>", $submission->data1); 322 323 // Verify the student assignment submission file upload exists. 324 $submissionfiles = $writer->get_files($subcontexts); 325 $this->assertTrue(array_key_exists('Student' . $student1->id . '-Course1-Ass2-(File 1 of 1)', $submissionfiles)); 326 327 // Test Student 2 export_data_for_user() - added assignment submissions for both assignments in Course 2. 328 $student2 = $DB->get_record('user', ['username' => 'student2']); 329 330 $contextlist = provider::get_contexts_for_userid($student2->id); 331 $approvedcontextlist = new approved_contextlist($student2, 'mod_assignment', $contextlist->get_contextids()); 332 333 // Retrieve Assignment Submissions data for Student 2. 334 provider::export_user_data($approvedcontextlist); 335 $contexts = $contextlist->get_contexts(); 336 337 // Context 1 - Course 2's Assignment 1 -- (offline). 338 $context = \context_module::instance($this->course2assignments['ass1']->cmid); 339 $this->assertContains($context, $contexts); 340 341 $writer = writer::with_context($context); 342 $subcontexts = [ 343 get_string('privacy:submissionpath', 'mod_assignment') 344 ]; 345 346 // Verify the student assignment submissions exists. 347 $submission = $writer->get_data($subcontexts); 348 $this->assertEquals("<p>Course 2 - Ass 1: " . $student2->id . "</p>", $submission->data1); 349 350 // Context 2 - Course 2's Assignment 2 -- (multiple file upload). 351 $context = \context_module::instance($this->course2assignments['ass2']->cmid); 352 $this->assertContains($context, $contexts); 353 354 $writer = writer::with_context($context); 355 $subcontexts = [ 356 get_string('privacy:submissionpath', 'mod_assignment') 357 ]; 358 359 // Verify the student assignment submission exists. 360 $submission = $writer->get_data($subcontexts); 361 $this->assertEquals("<p>Course 2 - Ass 2: " . $student2->id . "</p>", $submission->data1); 362 363 // Verify the student assignment submission file upload exists. 364 $submissionfiles = $writer->get_files($subcontexts); 365 $this->assertTrue(array_key_exists('Student' . $student2->id . '-Course2-Ass2-(File 1 of 2)', $submissionfiles)); 366 $this->assertTrue(array_key_exists('Student' . $student2->id . '-Course2-Ass2-(File 2 of 2)', $submissionfiles)); 367 } 368 369 /** 370 * Test for provider::delete_data_for_all_users_in_context(). 371 * 372 * @throws dml_exception 373 */ 374 public function test_delete_data_for_all_users_in_context() { 375 global $DB; 376 377 $this->resetAfterTest(true); 378 $this->create_courses_and_assignments(); 379 380 // Test teacher1 delete_data_for_all_users_in_context(). 381 $teacher1 = $DB->get_record('user', ['username' => 'teacher1']); 382 $contextlist = provider::get_contexts_for_userid($teacher1->id); 383 384 foreach ($contextlist as $context) { 385 provider::delete_data_for_all_users_in_context($context); 386 387 // Verify assignment submission(s) were deleted for the context. 388 $deleted = $this->get_assignment_submissions($context->id); 389 $this->assertCount(0, $deleted); 390 391 // Verify all the file submissions associated with the context for all users were deleted. 392 $files = $DB->get_records('files', ['component' => 'mod_assignment', 'filearea' => 'submission', 'contextid' => $context->id]); 393 $this->assertEquals(0, count($files)); 394 } 395 } 396 397 /** 398 * Test for provider::delete_data_for_user(). 399 * 400 * @throws dml_exception 401 */ 402 public function test_delete_data_for_user() { 403 global $DB; 404 405 $this->resetAfterTest(true); 406 $this->create_courses_and_assignments(); 407 408 // Test Teacher 1 delete_data_for_user(), should only remove the 1 test submission added by Teacher 1. 409 // Should not remove any assignment submission records marked by the teacher. 410 $teacher1 = $DB->get_record('user', ['username' => 'teacher1']); 411 $contextlist = provider::get_contexts_for_userid($teacher1->id); 412 $approvedcontextlist = new approved_contextlist($teacher1, 'mod_assignment', $contextlist->get_contextids()); 413 provider::delete_data_for_user($approvedcontextlist); 414 415 // Verify the submissions submitted by students still exists. 416 $markedsubmissions = $DB->get_records('assignment_submissions', ['teacher' => $teacher1->id]); 417 $this->assertCount(4, $markedsubmissions); 418 419 // Test student 1 delete_data_for_user(). 420 $student1 = $DB->get_record('user', ['username' => 'student1']); 421 $contextlist = provider::get_contexts_for_userid($student1->id); 422 $approvedcontextlist = new approved_contextlist($student1, 'mod_assignment', $contextlist->get_contextids()); 423 provider::delete_data_for_user($approvedcontextlist); 424 425 // Verify student 1's assignment submissions were deleted. 426 $assignmentsubmissions = $DB->get_records('assignment_submissions', ['userid' => $student1->id]); 427 $this->assertEquals(0, count($assignmentsubmissions)); 428 429 // Verify student 1's file submissions were deleted. 430 foreach ($contextlist->get_contextids() as $contextid) { 431 $files = $DB->get_records('files', ['component' => 'mod_assignment', 'filearea' => 'submission', 'contextid' => $contextid]); 432 $this->assertEquals(0, count($files)); 433 } 434 } 435 436 /** 437 * Test the deletion of a data for users. 438 */ 439 public function test_delete_data_for_users() { 440 global $DB; 441 $this->resetAfterTest(); 442 443 $student1 = $this->getDataGenerator()->create_user(['username' => 'student1']); 444 $student2 = $this->getDataGenerator()->create_user(['username' => 'student2']); 445 $student3 = $this->getDataGenerator()->create_user(['username' => 'student3']); 446 447 $course = $this->getDataGenerator()->create_course(); 448 $course1assignment = $this->getDataGenerator()->create_module('assignment', 449 [ 450 'course' => $course->id, 451 'name' => 'Course 1 - Assignment 1 (single file upload)', 452 'assignmenttype' => 'uploadsingle' 453 ] 454 ); 455 $context = \context_module::instance($course1assignment->cmid); 456 457 // Student one submission. 458 $this->add_file_assignment_submission( 459 $course1assignment, 460 $student1, 461 "Course 1 - Ass 2: " . $student1->id, 462 'Student' . $student1->id . '-Course1-Ass2' 463 ); 464 // Student two submission. 465 $this->add_file_assignment_submission( 466 $course1assignment, 467 $student2, 468 "Course 1 - Ass 2: " . $student2->id, 469 'Student' . $student2->id . '-Course1-Ass2' 470 ); 471 // Student three submission to be retained. 472 $this->add_file_assignment_submission( 473 $course1assignment, 474 $student3, 475 "Course 1 - Ass 2: " . $student3->id, 476 'Student' . $student3->id . '-Course1-Ass2' 477 ); 478 479 $files = $DB->get_records('files', [ 480 'component' => 'mod_assignment', 481 'filearea' => 'submission', 482 'contextid' => $context->id 483 ]); 484 $this->assertCount(6, $files); 485 486 $submissions = $this->get_assignment_submissions($context->id); 487 $this->assertCount(3, $submissions); 488 489 $userlist = new \core_privacy\local\request\approved_userlist($context, 'mod_assignment', [$student1->id, $student2->id]); 490 provider::delete_data_for_users($userlist); 491 492 $files = $DB->get_records('files', [ 493 'component' => 'mod_assignment', 494 'filearea' => 'submission', 495 'contextid' => $context->id 496 ]); 497 $this->assertCount(2, $files); 498 499 $submissions = $this->get_assignment_submissions($context->id); 500 $this->assertCount(1, $submissions); 501 } 502 503 // Start of helper functions. 504 505 /** 506 * Helper function to setup Course, users, and assignments for testing. 507 */ 508 protected function create_courses_and_assignments() { 509 // Create Courses, Users, and Assignments. 510 $course1 = $this->getDataGenerator()->create_course(['shortname' => 'course1']); 511 $course2 = $this->getDataGenerator()->create_course(['shortname' => 'course2']); 512 513 $teacher1 = $this->getDataGenerator()->create_user(['username' => 'teacher1']); 514 $teacher2 = $this->getDataGenerator()->create_user(['username' => 'teacher2']); 515 516 $student1 = $this->getDataGenerator()->create_user(['username' => 'student1']); 517 $student2 = $this->getDataGenerator()->create_user(['username' => 'student2']); 518 519 $this->course1students = [ 520 $student1 521 ]; 522 523 $this->course2students = [ 524 $student2 525 ]; 526 527 $course1assignment1 = $this->getDataGenerator()->create_module('assignment', 528 [ 529 'course' => $course1->id, 530 'name' => 'Course 1 - Assignment 1 (onlinetext)', 531 'assignmenttype' => 'onlinetext', 532 ] 533 ); 534 $course1assignment2 = $this->getDataGenerator()->create_module('assignment', 535 [ 536 'course' => $course1->id, 537 'name' => 'Course 1 - Assignment 2 (single file upload)', 538 'assignmenttype' => 'uploadsingle', 539 ] 540 ); 541 542 $this->course1assignments = [ 543 'ass1' => $course1assignment1, 544 'ass2' => $course1assignment2 545 ]; 546 547 $course2assignment1 = $this->getDataGenerator()->create_module('assignment', 548 [ 549 'course' => $course2->id, 550 'name' => 'Course 2 - Assignment 1 (offline)', 551 'assignmenttype' => 'offline', 552 ] 553 ); 554 $course2assignment2 = $this->getDataGenerator()->create_module('assignment', 555 [ 556 'course' => $course2->id, 557 'name' => 'Course 2 - Assignment 2 (multiple file upload)', 558 'assignmenttype' => 'upload', 559 ] 560 ); 561 562 $this->course2assignments = [ 563 'ass1' => $course2assignment1, 564 'ass2' => $course2assignment2 565 ]; 566 567 // Teacher 1 add test assignment submission for Course 1 - Assignment 1. 568 $this->add_assignment_submission( 569 $course1assignment1, 570 $teacher1, 571 "Course 1 - Ass 1: Teacher Test Submission" 572 ); 573 574 // Student 1 add assignment submissions for Course 1 - Assignment 1 and 2. 575 $this->add_assignment_submission( 576 $course1assignment1, 577 $student1, 578 "Course 1 - Ass 1: " . $student1->id 579 ); 580 $this->add_file_assignment_submission( 581 $course1assignment2, 582 $student1, 583 "Course 1 - Ass 2: " . $student1->id, 584 'Student' . $student1->id . '-Course1-Ass2' 585 ); 586 587 // Student 2 add assignment submissions for Course 2 - Assignment 1 and 2. 588 $this->add_assignment_submission( 589 $course2assignment1, 590 $student2, 591 "Course 2 - Ass 1: " . $student2->id 592 ); 593 $this->add_file_assignment_submission( 594 $course2assignment2, 595 $student2, 596 "Course 2 - Ass 2: " . $student2->id, 597 'Student' . $student2->id . '-Course2-Ass2', 598 2 599 ); 600 601 // Teacher 1 to mark assignment submissions for Course 1's Assignment 1 and 2. 602 $course1submissions = $this->get_course_assignment_submissions($course1->id); 603 foreach ($course1submissions as $submission) { 604 $this->mark_assignment_submission($submission->assignment, $submission->id, $teacher1, 49); 605 } 606 607 // Teacher 1 to mark assignment submissions for Course 2's Assignment 1 and 2. 608 $course2submissions = $this->get_course_assignment_submissions($course2->id); 609 foreach ($course2submissions as $submission) { 610 $this->mark_assignment_submission($submission->assignment, $submission->id, $teacher1, 50); 611 } 612 } 613 614 /** 615 * Helper function to add an assignment submission for testing. 616 * 617 * @param object $assignment Object containing assignment submission details to create for testing. 618 * @param object $user Object of the user making the assignment submission. 619 * @param string $submissiondata The onlintext string value of the assignment submission. 620 * @throws dml_exception 621 */ 622 protected function add_assignment_submission($assignment, $user, $submissiondata) { 623 global $DB; 624 625 $submission = (object) [ 626 'assignment' => $assignment->id, 627 'userid' => $user->id, 628 'timecreated' => date('U'), 629 'data1' => '<p>' . $submissiondata . '</p>', 630 'submissioncomment' => 'My submission by ' . $user->username 631 ]; 632 633 return $DB->insert_record('assignment_submissions', $submission); 634 } 635 636 /** 637 * Helper function to add an assignment submission with file submissions for testing. 638 * 639 * @param object $assignment Object containing assignment submission details to create for testing. 640 * @param object $user Object of the user making the assignment submission. 641 * @param string $submissiondata The onlintext string value of the assignment submission. 642 * @param string $filename The filename of the file submission included with the assignment submission. 643 * @param int $numfiles The number of files included with the assignment submission. 644 * @throws dml_exception 645 * @throws file_exception 646 * @throws stored_file_creation_exception 647 */ 648 protected function add_file_assignment_submission($assignment, $user, $submissiondata, $filename, $numfiles = 1) { 649 global $CFG, $DB; 650 651 $submission = (object) [ 652 'assignment' => $assignment->id, 653 'userid' => $user->id, 654 'timecreated' => date('U'), 655 'data1' => '<p>' . $submissiondata . '</p>', 656 'numfiles' => $numfiles, 657 'submissioncomment' => 'My submission by ' . $user->username 658 ]; 659 660 $submissionid = $DB->insert_record('assignment_submissions', $submission); 661 662 // Create a file submission with the test pdf. 663 $this->setUser($user->id); 664 $context = \context_module::instance($assignment->cmid); 665 666 $fs = get_file_storage(); 667 $sourcefile = $CFG->dirroot . '/mod/assign/feedback/editpdf/tests/fixtures/submission.pdf'; 668 669 for ($f = 1; $f <= $numfiles; $f++) { 670 $pdfsubmission = (object)array( 671 'contextid' => $context->id, 672 'component' => 'mod_assignment', 673 'filearea' => 'submission', 674 'itemid' => $submissionid, 675 'filepath' => '/', 676 'filename' => $filename . "-(File $f of $numfiles)" 677 ); 678 $fs->create_file_from_pathname($pdfsubmission, $sourcefile); 679 } 680 } 681 682 /** 683 * Helper function to retrieve the assignment submission records for a given course. 684 * 685 * @param int $courseid The course ID to get assignment submissions by. 686 * @return array Array of assignment submission details. 687 * @throws dml_exception 688 */ 689 protected function get_course_assignment_submissions($courseid) { 690 global $DB; 691 692 $sql = "SELECT s.id, 693 s.assignment, 694 s.userid, 695 s.timecreated, 696 s.timemodified, 697 s.numfiles, 698 s.data1, 699 s.data2, 700 s.grade, 701 s.submissioncomment, 702 s.format, 703 s.teacher, 704 s.timemarked, 705 s.mailed 706 FROM {assignment} a 707 JOIN {assignment_submissions} s ON s.assignment = a.id 708 WHERE a.course = :courseid"; 709 $params = [ 710 'courseid' => $courseid 711 ]; 712 713 return $DB->get_records_sql($sql, $params); 714 } 715 716 /** 717 * Helper function to update an assignment submission with grading details for a teacher. 718 * 719 * @param int $assignmentid The assignment ID to update assignment submissions with marking/graded details. 720 * @param int $submissionid The assignment submission ID to update with marking/grading details. 721 * @param int $teacher The teacher user ID to making the marking/grading details. 722 * @param int $gradedata The grade value set for the marking/grading details. 723 */ 724 protected function mark_assignment_submission($assignmentid, $submissionid, $teacher, $gradedata) { 725 global $DB; 726 727 $submission = (object) [ 728 'id' => $submissionid, 729 'assignment' => $assignmentid, 730 'grade' => $gradedata, 731 'teacher' => $teacher->id, 732 'timemarked' => date('U') 733 ]; 734 735 return $DB->update_record('assignment_submissions', $submission); 736 } 737 738 /** 739 * Helper function to retrieve the assignment records for a given context. 740 * 741 * @param int $contextid The context module ID value to retrieve assignment IDs by. 742 * @return array Array of assignment IDs. 743 * @throws dml_exception 744 */ 745 protected function get_assignments($contextid) { 746 global $DB; 747 748 $sql = "SELECT a.id 749 FROM {assignment} a 750 JOIN {course_modules} cm ON a.id = cm.instance 751 JOIN {modules} m ON m.id = cm.module AND m.name = :modulename 752 JOIN {context} ctx ON ctx.instanceid = cm.id AND ctx.contextlevel = :contextmodule 753 WHERE ctx.id = :contextid"; 754 $params = [ 755 'modulename' => 'assignment', 756 'contextmodule' => CONTEXT_MODULE, 757 'contextid' => $contextid 758 ]; 759 760 return $DB->get_records_sql($sql, $params); 761 } 762 763 /** 764 * Helper function to retrieve the assignment submission records for a given context. 765 * 766 * @param int $contextid The context module ID value to retrieve assignment submission IDs by. 767 * @return array Array of assignment submission IDs. 768 * @throws dml_exception 769 */ 770 protected function get_assignment_submissions($contextid) { 771 global $DB; 772 773 $sql = "SELECT s.id 774 FROM {assignment_submissions} s 775 JOIN {assignment} a ON a.id = s.assignment 776 JOIN {course_modules} cm ON a.id = cm.instance 777 JOIN {modules} m ON m.id = cm.module AND m.name = :modulename 778 JOIN {context} ctx ON ctx.instanceid = cm.id AND ctx.contextlevel = :contextmodule 779 WHERE ctx.id = :contextid"; 780 $params = [ 781 'modulename' => 'assignment', 782 'contextmodule' => CONTEXT_MODULE, 783 'contextid' => $contextid 784 ]; 785 786 return $DB->get_records_sql($sql, $params); 787 } 788 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body